4.9 x64dbg 内存处理与差异对比

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

LyScript 插件中针对内存读写函数的封装功能并不多,只提供了最基本的内存读取内存写入系列函数的封装,本章将继续对API接口进行封装,实现一些在软件逆向分析中非常实用的功能,例如ShellCode代码写出与置入,内存交换,内存区域对比,磁盘与内存镜像比较,内存特征码检索等功能,学会使用这些功能对于后续漏洞分析以及病毒分析都可以起到事半功倍的效果,读者应重点关注这些函数的使用方式。

4.9.1 实现ShellCode的灵活注入

Shellcode 是一种特殊类型的恶意代码,通常用于利用系统漏洞、执行恶意软件等攻击性行为。Shellcode 通常是一段二进制代码,没有可执行文件头,并且设计用于利用操作系统的特定漏洞,从而使攻击者能够获得对系统的控制或执行其他恶意操作。

由于 Shellcode 通常是在内存中执行的,因此它不需要像可执行文件一样拥有完整的文件结构。攻击者通常通过利用漏洞将Shellcode注入到受攻击系统的进程中,并使其在内存中执行,从而达到攻击目的。由于Shellcode是一种非常灵活的攻击工具,攻击者可以使用它来执行各种攻击行为,例如提权、执行远程命令、下载恶意软件等。因此,Shellcode已成为黑客和攻击者的常用工具之一。

通常读者应该自行准备好如下文本案例中所规范的ShellCode格式,这类格式通常经过处理后即可直接注入到远程进程内。

"\xfc\xe8\x8f\x00\x00\x00\x60\x31\xd2\x89\xe5\x64\x8b\x52\x30"
"\x8b\x52\x0c\x8b\x52\x14\x0f\xb7\x4a\x26\x31\xff\x8b\x72\x28"
"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\x49"
"\x75\xef\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78"
"\x85\xc0\x74\x4c\x01\xd0\x8b\x58\x20\x01\xd3\x50\x8b\x48\x18"
"\x85\xc9\x74\x3c\x31\xff\x49\x8b\x34\x8b\x01\xd6\x31\xc0\xac"

接着笔者将带大家实现一个将文件内的ShellCode注入到进程远程堆空间内的案例,既然要注入到远程堆中,那么第一步则是通过create_alloc(1024)在对端开辟一段堆空间,如果读者需要让该空间可被执行则需要调用set_local_protect(address,32,1024)将该地址设置为32也就是读写执行,设置长度为1024字节,接着通过read_shellcode()函数从文本中读取ShellCode代码,并作压缩处理,最后通过循环write_memory_byte写内存的方式将其逐字节写出,总结起来核心代码如下所示;

from LyScript32 import MyDebug

# 将shellcode读入内存
def read_shellcode(path):
    shellcode_list = []
    with open(path, "r", encoding="utf-8") as fp:
        for index in fp.readlines():
            shellcode_line = index.replace('"', "").replace(" ", "").replace("\n", "").replace(";", "")
            for code in shellcode_line.split("\\x"):
                if code != "" and code != "\\n":
                    shellcode_list.append("0x" + code)
    return shellcode_list

if __name__ == "__main__":
    dbg = MyDebug()
    dbg.connect()

    # 开辟堆空间
    address = dbg.create_alloc(1024)
    print("开辟堆空间: {}".format(hex(address)))
    if address == False:
        exit()

    # 设置内存可执行属性
    dbg.set_local_protect(address, 32, 1024)

    # 从文本中读取shellcode
    shellcode = read_shellcode("c://shellcode.txt")

    # 循环写入到内存
    for code_byte in range(0, len(shellcode)):
        bytef = int(shellcode[code_byte], 16)
        dbg.write_memory_byte(code_byte + address, bytef)

    # 设置EIP位置
    dbg.set_register("eip", address)

    input()
    dbg.delete_alloc(address)

    dbg.close()

运行这段程序,则读者应该能看到如下图所示的输出结果,这说明我们的数据已经写出到对端堆中了;

