LyScript 插件实现对特定汇编指令片段的批量搜索功能,用户传入一个汇编指令列表,然后循环搜索该列表内的所有指令特征,如果找到了,则返回该指令的内存地址。
得到汇编指令机器码: 该功能主要实现,得到用户传入汇编指令所对应的机器码,这段代码你可以这样来实现。
from LyScript32 import MyDebugif __name__ == "__main__" : dbg = MyDebug() connect_flag = dbg.connect() print ("连接状态: {}" .format (connect_flag)) addr = dbg.create_alloc(1024 ) print ("堆空间: {}" .format (hex (addr))) asm_size = dbg.assemble_code_size("mov eax,1" ) print ("汇编代码占用字节: {}" .format (asm_size)) write = dbg.assemble_write_memory(addr,"mov eax,1" ) byte_code = bytearray () for index in range (0 ,asm_size): read = dbg.read_memory_byte(addr + index) print ("{:02x} " .format (read),end="" ) dbg.delete_alloc(addr)
封装如上代码接口,实现get_opcode_from_assemble()
用户传入汇编指令,得到该指令对应机器码。
from LyScript32 import MyDebugdef get_opcode_from_assemble (dbg_ptr,asm ): byte_code = bytearray () addr = dbg_ptr.create_alloc(1024 ) if addr != 0 : asm_size = dbg_ptr.assemble_code_size(asm) write = dbg_ptr.assemble_write_memory(addr,asm) if write == True : for index in range (0 ,asm_size): read = dbg_ptr.read_memory_byte(addr + index) byte_code.append(read) dbg_ptr.delete_alloc(addr) return byte_code else : return bytearray (0 ) if __name__ == "__main__" : dbg = MyDebug() connect_flag = dbg.connect() print ("连接状态: {}" .format (connect_flag)) byte_array = get_opcode_from_assemble(dbg,"xor eax,eax" ) for index in byte_array: print (hex (index),end="" ) print () asm_list = ["xor eax,eax" , "xor ebx,ebx" , "mov eax,1" ] for index in asm_list: byte_array = get_opcode_from_assemble(dbg, index) for index in byte_array: print (hex (index),end="" ) print () dbg.close()
运行如上代码,可找出符合条件的内存地址。
批量搜索反汇编代码: 与搜索机器码类似,此功能实现了搜索代码段中所有指令集,匹配列表中是否存在,存在则返回地址。
from LyScript32 import MyDebugif __name__ == "__main__" : dbg = MyDebug() dbg.connect() local_base_start = dbg.get_local_base() local_base_end = local_base_start + dbg.get_local_size() print ("开始地址: {} --> 结束地址: {}" .format (hex (local_base_start),hex (local_base_end))) search_asm = ['test eax,eax' , 'cmp esi, edi' , 'pop edi' , 'cmp esi,edi' , 'jmp esp' ] while local_base_start <= local_base_end: disasm = dbg.get_disasm_one_code(local_base_start) print ("地址: 0x{:08x} --> 反汇编: {}" .format (local_base_start,disasm)) for index in range (0 , len (search_asm)): if disasm == search_asm[index]: print ("地址: {} --> 反汇编: {}" .format (hex (local_base_start), disasm)) local_base_start = local_base_start + dbg.get_disasm_operand_size(local_base_start) dbg.close()
搜索反汇编列表特征: 使用python实现方法,通过特定方法扫描内存范围,如果出现我们所需要的指令集序列,则输出该指令的具体内存地址。
from LyScript32 import MyDebugdef get_opcode_from_assemble (dbg_ptr,asm ): byte_code = bytearray () addr = dbg_ptr.create_alloc(1024 ) if addr != 0 : asm_size = dbg_ptr.assemble_code_size(asm) write = dbg_ptr.assemble_write_memory(addr,asm) if write == True : for index in range (0 ,asm_size): read = dbg_ptr.read_memory_byte(addr + index) byte_code.append(read) dbg_ptr.delete_alloc(addr) return byte_code else : return bytearray (0 ) def SearchOpCode (dbg_ptr, Search ): op_code = [] for index in Search: byte_array = get_opcode_from_assemble(dbg, index) for index in byte_array: op_code.append(hex (index)) x = [str (i) for i in op_code] search_code = [] for l in range (0 ,len (x)): if len (x[l]) <= 3 : search_code.append('' .join(x[l]).replace("0x" ,"" ).zfill(2 )) else : search_code.append('' .join(x[l]).replace("0x" , "" )) search_code = ' ' .join(search_code).replace("0x" , "" ) print ("被搜索字符串: {}" .format (search_code)) ref = dbg.scan_memory_one(search_code) if ref != None or ref != 0 : return ref else : return 0 return 0 if __name__ == "__main__" : dbg = MyDebug() connect_flag = dbg.connect() print ("连接状态: {}" .format (connect_flag)) SearchCode = [ ["pop ecx" , "pop ebp" , "ret" , "push ebp" ], ["push ebp" , "mov ebp,esp" ], ["mov ecx, dword ptr ds:[eax+0x3C]" , "add ecx, eax" ] ] for item in range (0 , len (SearchCode)): Search = SearchCode[item] ret = SearchOpCode(dbg, Search) print ("所搜指令所在内存: {}" .format (hex (ret))) dbg.close()
如上代码中,第一个函数get_opcode_from_assemble(dbg_ptr,asm)
用于将用户传入的汇编指令得到机器码,函数SearchOpCode(dbg_ptr, Search)
用于将用户传入的汇编列表转换成一个连续的字符串。
1.片段1实现了将机器码转为一个十六进制数组
op_code = [] for index in Search: byte_array = get_opcode_from_assemble(dbg, index) for index in byte_array: op_code.append(hex (index))
2.片段2将十六进制机器码去除0x前缀,并判断十六进制是否小于等于3位,如果是则输出前缀增加0补齐,否则直接输出到search_code
变量内。
x = [str (i) for i in op_code] search_code = [] for l in range (0 ,len (x)): if len (x[l]) <= 3 : search_code.append('' .join(x[l]).replace("0x" ,"" ).zfill(2 )) else : search_code.append('' .join(x[l]).replace("0x" , "" ))
3.片段3,最终调用搜索机器码命令,首先将字符串列表转换为字符串,然后调用dbg.scan_memory_one(search_code)
完成整个搜索过程。
search_code = ' ' .join(search_code).replace("0x" , "" ) print ("被搜索字符串: {}" .format (search_code))ref = dbg.scan_memory_one(search_code) if ref != None or ref != 0 : return ref else : return 0 return 0
最终调用,用户传入一个二维列表,即可依次搜索该列表内所有符合条件的内存地址。