-
Notifications
You must be signed in to change notification settings - Fork 5
/
CodeGenerator.py
172 lines (132 loc) · 4.75 KB
/
CodeGenerator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
from capstone import *
from capstone.x86 import *
from Instructions import *
# Basic code..
codeC = '''
#include "environment.h"
void func() {
%s}\n
int main() {
}
'''
''' Just load bytes in desired range '''
def loadCode(filename, start, stop):
f = open(filename, 'rb')
code = f.read()
return code[start:stop]
class CodeGenerator:
def __init__(self, name, start, stop, flags):
self.code = loadCode(name, start, stop)
self.cCode = ''
# Instruction lookup
self.cinstr = {
'mov' : mov,
'movzx' : movzx,
'movsx' : movzx,
'cdqe' : cdqe,
'sub' : sub,
'add' : add,
'inc' : inc,
'dec' : dec,
'cmp' : cmp,
'jmp' : jmp,
'jne' : jne,
'je' : je,
'jnb' : jnb,
'jb' : jb,
'jbe' : jbe
}
self.jumps = ['jmp', 'je', 'jne', 'jz', 'jnz', 'jnb', 'jb', 'jbe']
self.usedFlags = flags
# Init capstone
self.cs = Cs(CS_ARCH_X86, CS_MODE_64)
self.cs.detail = True
self.instructions = [x for x in self.cs.disasm(self.code, 0)]
self.jumpPlaces = {}
self.checkJumps()
# go go go
self.generate()
''' Just fill C template '''
def getAsC(self):
return codeC % self.cCode
''' Every jump must have place to jump,
here we check, that every jump has place,
if code is self-modyifing or jumps in middle of instruction
then this method will fail
'''
def checkJumps(self):
for instr in self.instructions:
# Is it jump?
if instr.mnemonic in self.jumps:
# Yes, so get address
addr = int(instr.operands[0].imm)
found = False
# Check existence of target instruction
for _instr in self.instructions:
if _instr.address == addr:
found = True
self.jumpPlaces[addr] = True
break
if not found:
print("Jump to nonexisting instr (Or jump in instr middle)...\nQuitting...")
exit(0)
''' Go over each instruction in range '''
def generate(self):
for inst in self.instructions:
# If we will jump to this instruction
# Add label for goto
if inst.address in self.jumpPlaces:
self.emit('_%x:' % (inst.address), indent=0)
# Operands is list of ops, 0, 1, 2 (may more) ops
ops = [x for x in inst.operands]
args = [self.buildOperand(inst, x) for x in ops]
#print('%x: %s %s -> %s' % (inst.address, inst.mnemonic, inst.op_str, '') )
# check is available
if inst.mnemonic not in self.cinstr:
print("Instruction not found...\nQuitting...")
exit(0)
# process instruction
self.cinstr[ inst.mnemonic ](*args, inst, self)
'''
Create Operand
'''
def buildOperand(self, instr, operand):
type = operand.type
# eg. regs.eax
if type == X86_OP_REG:
return Operand(type, instr.reg_name(operand.reg), operand.size)
# eg. rax + rbx * 1 - 0x13
if type == X86_OP_MEM:
baseReg = instr.reg_name(operand.mem.base)
displacement = operand.mem.disp
index, scale = (operand.mem.index, operand.mem.scale)
out = baseReg
if index:
out += '+' + instr.reg_name(index) + '*' + str(scale)
if displacement:
if displacement < 0: out += '-'
if displacement > 0: out += '+'
out += str(abs(displacement))
return Operand(type, out, operand.size)
# eg. 0x10
if type == X86_OP_IMM:
return Operand(type, str(operand.imm), operand.size)
raise "Unknown type..."
''' Spaces FTW '''
def emit(self, data, flags = '', actions = '', comment = '', indent = 1):
self.cCode += ' ' * indent
self.cCode += data + '; '
# Append comment
if len(comment):
self.cCode += '// ' + comment + '\n'
# Check is flag used, and append
if len(flags):
for (id, flag) in flags:
if id in self.usedFlags:
self.cCode += (' ' * indent) + ' ' + flag + ';\n'
# Add actions, executed after setting flags
if len(actions):
for action in actions:
self.cCode += (' ' * indent) + ' ' + action + ';\n'
if len(comment) == 0 and len(flags) == 0:
self.cCode += '\n'