首页 >> 大全

4.7 x64dbg 应用层的钩子扫描

2023-08-10 大全 38 作者:考证青年

所谓的应用层钩子(-level hooks)是一种编程技术,它允许应用程序通过在特定事件发生时执行特定代码来自定义或扩展其行为。这些事件可以是用户交互,系统事件,或者其他应用程序内部的事件。应用层钩子是在应用程序中添加自定义代码的一种灵活的方式。它们可以用于许多不同的用途,如安全审计、性能监视、访问控制和行为修改等。应用层钩子通常在应用程序的运行时被调用,可以执行一些预定义的操作或触发一些自定义代码。

通常情况下,第三方应用在需要扩展一个程序功能是都会采用挂钩子的方式实现,而由于内存数据被修改后磁盘数据依然是原始数据,这就给扫描这些钩子提供了便利,具体来说钩子扫描的原理是通过读取磁盘中的PE文件中的反汇编代码,并与内存中的代码作比较,当两者发生差异是则可以证明此处被挂了钩子。

本节内容中,笔者将通过一个案例并配合引擎来实现这个功能,之所以选用该引擎是因为该引擎支持包,可以非常容易的与插件互动,此外引擎在逆向工程、漏洞分析、恶意代码分析等领域有广泛的应用,著名反汇编调试器IDA则是使用了该引擎工作的。

的安装非常容易,只需要执行pip 即可完成,使用反汇编时读者只需要传入一个PE文件路径,并通过md.(, 0)即可实现反汇编任务;

代码首先使用库读取PE文件,获取文件的,以及名为".text"的节表的、和等信息。接下来,代码计算了".text"节表的起始地址和结束地址,然后使用文件指针读取文件中".text"节表的原始数据,并使用库进行反汇编。反汇编结果以字典形式存储,包括反汇编地址和反汇编指令。最后,函数返回了包含所有反汇编指令的列表。

from capstone import *
import pefiledef Disassembly(FilePath):opcode_list = []pe = pefile.PE(FilePath)ImageBase = pe.OPTIONAL_HEADER.ImageBasefor item in pe.sections:if str(item.Name.decode('UTF-8').strip(b'\x00'.decode())) == ".text":# print("虚拟地址: 0x%.8X 虚拟大小: 0x%.8X" %(item.VirtualAddress,item.Misc_VirtualSize))VirtualAddress = item.VirtualAddressVirtualSize = item.Misc_VirtualSizeActualOffset = item.PointerToRawDataStartVA = ImageBase + VirtualAddressStopVA = ImageBase + VirtualAddress + VirtualSizewith open(FilePath,"rb") as fp:fp.seek(ActualOffset)HexCode = fp.read(VirtualSize)md = Cs(CS_ARCH_X86, CS_MODE_32)for item in md.disasm(HexCode, 0):addr = hex(int(StartVA) + item.address)dic = {"Addr": str(addr) , "OpCode": item.mnemonic + " " + item.op_str}print("[+] 反汇编地址: {} 参数: {}".format(addr,dic))opcode_list.append(dic)return opcode_listif __name__ == "__main__":Disassembly("d://lyshark.exe")

当读者运行上方代码片段时,则可输出.exe程序内text节所有反汇编代码片段,输出效果如下图所示;

接着我们需要读入内存中的PE文件机器码并通过引擎反汇编为汇编指令集,如下ly函数则是实现内存反汇编的具体实现细节。

此案例中通过读入内存完整数据,并使用md.依次反汇编,并最终将结果存储到字典中保存。

