def callbackProcessing(self,inputLoggingList): """ This function is a callback from the API monitoring functions When the API monitoring functions is ready to start tracing, it calls this function from the debugger to start tracing The list of input values is written to a file or memory, then PauseProcess is called to force the debugger to suspend Suspending the debugger will then trigger the debugger to go into single stepping mode In single stepping mode, each instruction will be written to either memory or a file @param inputLoggingList: A list of input values to log @return: None """ data_addr = inputLoggingList.pop(0) data_size = inputLoggingList.pop(0) data = inputLoggingList.pop(0) handle = inputLoggingList.pop(0) caller_addr = inputLoggingList.pop(0) caller_name = inputLoggingList.pop(0) thread_id = inputLoggingList.pop(0) global instSeq self.logger.info( "Taking a memory snapshot then saving to the current idb file.") self.logger.info("CallbackProcessing called. Logging input... I %x %d %s 0x%x 0x%x %s 0x%x 0x%x" % \ (data_addr,data_size,toHex(data),thread_id,instSeq,caller_name,caller_addr,handle) ) self.memoryWriter.writeToFile("I %x %d %s 0x%x 0x%x %s 0x%x 0x%x\n" % \ (data_addr,data_size,toHex(data),thread_id,instSeq,caller_name,caller_addr,handle) ) #update the instruction sequence counter instSeq = instSeq+1 self.startTracing = True PauseProcess()
def dbg_step_into(self): """ Notified when the debugger is single stepping thru a process This is the main function for tracing, we analyze each instruction being executed The instruction along with its metadata is written to either memory or out to a file This is a standard IDA Debug Hook callback """ global instSeq eip = GetRegValue("EIP") DecodeInstruction(eip) inslen = cmd.size if cmd.size > 0: bytes = get_many_bytes(cmd.ea,cmd.size) self.memoryWriter.writeToFile("E 0x%x %x %s " % (cmd.ea,cmd.size,toHex(bytes))) instcode = c_byte*inslen instBytes = instcode() for i in range(inslen): instBytes[i]=get_byte(cmd.ea+i) curid = idc.GetCurrentThreadId() self.memoryWriter.writeToFile("0x%x 0x%x" % (curid, instSeq)) # current_thread_id instSeq = instSeq+1 instInfo = instDecode() if inslen > 0: self.xDecoder32.decode_inst(inslen, pointer(instBytes),ctypes.byref((instInfo))) else: self.logger.error( "Cannot decode instruction at 0x%x %x %s" % (cmd.ea,cmd.size,toHex(bytes)) ) self.logger.debug("source_operands_number=%d" % (instInfo.n_src_operand)) lReadEA = 0 lReadSize = 0 lWriteEA = 0 lWriteSize = 0 bSegFS = 0 regs = {} for i in range(instInfo.n_src_operand): self.logger.debug("%d: width=%d, rw=%d, type=%d, ea_string=%s" %(i, instInfo.src_operands[i]._width_bits,instInfo.src_operands[i]._rw,instInfo.src_operands[i]._type,instInfo.src_operands[i]._ea)) if(instInfo.src_operands[i]._type == REGISTER): if(instInfo.src_operands[i]._ea == "STACKPOP"): regs["ESP"] = GetRegValue("ESP") elif((instInfo.src_operands[i]._ea.find("EFLAGS"))!=-1): regs["eflags"] = GetRegValue("EFL") else: regs[instInfo.src_operands[i]._ea]= GetRegValue(instInfo.src_operands[i]._ea) elif(instInfo.src_operands[i]._type == MEMORY): #collect registers used to calculate memory address lBase = 0 lIndex = 0 lScale =0 lDisp = 0 parts = (instInfo.src_operands[i]._ea).split(":") for part in parts: comps = part.split("=") if(len(comps)==2): self.logger.debug("%s is %s"%(comps[0], comps[1])) if comps[0] =="SEG": if(comps[1]=="FS"): bSegFS = 1 self.logger.debug("SRC SEG==FS") continue elif comps[0] =="BASE": lBase = GetRegValue(comps[1]) regs[comps[1]] = GetRegValue(comps[1]) elif comps[0] =="INDEX": lIndex = GetRegValue(comps[1]) regs[comps[1]] = GetRegValue(comps[1]) elif comps[0] =="SCALE": lScale = int(comps[1]) elif comps[0] =="DISP": lDisp = int(comps[1]) else: break lReadEA = lBase + lIndex*lScale + lDisp if (instInfo.attDisa.find("lea")!=-1): # lea doesn't actually read lReadSize = 0 self.logger.debug("Encounter instruction lea:%s" %(instInfo.attDisa)) elif (bSegFS==1): lReadSize = 0 self.logger.debug("FS segement register ignored for NOW:%s" %(instInfo.attDisa)) else: lReadSize = instInfo.src_operands[i]._width_bits/8 self.logger.debug("lEA = 0x%x" %(lReadEA)) self.logger.debug("dest_operands_number=%d" % (instInfo.n_dest_operand)) for i in range(instInfo.n_dest_operand): self.logger.debug("%d: width=%d, rw=%d, type=%d, ea_string=%s" %(i, instInfo.dest_operands[i]._width_bits,instInfo.dest_operands[i]._rw,instInfo.dest_operands[i]._type,instInfo.dest_operands[i]._ea)) if(instInfo.dest_operands[i]._type == REGISTER): if(instInfo.dest_operands[i]._ea == "STACKPUSH"): #push ino stack regs["ESP"] = GetRegValue("ESP") elif((instInfo.dest_operands[i]._ea.find("EFLAGS"))!=-1): regs["eflags"] = GetRegValue("EFL") else: regs[instInfo.dest_operands[i]._ea]= GetRegValue(instInfo.dest_operands[i]._ea) elif(instInfo.dest_operands[i]._type == MEMORY): #collect registers used to calculate memory address lBase = 0 lIndex = 0 lScale =0 lDisp = 0 parts = (instInfo.dest_operands[i]._ea).split(":") for part in parts: comps = part.split("=") if(len(comps)==2): self.logger.debug("%s is %s" %(comps[0], comps[1])) if comps[0] =="SEG": if(comps[1]=="FS"): bSegFS = 1 self.logger.debug("DEST: SEG==FS") continue elif comps[0] =="BASE": lBase = GetRegValue(comps[1]) regs[comps[1]] = lBase self.logger.debug("BASE %s equals 0x%x" %(comps[1],lBase)) elif comps[0] =="INDEX": lIndex = GetRegValue(comps[1]) regs[comps[1]] = lIndex self.logger.debug("lIndex %s equals 0x%x" %(comps[1],lIndex)) elif comps[0] =="SCALE": lScale = int(comps[1]) self.logger.debug("lScale equals 0x%x" %(lScale)) elif comps[0] =="DISP": lDisp = int(comps[1]) self.logger.debug("lDisp equals 0x%x" %(lDisp)) else: break lWriteEA = lBase + lIndex*lScale + lDisp if (bSegFS==1): lWriteSize = 0 self.logger.debug("FS segement register ignored for NOW:%s" %(instInfo.attDisa)) else: lWriteSize = instInfo.dest_operands[i]._width_bits/8 self.logger.debug("lEA = 0x%x" %(lWriteEA)) self.memoryWriter.writeToFile(" Reg( ") for reg in regs: self.memoryWriter.writeToFile("%s=0x%x " %(reg,regs[reg])) self.memoryWriter.writeToFile(") ") if lReadEA!=0 and lReadSize!=0: self.memoryWriter.writeToFile("R %d %x " % (lReadSize,lReadEA)) for j in range(lReadSize): value = DbgByte(lReadEA+j) if(value is not None): if(j==0): self.memoryWriter.writeToFile("%x" %(value)) else: self.memoryWriter.writeToFile("_%x" %(value)) else: self.memoryWriter.writeToFile("X") if lWriteEA!=0 and lWriteSize!=0: # no need to get contents from the write address self.memoryWriter.writeToFile(" W %d %x " % (lWriteSize,lWriteEA)) self.memoryWriter.writeToFile("\n") request_step_into() else: self.logger.error("The instruction at 0x%x has 0 size." % cmd.ea)