Nota: Este es un prototipo de trabajo en progreso, por favor trátelo como tal. ¡Las solicitudes de extracción son bienvenidas! Puedes mojarte los pies con buenos primeros problemas
Una biblioteca fácil de usar para emular el código en archivos minidump. Aquí hay algunos enlaces a publicaciones/videos usando el Detumador:
¡No dude en enviar una solicitud de extracción para agregar su artículo aquí!
El ejemplo a continuación abre StringEncryptionFun_x64.dmp (descargue una copia aquí), asigna algo de memoria y llama a la función de descifrado al 0x140001000 para descifrar la cadena al 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 } '" ) El StringEncryptionFun_x64.dmp se recopila en el punto de entrada del ejemplo tests/StringEncryptionFun . Puede obtener los binarios compilados para StringEncryptionFun aquí
from dumpulator import Dumpulator
dp = Dumpulator ( "StringEncryptionFun_x64.dmp" , trace = True )
dp . start ( dp . regs . rip ) Esto creará StringEncryptionFun_x64.dmp.trace con una lista de instrucciones ejecutadas y algunas indicaciones útiles al cambiar de módulos, etc. Tenga en cuenta que el rastreo ralentiza significativamente la emulación y está destinada principalmente a la depuración.
from dumpulator import Dumpulator
dp = Dumpulator ( "my.dmp" )
buf = dp . call ( 0x140001000 )
dp . read_str ( buf , encoding = 'utf-16' )Digamos que tiene la siguiente función:
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]
Solo desea ejecutar el Prolog y configurar algunos 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 ) } " ) La bandera quiet suprime los registros sobre DLL cargadas y configuradas las regiones de memoria (para usar en scripts donde desea reducir el spam de registro).
Puede (re) implementar syscalls usando el decorador @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_IMPLEMENTEDTodos los prototipos de la función syscall se pueden encontrar en ntsyscalls.py. También hay muchos ejemplos sobre cómo usar la API.
Para enganchar una implementación de SYSCall existente, puede hacer lo siguiente:
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
) Desde v0.2.0 hay soporte para declarar fácilmente sus propias estructuras:
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 estas estructuras, debe utilizar una instancia 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 Si pasa un valor de puntero como segundo argumento, la estructura se leerá de la memoria. Puedes declarar punteros con myptr: P[MY_STRUCT] y los desamare con myptr[0] .
Hay un simple complemento X64DBG disponible llamado minidumpplugin El comando Minidump se ha integrado en X64DBG desde 2022-10-10. Para crear un volcado, pause la ejecución y ejecute el comando MiniDump my.dmp .
De Pypi (último lanzamiento):
python -m pip install dumpulator
Para instalar desde la fuente:
python setup.py install
Instalar para un entorno de desarrollo:
python setup.py develop
Lo que distingue el Dumpulador de Sandboxes como Speakeasy y Qiling es que la memoria de proceso completa está disponible. Esto mejora el rendimiento porque puede emular grandes partes del malware sin que se vaya de unicornio. Además, solo se deben emular syscalls para proporcionar un entorno realista de Windows (ya que todo es un entorno de proceso legítimo).