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