freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

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

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 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录