天天看點

LyScript 實作Hook改寫MessageBox

LyScript 可實作自定義彙編指令的替換功能,使用者可以自行編寫一段彙編指令,将程式中特定的通用函數進行功能改寫與轉向操作,此功能原理是簡單的Hook操作。

LyScript 可實作自定義彙編指令的替換功能,使用者可以自行編寫一段彙編指令,将程式中特定的通用函數進行功能改寫與轉向操作,此功能原理是簡單的Hook操作。

首先我們先來實作一個Hook模闆,在代碼中實作中轉機制,如下代碼以​

​MessageBoxA​

​函數為案例實作修改彙編參數傳遞。

from LyScript32 import MyDebug

# 傳入彙編清單,寫出到記憶體
def assemble(dbg, address=0, asm_list=[]):
    asm_len_count = 0
    for index in range(0,len(asm_list)):
        # 寫出到記憶體
        dbg.assemble_at(address, asm_list[index])
        # print("位址: {} --> 長度計數器: {} --> 寫出: {}".format(hex(address + asm_len_count), asm_len_count,asm_list[index]))
        # 得到asm長度
        asm_len_count = dbg.assemble_code_size(asm_list[index])
        # 位址每次遞增
        address = address + asm_len_count

if __name__ == "__main__":
    dbg = MyDebug()
    connect_flag = dbg.connect()
    print("連接配接狀态: {}".format(connect_flag))

    # 找到MessageBoxA
    messagebox_address = dbg.get_module_from_function("user32.dll","MessageBoxA")
    print("MessageBoxA記憶體位址 = {}".format(hex(messagebox_address)))

    # 配置設定空間
    HookMem = dbg.create_alloc(1024)
    print("自定義記憶體空間: {}".format(hex(HookMem)))

    # 寫出FindWindowA記憶體位址,跳轉位址
    asm = [
        f"push {hex(HookMem)}",
        "ret"
    ]

    # 将清單中的彙編指令寫出到記憶體
    assemble(dbg,messagebox_address,asm)

    dbg.close()      

上方代碼中可以看到,首先擷取到​

​MessageBoxA​

​​函數記憶體位址,然後我們通過​

​dbg.create_alloc(1024)​

​​配置設定一段空間,并利用​

​assemble()​

​函數寫出一個跳轉指令。

此段代碼執行後,​

​MessageBoxA​

​處的指令将被替換,跳轉到我們自己配置設定的記憶體中去。

LyScript 實作Hook改寫MessageBox

接着我們就來實作功能改寫,将彈窗中的消息替換成我們自己的版權資訊,此處先給出代碼。

from LyScript32 import MyDebug

# 傳入彙編清單,寫出到記憶體
def assemble(dbg, address=0, asm_list=[]):
    asm_len_count = 0
    for index in range(0,len(asm_list)):
        # 寫出到記憶體
        dbg.assemble_at(address, asm_list[index])
        # print("位址: {} --> 長度計數器: {} --> 寫出: {}".format(hex(address + asm_len_count), asm_len_count,asm_list[index]))
        # 得到asm長度
        asm_len_count = dbg.assemble_code_size(asm_list[index])
        # 位址每次遞增
        address = address + asm_len_count

if __name__ == "__main__":
    dbg = MyDebug()
    connect_flag = dbg.connect()
    print("連接配接狀态: {}".format(connect_flag))

    # 找到MessageBoxA
    messagebox_address = dbg.get_module_from_function("user32.dll","MessageBoxA")
    print("MessageBoxA記憶體位址 = {}".format(hex(messagebox_address)))

    # 配置設定空間
    HookMem = dbg.create_alloc(1024)
    print("自定義記憶體空間: {}".format(hex(HookMem)))

    # 寫出FindWindowA記憶體位址,跳轉位址
    asm = [
        f"push {hex(HookMem)}",
        "ret"
    ]

    # 将清單中的彙編指令寫出到記憶體
    assemble(dbg,messagebox_address,asm)

    # 定義兩個變量,存放字元串
    MsgBoxAddr = dbg.create_alloc(512)
    MsgTextAddr = dbg.create_alloc(512)

    # 填充字元串内容
    # lyshark 标題
    txt = [0x6c, 0x79, 0x73, 0x68, 0x61, 0x72, 0x6b]
    # 内容 lyshark.com
    box = [0x6C, 0x79, 0x73, 0x68, 0x61, 0x72, 0x6B, 0x2E, 0x63, 0x6F, 0x6D]

    for txt_count in range(0,len(txt)):
        dbg.write_memory_byte(MsgBoxAddr + txt_count, txt[txt_count])

    for box_count in range(0,len(box)):
        dbg.write_memory_byte(MsgTextAddr + box_count, box[box_count])

    print("标題位址: {} 内容: {}".format(hex(MsgBoxAddr),hex(MsgTextAddr)))

    # 此處是MessageBox替換後的片段
    PatchCode =\
    [
        "mov edi, edi",
        "push ebp",
        "mov ebp,esp",
        "push -1",
        "push 0",
        "push dword ptr ss:[ebp+0x14]",
        f"push {hex(MsgBoxAddr)}",
        f"push {hex(MsgTextAddr)}",
        "push dword ptr ss:[ebp+0x8]",
        "call 0x76030E20",
        "pop ebp",
        "ret 0x10"
    ]

    # 寫出到自定義記憶體
    assemble(dbg, HookMem, PatchCode)

    print("位址已被替換,可以運作了.")
    dbg.set_debug("Run")
    dbg.set_debug("Run")

    dbg.close()      

首先程式運作後,會經過​

​assemble(dbg,messagebox_address,asm)​

​彙編寫出的位置,此處是一個跳轉,直接跳轉到我們自己申請的記憶體空間内。

LyScript 實作Hook改寫MessageBox

當EIP走到此處後,跳轉到我們自己建構的彈窗位置,此處的代碼如下。

LyScript 實作Hook改寫MessageBox

當彈窗運作後,讀入的記憶體位址有兩處​

​MsgBoxAddr​

​​是消息​

​MsgTextAddr​

​​是文本,這兩處位置都被python中的​

​push {hex()}​

​替換掉了,當運作彈窗後,就是執行我們自己的函數。