def memcmp(self, dp1, dp2, n): d1 = idc.DbgRead(dp1, n) d2 = idc.DbgRead(dp2, n) if d1 == d2: return 0 else: return 1
def dbg_bpt(self, tid, ea): try: if self.done: print('should be done') return 0 if ea == self.send_req_ea: print('ON SEND REQ') self.reqid += 1 a = read_u32(idautils.cpu.esp + 4) b = read_u32(idautils.cpu.esp + 8) print(a, b) a = get_str(a) b = get_str(b) print(a, b) content = req_web(a, b) do_ret() ea = self.bufs[self.reqid - 1] idautils.cpu.eax = ea idc.DbgWrite(ea, content) print('GOT CONTENT >> ', content) if self.reqid >= 4: self.done = 1 elif ea == self.decrypt_end_ea: tmp = read_u32(idautils.cpu.eax) rem = idc.DbgRead(idautils.cpu.eax + 4, 0x3000) print('DECRYPTING >>>', tmp, rem) except Exception as e: tb.print_exc() self.done = 1 print('FAILURE') return 0
def decode_seg(self, seg_addr, mem_seg): sz = read_u32(seg_addr + 0) addr = read_u32(seg_addr + 0x18) print('HAS SEG >> ', seg_addr, hex(addr), hex(sz), mem_seg) inspos_ptr = read_u32(seg_addr + 12) pos = 0 inslst = [] content = bytearray() self.call(self.virtual_protect_ea, addr, sz, 4, idautils.cpu.esp) yield while pos < sz: ipos = read_u32(inspos_ptr) if pos > ipos: break assert pos == ipos, '%s %s'%(pos, ipos) csize = read_u32(inspos_ptr + 4) inslst.append((pos, csize)) pos += csize inspos_ptr += 8 assert pos <= sz for ins, sz in inslst: target_addr = addr + ins push(mem_seg) push(target_addr) push(seg_addr-8) self.call(self.decode_seg_ea, seg_addr-8, target_addr, mem_seg) yield assert idautils.cpu.eip == self.ret_pad_ea content[ins:ins+sz] = idc.DbgRead(target_addr, sz) self.segs.append(dict(sz=sz, addr=addr, content=base64.b64encode(content), mem_seg=mem_seg, seg_addr=seg_addr))
def send_fixed_handler(self, bufaddr, n): have = idc.DbgRead(bufaddr, n) expected = self.v2c.read(n) #print('EXPEcted ', expected) #print('have ', have) #assert have == expected return 1
def save_screen(self): w=1280 h=720 buf=idc.DbgRead(self.screen_buf_ea, w*h*4) filename='/tmp/imgs/f1_%05d.p7'%self.screen_count open(filename, 'wb').write(buf) self.screen_count+=1 self.last_edi=None
def memchr(self, dp, c, n): c = chr(c) data = idc.DbgRead(dp, n) offset = data.find(c) if offset == -1: return 0 else: return dp + offset
def get_str(addr): s = '' n = 0x100 while True: x = idc.DbgRead(addr, n) for j in range(len(x)): if ord(x[j]) == 0: s += x[:j] return s s += x addr += len(x) return s
def handler(self): if 1: b1 = 'sn00gle-fl00gle-p00dlekins' dst = idautils.cpu.esp + 0x100 dstsize = 0x102 idc.DbgWrite(dst, '\x00'*dstsize) buf = dst - len(b1)-10 idc.DbgWrite(buf, b1+'\x00') gen_perm_ea = idc.LocByName('generate_perm') mix_ea = idc.LocByName('mix_things') pass1_ea = idc.LocByName('PASSWORD1') pass1_len = read_u32(idc.LocByName('PASSWORD1_LEN')) finalsize = pass1_len finaldest = idautils.cpu.esp - 2*finalsize idc.DbgWrite(finaldest, '\x00'*(finalsize+1)) self.call(gen_perm_ea, dst, buf, len(b1)) yield print(hex(dst), hex(pass1_ea), hex(finaldest), hex(pass1_len)) #self.done = 1 #return self.call(mix_ea, dst, pass1_ea, finaldest, pass1_len) yield with open('./final.data', 'wb') as f: f.write(idc.DbgRead(finaldest, pass1_len)) else: stride = 0x24 nseg = read_u32(self.rx_seg_count) base_addr = self.rx_seg_desc print('HANDLER', nseg) for i in range(nseg): seg_addr = base_addr + stride * i for data in self.decode_seg(seg_addr, False): yield nseg = read_u32(self.rw_seg_count) base_addr = self.rw_seg_desc for i in range(nseg): seg_addr = base_addr + stride * i for data in self.decode_seg(seg_addr, True): yield print('dumping handler') json.dump(self.segs, open('./dump.json', 'w')) self.done = 1
def dbg_bpt(self, tid, ea): #if ea == self.cond_ea: # self.done = True # self.res_val = idc.DbgDword(idautils.cpu.esi) print('ON >> ', hex(ea), 'want ', hex(self.fill_obj)) if ea == self.fill_obj: idc.DbgWrite(idautils.cpu.edx + 0x638, struct.pack('<I', 0xc0000000)) idc.DbgWrite(idautils.cpu.edx, open('/tmp/data.out', 'rb').read()) idautils.cpu.eip = self.fill_ret print('JUMPING') elif ea == self.choose_item: idautils.cpu.eax = self.item elif ea == self.file_ea: buf = idc.DbgRead(idautils.cpu.edi, idautils.cpu.esi) x = open('/tmp/chall11_out_%d.out' % self.item, 'wb') x.write(buf) x.close() self.done = 1 return 0
def getMemory(self, pos, l): return idc.DbgRead(pos, l)
def read_u32(addr): return struct.unpack('<I', idc.DbgRead(addr, 4))[0]
def fwrite(self, ptr, size, nmemb, fd): data = idc.DbgRead(ptr, (size * nmemb)) self._write(fd, data) return len(data)
def dbg_bpt(self, tid, ea): #if ea == self.cond_ea: # self.done = True # self.res_val = idc.DbgDword(idautils.cpu.esi) #print('ON >> ', hex(ea), 'want ') try: if ea == self.push_screen_ea: tmp=idc.DbgRead(self.screen_buf_ea, 6) self.screen_data.append(tmp) print('pushing screen here', tmp) self.count += 1 if 0 and self.count == 10000: self.done = 1 if self.count%10==0: self.save_screen() elif ea == self.deque_ea: recv_word = idautils.cpu.eax mask=idc.DbgDword(idautils.cpu.ebp-0x6070) self.dec_data.append([recv_word, mask]) if 1 and len(self.dec_data)==0x1000/8: self.done=1 print('DEQUE >> ', hex(recv_word), hex(mask)) elif ea == self.prepare_reg_send: if 1: return idc.DbgWrite(idautils.cpu.esp+0x3c-0x1d, chr(self.cur_byte)) abc=idc.DbgRead(idautils.cpu.esp+0x3c-0x1d, 1) print('SENDING CHAR >> ', abc, self.cur_byte) self.tmp_tb=[] self.last_edi=idautils.cpu.edi elif ea == self.enqueue_func: print('SKIPPING ENQUEUE') if 0: return do_ret() elif ea == self.enqueue_ea: #if 0: return if self.tmp_tb is not None: nedi=idautils.cpu.edi send_word=(nedi-self.last_edi)%8 self.last_edi=nedi self.tmp_tb.append(send_word) self.tb2.append([nedi, hex(idautils.cpu.eax)]) print('GOT TB LEN ', self.tmp_tb) if len(self.tmp_tb)==3: self.enc_data.append(self.tmp_tb) self.tmp_tb=None self.cur_byte+=1 self.last_edi=None if self.cur_byte==256: self.done=1 print('ENQUEUE >> ', send_word) elif ea == self.prepare_str_ea: if 1: return buf_len = idc.DbgDword(idautils.cpu.esi + 0x38) buf_addr = idc.DbgDword(idautils.cpu.esi + 0x34) buf = idc.DbgRead(buf_addr, buf_len) print(buf_len, buf_addr, buf) assert len(self.want_str) <= buf_len idc.DbgWrite(buf_addr, self.want_str) idc.DbgWrite(idautils.cpu.esi + 0x38, struct.pack('<I', len(self.want_str))) print('string is set') #self.done = 1 elif ea==self.test_time_end: if self.time>=3600*24: self.done=1 #entre 23h et 1h else: idautils.cpu.eip=self.test_time_start resv=idautils.cpu.eax h,m,s=self.get_time(self.time) print 'REsult: %d:%d:%d >> %d'%(h,m,s,resv) self.time+=60 elif ea==self.test_time_mod: h,m,s=self.get_time(self.time) addr=idautils.cpu.ebx write_u16(addr+4*2, h) write_u16(addr+5*2, m) write_u16(addr+6*2, s) except: traceback.print_exc() print('FAILED here') self.done=1 return 0
def wcsncpy_handler(self, dest, src, n): print('WCSNCPY >> ', idc.DbgRead(src, n * 2)) return RetAction('continue')
def create_process_w_handler(self): print('CreateProcess >> ', make_print(idc.DbgRead(idautils.cpu.edx, 100))) #self.done = 1 return RetAction('continue')
def write_file_handler(self, handle, buf, n): print('WriteFile >> ', make_print(idc.DbgRead(buf, n)), n) return RetAction('continue')
def memcpy_handler(self, dest, src, n): print('MEMCPY >> ', idc.DbgRead(src, n)) return RetAction('continue')
def Handler(self): ''' Breakpoint condition handler, called by IDA to evaluate conditional brekpoints. It in turn calls the appropriate function handler, populates the return value and puts execution back at the return address. This is a (slight) abuse of IDA's conditional breakpoints; this function always returns 0, indicating that the breakpoint condition has not been met. However, it does ensure that every call to a given function can be intercepted and simulated, regardless of whether the process is running freely, or the function has been stepped over, stepped into, etc. ''' retval = 0 retaddr = None if self.verbose: print self.FUNCTION_HANDLERS for (name, properties) in self.FUNCTION_HANDLERS.iteritems(): if self.cpu.ProgramCounter() == properties["address"]: handler = properties["handler"] break # If no explicit handler was found, use the default handler if not handler and self.DEFAULT_HANDLER: handler = self.DEFAULT_HANDLER if handler: if self.verbose: print "Using function handler:", handler.__name__ parameters = {} # Enumerate the arguments and default values for the handler args, varargs, keywords, defaults = inspect.getargspec(handler) try: defaults = dict(zip(reversed(args), reversed(defaults))) except: defaults = {} # Build the handler parameters try: i = 0 for arg in args: if arg != 'self': parameters[arg] = self.cpu.Argument(i) if defaults.has_key(arg): # If default value is of type string, get the string automatically if type(defaults[arg]) == type(''): parameters[arg] = idc.GetString( parameters[arg]) # If default value is of type list, get an array of bytes elif type(defaults[arg]) == type([]) and len( defaults[arg]) == 1: parameters[arg] = [ c for c in idc.DbgRead( parameters[arg], defaults[arg][0]) ] i += 1 except Exception, e: print "WARNING: Failed to parse handler parameters:", str(e) parameters = {} try: retval = handler(**parameters) except JumpTo, offset: retaddr = self.cpu.ReturnAddress() + offset.message
def handler(self): assert_on_addr(self.run_call_addr) #PYALOD ENTRY: 00404000 self.diff = idautils.cpu.ecx - idc.LocByName('PAYLOAD_ENTRY') self.find_sym_addr = self.sym('find_sym') # 40b420 self.mainloop_addr = self.add_bpt_on_sym('mainloop') print('MAINLOOP ', hex(self.mainloop_addr)) yield assert_on_addr(self.mainloop_addr) print('INDEED ON ADDR, start get syms') if 1: self.replay_handlers[self.sym( 'generate_random_buf')] = self.generate_random_buf_handler self.replay_handlers[self.sym( 'send_fixed')] = self.send_fixed_handler self.replay_handlers[self.sym( 'recv_fixed_len')] = self.recv_fixed_handler self.replay_handlers[self.sym( 'initiate_conn')] = self.initiate_conn_handler self.replay_handlers[self.sym( 'do_recv')] = self.do_recv_handler self.replay_handlers[self.sym( 'listen_initiate')] = self.undefined_handler self.replay_handlers[self.sym( 'caller_ntdll_strncpy')] = self.memcpy_handler self.replay_handlers[self.sym( 'caller_ntdll_wcsncpy')] = self.wcsncpy_handler self.replay_handlers[self.sym( 'caller_ntdll_memcpy')] = self.memcpy_handler self.replay_handlers[ self.sym('caller_kernel32_CreateProcessW' )] = self.create_process_w_handler self.replay_handlers[self.sym( 'caller_kernel32_WriteFile')] = self.write_file_handler self.replay_handlers[self.sym( 'caller_mpr_WNetOpenEnumW')] = self.wnet_open_enum_handler self.replay_handlers[self.sym('caller_mpr_WNetEnumResourceW' )] = self.wnet_enum_rsc_handler #self.replay_handlers[self.sym('caller_kernel32_FindNextFileW')] = self.find_next_filew_handler self.replay_handlers[self.sym( 'handle_conn_end')] = self.stop_handler self.replay_handlers[self.sym( 'caller_mpr_WNetAddConnection2W')] = self.stop_handler self.counts = defaultdict(lambda: 0) for silent_addr in self.syms_to_find.values(): if not silent_addr in self.replay_handlers: self.replay_handlers[silent_addr] = self.silent_handler for k in self.replay_handlers.keys(): self.add_bpt(k) if 1: xx = './conn2.packets.pickle' data = pickle.load(open(xx, 'rb')) self.c2v = io.BytesIO(data['c2v']['key']) print('start try packets') for _ in self.wait_until('generate_random_buf'): yield self.curkey = data['v2c']['key'] print('On generate_random_buf_handler') self.replay_handler(self.ea, key=True) yield if 0: for _ in self.wait_until('recv_packet'): yield pkts = data['c2v']['packets'] for i, pkt in enumerate(pkts): print('============', i) print('============', i) print('============', i) print('============', i) print('============', i) print('============', i) print('============', i) self.c2v = io.BytesIO(pkt[1]) self.curkey = pkt[1][0x2a:0x2a + 4] for _ in self.wait_until('recv_packet_end'): yield for _ in self.wait_until('recv_packet'): yield else: cnt = 0 for i, pkt in enumerate(data['c2v']['packets']): for _ in self.wait_until('recv_packet'): yield self.c2v = io.BytesIO(pkt[1]) for _ in self.wait_until('recv_packet_end'): yield ptr = idautils.cpu.ebp - 8 data_ptr = read_u32(ptr) with open('./output/' + xx + '_cmd_%04d.out' % i, 'wb') as f: if i == 11: f.write(idc.DbgRead(data_ptr, 0x8000)) else: f.write(idc.DbgRead(data_ptr, 0x2000)) idautils.cpu.eip = self.sym('recv_packet_start') cnt += 1 else: self.do_replay = 1 assert 0 if 0: for cst, target_func in self.syms_to_find.items(): self.call1(self.find_sym_addr, cst) yield assert_on_addr(self.ret_pad_ea) addr = idautils.cpu.eax name = idc.Name(addr) self.onames.append((target_func, 'caller_' + name)) self.done = 1 yield