참고 : 이것은 진행중인 프로토 타입입니다. 풀 요청을 환영합니다! 좋은 첫 번째 문제로 발을 적시게 할 수 있습니다.
Minidump 파일에서 코드를 에뮬레이션하기위한 사용하기 쉬운 라이브러리. 다음은 dumpulator를 사용하여 게시물/비디오에 대한 몇 가지 링크입니다.
여기에 기사를 추가하기 위해 풀 요청을 보내 주시기 바랍니다!
아래의 예는 StringEncryptionFun_x64.dmp (여기에서 사본 다운로드)를 열고 일부 메모리를 할당하고 0x140001000 의 암호 해독 함수를 호출하여 문자열을 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 } '" ) StringEncryptionFun_x64.dmp 는 tests/StringEncryptionFun 예제의 진입 점에서 수집됩니다. StringEncryptionFun 용 컴파일 된 바이너리를 여기에서 얻을 수 있습니다
from dumpulator import Dumpulator
dp = Dumpulator ( "StringEncryptionFun_x64.dmp" , trace = True )
dp . start ( dp . regs . rip ) 이렇게하면 모듈 등을 전환 할 때 실행 된 지침 목록과 몇 가지 유용한 표시가있는 StringEncryptionFun_x64.dmp.trace 가 생성됩니다. 추적은 에뮬레이션을 크게 느리게하고 대부분 디버깅을 의미합니다.
from dumpulator import Dumpulator
dp = Dumpulator ( "my.dmp" )
buf = dp . call ( 0x140001000 )
dp . read_str ( buf , encoding = 'utf-16' )다음과 같은 기능이 있다고 가정합니다.
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]
프롤로그를 실행하고 몇 가지 레지스터를 설정하려고합니다.
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 ) } " ) quiet 플래그는로드 된 DLL 및 메모리 영역에 대한 로그를 억제합니다 (로그 스팸을 줄이려는 스크립트에서 사용).
@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에서 찾을 수 있습니다. API 사용 방법에 대한 예가 많이 있습니다.
기존 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: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
) v0.2.0 이므로 자신의 구조를 쉽게 선언 할 수있는 지원이 있습니다.
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] 로 해석 할 수 있습니다.
MinidumpPlugin이라는 간단한 x64dbg 플러그인이 있습니다 Minidump 명령은 2022-10-10 년 이후 x64dbg에 통합되었습니다. 덤프를 만들려면 실행을 일시 중지하고 명령 MiniDump my.dmp 실행하십시오.
PYPI (최신 릴리스) :
python -m pip install dumpulator
소스에서 설치하려면 :
python setup.py install
개발 환경을 위해 설치 :
python setup.py develop
Speakeasy 및 Qiling과 같은 샌드 박스와 차별화되는 것은 전체 프로세스 메모리를 사용할 수 있다는 것입니다. 유니콘을 떠나지 않고도 맬웨어의 많은 부분을 모방 할 수 있기 때문에 성능이 향상됩니다. 또한 현실적인 Windows 환경을 제공하기 위해 SyScall 만 모방해야합니다 (실제로 모든 것이 합법적 인 프로세스 환경 이므로 ).