4.7 x64dbg 应用层的钩子扫描

这篇具有很好参考价值的文章主要介绍了4.7 x64dbg 应用层的钩子扫描。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

  • Capstone引擎的主要特点包括:

  • 支持多种指令集:支持x86、ARM、MIPS、PowerPC等多种指令集,且能够在不同的平台上运行。

  • 轻量级高效:采用C语言编写,代码简洁高效,反汇编速度快。

  • 易于使用:提供了易于使用的API和文档,支持Python、Ruby、Java等多种编程语言。

  • 可定制性:提供了多种可配置选项,能够满足不同用户的需求。

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

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

from capstone import *
import pefile

def Disassembly(FilePath):
    opcode_list = []
    pe = pefile.PE(FilePath)
    ImageBase = pe.OPTIONAL_HEADER.ImageBase

    for 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.VirtualAddress
            VirtualSize = item.Misc_VirtualSize
            ActualOffset = item.PointerToRawData
    StartVA = ImageBase + VirtualAddress
    StopVA = ImageBase + VirtualAddress + VirtualSize
    with 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_list

if __name__ == "__main__":
    Disassembly("d://lyshark.exe")

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

4.7 x64dbg 应用层的钩子扫描

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

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

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.address
        dasm_memory_dict.append({"address": str(addr), "opcode": item.mnemonic + " " + item.op_str})
    return dasm_memory_dict

if __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()

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

4.7 x64dbg 应用层的钩子扫描

这两项功能实现之后,那么实现内存与磁盘之间的比对工作将变得很容易实现,如下代码中首先通过get_memory_disassembly获取到内存反汇编指令,然后通过get_file_disassembly获取磁盘反汇编指令,并将两者dasm_memory_list[index] != dasm_file_list[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.address
        dic = {"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.ImageBase

    for 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.VirtualAddress
            VirtualSize = item.Misc_VirtualSize
            ActualOffset = item.PointerToRawData
    StartVA = ImageBase + VirtualAddress
    StopVA = ImageBase + VirtualAddress + VirtualSize
    with 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_list

if __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()

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

4.7 x64dbg 应用层的钩子扫描文章来源地址https://www.toymoban.com/news/detail-540188.html

到了这里,关于4.7 x64dbg 应用层的钩子扫描的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 逆向学习X64DBG

    目标游戏:焰影神兵 目的:更改玩家名称(中文名称) 使用X64dbg可以快速搜索游戏人名,所以本次逆向使用该工具进行工作。  原来的名字:平家物语  现在我们想改成:源氏物语。所以打开X32/64dbg 附加后,选择shadowFlare。 点击 内存映射   右键, 点击 \\\"查找特征码\\\"    然

    2024年02月01日
    浏览(42)
  • 1.1 熟悉x64dbg调试器

    x64dbg 是一款开源、免费、功能强大的动态反汇编调试器,它能够在 Windows 平台上进行应用程序的反汇编、调试和分析工作。与传统的调试器如 Ollydbg 相比,x64dbg调试器的出现填补了 Ollydbg 等传统调试器的不足,为反汇编调试工作提供了更高效、更可靠的解决方案。正是因为有

    2024年02月12日
    浏览(38)
  • 4.3 x64dbg 搜索内存可利用指令

    发现漏洞的第一步则是需要寻找到可利用的反汇编指令片段,在某些时候远程缓冲区溢出需要通过类似于 jmp esp 等特定的反汇编指令实现跳转功能,并以此来执行布置好的 ShellCode 恶意代码片段, LyScript 插件则可以很好的完成对当前进程内存中特定函数的检索工作。 一般而言

    2024年02月12日
    浏览(39)
  • 4.4 x64dbg 绕过反调试保护机制

    在Windows平台下,应用程序为了保护自己不被调试器调试会通过各种方法限制进程调试自身,通常此类反调试技术会限制我们对其进行软件逆向与漏洞分析,下面是一些常见的反调试保护方法: IsDebuggerPresent:检查当前程序是否在调试器环境下运行。 OutputDebugString:向调试器发

    2024年02月12日
    浏览(38)
  • 4.9 x64dbg 内存处理与差异对比

    LyScript 插件中针对内存读写函数的封装功能并不多,只提供了最基本的 内存读取 和 内存写入 系列函数的封装,本章将继续对API接口进行封装,实现一些在软件逆向分析中非常实用的功能,例如ShellCode代码写出与置入,内存交换,内存区域对比,磁盘与内存镜像比较,内存特

    2024年02月16日
    浏览(40)
  • 4.10 x64dbg 反汇编功能的封装

    LyScript 插件提供的反汇编系列函数虽然能够实现基本的反汇编功能,但在实际使用中,可能会遇到一些更为复杂的需求,此时就需要根据自身需要进行二次开发,以实现更加高级的功能。本章将继续深入探索反汇编功能,并将介绍如何实现反汇编代码的检索、获取上下一条代

    2024年02月13日
    浏览(43)
  • OllyDbg 与 x64Dbg 与 Windbg 与 IDA 区别是什么?

    OllyDbg 和 x64Dbg 大致属于同一类别。它们的主要优势是在没有符号信息的情况下进行调试(尽管它们也可以使用符号信息进行调试)。OllyDbg(封闭源代码)已经很久没有维护了,并且仅限于 x86 32 位。另一方面,x64Dbg 被积极维护,开源并且可以处理 x86 和 x64。两者都支持插件

    2024年02月08日
    浏览(41)
  • 【计算机网络概述】第二章:应用层:2.1 应用层原理

    客户端/服务器模式 peer to peer 模式(对等模式)        在第一章的内容中,我们学习了计算机网络的大体轮廓,因为在计算机网络中,我们需要记住非常多的专有名词,所以在第一章中,我们需要进行非常多的记忆。第一章还是非常重要的。        比如,我们所使用

    2024年01月18日
    浏览(53)
  • 应用层协议 HTTP

    我们已经学过 TCP/IP , 已然知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程。 我们还需要知道的是,我们把数据从 A 端传送到 B 端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,所以我们还需要一层协议,不关心通信细节,关心应用

    2024年02月06日
    浏览(44)
  • 应用层与传输层~

    应用层是负责应用程序之间沟通的一层。由于不同的网络应用的应用进程之间,有着不同的通信规则,因此自然就需要应用层协议来解决这些问题,这就构成了应用层的主要内容即:精确定义这些通信规则。 应用层有不少应用广泛的协议,像域名系统(DNS)、文件传输协议(

    2023年04月08日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包