freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

如何使用dumpulator模拟内存转储
2023-06-29 23:54:34
所属地 广西


关于dumpulator

dumpulator是一款功能强大且易于使用的代码库,广大研究人员可以使用dumpulator来模拟内存转储,并将该技术用于恶意软件分析和动态代码分析等场景。

工具下载

广大研究人员可以使用下列命令将该项目源码克隆至本地:

git clone https://github.com/mrexodia/dumpulator.git

或者直接访问该项目的【Releases页面】下载该工具的预编译版本。

除此之外,我们也可以直接通过PyPI安装:

python -m pip install dumpulator

然后执行安装脚本:

python setup.py install

工具使用

调用函数

from dumpulator import Dumpulator

 

dp = Dumpulator("StringEncryptionFun_x64.dmp")

temp_addr = dp.allocate(256)

dp.call(0x140001000, [temp_addr, 0x140017000])

decrypted = dp.read_str(temp_addr)

print(f"decrypted: '{decrypted}'")

执行跟踪

from dumpulator import Dumpulator

 

dp = Dumpulator("StringEncryptionFun_x64.dmp", trace=True)

dp.start(dp.regs.rip)

读取UTF-16字符串

from dumpulator import Dumpulator

 

dp = Dumpulator("my.dmp")

buf = dp.call(0x140001000)

dp.read_str(buf, encoding='utf-16')

自定义syscall实现

我们可以使用@syscall修饰符来实现syscall:

from dumpulator import *

from dumpulator.native import *

from dumpulator.handles import *

from dumpulator.memory import *

 

@syscall

def ZwQueryVolumeInformationFile(dp: Dumpulator,

                                 FileHandle: HANDLE,

                                 IoStatusBlock: P[IO_STATUS_BLOCK],

                                 FsInformation: PVOID,

                                 Length: ULONG,

                                 FsInformationClass: FSINFOCLASS

                                 ):

return STATUS_NOT_IMPLEMENTED

所有的syscall函数原型都可以在ntsyscalls.py中找到。

如需给一个现有的syscall实现一个钩子,可以参照下列例子:

import dumpulator.ntsyscalls as ntsyscalls

 

@syscall

def ZwOpenProcess(dp: Dumpulator,

                  ProcessHandle: Annotated[P[HANDLE], SAL("_Out_")],

                  DesiredAccess: Annotated[ACCESS_MASK, SAL("_In_")],

                  ObjectAttributes: Annotated[P[OBJECT_ATTRIBUTES], SAL("_In_")],

                  ClientId: Annotated[P[CLIENT_ID], SAL("_In_opt_")]

                  ):

    process_id = ClientId.read_ptr()

    assert process_id == dp.parent_process_id

    ProcessHandle.write_ptr(0x1337)

    return STATUS_SUCCESS

 

@syscall

def ZwQueryInformationProcess(dp: Dumpulator,

                              ProcessHandle: Annotated[HANDLE, SAL("_In_")],

                              ProcessInformationClass: Annotated[PROCESSINFOCLASS, SAL("_In_")],

                              ProcessInformation: Annotated[PVOID, SAL("_Out_writes_bytes_(ProcessInformationLength)")],

                              ProcessInformationLength: Annotated[ULONG, SAL("_In_")],

                              ReturnLength: Annotated[P[ULONG], SAL("_Out_opt_")]

                              ):

    if ProcessInformationClass == PROCESSINFOCLASS.ProcessImageFileNameWin32:

        if ProcessHandle == dp.NtCurrentProcess():

            main_module = dp.modules[dp.modules.main]

            image_path = main_module.path

        elif ProcessHandle == 0x1337:

            image_path = R"C:\Windows\explorer.exe"

        else:

            raise NotImplementedError()

        buffer = UNICODE_STRING.create_buffer(image_path, ProcessInformation)

        assert ProcessInformationLength >= len(buffer)

        if ReturnLength.ptr:

            dp.write_ulong(ReturnLength.ptr, len(buffer))

        ProcessInformation.write(buffer)

        return STATUS_SUCCESS

    return ntsyscalls.ZwQueryInformationProcess(dp,

                                                ProcessHandle,

                                                ProcessInformationClass,

                                                ProcessInformation,

                                                ProcessInformationLength,

                                                ReturnLength

                                                )

自定义结构体

该工具支持声明你自己的结构体:

from dumpulator.native import *

 

class PROCESS_BASIC_INFORMATION(Struct):

    ExitStatus: ULONG

    PebBaseAddress: PVOID

    AffinityMask: KAFFINITY

    BasePriority: KPRIORITY

    UniqueProcessId: ULONG_PTR

InheritedFromUniqueProcessId: ULONG_PTR

如需初始化这些结构体,则需要使用到一个Dumpulator实例:

pbi = PROCESS_BASIC_INFORMATION(dp)

assert ProcessInformationLength == Struct.sizeof(pbi)

pbi.ExitStatus = 259  # STILL_ACTIVE

pbi.PebBaseAddress = dp.peb

pbi.AffinityMask = 0xFFFF

pbi.BasePriority = 8

pbi.UniqueProcessId = dp.process_id

pbi.InheritedFromUniqueProcessId = dp.parent_process_id

ProcessInformation.write(bytes(pbi))

if ReturnLength.ptr:

    dp.write_ulong(ReturnLength.ptr, Struct.sizeof(pbi))

return STATUS_SUCCESS

如果你将一个指针值作为第二个参数传递,那么结构体将会从内存中被读取。我们可以使用myptr: P[MY_STRUCT]声明指针并使用myptr[0]来引用他们。

收集转储

从2022年10月10日起minidump命令就整合进了x64dbg中,如需创建一个转储,可以暂停工具的执行,并运行下列命令命令。

MiniDump my.dmp

许可证协议

本项目的开发与发布遵循BSL-1.0开源许可证协议。

项目地址

dumpulator:【GitHub传送门

参考资料

https://oalabs.openanalysis.net/

https://youtu.be/4Pfu98Xx9Yo

https://rioasmara.com/2022/07/23/emulating-malware-with-dumpulator/

https://research.openanalysis.net/emotet/emulation/config/dumpulator/malware/2022/05/19/emotet_x64_emulation.html

https://research.checkpoint.com/2022/native-function-and-assembly-code-invocation/

https://research.openanalysis.net/guloader/emulation/dumpulator/veh/exceptions/2023/01/15/dumpulator-veh.html

https://research.openanalysis.net/rhadamanthys/config/ida/shifted%20pointers/peb/_list_entry/_ldr_data_table_entry/2023/01/19/rhadamanthys.html

https://kienmanowar.wordpress.com/2023/05/22/case-study-decrypt-strings-using-dumpulator/

# 恶意软件分析 # 内存取证 # 内存转储
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录