4.9 x64dbg 内存处理与差异对比,《灰帽黑客:攻守道》,安全,网络,web安全

而有时我们还需要将这段代码反写,将一段我们挑选好的指令集保存到本地,此时就需要使用read_memory_byte依次循环读入数据,并动态写出到文件中,代码如下所示;

from LyScript32 import MyDebug

# 将特定内存保存到文本中
def write_shellcode(dbg,address,size,path):
    with open(path,"a+",encoding="utf-8") as fp:
        for index in range(0, size - 1):
            # 读取机器码
            read_code = dbg.read_memory_byte(address + index)

            if (index+1) % 16 == 0:
                print("\\x" + str(read_code))
                fp.write("\\x" + str(read_code) + "\n")
            else:
                print("\\x" + str(read_code),end="")
                fp.write("\\x" + str(read_code))

if __name__ == "__main__":
    dbg = MyDebug()
    dbg.connect()

    eip = dbg.get_register("eip")
    write_shellcode(dbg,eip,128,"d://shellcode.txt")
    dbg.close()

如上代码运行后,并可将EIP位置出的指令集前128字节动态写出到d://shellcode.txt文件内,输出效果图如下图所示;

4.9 x64dbg 内存处理与差异对比,《灰帽黑客:攻守道》,安全,网络,web安全

4.9.2 内存区域交换与对比

区域交换的原理是通过第三方变量依次交换内存两端的数据,例如将如下图中的0x5B00100x5B0070的前四个字节进行交换,则可调用memory_xchage(dbg, 5963792,5963792,4)传递参数实现,在调用前该内存区域如下图所示;

4.9 x64dbg 内存处理与差异对比,《灰帽黑客:攻守道》,安全,网络,web安全

通过运行如下代码片段,则可实现数据交换。

from LyScript32 import MyDebug

# 交换两个内存区域
def memory_xchage(dbg,memory_ptr_x,memory_ptr_y,bytes):
    ref = False
    for index in range(0,bytes):
        # 读取两个内存区域
        read_byte_x = dbg.read_memory_byte(memory_ptr_x + index)
        read_byte_y = dbg.read_memory_byte(memory_ptr_y + index)

        # 交换内存
        ref = dbg.write_memory_byte(memory_ptr_x + index,read_byte_y)
        ref = dbg.write_memory_byte(memory_ptr_y + index, read_byte_x)
    return ref

if __name__ == "__main__":
    dbg = MyDebug()
    dbg.connect()

    eip = dbg.get_register("eip")

    # 内存交换
    flag = memory_xchage(dbg, 5963792,5963888,4)
    print("内存交换状态: {}".format(flag))
    dbg.close()

交换后的内存区域如下图所示;

4.9 x64dbg 内存处理与差异对比,《灰帽黑客:攻守道》,安全,网络,web安全

4.9.3 内存与磁盘机器码对比

在某些时候我们还需要对比某个特定程序内存与磁盘之间的数据差异,这类需求的实现前提是实现两个特殊的读写函数,一般而言get_memory_hex_ascii函数可用于读出内存中的机器码数据,而get_file_hex_ascii则可用于读出磁盘中的机器码数据,将两者最进一步对比从而获取某些字节是否发生了改变。

首先实现get_memory_hex_ascii函数,该函数用于从给定的内存地址开始,读取指定长度的二进制数据,并将其转换为十六进制形式输出。具体解释如下:

  • 函数接收三个参数:内存地址address,偏移量offset,和要读取的长度len。
  • 定义变量count用于计算已经读取的字节数,并定义ref_memory_list用于存储读取的数据的十六进制形式。
  • 使用for循环读取指定范围内的二进制数据。
  • 调用dbg.read_memory_byte方法读取内存中的每个字节,并将其赋值给变量char。
  • 将读取的字节的十六进制表示输出到控制台。
  • 将读取的字节的十六进制形式存储到ref_memory_list列表中。
  • 如果已经读取了16个字节,就换行输出。
  • 如果字节的十六进制表示只有一位,则在前面添加一个0以保证两个字符宽度。
  • 最后返回ref_memory_list列表,包含了所有读取字节的十六进制形式。
