LyScript 插件中默認(rèn)提供了多種內(nèi)存特征掃描函數(shù),每一種掃描函數(shù)用法各不相同,在使用掃描函數(shù)時(shí)應(yīng)首先搞清楚不同函數(shù)之間的差異,本章內(nèi)容將分別詳細(xì)介紹每一種內(nèi)存掃描函數(shù)是如何靈活運(yùn)用,并實(shí)現(xiàn)一種內(nèi)存查殼腳本,可快速定位目標(biāo)程序加了什么殼以及尋找被加殼程序的入口點(diǎn)。
計(jì)算機(jī)中的殼定義
加殼通常指對(duì)可執(zhí)行文件或者動(dòng)態(tài)鏈接庫(kù)等二進(jìn)制文件進(jìn)行加密或壓縮等處理,以使得這些文件難以被反匯編或破解。通常情況下,加殼會(huì)增加二進(jìn)制文件的大小,并在程序運(yùn)行時(shí)增加一定的開(kāi)銷(xiāo)。加殼技術(shù)通常被用于保護(hù)軟件的知識(shí)產(chǎn)權(quán)和防止軟件被盜版。通過(guò)加殼,軟件開(kāi)發(fā)者可以使得軟件更難被破解和復(fù)制,從而保護(hù)自己的商業(yè)利益。
計(jì)算機(jī)中查殼的原理
軟件查殼的實(shí)現(xiàn)原理可以分為靜態(tài)分析和動(dòng)態(tài)分析兩種方式。靜態(tài)分析是指在不運(yùn)行被加殼程序的情況下,通過(guò)對(duì)程序的二進(jìn)制代碼進(jìn)行解析,識(shí)別出程序是否被加殼,以及加殼的種類(lèi)和方法。動(dòng)態(tài)分析是指通過(guò)運(yùn)行被加殼程序,并觀察程序運(yùn)行時(shí)的行為,識(shí)別程序是否被加殼,以及加殼的種類(lèi)和方法。
靜態(tài)分析的實(shí)現(xiàn)原理通常包括以下幾個(gè)步驟:
- 提取被分析程序的二進(jìn)制代碼;
- 識(shí)別程序的文件格式,并解析文件頭等元數(shù)據(jù)信息;
- 根據(jù)文件格式,從程序代碼中提取節(jié)區(qū)、導(dǎo)入表、導(dǎo)出表等重要信息;
- 分析程序的代碼段,并檢查代碼中是否存在加殼相關(guān)的特征,如代碼的執(zhí)行流程、加密算法等;
- 根據(jù)分析結(jié)果,判斷程序是否被加殼,以及加殼的種類(lèi)和方法。
靜態(tài)分析的優(yōu)點(diǎn)是分析速度快,不需要運(yùn)行程序,可以有效地識(shí)別出程序中的加殼。但是它也有一些缺點(diǎn),例如無(wú)法識(shí)別動(dòng)態(tài)加載的加殼、易受代碼混淆和反調(diào)試等技術(shù)的影響。
動(dòng)態(tài)分析的實(shí)現(xiàn)原理通常包括以下幾個(gè)步驟:
- 啟動(dòng)被分析程序,并在程序運(yùn)行期間捕捉程序的行為;
- 跟蹤程序的執(zhí)行流程,并分析程序的內(nèi)存、寄存器、堆棧等狀態(tài)信息;
- 檢查程序的內(nèi)存中是否存在加殼相關(guān)的特征,如解密函數(shù)、加殼程序等;
- 根據(jù)分析結(jié)果,判斷程序是否被加殼,以及加殼的種類(lèi)和方法。
動(dòng)態(tài)分析的優(yōu)點(diǎn)是可以識(shí)別動(dòng)態(tài)加載的加殼,并且可以有效地避免代碼混淆和反調(diào)試等技術(shù)的影響。但是它也有一些缺點(diǎn),例如需要運(yùn)行被分析程序,因此可能會(huì)影響程序的性能和穩(wěn)定性,并且可能會(huì)被加殼程序的反調(diào)試技術(shù)所繞過(guò)。
本例中將采用scan_memory_all()
函數(shù)對(duì)特定內(nèi)存進(jìn)行動(dòng)態(tài)掃描,該函數(shù)用來(lái)掃描當(dāng)前進(jìn)程內(nèi)EIP所指向位置處整個(gè)內(nèi)存段中符合條件的特征,如果找到了則返回一個(gè)列表,如果沒(méi)有找到則返回False,該函數(shù)與scan_memory_one()
函數(shù)原理是一致的,唯一的不同是all
以列表形式返回所有匹配到的行,one
則只返回匹配到的第一條記錄,這兩個(gè)函數(shù)都支持??
模糊匹配。
如果載入一個(gè)程序,默認(rèn)停留在系統(tǒng)領(lǐng)空,則調(diào)用該函數(shù)你所能得到的特征記錄只能是系統(tǒng)領(lǐng)空當(dāng)前dll內(nèi)的特征集。
例如在程序被載入后,其EIP
指針默認(rèn)會(huì)停留在ntdll.dll
模塊上,需要注意的是,函數(shù)scan_memory_one
用于掃描并返回第一段符合條件的內(nèi)存,函數(shù)scan_memory_all
則用于掃描并輸出當(dāng)前所有符合條件的內(nèi)存地址;
>>> from LyScript32 import MyDebug
>>>
>>> dbg = MyDebug()
>>> conn = dbg.connect()
>>>
>>> ref_one = dbg.scan_memory_one("55 8b ec")
>>> ref_one
1995793090
>>>
>>> ref_all = dbg.scan_memory_all("55 8b ec")
>>> ref_all
[1995793090, 1995793298, 1995793455, 1995793799, 1995794214]
而有時(shí),我們需要指定掃描某個(gè)模塊,例如掃描進(jìn)程內(nèi)的msvcr120.dll
模塊里面的特征,則此時(shí)讀者可調(diào)用scan_memory_any()
函數(shù),該函數(shù)無(wú)需切換到模塊入口處即可實(shí)現(xiàn)掃描特定模塊內(nèi)的特征,不過(guò)該函數(shù)只能返回找到的第一條記錄,且需要傳入掃描起始位置以及掃描長(zhǎng)度,不過(guò)得到這些參數(shù)并不難。
from LyScript32 import MyDebug
if __name__ == "__main__":
dbg = MyDebug()
conn = dbg.connect()
# 得到進(jìn)程模塊
local_module = dbg.get_all_module()[0]
# 得到模塊參數(shù)
module_base = local_module.get("base")
module_size = local_module.get("size")
print("基地址: {} 長(zhǎng)度: {} 結(jié)束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
# 掃描內(nèi)存
ref = dbg.scan_memory_any(module_base,module_size,"55 8b ec ??")
if ref != False:
print("找到內(nèi)存: {}".format(hex(ref)))
dbg.close()
運(yùn)行如上所示的代碼片段,則默認(rèn)會(huì)掃描進(jìn)程內(nèi)第一個(gè)模塊也就是主程序模塊內(nèi)的,特征55 8b ec ??
指令集,當(dāng)找到后會(huì)輸出如下圖所示的提示信息;
如上代碼中的內(nèi)存掃描方法如果能被讀者理解,那么查殼這個(gè)功能就變得很簡(jiǎn)單了,市面上的查殼軟件PEID等基本都是采用特征碼定位的方式,所以我們想要實(shí)現(xiàn)查殼以及檢測(cè)編譯器特征可以采用特征碼掃描法,只需要將上述代碼更改一下,即可實(shí)現(xiàn)查殼功能。
from LyScript32 import MyDebug
# 查殼功能
def Scan(dbg, string):
# 得到進(jìn)程模塊
local_module = dbg.get_all_module()[0]
# 得到模塊參數(shù)
module_base = local_module.get("base")
module_size = local_module.get("size")
# print("基地址: {} 長(zhǎng)度: {} 結(jié)束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
# 掃描內(nèi)存
ref = dbg.scan_memory_any(module_base,module_size,string)
if ref != False:
return True
return False
if __name__ == "__main__":
dbg = MyDebug()
conn = dbg.connect()
# 存儲(chǔ)特征碼
signs = [
{"key": "Microsoft Visual C++ 2013", "value": "e8 ?? ?? ?? ?? e9 ?? ?? ?? ?? 55 8b ec"},
{"key": "UPX 3.96w", "value": "60 be ?? ?? ?? ?? 8d be 00 90 ff ff 57"}
]
for index in signs:
check = Scan(dbg, index.get("value"))
if check == True:
print("編譯特征: {}".format(index.get("key")))
dbg.close()
當(dāng)運(yùn)行上述代碼片段,則將會(huì)尋找特定指令集,如果找到則說(shuō)明采用的是特定的加殼程序或特定編譯器編譯生成的,輸出效果圖如下所示;
通過(guò)運(yùn)用scan_memory_one()
函數(shù),讀者何以很容易的實(shí)現(xiàn)對(duì)特定內(nèi)存區(qū)域的尋找,以32為代碼為例,通過(guò)get_register
函數(shù)獲取到當(dāng)前EIP的內(nèi)存地址,并通過(guò)read_memory_word
讀入前四個(gè)字節(jié)的數(shù)據(jù),當(dāng)前四個(gè)字節(jié)的數(shù)據(jù)為0xBE60
此時(shí)說(shuō)明是UPX殼的開(kāi)頭,通過(guò)scan_memory_one("83 EC ?? E9")
匹配特征碼,當(dāng)找到后順勢(shì)在此處set_breakpoint(patternAddr)
下一個(gè)斷點(diǎn),程序通過(guò)不斷地運(yùn)行,最終即可定位到程序真正的入口地址;
from LyScript32 import MyDebug
if __name__ == "__main__":
# 初始化
dbg = MyDebug()
# 連接到調(diào)試器
connect_flag = dbg.connect()
print("連接狀態(tài): {}".format(connect_flag))
# 檢測(cè)套接字是否還在
ref = dbg.is_connect()
print("是否在連接: ", ref)
is_64 = False
# 判斷是否時(shí)64位數(shù)
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")
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()
運(yùn)行上述代碼片段,則會(huì)看到如下圖所示的輸出效果,并以自動(dòng)跳轉(zhuǎn)到了程序的真正入口位置0x40153e
,此時(shí)用戶(hù)只需要脫殼轉(zhuǎn)存即可;文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-537449.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-537449.html
到了這里,關(guān)于4.6 x64dbg 內(nèi)存掃描與查殼實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!