Nota: Este é um protótipo de trabalho em andamento, trate-o como tal. Os pedidos de puxão são bem -vindos! Você pode molhar os pés com bons primeiros problemas
Uma biblioteca fácil de usar para emular o código em arquivos Minidump. Aqui estão alguns links para postagens/vídeos usando dumpulator:
Sinta -se à vontade para enviar uma solicitação de tração para adicionar seu artigo aqui!
O exemplo abaixo abre StringEncryptionFun_x64.dmp (faça o download de uma cópia aqui), aloca alguma memória e chama a função de descriptografia em 0x140001000 para descriptografar a string em 0x140017000 :
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 } '" ) O StringEncryptionFun_x64.dmp é coletado no ponto de entrada do exemplo de tests/StringEncryptionFun . Você pode obter os binários compilados para StringEncryptionFun aqui
from dumpulator import Dumpulator
dp = Dumpulator ( "StringEncryptionFun_x64.dmp" , trace = True )
dp . start ( dp . regs . rip ) Isso criará StringEncryptionFun_x64.dmp.trace com uma lista de instruções executadas e algumas indicações úteis ao alternar os módulos etc. Observe que o rastreamento diminui significativamente a emulação e é principalmente destinada a depuração.
from dumpulator import Dumpulator
dp = Dumpulator ( "my.dmp" )
buf = dp . call ( 0x140001000 )
dp . read_str ( buf , encoding = 'utf-16' )Diga que você tem a seguinte função:
00007FFFC81C06C0 | mov qword ptr [rsp+0x10],rbx ; prolog_start
00007FFFC81C06C5 | mov qword ptr [rsp+0x18],rsi
00007FFFC81C06CA | push rbp
00007FFFC81C06CB | push rdi
00007FFFC81C06CC | push r14
00007FFFC81C06CE | lea rbp,qword ptr [rsp-0x100]
00007FFFC81C06D6 | sub rsp,0x200 ; prolog_end
00007FFFC81C06DD | mov rax,qword ptr [0x7FFFC8272510]
Você só deseja executar o Prolog e configurar alguns registros:
from dumpulator import Dumpulator
prolog_start = 0x00007FFFC81C06C0
# we want to stop the instruction after the prolog
prolog_end = 0x00007FFFC81C06D6 + 7
dp = Dumpulator ( "my.dmp" , quiet = True )
dp . regs . rcx = 0x1337
dp . start ( begin = prolog_start , end = prolog_end )
print ( f"rsp: { hex ( dp . regs . rsp ) } " ) A bandeira quiet suprime os logs sobre as DLLs carregadas e as regiões de memória configuradas (para uso em scripts onde você deseja reduzir o spam de log).
Você pode (re) implementar syscalls usando o @syscall Decorator:
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_IMPLEMENTEDTodos os protótipos de função syscall podem ser encontrados em tsysCalls.py. Também existem muitos exemplos sobre como usar a API.
Para conectar uma implementação Syscall existente, você pode fazer o seguinte:
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:Windowsexplorer.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
) Como v0.2.0 há suporte para declarar facilmente suas próprias estruturas:
from dumpulator . native import *
class PROCESS_BASIC_INFORMATION ( Struct ):
ExitStatus : ULONG
PebBaseAddress : PVOID
AffinityMask : KAFFINITY
BasePriority : KPRIORITY
UniqueProcessId : ULONG_PTR
InheritedFromUniqueProcessId : ULONG_PTR Para instanciar essas estruturas, você deve usar uma instância 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 Se você passar por um valor de ponteiro como segundo argumento, a estrutura será lida na memória. Você pode declarar ponteiros com myptr: P[MY_STRUCT] e desreferências com myptr[0] .
Existe um plugin x64dbg simples disponível chamado Minidumpplugin O comando Minidump foi integrado ao X64DBG desde 2022-10-10. Para criar um despejo, pause a execução e execute o comando MiniDump my.dmp .
De Pypi (versão mais recente):
python -m pip install dumpulator
Para instalar da fonte:
python setup.py install
Instale para um ambiente de desenvolvimento:
python setup.py develop
O que diferencia o dumpulator de caixas de areia como SpeakeAsy e Qiling é que a memória completa do processo está disponível. Isso melhora o desempenho porque você pode imitar grandes partes de malware sem nunca deixar o Unicorn. Além disso, apenas os syscalls precisam ser imitados para fornecer um ambiente realista do Windows (já que tudo é realmente um ambiente de processo legítimo).