# 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
    count = 0
    ref_memory_list = []
    for index in range(offset,len):
        # 读出数据
        char = dbg.read_memory_byte(address + index)
        count = count + 1

        if count % 16 == 0:
            if (char) < 16:
                print("0" + hex((char))[2:])
                ref_memory_list.append("0" + hex((char))[2:])
            else:
                print(hex((char))[2:])
                ref_memory_list.append(hex((char))[2:])
        else:
            if (char) < 16:
                print("0" + hex((char))[2:] + " ",end="")
                ref_memory_list.append("0" + hex((char))[2:])
            else:
                print(hex((char))[2:] + " ",end="")
                ref_memory_list.append(hex((char))[2:])
    return ref_memory_list

其次实现get_memory_hex_ascii函数,该函数用于从给定的文件路径中读取指定长度的二进制数据,并将其转换为十六进制形式输出。具体解释如下:

  • 函数接收三个参数:文件路径path,偏移量offset,和要读取的长度len。
  • 定义变量count用于计算已经读取的字节数,并定义ref_file_list用于存储读取的数据的十六进制形式。
  • 使用with open语句打开指定路径的文件,并使用rb模式以二进制方式读取。
  • 使用fp.seek方法将文件指针移动到指定的偏移量offset处。
  • 使用for循环读取指定长度的二进制数据。
  • 使用fp.read(1)方法读取一个字节的数据,并将其赋值给变量char。
  • 将读取的字节的十六进制表示输出到控制台。
  • 将读取的字节的十六进制形式存储到ref_file_list列表中。
  • 如果已经读取了16个字节,就换行输出。
  • 如果字节的十六进制表示只有一位,则在前面添加一个0以保证两个字符宽度。
  • 最后返回ref_file_list列表,包含了所有读取字节的十六进制形式。
# 读取程序中的磁盘镜像中的机器码
def get_file_hex_ascii(path,offset,len):
    count = 0
    ref_file_list = []

    with open(path, "rb") as fp:
        # file_size = os.path.getsize(path)
        fp.seek(offset)

        for item in range(offset,offset + len):
            char = fp.read(1)
            count = count + 1
            if count % 16 == 0:
                if ord(char) < 16:
                    print("0" + hex(ord(char))[2:])
                    ref_file_list.append("0" + hex(ord(char))[2:])
                else:
                    print(hex(ord(char))[2:])
                    ref_file_list.append(hex(ord(char))[2:])
            else:
                if ord(char) < 16:
                    print("0" + hex(ord(char))[2:] + " ", end="")
                    ref_file_list.append("0" + hex(ord(char))[2:])
                else:
                    print(hex(ord(char))[2:] + " ", end="")
                    ref_file_list.append(hex(ord(char))[2:])
    return ref_file_list

有了这两个函数读者就可以实现依次输出内存与磁盘中的机器码功能,

import binascii,os,sys
from LyScript32 import MyDebug

# 得到程序的内存镜像中的机器码
def get_memory_hex_ascii(address,offset,len):
    pass

# 读取程序中的磁盘镜像中的机器码
def get_file_hex_ascii(path,offset,len):
    pass

if __name__ == "__main__":
    dbg = MyDebug()

    connect_flag = dbg.connect()
    print("连接状态: {}".format(connect_flag))

    module_base = dbg.get_base_from_address(dbg.get_local_base())
    print("模块基地址: {}".format(hex(module_base)))

    # 得到内存机器码
    memory_hex_byte = get_memory_hex_ascii(module_base,0,100)

    # 得到磁盘机器码
    file_hex_byte = get_file_hex_ascii("d://lyshark.exe",0,100)

    # 输出机器码
    print("\n内存机器码: ",memory_hex_byte)
    print("\n磁盘机器码: ",file_hex_byte)

    dbg.close()