import binascii,os,sys
import pefile
from capstone import *
from LyScript32 import MyDebug# 得到内存反汇编代码
def get_memory_disassembly(address,offset,len):# 反汇编列表dasm_memory_dict = []# 内存列表ref_memory_list = bytearray()# 读取数据for index in range(offset,len):char = dbg.read_memory_byte(address + index)ref_memory_list.append(char)# 执行反汇编md = Cs(CS_ARCH_X86,CS_MODE_32)for item in md.disasm(ref_memory_list,0x1):addr = int(pe_base) + item.addressdasm_memory_dict.append({"address": str(addr), "opcode": item.mnemonic + " " + item.op_str})return dasm_memory_dictif __name__ == "__main__":dbg = MyDebug()dbg.connect()pe_base = dbg.get_local_base()pe_size = dbg.get_local_size()print("模块基地址: {}".format(hex(pe_base)))print("模块大小: {}".format(hex(pe_size)))# 得到内存反汇编代码dasm_memory_list = get_memory_disassembly(pe_base,0,pe_size)print(dasm_memory_list)dbg.close()

执行如上所示代码,则可输出当前程序内存中的反汇编指令集,并以字典的方式输出,效果图如下所示;

这两项功能实现之后,那么实现内存与磁盘之间的比对工作将变得很容易实现,如下代码中首先通过ly获取到内存反汇编指令,然后通过获取磁盘反汇编指令,并将两者[index] != [index]最比较,以此来判断特定内存是否被挂钩;

import binascii,os,sys
import pefile
from capstone import *
from LyScript32 import MyDebug# 得到内存反汇编代码
def get_memory_disassembly(address,offset,len):# 反汇编列表dasm_memory_dict = []# 内存列表ref_memory_list = bytearray()# 读取数据for index in range(offset,len):char = dbg.read_memory_byte(address + index)ref_memory_list.append(char)# 执行反汇编md = Cs(CS_ARCH_X86,CS_MODE_32)for item in md.disasm(ref_memory_list,0x1):addr = int(pe_base) + item.addressdic = {"address": str(addr), "opcode": item.mnemonic + " " + item.op_str}dasm_memory_dict.append(dic)return dasm_memory_dict# 反汇编文件中的机器码
def get_file_disassembly(path):opcode_list = []pe = pefile.PE(path)ImageBase = pe.OPTIONAL_HEADER.ImageBasefor item in pe.sections:if str(item.Name.decode('UTF-8').strip(b'\x00'.decode())) == ".text":# print("虚拟地址: 0x%.8X 虚拟大小: 0x%.8X" %(item.VirtualAddress,item.Misc_VirtualSize))VirtualAddress = item.VirtualAddressVirtualSize = item.Misc_VirtualSizeActualOffset = item.PointerToRawDataStartVA = ImageBase + VirtualAddressStopVA = ImageBase + VirtualAddress + VirtualSizewith open(path,"rb") as fp:fp.seek(ActualOffset)HexCode = fp.read(VirtualSize)md = Cs(CS_ARCH_X86, CS_MODE_32)for item in md.disasm(HexCode, 0):addr = hex(int(StartVA) + item.address)dic = {"address": str(addr) , "opcode": item.mnemonic + " " + item.op_str}# print("{}".format(dic))opcode_list.append(dic)return opcode_listif __name__ == "__main__":dbg = MyDebug()dbg.connect()pe_base = dbg.get_local_base()pe_size = dbg.get_local_size()print("模块基地址: {}".format(hex(pe_base)))print("模块大小: {}".format(hex(pe_size)))# 得到内存反汇编代码dasm_memory_list = get_memory_disassembly(pe_base,0,pe_size)dasm_file_list = get_file_disassembly("d://lyshark.exe")# 循环对比内存与文件中的机器码for index in range(0,len(dasm_file_list)):if dasm_memory_list[index] != dasm_file_list[index]:print("地址: {:8} --> 内存反汇编: {:32} --> 磁盘反汇编: {:32}".format(dasm_memory_list[index].get("address"),dasm_memory_list[index].get("opcode"),dasm_file_list[index].get("opcode")))dbg.close()

运行上方代码片段,耐性等待一段时间,则可输出内存与磁盘反汇编指令集列表,输出效果图如下所示;

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了