<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
LyScript 針對記憶體讀寫函數的封裝功能並不多,只提供了記憶體讀取和記憶體寫入函數的封裝,本篇文章將繼續對API進行封裝,實現一些在軟體逆向分析中非常實用的功能,例如記憶體交換,記憶體區域對比,磁碟與記憶體映象比較,特徵碼檢索等功能。
LyScript專案地址:https://github.com/lyshark/LyScript
實現被載入程式內特定一塊記憶體區域的交換,該方法實現原理就是兩個變數之間的交換,只是在交換時需要逐個位元組進行,呼叫read_memory_byte()
函數實現起了很容易。
from LyScript32 import MyDebug # 交換兩個記憶體區域 def memory_xchage(dbg,memory_ptr_x,memory_ptr_y,bytes): ref = False for index in range(0,bytes): # 讀取兩個記憶體區域 read_byte_x = dbg.read_memory_byte(memory_ptr_x + index) read_byte_y = dbg.read_memory_byte(memory_ptr_y + index) # 交換記憶體 ref = dbg.write_memory_byte(memory_ptr_x + index,read_byte_y) ref = dbg.write_memory_byte(memory_ptr_y + index, read_byte_x) return ref if __name__ == "__main__": dbg = MyDebug() dbg.connect() eip = dbg.get_register("eip") # 記憶體交換 flag = memory_xchage(dbg, 6815744,6815776,4) print("記憶體交換狀態: {}".format(flag)) dbg.close()
PE檔案頭節點交換後如下:
可用於對比該程序記憶體中的特定一塊區域的差異,返回是列表中的字典形式,分別傳入對比記憶體x,y以及需要對比的記憶體長度,此處建議不要超過1024位元組。
from LyScript32 import MyDebug # 對比兩個記憶體區域 def memory_cmp(dbg,memory_ptr_x,memory_ptr_y,bytes): cmp_memory = [] for index in range(0,bytes): item = {"addr":0, "x": 0, "y": 0} # 讀取兩個記憶體區域 read_byte_x = dbg.read_memory_byte(memory_ptr_x + index) read_byte_y = dbg.read_memory_byte(memory_ptr_y + index) if read_byte_x != read_byte_y: item["addr"] = memory_ptr_x + index item["x"] = read_byte_x item["y"] = read_byte_y cmp_memory.append(item) return cmp_memory if __name__ == "__main__": dbg = MyDebug() dbg.connect() eip = dbg.get_register("eip") # 記憶體對比 cmp_ref = memory_cmp(dbg, 6815744,6815776,4) for index in range(0,len(cmp_ref)): print("地址: 0x{:08X} -> X: 0x{:02x} -> y: 0x{:02x}".format(cmp_ref[index].get("addr"),cmp_ref[index].get("x"),cmp_ref[index].get("y"))) dbg.close()
對位元定記憶體區域,返回差異位元組地址:
通過呼叫read_memory_byte()
函數,或者open()
開啟檔案,等就可以得到程式磁碟與記憶體中特定位置的機器碼引數,然後通過對每一個列表中的位元組進行比較,就可得到特定位置下磁碟與記憶體中的資料是否一致的判斷。
#coding: utf-8 import binascii,os,sys from LyScript32 import MyDebug # 得到程式的記憶體映象中的機器碼 def get_memory_hex_ascii(address,offset,len): count = 0 ref_memory_list = [] for index in range(offset,len): # 讀出資料 char = dbg.read_memory_byte(address + index) count = count + 1 if count % 16 == 0: if (char) < 16: print("0" + hex((char))[2:]) ref_memory_list.append("0" + hex((char))[2:]) else: print(hex((char))[2:]) ref_memory_list.append(hex((char))[2:]) else: if (char) < 16: print("0" + hex((char))[2:] + " ",end="") ref_memory_list.append("0" + hex((char))[2:]) else: print(hex((char))[2:] + " ",end="") ref_memory_list.append(hex((char))[2:]) return ref_memory_list # 讀取程式中的磁碟映象中的機器碼 def get_file_hex_ascii(path,offset,len): count = 0 ref_file_list = [] with open(path, "rb") as fp: # file_size = os.path.getsize(path) fp.seek(offset) for item in range(offset,offset + len): char = fp.read(1) count = count + 1 if count % 16 == 0: if ord(char) < 16: print("0" + hex(ord(char))[2:]) ref_file_list.append("0" + hex(ord(char))[2:]) else: print(hex(ord(char))[2:]) ref_file_list.append(hex(ord(char))[2:]) else: if ord(char) < 16: print("0" + hex(ord(char))[2:] + " ", end="") ref_file_list.append("0" + hex(ord(char))[2:]) else: print(hex(ord(char))[2:] + " ", end="") ref_file_list.append(hex(ord(char))[2:]) return ref_file_list if __name__ == "__main__": dbg = MyDebug() connect_flag = dbg.connect() print("連線狀態: {}".format(connect_flag)) module_base = dbg.get_base_from_address(dbg.get_local_base()) print("模組基地址: {}".format(hex(module_base))) # 得到記憶體機器碼 memory_hex_byte = get_memory_hex_ascii(module_base,0,100) # 得到磁碟機器碼 file_hex_byte = get_file_hex_ascii("d://Win32Project1.exe",0,100) # 輸出機器碼 print("n記憶體機器碼: ",memory_hex_byte) print("n磁碟機器碼: ",file_hex_byte) dbg.close()
讀取後輸出時會預設十六個字元一次換行,輸出效果如下。
我們繼續增加磁碟與記憶體對比過程,然後就能實現對特定記憶體區域與磁碟區域位元組碼一致性的判斷。
#coding: utf-8 import binascii,os,sys from LyScript32 import MyDebug # 得到程式的記憶體映象中的機器碼 def get_memory_hex_ascii(address,offset,len): count = 0 ref_memory_list = [] for index in range(offset,len): # 讀出資料 char = dbg.read_memory_byte(address + index) count = count + 1 if count % 16 == 0: if (char) < 16: print("0" + hex((char))[2:]) ref_memory_list.append("0" + hex((char))[2:]) else: print(hex((char))[2:]) ref_memory_list.append(hex((char))[2:]) else: if (char) < 16: print("0" + hex((char))[2:] + " ",end="") ref_memory_list.append("0" + hex((char))[2:]) else: print(hex((char))[2:] + " ",end="") ref_memory_list.append(hex((char))[2:]) return ref_memory_list # 讀取程式中的磁碟映象中的機器碼 def get_file_hex_ascii(path,offset,len): count = 0 ref_file_list = [] with open(path, "rb") as fp: # file_size = os.path.getsize(path) fp.seek(offset) for item in range(offset,offset + len): char = fp.read(1) count = count + 1 if count % 16 == 0: if ord(char) < 16: print("0" + hex(ord(char))[2:]) ref_file_list.append("0" + hex(ord(char))[2:]) else: print(hex(ord(char))[2:]) ref_file_list.append(hex(ord(char))[2:]) else: if ord(char) < 16: print("0" + hex(ord(char))[2:] + " ", end="") ref_file_list.append("0" + hex(ord(char))[2:]) else: print(hex(ord(char))[2:] + " ", end="") ref_file_list.append(hex(ord(char))[2:]) return ref_file_list if __name__ == "__main__": dbg = MyDebug() connect_flag = dbg.connect() print("連線狀態: {}".format(connect_flag)) module_base = dbg.get_base_from_address(dbg.get_local_base()) print("模組基地址: {}".format(hex(module_base))) # 得到記憶體機器碼 memory_hex_byte = get_memory_hex_ascii(module_base,0,1024) # 得到磁碟機器碼 file_hex_byte = get_file_hex_ascii("d://Win32Project1.exe",0,1024) # 輸出機器碼 for index in range(0,len(memory_hex_byte)): # 比較磁碟與記憶體是否存在差異 if memory_hex_byte[index] != file_hex_byte[index]: # 存在差異則輸出 print("n相對位置: [{}] --> 磁碟位元組: 0x{} --> 記憶體位元組: 0x{}". format(index,memory_hex_byte[index],file_hex_byte[index])) dbg.close()
程式碼執行後即可輸出,存在差異的相對位置:
通過封裝的get_memory_hex_ascii
得到記憶體機器碼,然後再使用如下過程實現輸出該記憶體中的機器碼所對應的ASCII碼。
from LyScript32 import MyDebug import os,sys # 轉為ascii def to_ascii(h): list_s = [] for i in range(0, len(h), 2): list_s.append(chr(int(h[i:i+2], 16))) return ''.join(list_s) # 轉為16進位制 def to_hex(s): list_h = [] for c in s: list_h.append(hex(ord(c))[2:]) return ''.join(list_h) # 得到程式的記憶體映象中的機器碼 def get_memory_hex_ascii(address,offset,len): count = 0 ref_memory_list = [] for index in range(offset,len): # 讀出資料 char = dbg.read_memory_byte(address + index) count = count + 1 if count % 16 == 0: if (char) < 16: ref_memory_list.append("0" + hex((char))[2:]) else: ref_memory_list.append(hex((char))[2:]) else: if (char) < 16: ref_memory_list.append("0" + hex((char))[2:]) else: ref_memory_list.append(hex((char))[2:]) return ref_memory_list if __name__ == "__main__": dbg = MyDebug() dbg.connect() eip = dbg.get_register("eip") # 得到模組基地址 module_base = dbg.get_base_from_address(dbg.get_local_base()) # 得到指定區域記憶體機器碼 ref_memory_list = get_memory_hex_ascii(module_base,0,1024) # 解析ascii碼 break_count = 1 for index in ref_memory_list: if break_count %32 == 0: print(to_ascii(hex(int(index, 16))[2:])) else: print(to_ascii(hex(int(index, 16))[2:]),end="") break_count = break_count + 1 dbg.close()
輸出效果如下,如果換成中文,那就是一箇中文搜尋引擎了。
通過二次封裝get_memory_hex_ascii()
實現掃描記憶體特徵碼功能,如果存在則返回True否則返回False。
from LyScript32 import MyDebug import os,sys # 得到程式的記憶體映象中的機器碼 def get_memory_hex_ascii(address,offset,len): count = 0 ref_memory_list = [] for index in range(offset,len): # 讀出資料 char = dbg.read_memory_byte(address + index) count = count + 1 if count % 16 == 0: if (char) < 16: ref_memory_list.append("0" + hex((char))[2:]) else: ref_memory_list.append(hex((char))[2:]) else: if (char) < 16: ref_memory_list.append("0" + hex((char))[2:]) else: ref_memory_list.append(hex((char))[2:]) return ref_memory_list # 在指定區域內搜尋特定的機器碼,如果完全匹配則返回 def search_hex_ascii(address,offset,len,hex_array): # 得到指定區域記憶體機器碼 ref_memory_list = get_memory_hex_ascii(address,offset,len) array = [] # 迴圈輸出位元組 for index in range(0,len + len(hex_array)): # 如果有則繼續裝 if len(hex_array) != len(array): array.append(ref_memory_list[offset + index]) else: for y in range(0,len(array)): if array[y] != ref_memory_list[offset + index + y]: return False array.clear() return False if __name__ == "__main__": dbg = MyDebug() dbg.connect() eip = dbg.get_register("eip") # 得到模組基地址 module_base = dbg.get_base_from_address(dbg.get_local_base()) re = search_hex_ascii(module_base,0,100,hex_array=["0x4d","0x5a"]) dbg.close()
特徵碼掃描一般不需要自己寫,自己寫的麻煩,而且不支援萬用字元,可以直接呼叫我們API中封裝好的scan_memory_one()
它可以支援??
萬用字元模糊匹配,且效率要高許多。
到此這篇關於LyScript實現記憶體交換與差異對比的方法詳解的文章就介紹到這了,更多相關LyScript記憶體交換 對比內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45