LyScript 插件可實現對壓縮殼的快速脫殼操作,目前支持兩種脫殼方式,一種是運用API接口自己編寫脫殼過程,另一種是直接加載現有的脫殼腳本運行脫殼。
LyScript項目地址: https://github.com/lyshark/LyScript
首先準備一個加了UPX壓縮殼的程序,然後我們通過自己編寫腳本完成脫殼任務。 我們將當前EIP停留在UPX殼的首地址處,執行如下腳本,將可以自動尋找到當前EIP的具體位置。
from LyScript32 import MyDebug
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
# 連接到調試器
connect_flag = dbg.connect()
print("連接狀態: {}".format(connect_flag))
# 檢測套接字是否還在
ref = dbg.is_connect()
print("是否在連接: ", ref)
is_64 = False
# 判斷是否時64位數
if is_64 == False:
currentIP = dbg.get_register("eip")
if dbg.read_memory_word(currentIP) != int(0xBE60):
print("[-] 可能不是UPX")
dbg.close()
patternAddr = dbg.scan_memory_one("83 EC ?? E9 ?? ?? ?? ?? 00")
print("匹配到的地址: {}".format(hex(patternAddr)))
dbg.set_breakpoint(patternAddr)
dbg.set_debug("Run")
dbg.set_debug("Wait")
dbg.delete_breakpoint(patternAddr)
dbg.set_debug("StepOver")
dbg.set_debug("StepOver")
print("[+] 程序OEP = 0x{:x}".format(dbg.get_register("eip")))
else:
currentIP = dbg.get_register("rip")
if dbg.read_memory_dword(currentIP) != int(0x55575653):
print("[-] 可能不是UPX")
dbg.close()
patternAddr = dbg.scan_memory_one("48 83 EC ?? E9")
print("匹配到的地址: {}".format(hex(patternAddr)))
dbg.set_breakpoint(patternAddr)
dbg.set_debug("Run")
dbg.set_debug("Wait")
dbg.delete_breakpoint(patternAddr)
dbg.set_debug("StepOver")
dbg.set_debug("StepOver")
print("[+] 程序OEP = 0x{:x}".format(dbg.get_register("eip")))
dbg.close()
運行如上代碼,將通過特徵碼快速定位並尋找到程序加殼前的OEP位置。
另一種方式是直接尋找原生脫殼腳本,並使用LyScript加載執行脫殼,如下是一段原生脫殼腳本,我們保存在磁盤中。
bphc //清除所有硬件斷點
sti //執行一次F8(步過)
bph esp,r,1 //對當前Esp棧頂下 硬件讀取斷點,設置一個字節 r代表讀取
erun //執行一次F9也就是運行起來,erun就是中間出異常了交給調試器執行
find eip,e9,1000 //利用Find功能在EIP位置尋找 jmp,搜索的內存大小爲1000
bphc
bph $result //搜尋的結果會放到 $result變量中
erun //執行
bphc
sto 2 //執行一下F7
cmt eip,"Current Eip is Oep Please Dump Entry" //在EIP位置填寫註釋
ret
接着通過LyScript插件,將其加載到x64dbg腳本引擎中,並直接運行。
from LyScript32 import MyDebug
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
# 連接到調試器
connect_flag = dbg.connect()
print("連接狀態: {}".format(connect_flag))
# 檢測套接字是否還在
ref = dbg.is_connect()
print("是否在連接: ", ref)
# 加載並運行腳本
dbg.script_loader("d://script.txt")
dbg.script_run()
dbg.close()
同樣可以尋找到正確的OEP位置。
此時直接在OEP位置執行轉存內存即可完成脫殼。