void GenerateUpperTriangularMatrices(NekDouble values[], NekDouble scale, boost::shared_ptr<NekMatrix<NekDouble, StandardMatrixTag> >& m1, boost::shared_ptr<NekMatrix<NekMatrix<NekDouble>, ScaledMatrixTag> >& m2, boost::shared_ptr<NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag> >& m3) { m1 = MakePtr(new NekMatrix<NekDouble, StandardMatrixTag>(4, 4, values, eUPPER_TRIANGULAR)); double inner_values[10]; std::transform(values, values+10, inner_values, boost::bind(std::divides<NekDouble>(), _1, scale)); boost::shared_ptr<NekMatrix<NekDouble> > inner( new NekMatrix<NekDouble>(4, 4, inner_values, eUPPER_TRIANGULAR)); m2 = MakePtr(new NekMatrix<NekMatrix<NekDouble>, ScaledMatrixTag>(scale, inner)); double block_1_values[] = {values[0], 0.0, values[1], values[2]}; double block_2_values[] = {values[3], values[4], values[6], values[7]}; double block_4_values[] = {values[5], 0.0, values[8], values[9]}; boost::shared_ptr<NekMatrix<NekDouble> > block1(new NekMatrix<NekDouble>(2, 2, block_1_values)); boost::shared_ptr<NekMatrix<NekDouble> > block2(new NekMatrix<NekDouble>(2, 2, block_2_values)); boost::shared_ptr<NekMatrix<NekDouble> > block4(new NekMatrix<NekDouble>(2, 2, block_4_values)); m3 = MakePtr(new NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag>(2, 2, 2, 2)); m3->SetBlock(0,0, block1); m3->SetBlock(0,1, block2); m3->SetBlock(1,1, block4); }
void DumpFirstLinkerMember(PVOID p) { DWORD cSymbols = *(PDWORD)p; PDWORD pMemberOffsets = MakePtr( PDWORD, p, 4 ); PSTR pSymbolName; unsigned i; cSymbols = ConvertBigEndian(cSymbols); pSymbolName = MakePtr( PSTR, pMemberOffsets, 4 * cSymbols ); printf("First Linker Member:\n"); printf( " Symbols: %08X\n", cSymbols ); printf( " MbrOffs Name\n -------- ----\n" ); for ( i = 0; i < cSymbols; i++ ) { DWORD offset; offset = ConvertBigEndian( *pMemberOffsets ); printf(" %08X %s\n", offset, pSymbolName); pMemberOffsets++; pSymbolName += strlen(pSymbolName) + 1; } }
static PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor(HMODULE hModule, LPCSTR szImportModule) { PIMAGE_DOS_HEADER pDOSHeader; PIMAGE_NT_HEADERS pNTHeader; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; if ((szImportModule == NULL) || (hModule == NULL)) return NULL; pDOSHeader = (PIMAGE_DOS_HEADER) hModule; if (IsBadReadPtr(pDOSHeader, sizeof(IMAGE_DOS_HEADER)) || (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)) { return NULL; } pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew); if (IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) || (pNTHeader->Signature != IMAGE_NT_SIGNATURE)) return NULL; if (pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0) return NULL; pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDOSHeader, pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); while (pImportDesc->Name) { PSTR szCurrMod = MakePtr(PSTR, pDOSHeader, pImportDesc->Name); if (_stricmp(szCurrMod, szImportModule) == 0) break; pImportDesc++; } if (pImportDesc->Name == (DWORD)0) return NULL; return pImportDesc; }
void DumpSecondLinkerMember(PVOID p) { DWORD cArchiveMembers = *(PDWORD)p; PDWORD pMemberOffsets = MakePtr( PDWORD, p, 4 ); DWORD cSymbols; PSTR pSymbolName; PWORD pIndices; unsigned i; cArchiveMembers = cArchiveMembers; // The number of symbols is in the DWORD right past the end of the // member offset array. cSymbols = pMemberOffsets[cArchiveMembers]; pIndices = MakePtr( PWORD, p, 4 + cArchiveMembers * sizeof(DWORD) + 4 ); pSymbolName = MakePtr( PSTR, pIndices, cSymbols * sizeof(WORD) ); printf("Second Linker Member:\n"); printf( " Archive Members: %08X\n", cArchiveMembers ); printf( " Symbols: %08X\n", cSymbols ); printf( " MbrOffs Name\n -------- ----\n" ); for ( i = 0; i < cSymbols; i++ ) { printf(" %08X %s\n", pMemberOffsets[pIndices[i] - 1], pSymbolName); pSymbolName += strlen(pSymbolName) + 1; } }
void GenerateFullMatrices(double values[], double scale, boost::shared_ptr<NekMatrix<NekDouble, StandardMatrixTag> >& m1, boost::shared_ptr<NekMatrix<NekMatrix<NekDouble>, ScaledMatrixTag> >& m2, boost::shared_ptr<NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag> >& m3) { m1 = MakePtr(new NekMatrix<NekDouble, StandardMatrixTag>(4, 4, values)); double inner_values[16]; std::transform(values, values+16, inner_values, boost::bind(std::divides<NekDouble>(), _1, scale)); boost::shared_ptr<NekMatrix<NekDouble> > inner( new NekMatrix<NekDouble>(4, 4, inner_values)); m2 = MakePtr(new NekMatrix<NekMatrix<NekDouble>, ScaledMatrixTag>(scale, inner)); double block_1_values[] = {values[0], values[1], values[4], values[5]}; double block_2_values[] = {values[2], values[3], values[6], values[7]}; double block_3_values[] = {values[8], values[9], values[12], values[13]}; double block_4_values[] = {values[10], values[11], values[14], values[15]}; boost::shared_ptr<NekMatrix<NekDouble> > block1(new NekMatrix<NekDouble>(2, 2, block_1_values)); boost::shared_ptr<NekMatrix<NekDouble> > block2(new NekMatrix<NekDouble>(2, 2, block_2_values)); boost::shared_ptr<NekMatrix<NekDouble> > block3(new NekMatrix<NekDouble>(2, 2, block_3_values)); boost::shared_ptr<NekMatrix<NekDouble> > block4(new NekMatrix<NekDouble>(2, 2, block_4_values)); m3 = MakePtr(new NekMatrix<NekMatrix<NekDouble>, BlockMatrixTag>(2, 2, 2, 2)); m3->SetBlock(0,0, block1); m3->SetBlock(1,0, block2); m3->SetBlock(0,1, block3); m3->SetBlock(1,1, block4); }
void init_core_dll() { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS32 nt; PIMAGE_EXPORT_DIRECTORY exp; dos = (PIMAGE_DOS_HEADER)LOAD_BASE; nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE, nt->OptionalHeader.DataDirectory[0].VirtualAddress); list_initialize(&core_dll.link); core_dll.img_base = LOAD_BASE; core_dll.img_size = nt->OptionalHeader.SizeOfImage; core_dll.img_md = NULL; core_dll.img_hdr = nt; core_dll.img_sec = MakePtr(PIMAGE_SECTION_HEADER,nt, sizeof(IMAGE_NT_HEADERS32)); core_dll.img_exp = MakePtr(PIMAGE_EXPORT_DIRECTORY,LOAD_BASE, nt->OptionalHeader.DataDirectory[0].VirtualAddress); core_dll.img_name = strupr(MakePtr(char*, LOAD_BASE, exp->Name)); dll_slab = slab_cache_create(sizeof(dll_t), 16,NULL,NULL,SLAB_CACHE_MAGDEFERRED); DBG("%s base %x size %x sections %d exports %x\n", core_dll.img_name, core_dll.img_base, core_dll.img_size, nt->FileHeader.NumberOfSections, core_dll.img_exp ); };
GLOBAL void InitTypes() { TypeNames[Uchar] = "unsigned char"; TypeNames[Schar] = "signed char"; TypeNames[Char] = "char"; TypeNames[Sshort] = "short"; TypeNames[Ushort] = "unsigned short"; TypeNames[Sint] = "int"; TypeNames[Uint] = "unsigned"; TypeNames[Int_ParseOnly] = "int"; TypeNames[Slong] = "long"; TypeNames[Ulong] = "unsigned long"; TypeNames[Slonglong] = "long long"; TypeNames[Ulonglong] = "unsigned long long"; TypeNames[Float] = "float"; TypeNames[Double] = "double"; TypeNames[Longdouble] = "long double"; TypeNames[Void] = "void"; TypeNames[Ellipsis] = "..."; EllipsisNode = MakePrim(EMPTY_TQ, Ellipsis); Undeclared = MakeDecl("undeclared!", EMPTY_TQ, NULL, NULL, NULL); PrimVoid = MakePrim(EMPTY_TQ, Void); PrimChar = MakePrim(EMPTY_TQ, Char); PrimSchar = MakePrim(EMPTY_TQ, Schar); PrimUchar = MakePrim(EMPTY_TQ, Uchar); PrimSshort = MakePrim(EMPTY_TQ, Sshort); PrimUshort = MakePrim(EMPTY_TQ, Ushort); PrimSint = MakePrim(EMPTY_TQ, Sint); PrimUint = MakePrim(EMPTY_TQ, Uint); PrimSlong = MakePrim(EMPTY_TQ, Slong); PrimUlong = MakePrim(EMPTY_TQ, Ulong); PrimSlonglong= MakePrim(EMPTY_TQ, Slonglong); PrimUlonglong= MakePrim(EMPTY_TQ, Ulonglong); PrimFloat = MakePrim(EMPTY_TQ, Float); PrimDouble = MakePrim(EMPTY_TQ, Double); PrimLongdouble= MakePrim(EMPTY_TQ, Longdouble); StaticString = MakePtr(EMPTY_TQ, MakePrim(T_STATIC, Char)); /* Make some standard zeros */ SintZero = MakeConstSint(0); UintZero = MakeConstUint(0); SlongZero = MakeConstSlong(0); UlongZero = MakeConstUlong(0); FloatZero = MakeConstFloat(0.0); DoubleZero = MakeConstDouble(0.0); /* Make some standard ones */ SintOne = MakeConstSint(1); UintOne = MakeConstUint(1); SlongOne = MakeConstSlong(1); UlongOne = MakeConstUlong(1); FloatOne = MakeConstFloat(1.0); DoubleOne = MakeConstDouble(1.0); PtrVoid = MakePtr(EMPTY_TQ, PrimVoid); PtrNull = MakeConstPtr(0); }
static BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs) { PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pOrigThunk; PIMAGE_THUNK_DATA pRealThunk; if (!IsNT() && ((size_t)hModule >= 0x80000000)) return FALSE; pImportDesc = GetNamedImportDescriptor(hModule, szImportModule); if (pImportDesc == NULL) return FALSE; pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk); pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk); while (pOrigThunk->u1.Function) { if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) { PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData); BOOL bDoHook; // When hook EditPlus, read pByName->Name[0] will case this dll terminate, so call IsBadReadPtr() here. if (IsBadReadPtr(pByName, sizeof(IMAGE_IMPORT_BY_NAME))) { pOrigThunk++; pRealThunk++; continue; } if ('\0' == pByName->Name[0]) { pOrigThunk++; pRealThunk++; continue; } bDoHook = FALSE; if ((szFunc[0] == pByName->Name[0]) && (_strcmpi(szFunc, (char*)pByName->Name) == 0)) { if (paHookFuncs) bDoHook = TRUE; } if (bDoHook) { MEMORY_BASIC_INFORMATION mbi_thunk; DWORD dwOldProtect; VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect); if (paOrigFuncs) *paOrigFuncs = (PROC)pRealThunk->u1.Function; pRealThunk->u1.Function = (DWORD)paHookFuncs; VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); return TRUE; } } pOrigThunk++; pRealThunk++; } return FALSE; }
//=========================================================================== // Top level routine to find the EXE's imports, and redirect them bool HookAPICalls( SDLLHook* Hook ) { if ( !Hook ) return false; HMODULE hModEXE = GetModuleHandle( 0 ); PIMAGE_NT_HEADERS pExeNTHdr = PEHeaderFromHModule( hModEXE ); if ( !pExeNTHdr ) return false; DWORD importRVA = pExeNTHdr->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if ( !importRVA ) return false; // Convert imports RVA to a usable pointer PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr( PIMAGE_IMPORT_DESCRIPTOR, hModEXE, importRVA ); // Save off imports address in a global for later use g_pFirstImportDesc = pImportDesc; bool returnVal = false; // Iterate through each import descriptor, and redirect if appropriate while ( pImportDesc->FirstThunk ) { PSTR pszImportModuleName = MakePtr( PSTR, hModEXE, pImportDesc->Name); OutputDebugString( "Checking: " ); OutputDebugString( pszImportModuleName ); OutputDebugString( "...\n" ); if ( lstrcmpi( pszImportModuleName, Hook->Name ) == 0 ) { OutputDebugString( "Found " ); OutputDebugString( Hook->Name ); OutputDebugString( "...\n" ); RedirectIAT( Hook, pImportDesc, (PVOID)hModEXE ); returnVal = true; } pImportDesc++; // Advance to next import descriptor } return returnVal; }
void* HAPIHook::InterceptDllMember(HMODULE hModule,char *szDllName,char *szFunctionName,DWORD pNewFunction) { EnterCriticalSection(&m_cs); PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNTHeader; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pThunk; DWORD dwOldProtect; DWORD dwOldProtect2; void *pOldFunction; if(!(pOldFunction = GetProcAddress(GetModuleHandle(szDllName),szFunctionName))) return 0; pDosHeader = (PIMAGE_DOS_HEADER)hModule; if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) return(NULL); pNTHeader = MakePtr(PIMAGE_NT_HEADERS,pDosHeader,pDosHeader->e_lfanew); if(pNTHeader->Signature != IMAGE_NT_SIGNATURE || ( pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR,pDosHeader,pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)) == (PIMAGE_IMPORT_DESCRIPTOR )pNTHeader) return(NULL); while(pImportDesc->Name) { char *szModuleName = MakePtr(char *,pDosHeader,pImportDesc->Name); if(!stricmp(szModuleName,szDllName)) break; pImportDesc++; } if(pImportDesc->Name == NULL) return(NULL); pThunk = MakePtr(PIMAGE_THUNK_DATA,pDosHeader,pImportDesc->FirstThunk); while(pThunk->u1.Function) { if(pThunk->u1.Function == (DWORD)pOldFunction) { VirtualProtect((void*)&pThunk->u1.Function,sizeof(DWORD),PAGE_EXECUTE_READWRITE,&dwOldProtect); pThunk->u1.Function = pNewFunction; VirtualProtect((void*)&pThunk->u1.Function,sizeof(DWORD),dwOldProtect,&dwOldProtect2 ); return(pOldFunction); } pThunk++; } LeaveCriticalSection(&m_cs); return(NULL); }
// // Do a hexadecimal dump of the raw data for all the sections. You // could just dump one section by adjusting the PIMAGE_SECTION_HEADER // and cSections parameters // void DumpRawSectionData(PIMAGE_SECTION_HEADER section, PVOID base, unsigned cSections) { unsigned i; char name[IMAGE_SIZEOF_SHORT_NAME + 1]; printf("Section Hex Dumps\n"); for ( i=1; i <= cSections; i++, section++ ) { // Make a copy of the section name so that we can ensure that // it's null-terminated memcpy(name, section->Name, IMAGE_SIZEOF_SHORT_NAME); name[IMAGE_SIZEOF_SHORT_NAME] = 0; // Don't dump sections that don't exist in the file! if ( section->PointerToRawData == 0 ) continue; printf( "section %02X (%s) size: %08X file offs: %08X\n", i, name, section->SizeOfRawData, section->PointerToRawData); HexDump( MakePtr(PBYTE, base, section->PointerToRawData), section->SizeOfRawData ); printf("\n"); } }
srv_t* __fastcall load_pe_driver(const char *path) { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS32 nt; drv_entry_t *drv_entry; addr_t *img_base ; srv_t *srv; img_base = load_image(path); if( ! img_base ) return 0; if( link_image( img_base ) ) { dos = (PIMAGE_DOS_HEADER)img_base; nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); drv_entry = MakePtr(drv_entry_t*, img_base, nt->OptionalHeader.AddressOfEntryPoint); srv = drv_entry(1); if(srv != NULL) srv->entry = nt->OptionalHeader.AddressOfEntryPoint + img_base; return srv; } else {
ULONG peDumpExports(HMODULE mod, BOOL noname) { if (!mod) { return ERROR_INVALID_PARAMETER; } PBYTE pImageBase = (PBYTE)mod; PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)pImageBase; // get pointers to 32 and 64 bit versions of the header. PIMAGE_NT_HEADERS32 pNTHeader = MakePtr( PIMAGE_NT_HEADERS32, dosHeader, dosHeader->e_lfanew ); PIMAGE_NT_HEADERS64 pNTHeader64 = (PIMAGE_NT_HEADERS64)pNTHeader; BOOL is64 = ( pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC ); ULONG gle; if (is64) { gle = peDumpExportsInternal((PBYTE)mod,pNTHeader64,noname); } else { gle = peDumpExportsInternal((PBYTE)mod,pNTHeader,noname); } return gle; }
FARPROC GetRemoteProcAddress(unsigned long pId, char *module, char *func) { HMODULE remoteMod = GetRemoteModuleHandle(pId, module); HMODULE localMod = GetModuleHandle(module); // Account for potential differences in base address // of modules in different processes. unsigned long delta = MakeDelta(unsigned long, remoteMod, localMod); return MakePtr(FARPROC, GetProcAddress(localMod, func), delta); }
HRESULT CPEFile::Open(LPCTSTR pszFile, BOOL bReadOnly) { HRESULT hr = S_OK; Close(); m_hFile = CreateFile(pszFile, GENERIC_READ | ((bReadOnly == FALSE) ? GENERIC_WRITE: 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hFile == INVALID_HANDLE_VALUE) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { m_hMap = CreateFileMapping(m_hFile, NULL, (bReadOnly == TRUE) ? PAGE_READONLY:PAGE_READWRITE, 0, 0, NULL); if (!m_hMap) { hr = HRESULT_FROM_WIN32(GetLastError()); } else { m_pBase = (PIMAGE_DOS_HEADER)MapViewOfFile(m_hMap, FILE_MAP_READ | ((bReadOnly == FALSE) ? FILE_MAP_WRITE:0), 0, 0, 0); if (!m_pBase) { hr = HRESULT_FROM_WIN32(GetLastError()); } } } if (SUCCEEDED(hr)) { PIMAGE_FILE_HEADER pImageHeader = (PIMAGE_FILE_HEADER)m_pBase; if (m_pBase->e_magic != IMAGE_DOS_SIGNATURE) { hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); } m_pNTHeader = MakePtr(PIMAGE_NT_HEADERS, m_pBase, m_pBase->e_lfanew); if (IsBadReadPtr(m_pNTHeader, sizeof(m_pNTHeader->Signature))) { hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); } else { if (m_pNTHeader->Signature != IMAGE_NT_SIGNATURE) { hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT); } } m_bIs64Bit = (m_pNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC); } if (FAILED(hr)) Close(); return hr; }
bool DumpDbgFile( MPanelItem *pRoot, PIMAGE_SEPARATE_DEBUG_HEADER pImageSepDbgHeader ) { DumpImageDbgHeader(pRoot, pImageSepDbgHeader); pRoot->printf("\n"); DumpSectionTable( pRoot, (PIMAGE_SECTION_HEADER)(pImageSepDbgHeader+1), pImageSepDbgHeader->NumberOfSections, TRUE); DumpDebugDirectory( pRoot, MakePtr(PIMAGE_DEBUG_DIRECTORY, pImageSepDbgHeader, sizeof(IMAGE_SEPARATE_DEBUG_HEADER) + (pImageSepDbgHeader->NumberOfSections * sizeof(IMAGE_SECTION_HEADER)) + pImageSepDbgHeader->ExportedNamesSize), pImageSepDbgHeader->DebugDirectorySize, (PBYTE)pImageSepDbgHeader); pRoot->printf("\n"); if ( g_pCOFFHeader ) { DumpCOFFHeader( pRoot, g_pCOFFHeader ); pRoot->printf("\n"); g_pCOFFSymbolTable = new COFFSymbolTable( MakePtr( PVOID, g_pCOFFHeader, g_pCOFFHeader->LvaToFirstSymbol), g_pCOFFHeader->NumberOfSymbols ); DumpCOFFSymbolTable( pRoot, g_pCOFFSymbolTable ); delete g_pCOFFSymbolTable; } if ( g_pCVHeader ) { DumpCVSymbolTable( pRoot, (PBYTE)g_pCVHeader, g_pMappedFileBase ); } return true; }
bool MapSections(HANDLE hProcess, void *moduleBase, void *dllBin, IMAGE_NT_HEADERS *ntHd) { IMAGE_SECTION_HEADER *header = IMAGE_FIRST_SECTION(ntHd); unsigned int nBytes = 0; unsigned int virtualSize = 0; unsigned int n = 0; // Loop through the list of sections for(unsigned int i = 0; ntHd->FileHeader.NumberOfSections; i++) { // Once we've reached the SizeOfImage, the rest of the sections // don't need to be mapped, if there are any. if(nBytes >= ntHd->OptionalHeader.SizeOfImage) break; WriteProcessMemory(hProcess, MakePtr(LPVOID, moduleBase, header->VirtualAddress), MakePtr(LPCVOID, dllBin, header->PointerToRawData), header->SizeOfRawData, (LPDWORD)&n); virtualSize = header->VirtualAddress; header++; virtualSize = header->VirtualAddress - virtualSize; nBytes += virtualSize; // Set the proper page protections for this section. // This really could be skipped, but it's not that // hard to implement and it makes it more like a // real loader. VirtualProtectEx(hProcess, MakePtr(LPVOID, moduleBase, header->VirtualAddress), virtualSize, header->Characteristics & 0x00FFFFFF, NULL); } return true; }
BOOL CRemoteLoader::ProcessSection( BYTE* Name, PVOID BaseAddress, PVOID RemoteAddress, ULONG RawData, ULONG VirtualAddress, ULONG RawSize, ULONG VirtualSize, ULONG ProtectFlag ) { DebugShout( "[ProcessSection] ProcessSection( %s, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X )", Name, BaseAddress, RemoteAddress, RawData, VirtualAddress, RawSize, VirtualSize, ProtectFlag ); HANDLE hProcess = GetProcess(); if( hProcess == INVALID_HANDLE_VALUE ) { hProcess = GetCurrentProcess(); } if( WriteProcessMemory( hProcess, MakePtr( PVOID, RemoteAddress, VirtualAddress ), MakePtr( PVOID, BaseAddress, RawData ), RawSize, NULL ) == FALSE ) { DebugShout( "[ProcessSection] Failed to write memory for (%s) -> (%s)", Name, LastErrorString() ); return FALSE; } DWORD dwOldProtect = NULL; if( VirtualProtectEx( hProcess, MakePtr( PVOID, RemoteAddress, VirtualAddress ), VirtualSize, ProtectFlag, &dwOldProtect ) == FALSE ) { DebugShout( "[ProcessSection] Failed to protect memory for (%s) -> (%s)", Name, LastErrorString() ); return FALSE; } return TRUE; }
int validate_pe(void *raw, size_t raw_size, int is_exec) { PIMAGE_DOS_HEADER dos; PIMAGE_NT_HEADERS32 nt; dos = (PIMAGE_DOS_HEADER)raw; if( !raw || raw_size < sizeof(IMAGE_DOS_HEADER) ) return 0; if( dos->e_magic != IMAGE_DOS_SIGNATURE || dos->e_lfanew <= 0) return 0; nt = MakePtr( PIMAGE_NT_HEADERS32, dos, dos->e_lfanew); if( (uint32_t)nt < (uint32_t)raw) return 0; if(nt->Signature != IMAGE_NT_SIGNATURE) return 0; if(nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return 0; if(is_exec && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) return 0; if(nt->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) return 0; if( is_exec && nt->OptionalHeader.ImageBase != 0) return 0; if(nt->OptionalHeader.SectionAlignment < 4096) { if(nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) return 0; } else if(nt->OptionalHeader.SectionAlignment < nt->OptionalHeader.FileAlignment) return 0; if(!IsPowerOf2(nt->OptionalHeader.SectionAlignment) || !IsPowerOf2(nt->OptionalHeader.FileAlignment)) return 0; if(nt->FileHeader.NumberOfSections > 96) return 0; return 1; }
EXE_FILE::EXE_FILE( PSTR pszFileName ) : MEMORY_MAPPED_FILE( pszFileName ) { m_errorType = errEXE_FILE_FILE_NOT_FOUND; m_secondaryHeaderOffset = -1; // A bogus value to catch bugs m_exeType = exeType_Invalid; if ( FALSE == MEMORY_MAPPED_FILE::IsValid() ) return; // m_errorType already set to errEXE_FILE_FILE_NOT_FOUND // If we get here, the file exists, and was mapped. We're still not // sure that it's a valid EXE though m_errorType = errEXE_FILE_INVALID_FORMAT; if ( GetFileSize() < sizeof(IMAGE_DOS_HEADER) ) return; PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)GetBase(); if ( IMAGE_DOS_SIGNATURE != pDosHdr->e_magic ) return; // If we get here, it's at least a DOS 'MZ' file m_errorType = errEXE_FILE_NO_ERROR; if ( pDosHdr->e_lfarlc < 0x40 ) // Theoretically, this field must be >= { // 0x40 for it to be a non-DOS executable m_exeType = exeType_DOS; return; } // Sanity check. Make sure the "new header" offset isn't past the end // of the file if ( pDosHdr->e_lfanew > (LONG)GetFileSize() ) return; // Make a pointer to the secondary header m_secondaryHeaderOffset = pDosHdr->e_lfanew; PWORD pSecondHdr = MakePtr( PWORD, GetBase(), m_secondaryHeaderOffset ); // Decide what type of EXE, based on the start of the secondary header switch ( *pSecondHdr ) { case IMAGE_OS2_SIGNATURE: m_exeType = exeType_NE; break; case IMAGE_VXD_SIGNATURE: m_exeType = exeType_VXD; break; case 0x4558: m_exeType = exeType_LX; break; // OS/2 2.X } if ( *(PDWORD)pSecondHdr == IMAGE_NT_SIGNATURE ) m_exeType = exeType_PE; }
// Main function // see description of PPGIParamsBlock in unpack.h // return TRUE if this pluging can handle the source // __declspec(dllexport) BOOL __stdcall PexPreloadImage(PPGIParamsBlock pPGI) { CString str; DWORD id = pPGI->dwInterface; PDWORD base = (DWORD *) pPGI->pInBuff; (pPGI->pCallBack)(id, 0, "Executing..."); PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER) base; PIMAGE_NT_HEADERS pSecondHdr = MakePtr( PIMAGE_NT_HEADERS, base, pDosHdr->e_lfanew ); PBYTE NTbase = (PBYTE) GetSectionPtr( pSecondHdr, (DWORD) base); if ( NTbase > ((PBYTE) base + pPGI->dwInSize)) { // str.Format("%s: Error in EXE file", PIABV); // (pPGI->pCallBack)(id, 0, str); // return FALSE; } if (NTbase) { // NTbase + 24 if (*(NTbase + 2) == 0xE9) str.Format("%s: File compressed with Aspack ver 2.11", PIABV); else if (*(PWORD)(NTbase + 0x3B2) == 0x01B8) str.Format("%s: File compressed with Aspack ver 2.12/2.12a/2.12b", PIABV); else if (*(PWORD)(NTbase + 0x3B3) == 0x01B8) str.Format("%s: File compressed with Aspack ver ??", PIABV); else if (*(PWORD)(NTbase + 0x4F4) == 0x01B8) str.Format("%s: File compressed with Aspack 2000", PIABV); else if (*(PWORD)(NTbase + 0x4F6) == 0x01B8) str.Format("%s: File compressed with Aspack 2001", PIABV); else if (*(PWORD)(NTbase + 0x4F6) == 0x01B8 && *(NTbase + 0x4DF) == 0x000443A02) str.Format("%s: File compressed with Aspack ver 2.1", PIABV); else if (*(PWORD)(NTbase + 0x4F6) == 0x01B8 && *(NTbase + 0x4DF) == 0x0004439FD) str.Format("%s: File compressed with Aspack ver ??", PIABV); else if (*(PWORD)(NTbase + 0x3BA) == 0x7561) str.Format("%s: File compressed with Aspack ver ??", PIABV); else if (*(NTbase + 2) == 0xE8) str.Format("%s: File compressed with Aspack ver 2.11c/d", PIABV); else return FALSE; } else return FALSE; (pPGI->pCallBack)(id, 0, str); // //void *p = (pPGI->pMemAllocator)(DWORD len); // Memory allocator for the returned Image // if (p) pPGI->pOutBuff = (LPVOID) p; // Initialize output buffer pointer // pPGI->dwOutSize = len; // Set output buffer size return TRUE; }
// Given a process ID, file pointer, NT header, and start of .idata, fix the imports bool FixImports(unsigned long pId, void *base, IMAGE_NT_HEADERS *ntHd, IMAGE_IMPORT_DESCRIPTOR *impDesc) { char *module; // Loop through all the required modules while((module = (char *)GetPtrFromRVA((DWORD)(impDesc->Name), ntHd, (PBYTE)base))) { // If the library is already loaded(like kernel32.dll or ntdll.dll) LoadLibrary will // just return the handle to that module. // A neat alternative would be to load them all again. This will help ensure // we have a working copy for our own function calls which is hidden :O HMODULE localMod = LoadLibraryA(module); // If the module isn't loaded in the remote process, we recursively call the // module mapping code. This has the added benefit of ensuring that any of // the current modules dependencies will be just as invisible as this one. if(!GetRemoteModuleHandle(pId, module)) MapRemoteModule(pId, module); // fix the time/date stamp impDesc->TimeDateStamp = ntHd->FileHeader.TimeDateStamp; // Lookup the first import thunk for this module // NOTE: It is possible this module could forward functions...which is something // that I really should handle. Maybe I'll add support for forward functions // a little bit later. IMAGE_THUNK_DATA *itd = (IMAGE_THUNK_DATA *)GetPtrFromRVA((DWORD)(impDesc->FirstThunk), ntHd, (PBYTE)base); while(itd->u1.AddressOfData) { IMAGE_IMPORT_BY_NAME *iibn; iibn = (IMAGE_IMPORT_BY_NAME *)GetPtrFromRVA((DWORD)(itd->u1.AddressOfData), ntHd, (PBYTE)base); itd->u1.Function = MakePtr(DWORD, GetRemoteProcAddress(pId, module, (char *)iibn->Name), 0); ++itd; } ++impDesc; } return true; }
void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size) { PPOOLHEADER pph; /* Points on area header. */ if (!memp) /*******************************************************************/ /* Allocation is to be done in the Sarea. */ /*******************************************************************/ memp = g->Sarea; //size = ((size + 3) / 4) * 4; /* Round up size to multiple of 4 */ size = ((size + 7) / 8) * 8; /* Round up size to multiple of 8 */ pph = (PPOOLHEADER)memp; #if defined(DEBUG2) || defined(DEBUG3) htrc("SubAlloc in %p size=%d used=%d free=%d\n", memp, size, pph->To_Free, pph->FreeBlk); #endif if ((uint)size > pph->FreeBlk) { /* Not enough memory left in pool */ char *pname = "Work"; sprintf(g->Message, "Not enough memory in %s area for request of %u (used=%d free=%d)", pname, (uint) size, pph->To_Free, pph->FreeBlk); #if defined(DEBUG2) || defined(DEBUG3) htrc("%s\n", g->Message); #endif longjmp(g->jumper[g->jump_level], 1); } /* endif size OS32 code */ /*********************************************************************/ /* Do the suballocation the simplest way. */ /*********************************************************************/ memp = MakePtr(memp, pph->To_Free); /* Points to suballocated block */ pph->To_Free += size; /* New offset of pool free block */ pph->FreeBlk -= size; /* New size of pool free block */ #if defined(DEBUG2) || defined(DEBUG3) htrc("Done memp=%p used=%d free=%d\n", memp, pph->To_Free, pph->FreeBlk); #endif return (memp); } /* end of PlugSubAlloc */
FARPROC GetRemoteProcAddress(const char *module, const char *func, short nPID) { HMODULE remoteMod = GetRemoteModuleHandle(module, nPID); HMODULE localMod = GetModuleHandle(module); // If the module isn't already loaded, we load it, but since many of the // modules we'll probably be loading will do nasty things like modify // memory and hook functions, we use the DONT_RESOLVE_DLL_REFERENCES flag, // so that LoadLibraryEx only loads the dll, but doesn't execute it. if(!localMod) localMod = LoadLibraryEx(module, NULL, DONT_RESOLVE_DLL_REFERENCES); // Account for potential differences in base address // of modules in different processes. int delta = MakeDelta(int, remoteMod, localMod); FARPROC LocalFunctionAddress = GetProcAddress(localMod, func); return MakePtr(FARPROC, LocalFunctionAddress, delta); }
/*---------------------------------------------------------------------- * DumpObjFile -- * * Dump an object file--either a full listing or just the exported * symbols. *---------------------------------------------------------------------- */ void DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full) { PIMAGE_SYMBOL PCOFFSymbolTable; DWORD COFFSymbolCount; //PCOFFSymbolTable = (PIMAGE_SYMBOL)LongToPtr( //((DWORD)PtrToLong( pImageFileHeader ) + pImageFileHeader->PointerToSymbolTable) ); PCOFFSymbolTable = MakePtr(PIMAGE_SYMBOL, pImageFileHeader, pImageFileHeader->PointerToSymbolTable); COFFSymbolCount = pImageFileHeader->NumberOfSymbols; if (full) { DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount); } else { DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount); } }
void TestExeFile( const char *pFilename, PIMAGE_DOS_HEADER dosHeader ) { PIMAGE_NT_HEADERS pNTHeader; pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew ); // First, verify that the e_lfanew field gave us a reasonable // pointer, then verify the PE signature. if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) || pNTHeader->Signature != IMAGE_NT_SIGNATURE ) { printf("Unhandled EXE type, or invalid .EXE (%s)\n", pFilename); return; } if ( HasSection( (PIMAGE_SECTION_HEADER)(pNTHeader+1), pNTHeader->FileHeader.NumberOfSections, "ValveDBG" ) ) { printf("%s is a debug build\n", pFilename); } }
void NTHeader::parsePEFile(const char* fileName) { hFile_ = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile_ == INVALID_HANDLE_VALUE) throw std::exception("Unable to open file!"); hFileMapping_ = CreateFileMapping(hFile_, NULL, PAGE_READONLY, 0, 0, NULL); if (hFileMapping_ == 0 ) { CloseHandle(hFile_); throw std::exception("Unable to create file mapping!"); } mappedView_ = (PBYTE)MapViewOfFile(hFileMapping_, FILE_MAP_READ, 0, 0, 0); if (mappedView_ == 0) { CloseHandle(hFileMapping_); CloseHandle(hFile_); throw std::exception("Unable to map view of file!"); } PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mappedView_; pNTHeader_ = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); }
/*---------------------------------------------------------------------- FUNCTION : GetNamedImportDescriptor DISCUSSION : Gets the import descriptor for the requested module. If the module is not imported in hModule, NULL is returned. This is a potential useful function in the future. PARAMETERS : hModule - The module to hook in. szImportMod - The module name to get the import descriptor for. RETURNS : NULL - The module was not imported or hModule is invalid. !NULL - The import descriptor. ----------------------------------------------------------------------*/ PIMAGE_IMPORT_DESCRIPTOR GetNamedImportDescriptor ( HMODULE hModule , LPCSTR szImportMod ) { // Always check parameters. ASSERT ( NULL != szImportMod ) ; ASSERT ( NULL != hModule ) ; if ( ( NULL == szImportMod ) || ( NULL == hModule ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( NULL ) ; } PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER)hModule ; // Is this the MZ header? if ( ( TRUE == IsBadReadPtr ( pDOSHeader , sizeof ( IMAGE_DOS_HEADER ) ) ) || ( IMAGE_DOS_SIGNATURE != pDOSHeader->e_magic ) ) { ASSERT ( FALSE ) ; SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( NULL ) ; } // Get the PE header. PIMAGE_NT_HEADERS pNTHeader = MakePtr ( PIMAGE_NT_HEADERS , pDOSHeader , pDOSHeader->e_lfanew ) ; // Is this a real PE image? if ( ( TRUE == IsBadReadPtr ( pNTHeader , sizeof ( IMAGE_NT_HEADERS ) ) ) || ( IMAGE_NT_SIGNATURE != pNTHeader->Signature ) ) { ASSERT ( FALSE ) ; SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( NULL ) ; } // If there is no imports section, leave now. if ( 0 == pNTHeader->OptionalHeader. DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]. VirtualAddress ) { return ( NULL ) ; } // Get the pointer to the imports section. PIMAGE_IMPORT_DESCRIPTOR pImportDesc = MakePtr ( PIMAGE_IMPORT_DESCRIPTOR , pDOSHeader , pNTHeader->OptionalHeader. DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ]. VirtualAddress ) ; // Loop through the import module descriptors looking for the // module whose name matches szImportMod. while ( NULL != pImportDesc->Name ) { PSTR szCurrMod = MakePtr ( PSTR , pDOSHeader , pImportDesc->Name ) ; if ( 0 == _stricmp ( szCurrMod , szImportMod ) ) { // Found it. break ; } // Look at the next one. pImportDesc++ ; } // If the name is NULL, then the module is not imported. if ( NULL == pImportDesc->Name ) { return ( NULL ) ; } // All OK, Jumpmaster! return ( pImportDesc ) ; }
BOOL BUGSUTIL_DLLINTERFACE __stdcall HookImportedFunctionsByName ( HMODULE hModule , LPCSTR szImportMod , UINT uiCount , LPHOOKFUNCDESCA paHookArray , PROC * paOrigFuncs , LPDWORD pdwHooked ) { // Double check the parameters. ASSERT ( NULL != szImportMod ) ; ASSERT ( 0 != uiCount ) ; ASSERT ( FALSE == IsBadReadPtr ( paHookArray , sizeof (HOOKFUNCDESC) * uiCount )); #ifdef _DEBUG if ( NULL != paOrigFuncs ) { ASSERT ( FALSE == IsBadWritePtr ( paOrigFuncs , sizeof ( PROC ) * uiCount ) ); } if ( NULL != pdwHooked ) { ASSERT ( FALSE == IsBadWritePtr ( pdwHooked , sizeof ( UINT ))); } // Check each function name in the hook array. { for ( UINT i = 0 ; i < uiCount ; i++ ) { ASSERT ( NULL != paHookArray[ i ].szFunc ) ; ASSERT ( '\0' != *paHookArray[ i ].szFunc ) ; // If the proc is not NULL, then it is checked. if ( NULL != paHookArray[ i ].pProc ) { ASSERT ( FALSE == IsBadCodePtr ( paHookArray[i].pProc)); } } } #endif // Do the parameter validation for real. if ( ( 0 == uiCount ) || ( NULL == szImportMod ) || ( TRUE == IsBadReadPtr ( paHookArray , sizeof (HOOKFUNCDESC) * uiCount ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } if ( ( NULL != paOrigFuncs ) && ( TRUE == IsBadWritePtr ( paOrigFuncs , sizeof ( PROC ) * uiCount ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } if ( ( NULL != pdwHooked ) && ( TRUE == IsBadWritePtr ( pdwHooked , sizeof ( UINT ) ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } // Is this a system DLL, which Windows95 will not let you patch // since it is above the 2GB line? if ( ( FALSE == IsNT ( ) ) && ( (DWORD)hModule >= 0x80000000 ) ) { SetLastErrorEx ( ERROR_INVALID_HANDLE , SLE_ERROR ) ; return ( FALSE ) ; } // TODO TODO // Should each item in the hook array be checked in release builds? if ( NULL != paOrigFuncs ) { // Set all the values in paOrigFuncs to NULL. memset ( paOrigFuncs , NULL , sizeof ( PROC ) * uiCount ) ; } if ( NULL != pdwHooked ) { // Set the number of functions hooked to zero. *pdwHooked = 0 ; } // Get the specific import descriptor. PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor ( hModule , szImportMod ); if ( NULL == pImportDesc ) { // The requested module was not imported. This is not an error. return ( TRUE ) ; } // Get the original thunk information for this DLL. I cannot use // the thunk information stored in the pImportDesc->FirstThunk // because the that is the array that the loader has already // bashed to fix up all the imports. This pointer gives us acess // to the function names. PIMAGE_THUNK_DATA pOrigThunk = MakePtr ( PIMAGE_THUNK_DATA , hModule , pImportDesc->OriginalFirstThunk ) ; // Get the array pointed to by the pImportDesc->FirstThunk. This is // where I will do the actual bash. PIMAGE_THUNK_DATA pRealThunk = MakePtr ( PIMAGE_THUNK_DATA , hModule , pImportDesc->FirstThunk ); // Loop through and look for the one that matches the name. while ( NULL != pOrigThunk->u1.Function ) { // Only look at those that are imported by name, not ordinal. if ( IMAGE_ORDINAL_FLAG != ( pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG )) { // Look get the name of this imported function. PIMAGE_IMPORT_BY_NAME pByName ; pByName = MakePtr ( PIMAGE_IMPORT_BY_NAME , hModule , pOrigThunk->u1.AddressOfData ) ; // If the name starts with NULL, then just skip out now. if ( '\0' == pByName->Name[ 0 ] ) { continue ; } // Determines if we do the hook. BOOL bDoHook = FALSE ; // TODO TODO // Might want to consider bsearch here. // See if the particular function name is in the import // list. It might be good to consider requiring the // paHookArray to be in sorted order so bsearch could be // used so the lookup will be faster. However, the size of // uiCount coming into this function should be rather // small but it is called for each function imported by // szImportMod. for ( UINT i = 0 ; i < uiCount ; i++ ) { if ( ( paHookArray[i].szFunc[0] == pByName->Name[0] ) && ( 0 == _strcmpi ( paHookArray[i].szFunc , (char*)pByName->Name ) ) ) { // If the proc is NULL, kick out, otherwise go // ahead and hook it. if ( NULL != paHookArray[ i ].pProc ) { bDoHook = TRUE ; } break ; } } if ( TRUE == bDoHook ) { // I found it. Now I need to change the protection to // writable before I do the blast. Note that I am now // blasting into the real thunk area! MEMORY_BASIC_INFORMATION mbi_thunk ; VirtualQuery ( pRealThunk , &mbi_thunk , sizeof ( MEMORY_BASIC_INFORMATION ) ) ; VERIFY ( VirtualProtect ( mbi_thunk.BaseAddress , mbi_thunk.RegionSize , PAGE_READWRITE , &mbi_thunk.Protect ) ) ; // Save the original address if requested. if ( NULL != paOrigFuncs ) { paOrigFuncs[i] = (PROC)pRealThunk->u1.Function ; } // Do the actual hook. pRealThunk->u1.Function = (DWORD)paHookArray[i].pProc ; DWORD dwOldProtect ; // Change the protection back to what it was before I // blasted. VERIFY ( VirtualProtect ( mbi_thunk.BaseAddress , mbi_thunk.RegionSize , mbi_thunk.Protect , &dwOldProtect ) ) ; if ( NULL != pdwHooked ) { // Increment the total number hooked. *pdwHooked += 1 ; } } } // Increment both tables. pOrigThunk++ ; pRealThunk++ ; } // All OK, JumpMaster! SetLastError ( ERROR_SUCCESS ) ; return ( TRUE ) ; }
bool RedirectIAT( SDLLHook* DLLHook, PIMAGE_IMPORT_DESCRIPTOR pImportDesc, PVOID pBaseLoadAddr ) { PIMAGE_THUNK_DATA pIAT; // Ptr to import address table PIMAGE_THUNK_DATA pINT; // Ptr to import names table PIMAGE_THUNK_DATA pIteratingIAT; // Figure out which OS platform we're on OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx( &osvi ); // If no import names table, we can't redirect this, so bail if ( pImportDesc->OriginalFirstThunk == 0 ) return false; pIAT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->FirstThunk ); pINT = MakePtr( PIMAGE_THUNK_DATA, pBaseLoadAddr, pImportDesc->OriginalFirstThunk ); // Count how many entries there are in this IAT. Array is 0 terminated pIteratingIAT = pIAT; unsigned cFuncs = 0; while ( pIteratingIAT->u1.Function ) { cFuncs++; pIteratingIAT++; } if ( cFuncs == 0 ) // If no imported functions, we're done! return false; // These next few lines ensure that we'll be able to modify the IAT, // which is often in a read-only section in the EXE. DWORD flOldProtect, flNewProtect, flDontCare; MEMORY_BASIC_INFORMATION mbi; // Get the current protection attributes VirtualQuery( pIAT, &mbi, sizeof(mbi) ); // remove ReadOnly and ExecuteRead attributes, add on ReadWrite flag flNewProtect = mbi.Protect; flNewProtect &= ~(PAGE_READONLY | PAGE_EXECUTE_READ); flNewProtect |= (PAGE_READWRITE); if ( !VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flNewProtect, &flOldProtect) ) { return false; } // If the Default hook is enabled, build an array of redirection stubs in the processes memory. DLPD_IAT_STUB * pStubs = 0; if ( DLLHook->UseDefault ) { // Allocate memory for the redirection stubs. Make one extra stub at the // end to be a sentinel pStubs = new DLPD_IAT_STUB[ cFuncs + 1]; if ( !pStubs ) return false; } // Scan through the IAT, completing the stubs and redirecting the IAT // entries to point to the stubs pIteratingIAT = pIAT; while ( pIteratingIAT->u1.Function ) { void* HookFn = 0; // Set to either the SFunctionHook or pStubs. if ( !IMAGE_SNAP_BY_ORDINAL( pINT->u1.Ordinal ) ) // import by name { PIMAGE_IMPORT_BY_NAME pImportName = MakePtr( PIMAGE_IMPORT_BY_NAME, pBaseLoadAddr, pINT->u1.AddressOfData ); // Iterate through the hook functions, searching for this import. SFunctionHook* FHook = DLLHook->Functions; while ( FHook->Name ) { if ( lstrcmpi( FHook->Name, (char*)pImportName->Name ) == 0 ) { OutputDebugString( "Hooked function: " ); OutputDebugString( (char*)pImportName->Name ); OutputDebugString( "\n" ); // Save the old function in the SFunctionHook structure and get the new one. FHook->OrigFn = (void*)pIteratingIAT->u1.Function; // cyber / cast as void* HookFn = FHook->HookFn; break; } FHook++; } // If the default function is enabled, store the name for the user. if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = (DWORD)&pImportName->Name; } else { // If the default function is enabled, store the ordinal for the user. if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = pINT->u1.Ordinal; } // If the default function is enabled, fill in the fields to the stub code. if ( DLLHook->UseDefault ) { pStubs->data_call = (DWORD)(PDWORD)DLLHook->DefaultFn - (DWORD)(PDWORD)&pStubs->instr_JMP; pStubs->data_JMP = *(PDWORD)pIteratingIAT - (DWORD)(PDWORD)&pStubs->count; // If it wasn't manually hooked, use the Stub function. if ( !HookFn ) HookFn = (void*)pStubs; } // Replace the IAT function pointer if we have a hook. if ( HookFn ) { // Cheez-o hack to see if what we're importing is code or data. // If it's code, we shouldn't be able to write to it if ( IsBadWritePtr( (PVOID)pIteratingIAT->u1.Function, 1 ) ) { pIteratingIAT->u1.Function = (DWORD)HookFn; // cyber / made PDWORD into DWORD } else if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { // Special hack for Win9X, which builds stubs for imported // functions in system DLLs (Loaded above 2GB). These stubs are // writeable, so we have to explicitly check for this case if ( pIteratingIAT->u1.Function > (DWORD)0x80000000 ) // cyber / made PDWORD into DWORD pIteratingIAT->u1.Function = (DWORD)HookFn; // cyber / made PDWORD into DWORD } } if ( DLLHook->UseDefault ) pStubs++; // Advance to next stub pIteratingIAT++; // Advance to next IAT entry pINT++; // Advance to next INT entry } if ( DLLHook->UseDefault ) pStubs->pszNameOrOrdinal = 0; // Final stub is a sentinel // Put the page attributes back the way they were. VirtualProtect( pIAT, sizeof(PVOID) * cFuncs, flOldProtect, &flDontCare); return true; }