LyScript 插件实现对特定汇编指令片段的批量搜索功能,用户传入一个汇编指令列表,然后循环搜索该列表内的所有指令特征,如果找到了,则返回该指令的内存地址。
得到汇编指令机器码: 该功能主要实现,得到用户传入汇编指令所对应的机器码,这段代码你可以这样来实现。
- from LyScript32 import MyDebug
-
- if __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 MyDebug
-
- # 传入汇编代码,得到对应机器码
- def 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)
- # print("汇编代码占用字节: {}".format(asm_size))
-
- 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)
- # print("{:02x} ".format(read),end="")
- 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 MyDebug
-
- if __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 MyDebug
-
- # 传入汇编代码,得到对应机器码
- def 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)
- # print("汇编代码占用字节: {}".format(asm_size))
-
- 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)
- # print("{:02x} ".format(read),end="")
- 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))
-
- # print("机器码列表: {}".format(op_code))
-
- # 将机器码列表转换为字符串
- # 1.先转成字符串列表
- x = [str(i) for i in op_code]
-
- # 2.将字符串列表转为字符串
- # search_code = ' '.join(x).replace("0x","")
- search_code = []
-
- # 增加小于三位前面的0
- for l in range(0,len(x)):
- if len(x[l]) <= 3:
- # 如果是小于3位数则在前面增加0
- # print(''.join(x[l]).replace("0x","").zfill(2))
- search_code.append(''.join(x[l]).replace("0x","").zfill(2))
- else:
- search_code.append(''.join(x[l]).replace("0x", ""))
-
- # 3.变成字符串
- 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
变量内。
- # 将机器码列表转换为字符串
- # 1.先转成字符串列表
- x = [str(i) for i in op_code]
-
- # 2.将字符串列表转为字符串
- # search_code = ' '.join(x).replace("0x","")
- search_code = []
-
- # 增加小于三位前面的0
- for l in range(0,len(x)):
- if len(x[l]) <= 3:
- # 如果是小于3位数则在前面增加0
- # print(''.join(x[l]).replace("0x","").zfill(2))
- 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
最终调用,用户传入一个二维列表,即可依次搜索该列表内所有符合条件的内存地址。
LyScript项目地址: https://github.com/lyshark/LyScript