Remarque: Il s'agit d'un prototype de travail en cours, veuillez le traiter comme tel. Les demandes de traction sont les bienvenues! Vous pouvez vous mouiller les pieds avec de bons premiers problèmes
Une bibliothèque facile à utiliser pour émuler du code dans les fichiers MiniDump. Voici quelques liens vers des publications / vidéos à l'aide de Dumpulator:
N'hésitez pas à envoyer une demande de traction pour ajouter votre article ici!
L'exemple ci-dessous ouvre StringEncryptionFun_x64.dmp (téléchargez une copie ici), alloue de la mémoire et appelle la fonction de décryptage à 0x140001000 pour décrypter la chaîne à 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 } '" ) Le StringEncryptionFun_x64.dmp est collecté au point d'entrée de l'exemple tests/StringEncryptionFun . Vous pouvez obtenir les binaires compilés pour StringEncryptionFun ici
from dumpulator import Dumpulator
dp = Dumpulator ( "StringEncryptionFun_x64.dmp" , trace = True )
dp . start ( dp . regs . rip ) Cela créera StringEncryptionFun_x64.dmp.trace avec une liste d'instructions exécutées et quelques indications utiles lors du changement de modules, etc. Notez que le traçage ralentit considérablement l'émulation et il est principalement destiné à déboguer.
from dumpulator import Dumpulator
dp = Dumpulator ( "my.dmp" )
buf = dp . call ( 0x140001000 )
dp . read_str ( buf , encoding = 'utf-16' )Dites que vous avez la fonction suivante:
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]
Vous voulez seulement exécuter le Prolog et configurer certains registres:
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 ) } " ) L'indicateur quiet supprime les journaux sur les DLL chargés et les régions de mémoire (pour une utilisation dans les scripts où vous souhaitez réduire le spam de journaux).
Vous pouvez (re) implémenter des systèmes en utilisant le décorateur @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_IMPLEMENTEDTous les prototypes de fonction syscall peuvent être trouvés dans ntsyscalls.py. Il existe également de nombreux exemples sur la façon d'utiliser l'API.
Pour accrocher une implémentation système existante, vous pouvez effectuer ce qui suit:
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
) Depuis v0.2.0 il y a un support pour déclarer facilement vos propres structures:
from dumpulator . native import *
class PROCESS_BASIC_INFORMATION ( Struct ):
ExitStatus : ULONG
PebBaseAddress : PVOID
AffinityMask : KAFFINITY
BasePriority : KPRIORITY
UniqueProcessId : ULONG_PTR
InheritedFromUniqueProcessId : ULONG_PTR Pour instancier ces structures, vous devez utiliser une instance 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 vous passez une valeur de pointeur comme deuxième argument, la structure sera lue à partir de la mémoire. Vous pouvez déclarer des pointeurs avec myptr: P[MY_STRUCT] et les déférences avec myptr[0] .
Il y a un simple plugin x64dbg disponible appelé mini-timuplugin La commande MINIDump est intégrée dans X64DBG depuis 2022-10-10. Pour créer un vidage, arrêtez l'exécution et exécutez la commande MiniDump my.dmp .
De PYPI (dernière version):
python -m pip install dumpulator
Pour installer à partir de la source:
python setup.py install
Installer pour un environnement de développement:
python setup.py develop
Ce qui distingue Dumpulator des bacs de sable comme Speakeasy et Qiling, c'est que la mémoire de processus complète est disponible. Cela améliore les performances car vous pouvez imiter de grandes parties de logiciels malveillants sans jamais quitter la licorne. De plus, seuls les systèmes doivent être émulés pour fournir un environnement Windows réaliste (car tout est en fait un environnement de processus légitime).