Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

lots of code changes

  • Loading branch information...
commit d0e1687ca77c825520dc4bb2fb448ce40f836f99 1 parent a3b5caa
@brad-anton brad-anton authored
View
24 README
@@ -1,4 +1,4 @@
-DLLInjector v0.1
+DLLInjector v0.2
brad.antoniewicz@foundstone.com
--------------------------------------------------
@@ -7,6 +7,8 @@ that work across multiple Windows versions. The user defines
a DLL, a process ID, and technique and the tool attempts to
inject the DLL into the process and execute it.
+This was built using Microsoft Visual Studio 2010
+
It currently supports the following methods:
1. CreateRemoteThread()
@@ -25,7 +27,14 @@ It currently supports the following methods:
http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html
http://www.kdsbest.com/?p=159
-
+
+ 4. RtlCreateUserThread()
+ The following sites were used as a reference when implementing
+ this method:
+
+ http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html?showComment=1338375764336#c4138436235159645886
+ http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html
+
Todo:
1. Implement SetWindowsHookEx() Method
http://www.kdsbest.com/?p=179
@@ -33,14 +42,13 @@ Todo:
2. Implement QueueUserAPC() Method
http://webcache.googleusercontent.com/search?q=cache:G8i5oxOWbDMJ:www.hackforums.net/archive/index.php/thread-2442150.html+&cd=3&hl=en&ct=clnk&gl=us&client=firefox-a
- 3. Implement RtlCreateUserThread() Method
- http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html?showComment=1338375764336#c4138436235159645886
- http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html
-
- 4. Implement PrivEscalation as per:
+ 3. Implement PrivEscalation as per:
https://github.com/rapid7/metasploit-framework/tree/master/external/source/meterpreter/source/extensions/priv/server/elevate
The original inspiration for this tool was from VMInjector:
- https://github.com/batistam/VMInjector
+ https://github.com/batistam/VMInjector
+
+Lots of great info here:
+ https://github.com/stephenfewer/ReflectiveDLLInjection
View
BIN  Release/dllInjector-x64.exe
Binary file not shown
View
BIN  Release/dllInjector-x64.pdb
Binary file not shown
View
BIN  Release/dllInjector-x86.exe
Binary file not shown
View
BIN  Release/dllInjector-x86.pdb
Binary file not shown
View
BIN  Release/reflective_dll.dll
Binary file not shown
View
BIN  Release/reflective_dll.x64.dll
Binary file not shown
View
BIN  dllinjector.ncb
Binary file not shown
View
BIN  dllinjector.sdf
Binary file not shown
View
31 dllinjector.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dllInjector", "src\dllInject.vcxproj", "{DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ Release64|Win32 = Release64|Win32
+ Release64|x64 = Release64|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Debug|Win32.Build.0 = Debug|Win32
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Debug|x64.ActiveCfg = Debug|x64
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Debug|x64.Build.0 = Debug|x64
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release|Win32.ActiveCfg = Release|Win32
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release|Win32.Build.0 = Release|Win32
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release|x64.ActiveCfg = Release|x64
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release|x64.Build.0 = Release|x64
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release64|Win32.ActiveCfg = Release|Win32
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release64|x64.ActiveCfg = Release64|x64
+ {DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}.Release64|x64.Build.0 = Release64|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
View
BIN  dllinjector.suo
Binary file not shown
View
94 src/AllocWriteDLL.cpp
@@ -0,0 +1,94 @@
+/*
+ AllocWriteMethods.cpp
+ brad.antoniewicz@foundstone.com
+
+ These functions return the value to start execution, and set value of lpExecParam
+
+*/
+#include "LoadLibraryR.h"
+#include <stdio.h>
+
+LPTHREAD_START_ROUTINE AllocWriteDLL(HANDLE hTargetProcHandle, LPCSTR dllPath) {
+ HANDLE hFile = NULL;
+ DWORD dwLength = 0;
+ DWORD dwBytesRead = 0;
+ DWORD dwReflectiveLoaderOffset = 0;
+ LPVOID lpWriteBuff = NULL;
+ LPVOID lpDllAddr = NULL;
+
+ printf("\t[+] Allocating space for entire DLL\n");
+
+ hFile = CreateFileA( dllPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ if( hFile == INVALID_HANDLE_VALUE ) {
+ printf("\n[!] ERROR: Could not open DLL!\n");
+ return NULL;
+ }
+
+ dwLength = GetFileSize( hFile, NULL );
+ if( dwLength == INVALID_FILE_SIZE || dwLength == 0 ) {
+ printf("\n[!] ERROR: Invalid DLL file size!\n");
+ return NULL;
+ }
+ lpWriteBuff = HeapAlloc( GetProcessHeap(), 0, dwLength );
+ if( !lpWriteBuff ) {
+ printf("\n[!] ERROR: Failed to allocate memory for DLL!\n");
+ return NULL;
+ }
+
+ if( ReadFile( hFile, lpWriteBuff, dwLength, &dwBytesRead, NULL ) == FALSE ){
+ printf("\n[!] ERROR: Failed to read DLL!\n");
+ return NULL;
+ }
+
+ lpDllAddr = VirtualAllocEx(hTargetProcHandle, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+
+ printf("\t\t[+] Writing into the current process space at 0x%08x\n", lpDllAddr);
+
+ if (WriteProcessMemory(hTargetProcHandle, lpDllAddr, lpWriteBuff, dwLength, NULL) == 0) {
+ printf("\n[!] WriteProcessMemory Failed [%u]\n", GetLastError());
+ return NULL;
+ }
+
+ dwReflectiveLoaderOffset = GetReflectiveLoaderOffset(lpWriteBuff);
+
+ HeapFree( GetProcessHeap(), 0, lpWriteBuff );
+
+ if( !dwReflectiveLoaderOffset ) {
+ printf("\n[!] Error calculating Offset - Wrong Architecture?\n");
+ return NULL;
+ }
+
+ return (LPTHREAD_START_ROUTINE) ( (ULONG_PTR) lpDllAddr + dwReflectiveLoaderOffset );
+
+}
+
+LPTHREAD_START_ROUTINE AllocWritePath(HANDLE hTargetProcHandle, LPCSTR dllPath, LPVOID *lpExecParam) {
+
+ unsigned int writeLen = 0;
+ LPVOID lpDllAddr = NULL;
+ LPVOID lpWriteVal = NULL;
+ LPVOID loadLibAddr = NULL;
+
+ printf("\t[+] Allocating space for the path of the DLL\n");
+
+ lpDllAddr = VirtualAllocEx(hTargetProcHandle, NULL, strlen(dllPath), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+
+ printf("\t\t[+] Writing into the current process space at 0x%08x\n", lpDllAddr);
+ if (WriteProcessMemory(hTargetProcHandle, lpDllAddr, dllPath, strlen(dllPath), NULL) == 0) {
+ printf("\n[!] WriteProcessMemory Failed [%u]\n", GetLastError());
+ return NULL;
+ }
+
+ *lpExecParam = (LPVOID *)lpDllAddr;
+
+ printf("\t\t[+] Looking for LoadLibrary in kernel32\n");
+ loadLibAddr = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
+ if (loadLibAddr == NULL) {
+ printf("\n[!] Failed to find LoadLibrary in Kernel32! Quiting...\n");
+ return NULL;
+ }
+ printf("\t\t[+] Found at 0x%08x\n",loadLibAddr);
+
+ return (LPTHREAD_START_ROUTINE) loadLibAddr;
+
+}
View
11 src/AllocWriteDLL.h
@@ -0,0 +1,11 @@
+/*
+ AllocWriteDLL.h
+ brad.antoniewicz@foundstone.com
+
+ Contains headers for the Alloc/Write/Determine Address functions.
+ See AllocWriteDLL.cpp for more information
+
+*/
+
+LPTHREAD_START_ROUTINE AllocWriteDLL(HANDLE hTargetProcHandle, LPCSTR dllPath);
+LPTHREAD_START_ROUTINE AllocWritePath(HANDLE hTargetProcHandle, LPCSTR dllPath, LPVOID *lpExecParam);
View
254 src/ExecThread.cpp
@@ -0,0 +1,254 @@
+/*
+ CreateMethods.cpp
+ brad.antoniewicz@foundstone.com
+
+ Contains the thread creation functions.
+
+ Currently implements:
+
+ 1. Suspend/Inject/Resume Method
+ 2. ntCreateThreadEx()
+ 3. RtlCreateUserThread()
+*/
+
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <tlhelp32.h>
+#include "ExecThread.h"
+#include "AllocWriteDLL.h"
+
+#ifndef _WIN64
+VOID suspendInjectResume(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {
+ /*
+ This is a mixture from the following sites:
+
+ http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html
+ http://www.kdsbest.com/?p=159
+
+ */
+
+ HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ HANDLE hSnapshot2 = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ HANDLE thread = NULL;
+ THREADENTRY32 te;
+ THREADENTRY32 te2;
+
+ CONTEXT ctx;
+ DWORD firstThread = 0;
+ HANDLE targetThread = NULL;
+
+ LPVOID scAddr;
+
+ int i;
+
+ unsigned char sc[] = {
+ // Push all flags
+ 0x9C,
+ // Push all register
+ 0x60,
+ // Push 3,4,5,6 (dllPathAddr)
+ 0x68, 0xAA, 0xAA, 0xAA, 0xAA,
+ // Mov eax, 8,9,10, 11 (loadLibAddr)
+ 0xB8, 0xBB, 0xBB, 0xBB, 0xBB,
+ // Call eax
+ 0xFF, 0xD0,
+ // Pop all register
+ 0x61,
+ // Pop all flags
+ 0x9D,
+ // Ret
+ 0xC3
+ };
+
+ te.dwSize = sizeof(THREADENTRY32);
+ te2.dwSize = sizeof(THREADENTRY32);
+ ctx.ContextFlags = CONTEXT_FULL;
+
+ sc[3] = ((unsigned int) dllPathAddr & 0xFF);
+ sc[4] = (((unsigned int) dllPathAddr >> 8 )& 0xFF);
+ sc[5] = (((unsigned int) dllPathAddr >> 16 )& 0xFF);
+ sc[6] = (((unsigned int) dllPathAddr >> 24 )& 0xFF);
+
+ sc[8] = ((unsigned int) loadLibAddr & 0xFF);
+ sc[9] = (((unsigned int) loadLibAddr >> 8 )& 0xFF);
+ sc[10] = (((unsigned int) loadLibAddr >> 16 )& 0xFF);
+ sc[11] = (((unsigned int) loadLibAddr >> 24 )& 0xFF);
+
+
+
+ // Suspend Threads
+ if(Thread32First(hSnapshot, &te)) {
+ do {
+ if(te.th32OwnerProcessID == GetProcessId(hHandle)) {
+ if ( firstThread == 0 )
+ firstThread = te.th32ThreadID;
+ thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te.th32ThreadID);
+ if(thread != NULL) {
+ printf("\t[+] Suspending Thread 0x%08x\n", te.th32ThreadID);
+ SuspendThread(thread);
+ CloseHandle(thread);
+ } else {
+ printf("\t[+] Could not open thread!\n");
+ }
+ }
+ } while(Thread32Next(hSnapshot, &te));
+ } else {
+ printf("\t[+] Could not Thread32First! [%d]\n", GetLastError());
+ CloseHandle(hSnapshot);
+ exit(-1);
+ }
+ CloseHandle(hSnapshot);
+
+ printf("\t[+] Our Launcher Code:\n\t");
+ for (i=0; i<17; i++)
+ printf("%02x ",sc[i]);
+ printf("\n");
+ // Get/Save EIP, Inject
+ printf("\t[+] Targeting Thread 0x%08x\n",firstThread);
+ targetThread = OpenThread(THREAD_ALL_ACCESS, FALSE, firstThread);
+ if (GetThreadContext(targetThread, &ctx) == 0)
+ printf("[!] GetThreadContext Failed!\n");
+ printf("\t[+] Current Registers: \n\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp);
+
+ printf("\t[+] Saving EIP for our return\n");
+ ctx.Esp -= sizeof(unsigned int);
+ WriteProcessMemory(hHandle, (LPVOID)ctx.Esp, (LPCVOID)&ctx.Eip, sizeof(unsigned int), NULL);
+ printf("\t\tEIP[0x%08x] ESP[0x%08x] EBP[0x%08x]\n", ctx.Eip, ctx.Esp, ctx.Ebp);
+
+ scAddr = VirtualAllocEx(hHandle, NULL, 17, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ printf("\t[+] Allocating 17 bytes for our Launcher Code [0x%08x][%d]\n", scAddr, GetLastError());
+
+ printf ("\t[+] Writing Launcher Code into targetThread [%d]\n", WriteProcessMemory(hHandle, scAddr, (LPCVOID)sc, 17, NULL));
+
+ printf("\t[+] Setting EIP to LauncherCode\n");
+ ctx.Eip = (DWORD)scAddr;
+ printf("\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp);
+
+ if (SetThreadContext(targetThread, &ctx) == 0)
+ printf("[!] SetThreadContext Failed!\n");
+
+ // Resume Threads
+ hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
+ te.dwSize = sizeof(THREADENTRY32);
+
+ if(Thread32First(hSnapshot2, &te2)) {
+ do {
+ if(te2.th32OwnerProcessID == GetProcessId(hHandle)) {
+ thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te2.th32ThreadID);
+ if(thread != NULL) {
+ printf("\t[+] Resuming Thread 0x%08x\n", te2.th32ThreadID);
+ ResumeThread(thread);
+ if (te2.th32ThreadID == firstThread)
+ WaitForSingleObject(thread, 5000);
+ CloseHandle(thread);
+ } else {
+ printf("\t[+] Could not open thread!\n");
+ }
+ }
+ } while(Thread32Next(hSnapshot2, &te2));
+ } else {
+ printf("\t[+] Could not Thread32First! [%d]\n", GetLastError());
+ CloseHandle(hSnapshot2);
+ exit(-1);
+ }
+ CloseHandle(hSnapshot2);
+}
+#endif
+
+HANDLE bCreateRemoteThread(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {
+
+ HANDLE hRemoteThread = NULL;
+
+ LPVOID ntCreateThreadExAddr = NULL;
+ NtCreateThreadExBuffer ntbuffer;
+ DWORD temp1 = 0;
+ DWORD temp2 = 0;
+
+ ntCreateThreadExAddr = GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtCreateThreadEx");
+
+ if( ntCreateThreadExAddr ) {
+
+ ntbuffer.Size = sizeof(struct NtCreateThreadExBuffer);
+ ntbuffer.Unknown1 = 0x10003;
+ ntbuffer.Unknown2 = 0x8;
+ ntbuffer.Unknown3 = &temp2;
+ ntbuffer.Unknown4 = 0;
+ ntbuffer.Unknown5 = 0x10004;
+ ntbuffer.Unknown6 = 4;
+ ntbuffer.Unknown7 = &temp1;
+ ntbuffer.Unknown8 = 0;
+
+ LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx)ntCreateThreadExAddr;
+ NTSTATUS status = funNtCreateThreadEx(
+ &hRemoteThread,
+ 0x1FFFFF,
+ NULL,
+ hHandle,
+ (LPTHREAD_START_ROUTINE)loadLibAddr,
+ dllPathAddr,
+ FALSE,
+ NULL,
+ NULL,
+ NULL,
+ &ntbuffer
+ );
+
+ if (hRemoteThread == NULL) {
+ printf("\t[!] NtCreateThreadEx Failed! [%d][%08x]\n", GetLastError(), status);
+ return NULL;
+ } else {
+ return hRemoteThread;
+ }
+ } else {
+ printf("\n[!] Could not find NtCreateThreadEx!\n");
+ }
+ return NULL;
+
+}
+
+HANDLE bCreateUserThread(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {
+ /*
+ Provided help
+ http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html?showComment=1338375764336#c4138436235159645886
+ http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html
+ http://www.rohitab.com/discuss/topic/39493-using-rtlcreateuserthread/
+ */
+
+
+ HANDLE hRemoteThread = NULL;
+ LPVOID rtlCreateUserAddr = NULL;
+
+ CLIENT_ID cid;
+
+ rtlCreateUserAddr = GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlCreateUserThread");
+
+ if( rtlCreateUserAddr ) {
+
+ LPFUN_RtlCreateUserThread funRtlCreateUserThread = (LPFUN_RtlCreateUserThread)rtlCreateUserAddr;
+ funRtlCreateUserThread(
+ hHandle, // ProcessHandle
+ NULL, // SecurityDescriptor (OPTIONAL)
+ FALSE, // CreateSuspended
+ 0, // StackZeroBits
+ 0, // StackReserved
+ 0, // StackCommit
+ (PVOID) loadLibAddr,// StartAddress
+ (PVOID) dllPathAddr,// StartParameter (OPTIONAL)
+ &hRemoteThread, // ThreadHandle
+ &cid // ClientID
+ );
+
+ if (hRemoteThread == NULL) {
+ printf("\t[!] RtlCreateUserThread Failed! [%d]\n", GetLastError());
+ return NULL;
+ } else {
+ return hRemoteThread;
+ }
+ } else {
+ printf("\n[!] Could not find RtlCreateUserThread!\n");
+ }
+ return NULL;
+
+}
View
61 src/ExecThread.h
@@ -0,0 +1,61 @@
+/*
+ CreateMethods.h
+ brad.antoniewicz@foundstone.com
+
+ Contains headers for the thread creation functions.
+ See CreateMethods.cpp for more information
+
+*/
+
+struct NtCreateThreadExBuffer {
+ ULONG Size;
+ ULONG Unknown1;
+ ULONG Unknown2;
+ PULONG Unknown3;
+ ULONG Unknown4;
+ ULONG Unknown5;
+ ULONG Unknown6;
+ PULONG Unknown7;
+ ULONG Unknown8;
+ };
+
+
+typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) (
+ OUT PHANDLE hThread,
+ IN ACCESS_MASK DesiredAccess,
+ IN LPVOID ObjectAttributes,
+ IN HANDLE ProcessHandle,
+ IN LPTHREAD_START_ROUTINE lpStartAddress,
+ IN LPVOID lpParameter,
+ IN BOOL CreateSuspended,
+ IN ULONG StackZeroBits,
+ IN ULONG SizeOfStackCommit,
+ IN ULONG SizeOfStackReserve,
+ OUT LPVOID lpBytesBuffer
+);
+
+typedef struct _CLIENT_ID
+{
+ PVOID UniqueProcess;
+ PVOID UniqueThread;
+} CLIENT_ID, *PCLIENT_ID;
+
+typedef long (WINAPI *LPFUN_RtlCreateUserThread)(
+ HANDLE, // ProcessHandle
+ PSECURITY_DESCRIPTOR, // SecurityDescriptor (OPTIONAL)
+ BOOLEAN, // CreateSuspended
+ ULONG, // StackZeroBits
+ PULONG, // StackReserved
+ PULONG, // StackCommit
+ PVOID, // StartAddress
+ PVOID, // StartParameter (OPTIONAL)
+ PHANDLE, // ThreadHandle
+ PCLIENT_ID // ClientID
+);
+
+
+#ifndef _WIN64
+VOID suspendInjectResume(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr);
+#endif
+HANDLE bCreateRemoteThread(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr);
+HANDLE bCreateUserThread(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr);
View
120 src/Inject.c
@@ -0,0 +1,120 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "LoadLibraryR.h"
+
+#pragma comment(lib,"Advapi32.lib")
+
+#define BREAK_WITH_ERROR( e ) { printf( "[-] %s. Error=%d", e, GetLastError() ); break; }
+
+// Simple app to inject a reflective DLL into a process vis its process ID.
+int main( int argc, char * argv[] )
+{
+ HANDLE hFile = NULL;
+ HANDLE hModule = NULL;
+ HANDLE hProcess = NULL;
+ HANDLE hToken = NULL;
+ LPVOID lpBuffer = NULL;
+ DWORD dwLength = 0;
+ DWORD dwBytesRead = 0;
+ DWORD dwProcessId = 0;
+ TOKEN_PRIVILEGES priv = {0};
+
+#ifdef WIN_X64
+ char * cpDllFile = "reflective_dll.x64.dll";
+#else
+#ifdef WIN_X86
+ char * cpDllFile = "reflective_dll.dll";
+#else WIN_ARM
+ char * cpDllFile = "reflective_dll.arm.dll";
+#endif
+#endif
+
+ do
+ {
+ // Usage: inject.exe [pid] [dll_file]
+
+ if( argc == 1 )
+ dwProcessId = GetCurrentProcessId();
+ else
+ dwProcessId = atoi( argv[1] );
+
+ if( argc >= 3 )
+ cpDllFile = argv[2];
+
+ hFile = CreateFileA( cpDllFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+ if( hFile == INVALID_HANDLE_VALUE )
+ BREAK_WITH_ERROR( "Failed to open the DLL file" );
+
+ dwLength = GetFileSize( hFile, NULL );
+ if( dwLength == INVALID_FILE_SIZE || dwLength == 0 )
+ BREAK_WITH_ERROR( "Failed to get the DLL file size" );
+
+ lpBuffer = HeapAlloc( GetProcessHeap(), 0, dwLength );
+ if( !lpBuffer )
+ BREAK_WITH_ERROR( "Failed to get the DLL file size" );
+
+ if( ReadFile( hFile, lpBuffer, dwLength, &dwBytesRead, NULL ) == FALSE )
+ BREAK_WITH_ERROR( "Failed to alloc a buffer!" );
+
+ if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
+ {
+ priv.PrivilegeCount = 1;
+ priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) )
+ AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL );
+
+ CloseHandle( hToken );
+ }
+
+ hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwProcessId );
+ if( !hProcess )
+ BREAK_WITH_ERROR( "Failed to open the target process" );
+
+ hModule = LoadRemoteLibraryR( hProcess, lpBuffer, dwLength, NULL );
+ if( !hModule )
+ BREAK_WITH_ERROR( "Failed to inject the DLL" );
+
+ printf( "[+] Injected the '%s' DLL into process %d.", cpDllFile, dwProcessId );
+
+ WaitForSingleObject( hModule, -1 );
+
+ } while( 0 );
+
+ if( lpBuffer )
+ HeapFree( GetProcessHeap(), 0, lpBuffer );
+
+ if( hProcess )
+ CloseHandle( hProcess );
+
+ return 0;
+}
View
234 src/LoadLibraryR.cpp
@@ -0,0 +1,234 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#include "LoadLibraryR.h"
+#include <stdio.h>
+//===============================================================================================//
+DWORD Rva2Offset( DWORD dwRva, UINT_PTR uiBaseAddress )
+{
+ WORD wIndex = 0;
+ PIMAGE_SECTION_HEADER pSectionHeader = NULL;
+ PIMAGE_NT_HEADERS pNtHeaders = NULL;
+
+ pNtHeaders = (PIMAGE_NT_HEADERS)(uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew);
+
+ pSectionHeader = (PIMAGE_SECTION_HEADER)((UINT_PTR)(&pNtHeaders->OptionalHeader) + pNtHeaders->FileHeader.SizeOfOptionalHeader);
+
+ if( dwRva < pSectionHeader[0].PointerToRawData )
+ return dwRva;
+
+ for( wIndex=0 ; wIndex < pNtHeaders->FileHeader.NumberOfSections ; wIndex++ )
+ {
+ if( dwRva >= pSectionHeader[wIndex].VirtualAddress && dwRva < (pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].SizeOfRawData) )
+ return ( dwRva - pSectionHeader[wIndex].VirtualAddress + pSectionHeader[wIndex].PointerToRawData );
+ }
+
+ return 0;
+}
+//===============================================================================================//
+DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer )
+{
+ UINT_PTR uiBaseAddress = 0;
+ UINT_PTR uiExportDir = 0;
+ UINT_PTR uiNameArray = 0;
+ UINT_PTR uiAddressArray = 0;
+ UINT_PTR uiNameOrdinals = 0;
+ DWORD dwCounter = 0;
+#ifdef _WIN64
+ DWORD dwCompiledArch = 2;
+#else
+ // This will catch Win32 and WinRT.
+ DWORD dwCompiledArch = 1;
+#endif
+
+ uiBaseAddress = (UINT_PTR)lpReflectiveDllBuffer;
+
+ // get the File Offset of the modules NT Header
+ uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
+
+ // currenlty we can only process a PE file which is the same type as the one this fuction has
+ // been compiled as, due to various offset in the PE structures being defined at compile time.
+ if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x010B ) // PE32
+ {
+ if( dwCompiledArch != 1 )
+ return 0;
+ }
+ else if( ((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.Magic == 0x020B ) // PE64
+ {
+ if( dwCompiledArch != 2 )
+ return 0;
+ }
+ else
+ {
+ return 0;
+ }
+
+ // uiNameArray = the address of the modules export directory entry
+ uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
+
+ // get the File Offset of the export directory
+ uiExportDir = uiBaseAddress + Rva2Offset( ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress, uiBaseAddress );
+
+ // get the File Offset for the array of name pointers
+ uiNameArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames, uiBaseAddress );
+
+ // get the File Offset for the array of addresses
+ uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
+
+ // get the File Offset for the array of name ordinals
+ uiNameOrdinals = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals, uiBaseAddress );
+
+ // get a counter for the number of exported functions...
+ dwCounter = ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->NumberOfNames;
+
+ // loop through all the exported functions to find the ReflectiveLoader
+ while( dwCounter-- )
+ {
+ char * cpExportedFunctionName = (char *)(uiBaseAddress + Rva2Offset( DEREF_32( uiNameArray ), uiBaseAddress ));
+
+ if( strstr( cpExportedFunctionName, "ReflectiveLoader" ) != NULL )
+ {
+ // get the File Offset for the array of addresses
+ uiAddressArray = uiBaseAddress + Rva2Offset( ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions, uiBaseAddress );
+
+ // use the functions name ordinal as an index into the array of name pointers
+ uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
+
+ // return the File Offset to the ReflectiveLoader() functions code...
+ return Rva2Offset( DEREF_32( uiAddressArray ), uiBaseAddress );
+ }
+ // get the next exported function name
+ uiNameArray += sizeof(DWORD);
+
+ // get the next exported function name ordinal
+ uiNameOrdinals += sizeof(WORD);
+ }
+
+ return 0;
+}
+//===============================================================================================//
+// Loads a DLL image from memory via its exported ReflectiveLoader function
+HMODULE WINAPI LoadLibraryR( LPVOID lpBuffer, DWORD dwLength )
+{
+ HMODULE hResult = NULL;
+ DWORD dwReflectiveLoaderOffset = 0;
+ DWORD dwOldProtect1 = 0;
+ DWORD dwOldProtect2 = 0;
+ REFLECTIVELOADER pReflectiveLoader = NULL;
+ DLLMAIN pDllMain = NULL;
+
+ if( lpBuffer == NULL || dwLength == 0 )
+ return NULL;
+
+ __try
+ {
+ // check if the library has a ReflectiveLoader...
+ dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );
+ if( dwReflectiveLoaderOffset != 0 )
+ {
+ pReflectiveLoader = (REFLECTIVELOADER)((UINT_PTR)lpBuffer + dwReflectiveLoaderOffset);
+
+ // we must VirtualProtect the buffer to RWX so we can execute the ReflectiveLoader...
+ // this assumes lpBuffer is the base address of the region of pages and dwLength the size of the region
+ if( VirtualProtect( lpBuffer, dwLength, PAGE_EXECUTE_READWRITE, &dwOldProtect1 ) )
+ {
+ // call the librarys ReflectiveLoader...
+ pDllMain = (DLLMAIN)pReflectiveLoader();
+ if( pDllMain != NULL )
+ {
+ // call the loaded librarys DllMain to get its HMODULE
+ if( !pDllMain( NULL, DLL_QUERY_HMODULE, &hResult ) )
+ hResult = NULL;
+ }
+ // revert to the previous protection flags...
+ VirtualProtect( lpBuffer, dwLength, dwOldProtect1, &dwOldProtect2 );
+ }
+ }
+ }
+ __except( EXCEPTION_EXECUTE_HANDLER )
+ {
+ hResult = NULL;
+ }
+
+ return hResult;
+}
+//===============================================================================================//
+// Loads a PE image from memory into the address space of a host process via the image's exported ReflectiveLoader function
+// Note: You must compile whatever you are injecting with REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
+// defined in order to use the correct RDI prototypes.
+// Note: The hProcess handle must have these access rights: PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION |
+// PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ
+// Note: If you are passing in an lpParameter value, if it is a pointer, remember it is for a different address space.
+// Note: This function currently cant inject accross architectures, but only to architectures which are the
+// same as the arch this function is compiled as, e.g. x86->x86 and x64->x64 but not x64->x86 or x86->x64.
+HANDLE WINAPI LoadRemoteLibraryR( HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter )
+{
+ BOOL bSuccess = FALSE;
+ LPVOID lpRemoteLibraryBuffer = NULL;
+ LPTHREAD_START_ROUTINE lpReflectiveLoader = NULL;
+ HANDLE hThread = NULL;
+ DWORD dwReflectiveLoaderOffset = 0;
+ DWORD dwThreadId = 0;
+
+ __try
+ {
+ do
+ {
+ if( !hProcess || !lpBuffer || !dwLength )
+ break;
+
+ // check if the library has a ReflectiveLoader...
+ dwReflectiveLoaderOffset = GetReflectiveLoaderOffset( lpBuffer );
+ if( !dwReflectiveLoaderOffset )
+ break;
+
+ // alloc memory (RWX) in the host process for the image...
+ lpRemoteLibraryBuffer = VirtualAllocEx( hProcess, NULL, dwLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+ if( !lpRemoteLibraryBuffer )
+ break;
+
+ // write the image into the host process...
+ if( !WriteProcessMemory( hProcess, lpRemoteLibraryBuffer, lpBuffer, dwLength, NULL ) )
+ break;
+
+ // add the offset to ReflectiveLoader() to the remote library address...
+ lpReflectiveLoader = (LPTHREAD_START_ROUTINE)( (ULONG_PTR)lpRemoteLibraryBuffer + dwReflectiveLoaderOffset );
+
+ // create a remote thread in the host process to call the ReflectiveLoader!
+ hThread = CreateRemoteThread( hProcess, NULL, 1024*1024, lpReflectiveLoader, lpParameter, (DWORD)NULL, &dwThreadId );
+
+ } while( 0 );
+
+ }
+ __except( EXCEPTION_EXECUTE_HANDLER )
+ {
+ hThread = NULL;
+ }
+
+ return hThread;
+}
+//===============================================================================================//
View
42 src/LoadLibraryR.h
@@ -0,0 +1,42 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#ifndef _REFLECTIVEDLLINJECTION_LOADLIBRARYR_H
+#define _REFLECTIVEDLLINJECTION_LOADLIBRARYR_H
+//===============================================================================================//
+#include "ReflectiveDLLInjection.h"
+
+
+DWORD GetReflectiveLoaderOffset( VOID * lpReflectiveDllBuffer );
+
+HMODULE WINAPI LoadLibraryR( LPVOID lpBuffer, DWORD dwLength );
+
+HANDLE WINAPI LoadRemoteLibraryR( HANDLE hProcess, LPVOID lpBuffer, DWORD dwLength, LPVOID lpParameter );
+
+//===============================================================================================//
+#endif
+//===============================================================================================//
View
53 src/ReflectiveDLLInjection.h
@@ -0,0 +1,53 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
+#define _REFLECTIVEDLLINJECTION_REFLECTIVEDLLINJECTION_H
+//===============================================================================================//
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+// we declare some common stuff in here...
+
+#define DLL_METASPLOIT_ATTACH 4
+#define DLL_METASPLOIT_DETACH 5
+#define DLL_QUERY_HMODULE 6
+
+#define DEREF( name )*(UINT_PTR *)(name)
+#define DEREF_64( name )*(DWORD64 *)(name)
+#define DEREF_32( name )*(DWORD *)(name)
+#define DEREF_16( name )*(WORD *)(name)
+#define DEREF_8( name )*(BYTE *)(name)
+
+typedef DWORD (WINAPI * REFLECTIVELOADER)( VOID );
+typedef BOOL (WINAPI * DLLMAIN)( HINSTANCE, DWORD, LPVOID );
+
+#define DLLEXPORT __declspec( dllexport )
+
+//===============================================================================================//
+#endif
+//===============================================================================================//
View
496 src/ReflectiveLoader.cpp
@@ -0,0 +1,496 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#include "ReflectiveLoader.h"
+//===============================================================================================//
+// Our loader will set this to a pseudo correct HINSTANCE/HMODULE value
+HINSTANCE hAppInstance = NULL;
+//===============================================================================================//
+#pragma intrinsic( _ReturnAddress )
+// This function can not be inlined by the compiler or we will not get the address we expect. Ideally
+// this code will be compiled with the /O2 and /Ob1 switches. Bonus points if we could take advantage of
+// RIP relative addressing in this instance but I dont believe we can do so with the compiler intrinsics
+// available (and no inline asm available under x64).
+__declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)_ReturnAddress(); }
+//===============================================================================================//
+
+// Note 1: If you want to have your own DllMain, define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN,
+// otherwise the DllMain at the end of this file will be used.
+
+// Note 2: If you are injecting the DLL via LoadRemoteLibraryR, define REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR,
+// otherwise it is assumed you are calling the ReflectiveLoader via a stub.
+
+// This is our position independent reflective DLL loader/injector
+#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
+DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( LPVOID lpParameter )
+#else
+DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader( VOID )
+#endif
+{
+ // the functions we need
+ LOADLIBRARYA pLoadLibraryA = NULL;
+ GETPROCADDRESS pGetProcAddress = NULL;
+ VIRTUALALLOC pVirtualAlloc = NULL;
+ NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;
+
+ USHORT usCounter;
+
+ // the initial location of this image in memory
+ ULONG_PTR uiLibraryAddress;
+ // the kernels base address and later this images newly loaded base address
+ ULONG_PTR uiBaseAddress;
+
+ // variables for processing the kernels export table
+ ULONG_PTR uiAddressArray;
+ ULONG_PTR uiNameArray;
+ ULONG_PTR uiExportDir;
+ ULONG_PTR uiNameOrdinals;
+ DWORD dwHashValue;
+
+ // variables for loading this image
+ ULONG_PTR uiHeaderValue;
+ ULONG_PTR uiValueA;
+ ULONG_PTR uiValueB;
+ ULONG_PTR uiValueC;
+ ULONG_PTR uiValueD;
+ ULONG_PTR uiValueE;
+
+ // STEP 0: calculate our images current base address
+
+ // we will start searching backwards from our callers return address.
+ uiLibraryAddress = caller();
+
+ // loop through memory backwards searching for our images base address
+ // we dont need SEH style search as we shouldnt generate any access violations with this
+ while( TRUE )
+ {
+ if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
+ {
+ uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
+ // some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
+ // we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
+ if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
+ {
+ uiHeaderValue += uiLibraryAddress;
+ // break if we have found a valid MZ/PE header
+ if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
+ break;
+ }
+ }
+ uiLibraryAddress--;
+ }
+
+ // STEP 1: process the kernels exports for the functions our loader needs...
+
+ // get the Process Enviroment Block
+#ifdef WIN_X64
+ uiBaseAddress = __readgsqword( 0x60 );
+#else
+#ifdef WIN_X86
+ uiBaseAddress = __readfsdword( 0x30 );
+#else WIN_ARM
+ //uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
+#endif
+#endif
+
+ // get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
+ uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;
+
+ // get the first entry of the InMemoryOrder module list
+ uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
+ while( uiValueA )
+ {
+ // get pointer to current modules name (unicode string)
+ uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
+ // set bCounter to the length for the loop
+ usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
+ // clear uiValueC which will store the hash of the module name
+ uiValueC = 0;
+
+ // compute the hash of the module name...
+ do
+ {
+ uiValueC = ror( (DWORD)uiValueC );
+ // normalize to uppercase if the madule name is in lowercase
+ if( *((BYTE *)uiValueB) >= 'a' )
+ uiValueC += *((BYTE *)uiValueB) - 0x20;
+ else
+ uiValueC += *((BYTE *)uiValueB);
+ uiValueB++;
+ } while( --usCounter );
+
+ // compare the hash with that of kernel32.dll
+ if( (DWORD)uiValueC == KERNEL32DLL_HASH )
+ {
+ // get this modules base address
+ uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
+
+ // get the VA of the modules NT Header
+ uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
+
+ // uiNameArray = the address of the modules export directory entry
+ uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
+
+ // get the VA of the export directory
+ uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
+
+ // get the VA for the array of name pointers
+ uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
+
+ // get the VA for the array of name ordinals
+ uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
+
+ usCounter = 3;
+
+ // loop while we still have imports to find
+ while( usCounter > 0 )
+ {
+ // compute the hash values for this function name
+ dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
+
+ // if we have found a function we want we get its virtual address
+ if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH )
+ {
+ // get the VA for the array of addresses
+ uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
+
+ // use this functions name ordinal as an index into the array of name pointers
+ uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
+
+ // store this functions VA
+ if( dwHashValue == LOADLIBRARYA_HASH )
+ pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
+ else if( dwHashValue == GETPROCADDRESS_HASH )
+ pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
+ else if( dwHashValue == VIRTUALALLOC_HASH )
+ pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
+
+ // decrement our counter
+ usCounter--;
+ }
+
+ // get the next exported function name
+ uiNameArray += sizeof(DWORD);
+
+ // get the next exported function name ordinal
+ uiNameOrdinals += sizeof(WORD);
+ }
+ }
+ else if( (DWORD)uiValueC == NTDLLDLL_HASH )
+ {
+ // get this modules base address
+ uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
+
+ // get the VA of the modules NT Header
+ uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;
+
+ // uiNameArray = the address of the modules export directory entry
+ uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
+
+ // get the VA of the export directory
+ uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
+
+ // get the VA for the array of name pointers
+ uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
+
+ // get the VA for the array of name ordinals
+ uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );
+
+ usCounter = 1;
+
+ // loop while we still have imports to find
+ while( usCounter > 0 )
+ {
+ // compute the hash values for this function name
+ dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );
+
+ // if we have found a function we want we get its virtual address
+ if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
+ {
+ // get the VA for the array of addresses
+ uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
+
+ // use this functions name ordinal as an index into the array of name pointers
+ uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );
+
+ // store this functions VA
+ if( dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH )
+ pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)( uiBaseAddress + DEREF_32( uiAddressArray ) );
+
+ // decrement our counter
+ usCounter--;
+ }
+
+ // get the next exported function name
+ uiNameArray += sizeof(DWORD);
+
+ // get the next exported function name ordinal
+ uiNameOrdinals += sizeof(WORD);
+ }
+ }
+
+ // we stop searching when we have found everything we need.
+ if( pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache )
+ break;
+
+ // get the next entry
+ uiValueA = DEREF( uiValueA );
+ }
+
+ // STEP 2: load our image into a new permanent location in memory...
+
+ // get the VA of the NT Header for the PE to be loaded
+ uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
+
+ // allocate all the memory for the DLL to be loaded into. we can load at any address because we will
+ // relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
+ uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+
+ // we must now copy over the headers
+ uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
+ uiValueB = uiLibraryAddress;
+ uiValueC = uiBaseAddress;
+
+ while( uiValueA-- )
+ *(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;
+
+ // STEP 3: load in all of our sections...
+
+ // uiValueA = the VA of the first section
+ uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );
+
+ // itterate through all sections, loading them into memory.
+ uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
+ while( uiValueE-- )
+ {
+ // uiValueB is the VA for this section
+ uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );
+
+ // uiValueC if the VA for this sections data
+ uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );
+
+ // copy the section over
+ uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
+
+ while( uiValueD-- )
+ *(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;
+
+ // get the VA of the next section
+ uiValueA += sizeof( IMAGE_SECTION_HEADER );
+ }
+
+ // STEP 4: process our images import table...
+
+ // uiValueB = the address of the import directory
+ uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
+
+ // we assume their is an import table to process
+ // uiValueC is the first entry in the import table
+ uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
+
+ // itterate through all imports
+ while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name )
+ {
+ // use LoadLibraryA to load the imported module into memory
+ uiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );
+
+ // uiValueD = VA of the OriginalFirstThunk
+ uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
+
+ // uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
+ uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );
+
+ // itterate through all imported functions, importing by ordinal if no name present
+ while( DEREF(uiValueA) )
+ {
+ // sanity check uiValueD as some compilers only import by FirstThunk
+ if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
+ {
+ // get the VA of the modules NT Header
+ uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
+
+ // uiNameArray = the address of the modules export directory entry
+ uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];
+
+ // get the VA of the export directory
+ uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );
+
+ // get the VA for the array of addresses
+ uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );
+
+ // use the import ordinal (- export ordinal base) as an index into the array of addresses
+ uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );
+
+ // patch in the address for this imported function
+ DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
+ }
+ else
+ {
+ // get the VA of this functions import by name struct
+ uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
+
+ // use GetProcAddress and patch in the address for this imported function
+ DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );
+ }
+ // get the next imported function
+ uiValueA += sizeof( ULONG_PTR );
+ if( uiValueD )
+ uiValueD += sizeof( ULONG_PTR );
+ }
+
+ // get the next import
+ uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
+ }
+
+ // STEP 5: process all of our images relocations...
+
+ // calculate the base address delta and perform relocations (even if we load at desired image base)
+ uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
+
+ // uiValueB = the address of the relocation directory
+ uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];
+
+ // check if their are any relocations present
+ if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
+ {
+ // uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
+ uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );
+
+ // and we itterate through all entries...
+ while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
+ {
+ // uiValueA = the VA for this relocation block
+ uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );
+
+ // uiValueB = number of entries in this relocation block
+ uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );
+
+ // uiValueD is now the first entry in the current relocation block
+ uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);
+
+ // we itterate through all the entries in the current block...
+ while( uiValueB-- )
+ {
+ // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
+ // we dont use a switch statement to avoid the compiler building a jump table
+ // which would not be very position independent!
+ if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
+ *(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
+ else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
+ *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
+#ifdef WIN_ARM
+ // Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.
+ else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T )
+ {
+ register DWORD dwInstruction;
+ register DWORD dwAddress;
+ register WORD wImm;
+ // get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)
+ dwInstruction = *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) );
+ // flip the words to get the instruction as expected
+ dwInstruction = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
+ // sanity chack we are processing a MOV instruction...
+ if( (dwInstruction & ARM_MOV_MASK) == ARM_MOVT )
+ {
+ // pull out the encoded 16bit value (the high portion of the address-to-relocate)
+ wImm = (WORD)( dwInstruction & 0x000000FF);
+ wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);
+ wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);
+ wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);
+ // apply the relocation to the target address
+ dwAddress = ( (WORD)HIWORD(uiLibraryAddress) + wImm ) & 0xFFFF;
+ // now create a new instruction with the same opcode and register param.
+ dwInstruction = (DWORD)( dwInstruction & ARM_MOV_MASK2 );
+ // patch in the relocated address...
+ dwInstruction |= (DWORD)(dwAddress & 0x00FF);
+ dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;
+ dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;
+ dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;
+ // now flip the instructions words and patch back into the code...
+ *(DWORD *)( uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD) ) = MAKELONG( HIWORD(dwInstruction), LOWORD(dwInstruction) );
+ }
+ }
+#endif
+ else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
+ *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
+ else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
+ *(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
+
+ // get the next entry in the current relocation block
+ uiValueD += sizeof( IMAGE_RELOC );
+ }
+
+ // get the next entry in the relocation directory
+ uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
+ }
+ }
+
+ // STEP 6: call our images entry point
+
+ // uiValueA = the VA of our newly loaded DLL/EXE's entry point
+ uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );
+
+ // We must flush the instruction cache to avoid stale code being used which was updated by our relocation processing.
+ pNtFlushInstructionCache( (HANDLE)-1, NULL, 0 );
+
+ // call our respective entry point, fudging our hInstance value
+#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
+ // if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
+ ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
+#else
+ // if we are injecting an DLL via a stub we call DllMain with no parameter
+ ((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
+#endif
+
+ // STEP 8: return our new entry point address so whatever called us can call DllMain() if needed.
+ return uiValueA;
+}
+//===============================================================================================//
+#ifndef REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
+
+BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
+{
+ BOOL bReturnValue = TRUE;
+ switch( dwReason )
+ {
+ case DLL_QUERY_HMODULE:
+ if( lpReserved != NULL )
+ *(HMODULE *)lpReserved = hAppInstance;
+ break;
+ case DLL_PROCESS_ATTACH:
+ hAppInstance = hinstDLL;
+ break;
+ case DLL_PROCESS_DETACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ break;
+ }
+ return bReturnValue;
+}
+
+#endif
+//===============================================================================================//
View
203 src/ReflectiveLoader.h
@@ -0,0 +1,203 @@
+//===============================================================================================//
+// Copyright (c) 2012, Stephen Fewer of Harmony Security (www.harmonysecurity.com)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are permitted
+// provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// * Redistributions in binary form must reproduce the above copyright notice, this list of
+// conditions and the following disclaimer in the documentation and/or other materials provided
+// with the distribution.
+//
+// * Neither the name of Harmony Security nor the names of its contributors may be used to
+// endorse or promote products derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//===============================================================================================//
+#ifndef _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
+#define _REFLECTIVEDLLINJECTION_REFLECTIVELOADER_H
+//===============================================================================================//
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+//#include <Winsock2.h>
+#include <intrin.h>
+
+#include "ReflectiveDLLInjection.h"
+
+typedef HMODULE (WINAPI * LOADLIBRARYA)( LPCSTR );
+typedef FARPROC (WINAPI * GETPROCADDRESS)( HMODULE, LPCSTR );
+typedef LPVOID (WINAPI * VIRTUALALLOC)( LPVOID, SIZE_T, DWORD, DWORD );
+typedef DWORD (NTAPI * NTFLUSHINSTRUCTIONCACHE)( HANDLE, PVOID, ULONG );
+
+#define KERNEL32DLL_HASH 0x6A4ABC5B
+#define NTDLLDLL_HASH 0x3CFA685D
+
+#define LOADLIBRARYA_HASH 0xEC0E4E8E
+#define GETPROCADDRESS_HASH 0x7C0DFCAA
+#define VIRTUALALLOC_HASH 0x91AFCA54
+#define NTFLUSHINSTRUCTIONCACHE_HASH 0x534C0AB8
+
+#define IMAGE_REL_BASED_ARM_MOV32A 5
+#define IMAGE_REL_BASED_ARM_MOV32T 7
+
+#define ARM_MOV_MASK (DWORD)(0xFBF08000)
+#define ARM_MOV_MASK2 (DWORD)(0xFBF08F00)
+#define ARM_MOVW 0xF2400000
+#define ARM_MOVT 0xF2C00000
+
+#define HASH_KEY 13
+//===============================================================================================//
+#pragma intrinsic( _rotr )
+
+__forceinline DWORD ror( DWORD d )
+{
+ return _rotr( d, HASH_KEY );
+}
+
+__forceinline DWORD hash( char * c )
+{
+ register DWORD h = 0;
+ do
+ {
+ h = ror( h );
+ h += *c;
+ } while( *++c );
+
+ return h;
+}
+//===============================================================================================//
+typedef struct _UNICODE_STR
+{
+ USHORT Length;
+ USHORT MaximumLength;
+ PWSTR pBuffer;
+} UNICODE_STR, *PUNICODE_STR;
+
+// WinDbg> dt -v ntdll!_LDR_DATA_TABLE_ENTRY
+//__declspec( align(8) )
+typedef struct _LDR_DATA_TABLE_ENTRY
+{
+ //LIST_ENTRY InLoadOrderLinks; // As we search from PPEB_LDR_DATA->InMemoryOrderModuleList we dont use the first entry.
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ PVOID DllBase;
+ PVOID EntryPoint;
+ ULONG SizeOfImage;
+ UNICODE_STR FullDllName;
+ UNICODE_STR BaseDllName;
+ ULONG Flags;
+ SHORT LoadCount;
+ SHORT TlsIndex;
+ LIST_ENTRY HashTableEntry;
+ ULONG TimeDateStamp;
+} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
+
+// WinDbg> dt -v ntdll!_PEB_LDR_DATA
+typedef struct _PEB_LDR_DATA //, 7 elements, 0x28 bytes
+{
+ DWORD dwLength;
+ DWORD dwInitialized;
+ LPVOID lpSsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ LPVOID lpEntryInProgress;
+} PEB_LDR_DATA, * PPEB_LDR_DATA;
+
+// WinDbg> dt -v ntdll!_PEB_FREE_BLOCK
+typedef struct _PEB_FREE_BLOCK // 2 elements, 0x8 bytes
+{
+ struct _PEB_FREE_BLOCK * pNext;
+ DWORD dwSize;
+} PEB_FREE_BLOCK, * PPEB_FREE_BLOCK;
+
+// struct _PEB is defined in Winternl.h but it is incomplete
+// WinDbg> dt -v ntdll!_PEB
+typedef struct __PEB // 65 elements, 0x210 bytes
+{
+ BYTE bInheritedAddressSpace;
+ BYTE bReadImageFileExecOptions;
+ BYTE bBeingDebugged;
+ BYTE bSpareBool;
+ LPVOID lpMutant;
+ LPVOID lpImageBaseAddress;
+ PPEB_LDR_DATA pLdr;
+ LPVOID lpProcessParameters;
+ LPVOID lpSubSystemData;
+ LPVOID lpProcessHeap;
+ PRTL_CRITICAL_SECTION pFastPebLock;
+ LPVOID lpFastPebLockRoutine;
+ LPVOID lpFastPebUnlockRoutine;
+ DWORD dwEnvironmentUpdateCount;
+ LPVOID lpKernelCallbackTable;
+ DWORD dwSystemReserved;
+ DWORD dwAtlThunkSListPtr32;
+ PPEB_FREE_BLOCK pFreeList;
+ DWORD dwTlsExpansionCounter;
+ LPVOID lpTlsBitmap;
+ DWORD dwTlsBitmapBits[2];
+ LPVOID lpReadOnlySharedMemoryBase;
+ LPVOID lpReadOnlySharedMemoryHeap;
+ LPVOID lpReadOnlyStaticServerData;
+ LPVOID lpAnsiCodePageData;
+ LPVOID lpOemCodePageData;
+ LPVOID lpUnicodeCaseTableData;
+ DWORD dwNumberOfProcessors;
+ DWORD dwNtGlobalFlag;
+ LARGE_INTEGER liCriticalSectionTimeout;
+ DWORD dwHeapSegmentReserve;
+ DWORD dwHeapSegmentCommit;
+ DWORD dwHeapDeCommitTotalFreeThreshold;
+ DWORD dwHeapDeCommitFreeBlockThreshold;
+ DWORD dwNumberOfHeaps;
+ DWORD dwMaximumNumberOfHeaps;
+ LPVOID lpProcessHeaps;
+ LPVOID lpGdiSharedHandleTable;
+ LPVOID lpProcessStarterHelper;
+ DWORD dwGdiDCAttributeList;
+ LPVOID lpLoaderLock;
+ DWORD dwOSMajorVersion;
+ DWORD dwOSMinorVersion;
+ WORD wOSBuildNumber;
+ WORD wOSCSDVersion;
+ DWORD dwOSPlatformId;
+ DWORD dwImageSubsystem;
+ DWORD dwImageSubsystemMajorVersion;
+ DWORD dwImageSubsystemMinorVersion;
+ DWORD dwImageProcessAffinityMask;
+ DWORD dwGdiHandleBuffer[34];
+ LPVOID lpPostProcessInitRoutine;
+ LPVOID lpTlsExpansionBitmap;
+ DWORD dwTlsExpansionBitmapBits[32];
+ DWORD dwSessionId;
+ ULARGE_INTEGER liAppCompatFlags;
+ ULARGE_INTEGER liAppCompatFlagsUser;
+ LPVOID lppShimData;
+ LPVOID lpAppCompatInfo;
+ UNICODE_STR usCSDVersion;
+ LPVOID lpActivationContextData;
+ LPVOID lpProcessAssemblyStorageMap;
+ LPVOID lpSystemDefaultActivationContextData;
+ LPVOID lpSystemAssemblyStorageMap;
+ DWORD dwMinimumStackCommit;
+} _PEB, * _PPEB;
+
+typedef struct
+{
+ WORD offset:12;
+ WORD type:4;
+} IMAGE_RELOC, *PIMAGE_RELOC;
+//===============================================================================================//
+#endif
+//===============================================================================================//
View
230 src/dllInject.vcproj
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="dllInjector"
+ ProjectGUID="{DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}"
+ RootNamespace="vminject2"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories=""
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\AllocWriteDLL.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\dllinject.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\ExecThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\LoadLibraryR.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\AllocWriteDLL.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ExecThread.h"
+ >
+ </File>
+ <File
+ RelativePath=".\LoadLibraryR.h"
+ >
+ </File>
+ <File
+ RelativePath=".\ReflectiveDLLInjection.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath="..\..\..\..\..\Desktop\vminject\vminjector32.dll"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\..\..\Desktop\vminject\vminjector64.dll"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
View
264 src/dllInject.vcxproj
@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release64|Win32">
+ <Configuration>Release64</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release64|x64">
+ <Configuration>Release64</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>dllInjector</ProjectName>
+ <ProjectGuid>{DF20DC75-A46A-4D25-9BFE-5BCA5D3B7847}</ProjectGuid>
+ <RootNamespace>vminject2</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release64|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release64|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release64|x64'">$(SolutionDir)$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release64|x64'">$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release64|x64'">false</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release64|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release64|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release64|x64'" />
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)-$(PlatformShortName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName)-$(Platform)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release64|Win32'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release64|x64'">
+ <ClCompile>
+ <Optimization>MaxSpeed</Optimization>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="AllocWriteDLL.cpp" />
+ <ClCompile Include="dllinject.cpp" />
+ <ClCompile Include="ExecThread.cpp" />
+ <ClCompile Include="LoadLibraryR.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AllocWriteDLL.h" />
+ <ClInclude Include="ExecThread.h" />
+ <ClInclude Include="LoadLibraryR.h" />
+ <ClInclude Include="ReflectiveDLLInjection.h" />
+ <ClInclude Include="resource.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="dllInjector.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
View
53 src/dllInject.vcxproj.filters
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="AllocWriteDLL.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllinject.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ExecThread.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="LoadLibraryR.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="AllocWriteDLL.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ExecThread.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="LoadLibraryR.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ReflectiveDLLInjection.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="dllInjector.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
View
BIN  src/dllInjector.aps
Binary file not shown
View
BIN  src/dllInjector.rc
Binary file not shown
View
539 src/dllinject.cpp
@@ -2,374 +2,149 @@
dllinjector -
brad.antoniewicz@foundstone.com
- This tool was initially written to support vminjector32.dll
- and vminector64.dll. It was later extended to support
- injecting DLLs on all Windows versions using a variety
- of methods.
+ This tool aims to implement various DLL injection
+ techniques. For more information on DLL injection
+ see http://blog.opensecurityresearch.com
+
+ This was built using Microsoft Visual Studio 2010
+
+ dllInjector currently supports using:
- vminjector credit:
- https://github.com/batistam/VMInjector
+ DLL Memory Allocation and Execution Techniques:
+ 1. Allocate memory for DLL Path and use LoadLibraryA().
+ 2. Allocate memory for full DLL and jump to the DLL's
+ entry point.
+ DLL Injection Techniques
+ 1. CreateRemoteThread()
+ 2. NtCreateThreadEx()
+ 3. Suspend, Inject, and Resume
+ 4. RtlCreateUserThread()
Todo:
1. Implement SetWindowsHookEx() Method
http://www.kdsbest.com/?p=179
2. Implement QueueUserAPC() Method
http://webcache.googleusercontent.com/search?q=cache:G8i5oxOWbDMJ:www.hackforums.net/archive/index.php/thread-2442150.html+&cd=3&hl=en&ct=clnk&gl=us&client=firefox-a
- 3. Implement RtlCreateUserThread() Method
- http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html?showComment=1338375764336#c4138436235159645886
- http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Executable%20Images/RtlCreateUserThread.html
- 4. Implement PrivEscalation as per:
+ 3. Implement PrivEscalation as per:
https://github.com/rapid7/metasploit-framework/tree/master/external/source/meterpreter/source/extensions/priv/server/elevate
/metasploit/msf3/external/source/meterpreter/source/extensions/priv/server/elevate
+ Credits:
+ vminjector - https://github.com/batistam/VMInjector
+ ReflectiveDLLInjection - https://github.com/stephenfewer/ReflectiveDLLInjection
*/
+#include <stdlib.h>
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <dos.h>
+#include "ExecThread.h"
+#include "AllocWriteDLL.h"
+#pragma comment(lib,"Advapi32.lib")
-#define VERSION 0.1
+#define VERSION 0.2
#define BUFSIZE 512
-struct NtCreateThreadExBuffer {
- ULONG Size;
- ULONG Unknown1;
- ULONG Unknown2;
- PULONG Unknown3;
- ULONG Unknown4;
- ULONG Unknown5;
- ULONG Unknown6;
- PULONG Unknown7;
- ULONG Unknown8;
- };
-
-typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) (
- OUT PHANDLE hThread,
- IN ACCESS_MASK DesiredAccess,
- IN LPVOID ObjectAttributes,
- IN HANDLE ProcessHandle,
- IN LPTHREAD_START_ROUTINE lpStartAddress,
- IN LPVOID lpParameter,
- IN BOOL CreateSuspended,
- IN ULONG StackZeroBits,
- IN ULONG SizeOfStackCommit,
- IN ULONG SizeOfStackReserve,
- OUT LPVOID lpBytesBuffer
-);
-
-
-void suspendInjectResume(HANDLE hHandle, LPVOID loadLibAddr, LPVOID dllPathAddr) {
- /*
- This is a mixture from the following sites:
-
- http://syprog.blogspot.com/2012/05/createremotethread-bypass-windows.html
- http://www.kdsbest.com/?p=159
-
- */
-
- HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
- HANDLE hSnapshot2 = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
- HANDLE thread = NULL;
- THREADENTRY32 te;
- THREADENTRY32 te2;
- CONTEXT ctx;
-
- DWORD firstThread = NULL;
- HANDLE targetThread = NULL;
-
- LPVOID scAddr;
-
- te.dwSize = sizeof(THREADENTRY32);
- te2.dwSize = sizeof(THREADENTRY32);
- ctx.ContextFlags = CONTEXT_FULL;
-
- int i;
-
- unsigned char sc[] = {
- // Push all flags
- 0x9C,
- // Push all register
- 0x60,
- // Push 3,4,5,6 (dllPathAddr)
- 0x68, 0xAA, 0xAA, 0xAA, 0xAA,
- // Mov eax, 8,9,10, 11 (loadLibAddr)
- 0xB8, 0xBB, 0xBB, 0xBB, 0xBB,
- // Call eax
- 0xFF, 0xD0,
- // Pop all register
- 0x61,
- // Pop all flags
- 0x9D,
- // Ret
- 0xC3
- };
-
-
- sc[3] = ((unsigned int) dllPathAddr & 0xFF);
- sc[4] = (((unsigned int) dllPathAddr >> 8 )& 0xFF);
- sc[5] = (((unsigned int) dllPathAddr >> 16 )& 0xFF);
- sc[6] = (((unsigned int) dllPathAddr >> 24 )& 0xFF);
-
- sc[8] = ((unsigned int) loadLibAddr & 0xFF);
- sc[9] = (((unsigned int) loadLibAddr >> 8 )& 0xFF);
- sc[10] = (((unsigned int) loadLibAddr >> 16 )& 0xFF);
- sc[11] = (((unsigned int) loadLibAddr >> 24 )& 0xFF);
-
-
-
- // Suspend Threads
- if(Thread32First(hSnapshot, &te)) {
- do {
- if(te.th32OwnerProcessID == GetProcessId(hHandle)) {
- if ( firstThread == NULL )
- firstThread = te.th32ThreadID;
- thread = OpenThread(THREAD_ALL_ACCESS | THREAD_GET_CONTEXT, FALSE, te.th32ThreadID);
- if(thread != NULL) {
- printf("\t[+] Suspending Thread 0x%08x\n", te.th32ThreadID);
- SuspendThread(thread);
- CloseHandle(thread);
- } else {
- printf("\t[+] Could not open thread!\n");
- }
- }
- } while(Thread32Next(hSnapshot, &te));
- } else {
- printf("\t[+] Could not Thread32First! [%d]\n", GetLastError());
- CloseHandle(hSnapshot);
- exit(-1);
- }
- CloseHandle(hSnapshot);
-
- printf("\t[+] Our Launcher Code:\n\t");
- for (i=0; i<17; i++)
- printf("%02x ",sc[i]);
- printf("\n");
- // Get/Save EIP, Inject
- printf("\t[+] Targeting Thread 0x%08x\n",firstThread);
- targetThread = OpenThread(THREAD_ALL_ACCESS, FALSE, firstThread);
- if (GetThreadContext(targetThread, &ctx) == 0)
- printf("[!] GetThreadContext Failed!\n");
- printf("\t[+] Current Registers: \n\t\tEIP[0x%08x] ESP[0x%08x]\n", ctx.Eip, ctx.Esp);
-
- printf("\t[+] Saving EIP for our return\n");
- ctx.Esp -= sizeof(unsigned int);
- WriteProcessMemory(hHandle, (LPVOID)ctx.Esp, (LPCVOID)&ctx.Eip, sizeof(unsigned int), NULL);
- printf("\t\tEIP[0x%08x] ESP[0x%08x] EBP[0x%08x]\n", ctx.Eip, ctx.Esp, ctx.Ebp);
-
- scAddr = VirtualAllocEx(hHandle, NULL, 17, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
- printf("\t[+] Allocating 17 bytes for our Launcher Code [0x%08x][%d]\n", scAddr, GetLastError());
-
- printf ("\t[+] Writing Launcher Code into targetThread [%d]\n", WriteProcessMemory(hHandle, scAddr, (LPCVOID)sc, 17, NULL));
-
- printf("\t[+] Setting EIP to LauncherCode\n");
- ctx.Eip = (DWORD)scAddr;