def get_j_type(self, opcode, address): OP = opcode >> 26 target = opcode & 0x3ffffff DR = self.decode_register if OP == 2: return ("j", [ir.jump(ir.constant_operand(((target<<2)&0xfffffff) + (address&0xf0000000)))]) elif OP == 3: return ("jal", [ir.operation(DR("$ra"),'=',DR('$pc'),'+',ir.constant_operand(4)), ir.call(ir.constant_operand(((target<<2)&0xfffffff) + (address&0xf0000000)), relative=0)])
def makeIR(self, instruction, size, operands, TMEM_IR, OPmode, addr): """ instruction -> dictionary of instruction information operands -> list of operand type and value TMEM_IR -> IR for complex memory access """ #print "-----make IR ------" m = instruction['mnemonic'] preload = False poststore = False #figure out if TMEM_IR is LOAD or STORE if TMEM_IR: #first operand is destination if 'reg/mem' in operands[0][0]: preload = True poststore = True elif 'reg/mem' in operands[1][0]: preload = True elif 'moffset' in operands[1][0]: preload = True IR = [] if m == "ADC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',operands[1][1],'+',self.DR("CF"))] elif m == "ADD": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',operands[1][1])] elif m == "AND": IR = [ir.operation(operands[0][1],'=',operands[0][1],'&',operands[1][1])] elif m == "CALL": if poststore: poststore = False IR = [ir.operation(self.DR("TVAL"),'=',self.DR("EIP"),"+",ir.constant_operand(size)), ir.operation(self.DR("ESP",OPmode),'=',self.DR("ESP"),'-',ir.constant_operand(4)), ir.store(self.DR("TVAL"),self.DR("ESP",OPmode))] #absolute jump vs relative jump if 'rel' in operands[0][0]: IR += [ir.operation(self.DR("tval"),'=',self.DR("EIP"),"+",operands[0][1],'+',ir.constant_operand(size)), ir.call(self.DR("tval"), relative=True) ] else: IR += [ir.call(operands[0][1])] #controversial... analyzer must know callee _should_ do this #IR += [ir.operation(self.DR('esp'),'=',self.DR('esp'),'+',ir.constant_operand(4))] elif m == "CLC": IR = [ir.operation(self.DR("CF"), '=', ir.constant_operand(0))] elif m == "CLD": IR = [ir.operation(self.DR("DF"), '=', ir.constant_operand(0))] elif m == "CMP": if poststore: poststore = False IR = [ir.operation(operands[0][1],'-',operands[1][1])] elif m == "DEC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'-',ir.constant_operand(1))] elif m == "INC": IR = [ir.operation(operands[0][1],'=',operands[0][1],'+',ir.constant_operand(1))] elif m == "IMUL": #XXXXX TODO FIX ME #EDX:EAX = a*b || IR = [ir.operation(operands[0][1], '=', operands[0][1], '*', operands[1][1])] if operands[0][1].register_name == 'eax': #TODO SIZE IR += [ir.operation(self.DR("EDX"), '=', '(', operands[0][1], '*', operands[1][1], ')', '>>', ir.constant_operand(32))] elif m == "JMP": if poststore: poststore = False #absolute jump vs relative jump if isinstance(operands[0][1], ir.constant_operand): DEST = ir.constant_operand(int(size + operands[0][1].value)) else: DEST = operands[0][1] if 'rel' in operands[0][0]: IR += [ir.jump(DEST,relative=True)] else: IR += [ir.jump(DEST)] elif 'J' == m[0]: #IR = [ir.operation(self.DR("tval"),'=',self.DR("EIP"),"+",operands[0][1])] DEST = ir.constant_operand(int(size + operands[0][1].value)) IR = [] if m == "JO": IR += [ir.operation(self.DR('OF'),'==',ir.constant_operand(1))] elif m == "JNO": IR += [ir.operation(self.DR('OF'),'==',ir.constant_operand(0))] elif m == "JB": IR += [ir.operation(self.DR('CF'),'==',ir.constant_operand(1))] elif m == "JNC": IR += [ir.operation(self.DR('CF'),'==',ir.constant_operand(0))] elif m == "JBE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1), '||', self.DR("CF"), '==', ir.constant_operand(1))] elif m == "JNBE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(0), '&&', self.DR("CF"), '==', ir.constant_operand(0))] elif m == "JS": IR += [ir.operation(self.DR('SF'),'==',ir.constant_operand(1))] elif m == "JNS": IR += [ir.operation(self.DR('SF'),'==',ir.constant_operand(0))] elif m == "JP": IR += [ir.operation(self.DR('PF'),'==',ir.constant_operand(1))] elif m == "JNP": IR += [ir.operation(self.DR('PF'),'==',ir.constant_operand(0))] elif m == "JL": IR += [ir.operation(self.DR('SF'),'!=',self.DR('OF'))] elif m == "JNL": IR += [ir.operation(self.DR('SF'),'==',self.DR('OF'))] elif m == "JLE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1), '||', self.DR("SF"), '!=', self.DR("OF"))] elif m == "JNLE": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(0), '&&', self.DR("SF"), '==', self.DR("OF"))] elif m == "JNZ": IR += [ir.operation(self.DR('ZF'),'==',ir.constant_operand(1))] elif m == "JZ": IR += [ir.operation(self.DR('ZF'), '==', ir.constant_operand(0))] if 'rel' in operands[0][0]: IR += [ir.branch_true(DEST)] else: IR += [ir.branch_true(operands[0][1])] elif m == "LEA": preload = False poststore = False IR = [ir.operation(operands[0][1], '=', self.DR("TMEM"))] elif m == "LEAVE": # mov esp, ebp # pop ebp IR = [ir.operation(self.DR("ESP"),'=',self.DR("EBP")), ir.load(self.DR("ESP"), self.DR("EBP")), ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"+",ir.constant_operand(4)) ] elif m == "MOV": #print hex(addr), operands if preload: if 'moffset' not in operands[1][0]: if operands[1][1].type != 'register' or operands[1][1].register_name != 'tval': preload = False if operands[0][1].type == 'register' and operands[0][1].register_name == 'tval': IR = [ir.operation(operands[1][1])] else: IR = [ir.operation(operands[0][1], '=', operands[1][1])] elif m == "MOVSX": #XXXXXX TODO sign extend IR = [ir.operation(operands[0][1], '=', operands[1][1])] elif m == "MOVZX": if '16' in operands[1][0]: mask = 0xff else: mask = 0xffff IR = [ir.operation(operands[0][1], '=', operands[1][1], '&', ir.constant_operand(mask))] elif m == "NOT": IR = [ir.operation(operands[0][1],'=','~',operands[0][1])] elif m == "OR": IR = [ir.operation(operands[0][1],'=',operands[0][1],'|',operands[1][1])] elif m == "POP": #TODO 0x20b6: pushl 0xff5b(%eax) no handled correctly IR = [ir.load(self.DR("ESP",OPmode), operands[0][1]), ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"+",ir.constant_operand(4))] elif m == "PUSH": if type(operands[0][1]) == str: IR = [ir.unhandled_instruction(instruction['mnemonic'])] else: IR = [ir.operation(self.DR("ESP",OPmode), '=', self.DR("ESP",OPmode),"-",ir.constant_operand(4)), ir.store(operands[0][1], self.DR("ESP",OPmode)), ] if operands[0][1].type == 'register' and operands[0][1].register_name != 'tval': poststore = False elif m == "RET": #pop eip preload = True IR = [ir.load(self.DR("ESP",OPmode), self.DR('TVAL')), ir.operation(self.DR('ESP',OPmode),'=',self.DR("ESP",OPmode),'+',ir.constant_operand(4)), ir.ret(self.DR('TVAL'))] elif m == "ROL": #XXX TODO FIX sz here sz = operands[0][1].size IR = [ir.operation(operands[0][1], '=', operands[0][1], '<<', operands[1][1], '|', operands[0][1],'>>', '(', ir.constant_operand(sz),'-',operands[1][1],')')] elif m == "ROR": sz = operands[0][1].size IR = [ir.operation(operands[0][1], '=', operands[0][1], '>>', operands[1][1], '|', operands[0][1],'<<', '(', ir.constant_operand(sz),'-',operands[1][1],')')] elif m == "SAL": IR = [ir.operation(operands[0][1],'=', '(', self.DR("CF"), '<<', ir.constant_operand(32), '+', operands[0][1], ')','>>',operands[1][1])] elif m == "SAR": IR = [ir.operation(operands[0][1],'=', '(', self.DR("CF"), '>>', ir.constant_operand(32), '+', operands[0][1], ')','<<',operands[1][1])] elif m == "SHL": IR = [ir.operation(operands[0][1],'=', operands[0][1],'<<',operands[1][1])] elif m == "SHR": IR = [ir.operation(operands[0][1],'=', operands[0][1],'>>',operands[1][1])] elif m == "SUB": IR = [ir.operation(operands[0][1],'=', operands[0][1],'-',operands[1][1])] elif m == "TEST": IR = [ir.operation(operands[0][1],'&',operands[1][1])] elif m == "XCHG": have_nop = 0 if operands[0][1].type == 'register' and operands[1][1].type == 'register': if operands[0][1].register_name == "eax" and operands[1][1].register_name == "eax": have_nop = 1 #TODO does not play well with TMEM if have_nop: IR = [ir.operation("NOP")] else: #XXXXX TODO TMEM IR = [ir.operation(self.DR("tval"),'=',operands[0][1]), ir.operation(operands[0][1],'=', operands[1][1]), ir.operation(operands[1][1],'=', self.DR("TVAL"))] elif m == "XOR": IR = [ir.operation(operands[0][1],'=', operands[0][1],'^',operands[1][1])] else: IR = [ir.unhandled_instruction(instruction['mnemonic'])] if TMEM_IR: #print "@@"#, preload, poststore, TMEM_IR out = [] if preload: out += TMEM_IR + [ir.load(self.DR("TMEM"),self.DR("TVAL"))] elif TMEM_IR: if not poststore: out += TMEM_IR if poststore: if IR[0].type == 'operation': #XXX implicit load store hack if len(IR[0].ops) == 1: IR = [ir.operation(self.DR('tval'),'=', *(IR[0].ops))] out += IR + TMEM_IR + [ir.store(self.DR("tval"), self.DR('TMEM'))] else: out += IR return out return IR
def get_r_type(self, opcode): function = opcode & 0x3f rs = (opcode>>21) & 0x1f rt = (opcode>>16) & 0x1f rd = (opcode>>11) & 0x1f sa = (opcode>>6) & 0x1f DR = self.decode_register instructions = { 0 : ("sll rd = rt << sa", [ir.operation(DR(rd),"=",DR(rs),"<<",DR(sa), signed=0)]), 2 : ("srl rd = rt >> sa", [ir.operation(DR(rd),"=",DR(rs),">>",DR(sa), signed=0)]), 3 : ("sra rd = rt >> sa", [ir.operation(DR(rd),"=",DR(rs),">>",DR(sa))]), 4 : "sllv", 6 : "srlv", 7 : "srav", 8 : ("jr PC = rs", [ir.jump(DR(rs))]), 9 : ("jalr rd = return_addr, PC = rs ", [ir.operation(DR(rd),'=',DR("$pc"),"+",ir.constant_operand(4)), ir.call(DR(rs))]), 12 : "syscall", 13 : "break", 15 : "sync", 16 : ("mfhi", [ir.operation(DR(rd),'=',DR("HILO"))]), 17 : ("mthi", [ir.operation(DR("HILO"),'=',DR(rs),'<<',ir.constant_operand(32))]), 18 : ("mflo", [ir.operation(DR(rd),'=',DR("HILO"))]), 19 : ("mtlo", [ir.operation(DR("HILO"),'=',DR(rs))]), 24 : ("mult LO,HI = rs*rt", [ir.operation(DR("HILO"),"=",DR(rs),"*",DR(rt))]), 25 : ("multu", [ir.operation(DR("HILO"),"=",DR(rs),"*",DR(rt), signed=0)]), 26 : ("div", [ir.operation(DR("HILO"),"=",DR(rs),"/",DR(rt))]), 27 : ("divu", [ir.operation(DR("HILO"),"=",DR(rs),"/",DR(rt), signed=0)]), 28 : "dmult", 29 : "dmultu", 30 : "ddiv", 31 : "ddivu", 32 : ("add rd = rs + rt", [ir.operation(DR(rd),"=",DR(rs),"+",DR(rt))]), 33 : ("addu", [ir.operation(DR(rd),"=",DR(rs),"+",DR(rt), signed=0)]), 34 : ("sub", [ir.operation(DR(rd),'=',DR(rs),"-",DR(rt))]), 35 : ("subu", [ir.operation(DR(rd),'=',DR(rs),"-",DR(rt), signed=0)]), 36 : ("and", [ir.operation(DR(rd),"=",DR(rs),"&",DR(rt))]), 37 : ("or", [ir.operation(DR(rd),"=",DR(rs),"|",DR(rt))]), 38 : ("xor", [ir.operation(DR(rd),"=",DR(rs),"^",DR(rt))]), 39 : ("nor", [ir.operation(DR(rd),'=',DR(rs),"~",DR(rt))]), 42 : ("slt", [ir.operation(DR(rd),'=',DR(rs), "<", DR(rt))]), 43 : ("sltu", [ir.operation(DR(rd),'=',DR(rs), "<", DR(rt), signed=0)]), 45 : ("daddu", [ir.operation(DR(rd),'=',DR(rs), "+", DR(rt), signed=0)]), 47 : ("dsubu", [ir.operation(DR(rd),'=',DR(rs), "-", DR(rt), signed=0)]), 52 : "teq", 56 : "dssl", 58 : "todo", 59 : "dsra", 60 : "dsll32", 62 : "dsrl32", 63 : "dsra32" } if function in instructions: instr = instructions[function] if "jr" in instr[0]: if instr[1][0].dest == DR("$ra"): #this instruction is considered a 'ret' instr[1][0] = ir.ret(DR("$ra")) return instr else: raise Exception("unknown function code for R types: %d"%function)