如上代码片段的输出效果如下图所示,分别得到该进程的内存与磁盘机器码格式,取前100个字节作比较;

4.9 x64dbg 内存处理与差异对比,《灰帽黑客:攻守道》,安全,网络,web安全

至于如何做对比,读者只需要通过for循环输出其参数即可得到,这里就不做截图演示了,效果同理;文章来源地址https://www.toymoban.com/news/detail-567439.html

    # 输出机器码
    for index in range(0,len(memory_hex_byte)):
        # 比较磁盘与内存是否存在差异
        if memory_hex_byte[index] != file_hex_byte[index]:
            # 存在差异则输出
            print("\n相对位置: [{}] --> 磁盘字节: 0x{} --> 内存字节: 0x{}".
                  format(index,memory_hex_byte[index],file_hex_byte[index]))
    dbg.close()

到了这里,关于4.9 x64dbg 内存处理与差异对比的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 4.5 x64dbg 探索钩子劫持技术

    钩子劫持技术是计算机编程中的一种技术,它们可以让开发者拦截系统函数或应用程序函数的调用,并在函数调用前或调用后执行自定义代码,钩子劫持技术通常用于病毒和恶意软件,也可以让开发者扩展或修改系统函数的功能,从而提高软件的性能和增加新功能。 4.5.1 探索

    2024年02月13日
    浏览(39)
  • 4.8 x64dbg 学会扫描应用堆栈

    堆栈是计算机中的两种重要数据结构 堆(Heap)和栈(Stack)它们在计算机程序中起着关键作用,在内存中堆区(用于动态内存分配)和栈区(用于存储函数调用、局部变量等临时数据),进程在运行时会使用堆栈进行参数传递,这些参数包括局部变量,临时空间以及函数切换

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

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

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

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

    2024年02月13日
    浏览(38)
  • 4.2 x64dbg 针对PE文件的扫描

    通过运用 LyScript 插件并配合 pefile 模块,即可实现对特定PE文件的扫描功能,例如载入PE程序到内存,验证PE启用的保护方式,计算PE节区内存特征,文件FOA与内存VA转换等功能的实现,首先简单介绍一下 pefile 模块。 pefile模块是一个用于解析Windows可执行文件(PE文件)的Pytho

    2024年02月12日
    浏览(27)
  • 4.7 x64dbg 应用层的钩子扫描

    所谓的应用层钩子(Application-level hooks)是一种编程技术,它允许应用程序通过在特定事件发生时执行特定代码来自定义或扩展其行为。这些事件可以是用户交互,系统事件,或者其他应用程序内部的事件。应用层钩子是在应用程序中添加自定义代码的一种灵活的方式。它们

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

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

    2024年02月08日
    浏览(37)
  • win10 x64实现内存注入DLL

    1:win10最新版本 2:vs2019 dll配置环境 一:属性–链接器–常规–启用增量链接:否 二:属性–链接器–高级–随机地址:否 固定基址:是 三:属性–c/c+±-代码生成–基本运行时检查:默认值 安全检查:禁用安全检查(G/S) 注入成功后会创建一个线程打印:jinrule字符串 不

    2024年02月12日
    浏览(30)
  • Python 图像处理:对比两张图片的差异

    在图像处理领域,对比两张图片的差异是一项常见的任务。Python 提供了许多强大的工具和库,使我们能够轻松地实现这一目标。本文将介绍如何使用 Python 对比两张图片,检测和可视化它们之间的差异。 在开始之前,我们首先需要定义图像差异。图像差异可以被理解为两张图

    2024年02月11日
    浏览(31)
  • PDF 文档处理:使用 Java 对比 PDF 找出内容差异

    不论是在团队写作还是在个人工作中,PDF 文档往往会经过多次修订和更新。掌握 PDF 文档内容的变化对于管理文档有极大的帮助。通过对比 PDF 文档,用户可以快速找出文档增加、删除和修改的内容,更好地了解文档的演变过程,轻松地管理文档。本文将介绍如何通过 Java 程

    2024年02月08日
    浏览(49)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包