首頁 > 軟體

詳解LyScript 記憶體掃描與查殼實現

2022-09-12 18:01:25

正文

LyScript 中提供了多種記憶體特徵掃描函數,每一種掃描函數用法各不相同,在使用掃描函數時應首先搞清楚他們之間的差異,如下將分別詳細介紹每一種記憶體掃描函數是如何靈活運用的,最後將實現一個簡易版記憶體查殼指令碼,可快速定位目標程式加了什麼殼。

先來了解第一個函數scan_memory_all()的特點,該函數用來掃描當前程序內EIP所指向位置處整個記憶體段中符合條件的特徵,如果找到了則返回一個列表,如果沒有找到則返回False,該函數與scan_memory_one()函數原理是一致的,唯一的不同是all以列表形式返回所有匹配到的行,one則只返回匹配到的第一條記錄,這兩個函數都支援??模糊匹配。

如果載入一個程式,預設停留在系統領空,則呼叫該函數你所能得到的特徵記錄只能是系統領空特定dll內的特徵集。

掃描ntdll.dll模組

例如掃描ntdll.dll模組內的所有特徵欄位是55 8b ec 83 e4的記錄,程式碼是這樣的。

from LyScript32 import MyDebug
if __name__ == "__main__":
    dbg = MyDebug()
    conn = dbg.connect()
    ref_one = dbg.scan_memory_one("55 8b ec 83 e4")
    print("掃描一行: {}".format(hex(ref_one)))
    ref_all = dbg.scan_memory_all("55 8b ec 83 e4")
    for index in range(0, len(ref_all)):
        print("記錄: {} 地址: {}".format(index,hex(ref_all[index])))
    dbg.close()

執行效果如下:

有時我們需要指定掃描某個模組,例如掃描程序內的msvcr120.dll模組,裡面的特徵值。

此時需要想得到該模組的入口地址,然後將EIP切換過去,此時在呼叫scan_memory_all()來完成搜尋,當然最好先備份原始EIP位置,這樣掃描完以後可以直接切回去。

from LyScript32 import MyDebug
if __name__ == "__main__":
    dbg = MyDebug()
    conn = dbg.connect()
    # 得到所有模組
    local_module_base = dbg.get_all_module()
    for index in local_module_base:
        # 找到需要的模組
        if index.get("name") == "msvcr120.dll":
            entry = index.get("entry")
            print("掃描入口: {}".format(hex(entry)))
            # 切過去
            dbg.set_register("eip",entry)
            # 開始搜尋特徵
            scan_ref = dbg.scan_memory_all("5d c2 0c 00 55 8b ec")
            for x in scan_ref:
                print("掃描到: {}".format(hex(x)))
    dbg.close()

輸出結果如下:

當然為了使掃描效率更高一些,新版外掛中新增了scan_memory_any()函數,該函數無需切換到模組入口處即可實現掃描特定模組內的特徵,不過該函數只能返回找到的第一條記錄,且需要傳入掃描起始位置以及掃描長度,不過得到這些引數並不難。

from LyScript32 import MyDebug
if __name__ == "__main__":
    dbg = MyDebug()
    conn = dbg.connect()
    # 得到程序模組
    local_module = dbg.get_all_module()[0]
    # 得到模組引數
    module_base = local_module.get("base")
    module_size = local_module.get("size")
    print("基地址: {} 長度: {} 結束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
    # 掃描記憶體
    ref = dbg.scan_memory_any(module_base,module_size,"51 5c a8 f8 4c 34 33")
    if ref != False:
        print("找到記憶體: {}".format(hex(ref)))
    dbg.close()

掃描結果如下:

查殼功能

如上記憶體掃描方法如果可以搞明白,那麼查殼這個功能就變得很簡單了,市面上的查殼軟體PEID等基本都是採用特徵碼定位的方式,所以我們想要實現查殼以及檢測編譯器特徵可以採用特徵碼掃描法,如下程式碼即可實現查殼功能。

from LyScript32 import MyDebug
# 查殼功能
def scan(dbg, string):
    # 得到程序模組
    local_module = dbg.get_all_module()[0]
    # 得到模組引數
    module_base = local_module.get("base")
    module_size = local_module.get("size")
    # print("基地址: {} 長度: {} 結束地址: {}".format(hex(module_base),hex(module_size),hex(module_base+module_size)))
    # 掃描記憶體
    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()
    # 儲存特徵碼
    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()

分別檢測後輸出結果如下:

upx加殼軟體輸出為

vs2013編譯器特徵輸出

以上就是詳解LyScript 記憶體掃描與查殼實現的詳細內容,更多關於LyScript 記憶體掃描查殼的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com