#include #include "symbols.h" #include "rva.h" #include "tea.h" #include "macro.h" #pragma section(".peexe32", read, write, execute) typedef short relocation_entry; /** * !_configuration **/ typedef struct _configuration { ULONG64 dwRelocSize; ULONG64 lpRelocAddress; ULONG64 _key0; ULONG64 _key1; ULONG64 _baseAddress; BYTE decrypted; } CONFIGURATION; __declspec(allocate(".peexe32")) CONFIGURATION exe_configuration = { 0xBABECAFEBAD00021, 0xBABECAFEBAD00020, 0xBABECAFEBAD00010, 0xBABECAFEBAD00011, 0xBABECAFEBAD00100, FALSE }; //__declspec(allocate(".peexe32")) //VirtualProtect_ptr _exe_VirtualProtect; //__declspec(allocate(".peexe32")) //VirtualAlloc_ptr _exe_VirtualAlloc; typedef struct base_relocation_block { DWORD PageRVA; DWORD BlockSize; } base_relocation_block_t; typedef struct base_relocation_entry { WORD offset : 12; WORD type : 4; } base_relocation_entry_t; #define relocation_block_t base_relocation_block_t #define relocation_entry_t base_relocation_entry_t #ifdef _BUILD32 extern "C" IMAGE_DOS_HEADER __ImageBase; typedef SIZE_T (WINAPI *VirtualQuery_ptr)(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); #pragma code_seg(".peexe32") static LPVOID rva2addr(PIMAGE_DOS_HEADER pImageDosHeader, PIMAGE_NT_HEADERS32 pImageNtHeaders32, LPVOID lpAddress) { ULONG64 dwImageDosHeader = (ULONG) pImageDosHeader; // new base address! ULONG64 dwAddress = (ULONG) lpAddress; // rva if (dwAddress > pImageNtHeaders32->OptionalHeader.ImageBase) dwAddress -= pImageNtHeaders32->OptionalHeader.ImageBase; dwAddress += dwImageDosHeader; return (LPVOID) dwAddress; } #pragma code_seg(".peexe32") void reloc_entry_get(relocation_entry *entry, short *type, long *offset) { *type = ((*entry & 0xf000) >> 12); *offset = (*entry & 0x0fff); return; } #pragma code_seg(".peexe32") static void Reloc_Process_Entry() { } #pragma code_seg(".peexe32") base_relocation_block_t* next_page(base_relocation_block_t *page) { return CALC_OFFSET(base_relocation_block_t *, page, page->BlockSize); } #pragma code_seg(".peexe32") static void Reloc_Process(LPVOID pModule, PIMAGE_NT_HEADERS32 pImageNtHeader, PIMAGE_SECTION_HEADER pSectionPointer, LPVOID lpRelocAddress, DWORD dwRelocSize, PIMAGE_SECTION_HEADER pTextPointer) { if (dwRelocSize == 0 || lpRelocAddress == NULL) { return; // no reloc table here! } //DWORD ImageBase = (DWORD) exe_configuration._baseAddress; DWORD delta = (DWORD) exe_configuration._baseAddress - (DWORD) pModule; base_relocation_block_t *relocation_page = (base_relocation_block_t *) lpRelocAddress; #define RELOC_IN_RANGE(page, section) (page->PageRVA >= section->VirtualAddress) && (page->PageRVA <= (section->VirtualAddress + section->Misc.VirtualSize)) // for each page! while(relocation_page->BlockSize > 0) { if (RELOC_IN_RANGE(relocation_page, pSectionPointer)) { // ok.. we can process this page! int BlockSize = relocation_page->BlockSize - 8; relocation_entry *entries = CALC_OFFSET(relocation_entry *, relocation_page, 8); while(BlockSize > 0) { short type; long offset; reloc_entry_get(entries, &type, &offset); ULONG *ptr = CALC_OFFSET(PULONG, pModule, offset + relocation_page->PageRVA); //ULONG value = *ptr; if (type == IMAGE_REL_BASED_HIGHLOW) { *ptr += delta; } else if (type == IMAGE_REL_BASED_ABSOLUTE) { // break! break; } entries++; BlockSize -= 2; } relocation_page = next_page(relocation_page); } } } #pragma code_seg(".peexe32") static void __memcpy(char *dst, char *src, int size) { while(size-- > 0) { *dst++=*src++; } } typedef void (tea_decrypt_ptr)(uint32_t* v, uint32_t* k); #pragma code_seg(".peexe32") static tea_decrypt_ptr *load_decrypt() { char *decrypt = (char *)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE); void *start = static_cast(&tea_decrypt); void *end = static_cast(&tea_decrypt_end_marker); int size = static_cast((int) end - (int) start); char *src = static_cast(start); char *dst = decrypt; while(size-- > 0) { *dst ++ = (*src++ ^ 0x66); } return (tea_decrypt_ptr *) decrypt; } #pragma code_seg(".peexe32") static BOOL WINAPI decrypt(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER) hinstDLL; PIMAGE_NT_HEADERS32 pImageNtHeaders32 = CALC_OFFSET(PIMAGE_NT_HEADERS32, pImageDosHeader, pImageDosHeader->e_lfanew); tea_decrypt_ptr *decrypt = load_decrypt(); if (pImageNtHeaders32->Signature != IMAGE_NT_SIGNATURE) { // I'm invalid file? return FALSE; } //short NumberOfSections = pImageNtHeaders32->FileHeader.NumberOfSections - 1; // I'm on tail!!! please don't patch myself! short NumberOfSections = 2; PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pImageNtHeaders32); DWORD dwOldPermissions = NULL, dwDummy = 0; while(NumberOfSections > 0) { pSection++; LPDWORD NameDW = (LPDWORD) (pSection->Name); if (!((NameDW[1] == 0x74 && NameDW[0] == 0x7865742e) || (NameDW[1] == 0x61 && NameDW[0] == 0x7461642e))) { continue; } NumberOfSections--; dwOldPermissions = 0; dwDummy = 0; //if ((pSection->Characteristics & IMAGE_SCN_MEM_SHARED) == IMAGE_SCN_MEM_SHARED) // shared memory! // continue; LPVOID lpAddress = rva2addr(pImageDosHeader, pImageNtHeaders32, (LPVOID) pSection->VirtualAddress); VirtualProtect(lpAddress, pSection->Misc.VirtualSize, PAGE_READWRITE, &dwOldPermissions); ULONG64 rc4key[2] = { exe_configuration._key0, exe_configuration._key1 }; DWORD sbox[4]; uint32_t *key = (uint32_t *) sbox; __memcpy((char *)key, (char *) rc4key, 16); LPDWORD encptr = (LPDWORD) lpAddress; for(DWORD dwPtr = 0; dwPtr < pSection->SizeOfRawData; dwPtr += 8, encptr += 2) decrypt((uint32_t *) encptr, key); VirtualProtect(lpAddress, pSection->Misc.VirtualSize, dwOldPermissions, &dwDummy); //pSection++; } NumberOfSections = pImageNtHeaders32->FileHeader.NumberOfSections - 1; // I'm on tail!!! please don't patch myself! pSection = IMAGE_FIRST_SECTION(pImageNtHeaders32); while(NumberOfSections > 0) { pSection++; dwOldPermissions = 0; dwDummy = 0; NumberOfSections--; if (exe_configuration.decrypted == 0) // relocation must be done only 1st time! { // apply reloc in current section! LPVOID lpAddress = rva2addr(pImageDosHeader, pImageNtHeaders32, (LPVOID) pSection->VirtualAddress); VirtualProtect(lpAddress, pSection->Misc.VirtualSize, PAGE_READWRITE, &dwOldPermissions); ULONG ptrReloc = CALC_OFFSET(ULONG, pImageDosHeader, (ULONG) exe_configuration.lpRelocAddress); Reloc_Process((LPVOID) pImageDosHeader, pImageNtHeaders32, pSection, (LPVOID) ptrReloc, exe_configuration.dwRelocSize, IMAGE_FIRST_SECTION(pImageNtHeaders32)); VirtualProtect(lpAddress, pSection->Misc.VirtualSize, dwOldPermissions, &dwDummy); } } // return TRUE; } #endif #ifdef _BUILD32 //#pragma code_seg(".peexe32") //static BOOL bProcessed = FALSE; struct _strings { char *szKernel32; char szVirtualProtect[0x20]; char szVirtualQuery[0x20]; char szGetModuleFileNameA[0x40]; char szGetModuleHandleA[0x40]; }; #pragma code_seg(".peexe32") char* WINAPI LookString(LPBYTE lpText, short position) { if (position == 0) return (char *) lpText; while(position > 0) { if (*lpText == 0) { position--; } lpText++; } return (char *) lpText; } #pragma code_seg(".peexe32") void WINAPI __fuckcrt0startup(struct _strings *ptr) { LPBYTE base; __asm { call __end __kernel32: __emit 'k' __emit 'e' __emit 'r' __emit 'n' __emit 'e' __emit 'l' __emit '3' __emit '2' __emit 00h __virtualquery: __emit 'V' __emit 'i' __emit 'r' __emit 't' __emit 'u' __emit 'a' __emit 'l' __emit 'Q' __emit 'u' __emit 'e' __emit 'r' __emit 'y' __emit 0x00 __getmodulefilenamea: __emit 'G' __emit 'e' __emit 't' __emit 'M' __emit 'o' __emit 'd' __emit 'u' __emit 'l' __emit 'e' __emit 'F' __emit 'i' __emit 'l' __emit 'e' __emit 'N' __emit 'a' __emit 'm' __emit 'e' __emit 'A' __emit 0x00 __getmodulehandlea: __emit 'G' __emit 'e' __emit 't' __emit 'M' __emit 'o' __emit 'd' __emit 'u' __emit 'l' __emit 'e' __emit 'H' __emit 'a' __emit 'n' __emit 'd' __emit 'l' __emit 'e' __emit 'A' __emit 0x00 __end: pop eax mov dword ptr [base], eax } //char szVirtualProtect[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'P', 'r', 'o', 't', 'e', 'c', 't', 0x00 }; ptr->szKernel32 = LookString(base, 0); //__memcpy(ptr->szVirtualProtect, szVirtualProtect, sizeof(szVirtualProtect)); __memcpy(ptr->szVirtualQuery, LookString(base, 1), sizeof(ptr->szVirtualQuery)); __memcpy(ptr->szGetModuleFileNameA, LookString(base, 2), sizeof(ptr->szGetModuleFileNameA)); __memcpy(ptr->szGetModuleHandleA, LookString(base, 3), sizeof(ptr->szGetModuleHandleA)); } #pragma code_seg(".peexe32") HANDLE WINAPI _heap_init (void) { HANDLE h = NULL; if ( ( h = HeapCreate(0, 0, 0)) == NULL ) return NULL; return h; } void WINAPI _heap_term (HANDLE _crtheap) { // destroy the large-block heap HeapDestroy(_crtheap); _crtheap=NULL; } #pragma code_seg(".peexe32") static int __cdecl check_managed_app ( void ) { PIMAGE_DOS_HEADER pDOSHeader; PIMAGE_NT_HEADERS pPEHeader; pDOSHeader = &__ImageBase; if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE) { return 0; } pPEHeader = (PIMAGE_NT_HEADERS) ((BYTE *) pDOSHeader + pDOSHeader->e_lfanew); if (pPEHeader->Signature != IMAGE_NT_SIGNATURE) { return 0; } if (pPEHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) { return 0; } /* prefast assumes we are overflowing __ImageBase */ #pragma warning(push) #pragma warning(disable:26000) if (pPEHeader->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR) { return 0; } #pragma warning(pop) return pPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress != 0; } #ifdef _WIN64 #define DEFAULT_SECURITY_COOKIE 0x00002B992DDFA232 #else /* _WIN64 */ #define DEFAULT_SECURITY_COOKIE 0xBB40E64E #endif /* _WIN64 */ __declspec(allocate(".peexe32")) UINT_PTR __security_cookie = DEFAULT_SECURITY_COOKIE; __declspec(allocate(".peexe32")) UINT_PTR __security_cookie_complement = ~(DEFAULT_SECURITY_COOKIE); typedef union { unsigned __int64 ft_scalar; FILETIME ft_struct; } FT; #pragma code_seg(".peexe32") void __cdecl __security_init_cookie(void) { UINT_PTR cookie; FT systime={0}; LARGE_INTEGER perfctr; /* * Do nothing if the global cookie has already been initialized. On x86, * reinitialize the cookie if it has been previously initialized to a * value with the high word 0x0000. Some versions of Windows will init * the cookie in the loader, but using an older mechanism which forced the * high word to zero. */ if (__security_cookie != DEFAULT_SECURITY_COOKIE #if defined (_X86_) && (__security_cookie & 0xFFFF0000) != 0 #endif /* defined (_X86_) */ ) { //__security_cookie_complement = ~__security_cookie; return; } /* * Initialize the global cookie with an unpredictable value which is * different for each module in a process. Combine a number of sources * of randomness. */ GetSystemTimeAsFileTime(&systime.ft_struct); #if defined (_WIN64) cookie = systime.ft_scalar; #else /* defined (_WIN64) */ cookie = systime.ft_struct.dwLowDateTime; cookie ^= systime.ft_struct.dwHighDateTime; #endif /* defined (_WIN64) */ cookie ^= GetCurrentProcessId(); cookie ^= GetCurrentThreadId(); cookie ^= GetTickCount(); QueryPerformanceCounter(&perfctr); #if defined (_WIN64) cookie ^= perfctr.QuadPart; #else /* defined (_WIN64) */ cookie ^= perfctr.LowPart; cookie ^= perfctr.HighPart; #endif /* defined (_WIN64) */ #if defined (_WIN64) /* * On Win64, generate a cookie with the most significant word set to zero, * as a defense against buffer overruns involving null-terminated strings. * Don't do so on Win32, as it's more important to keep 32 bits of cookie. */ cookie &= 0x0000FFFFffffFFFFi64; #endif /* defined (_WIN64) */ /* * Make sure the cookie is initialized to a value that will prevent us from * reinitializing it if this routine is ever called twice. */ if (cookie == DEFAULT_SECURITY_COOKIE) { cookie = DEFAULT_SECURITY_COOKIE + 1; } #if defined (_X86_) else if ((cookie & 0xFFFF0000) == 0) { cookie |= ( (cookie|0x4711) << 16); } #endif /* defined (_X86_) */ //__security_cookie = cookie; //__security_cookie_complement = ~cookie; } int stub0(DWORD dwParam) { int initret; int mainret = 0; int managedapp; STARTUPINFOW StartupInfo; GetStartupInfoW(&StartupInfo); check_managed_app(); struct _strings init; __fuckcrt0startup(&init); HANDLE hHeap = _heap_init(); HMODULE h = LoadLibraryA(init.szKernel32); //VirtualProtect_ptr p = (VirtualProtect_ptr) GetProcAddress(h, init.szVirtualProtect); VirtualQuery_ptr _vquery = (VirtualQuery_ptr) GetProcAddress(h, init.szVirtualQuery); MEMORY_BASIC_INFORMATION buffer; _vquery(CALC_OFFSET(LPVOID, &__ImageBase, 0x1000), &buffer, sizeof(buffer)); DWORD newptr = buffer.RegionSize + (DWORD) buffer.BaseAddress; _vquery((LPVOID) newptr, &buffer, sizeof(buffer)); DWORD ignore0 = 0x32323232; DWORD ignore1 = 0x64646464; VirtualProtect((LPVOID) newptr, buffer.RegionSize, PAGE_EXECUTE_READWRITE, &ignore0); VirtualProtect((LPVOID) h, 0x1000, PAGE_READONLY, &ignore1); // = p; //exe_g_hKernel32 = (HMODULE) &__ImageBase; //GetModuleHandleA_ptr _GetModuleHandleA = (GetModuleHandleA_ptr) GetProcAddress(h, init.szGetModuleHandleA); //= _GetModuleHandleA(NULL); /*init.szVirtualProtect[7] = 'A'; init.szVirtualProtect[8] = 'l'; init.szVirtualProtect[9] = 'l'; init.szVirtualProtect[0x0a] = 'o'; init.szVirtualProtect[0x0b] = 'c'; init.szVirtualProtect[0x0c] = 0x00;*/ //if (exe_configuration.decrypted == 0) /*exe_configuration.decrypted = */decrypt((HINSTANCE) &__ImageBase, DLL_PROCESS_ATTACH, NULL); BOOL bConditions[4]; bConditions[0] = ((dwParam >> 24) == 0x60); bConditions[1] = ((dwParam >> 16) & 0xff) == 0x0d; bConditions[2] = ((dwParam >> 8) & 0xff) == 0xb4; bConditions[3] = (dwParam & 0xff) == 0xb3; if (bConditions[0] && bConditions[1] && bConditions[2] && bConditions[3]) { return 0; } return _CrtStartup((HINSTANCE) &__ImageBase); } #pragma code_seg(".peexe32") _declspec(noreturn) extern "C" VOID WINAPI __crt0Startup(DWORD dwParam) { __security_init_cookie(); stub0(dwParam); } #endif .