- // 11-Nov-2008 Create by Benyanwk
- // Enviroment: Windows all platfrom.
- // Note: (1) Do not support x64
- // (2) Do not support file large than 4GB.
- // (3) Do not use SEH.
- // Revision:
- // 11-Nov-2008 ver1.0
- #define UNICODE
- #include <windows.h>
- #include <winnt.h> // include PE file header definition.
- #include <stdio.h>
- LPCTSTR GetErrMsg(void);
- DWORD
- GetSectionsInfo(
- PVOID pFile,
- PIMAGE_SECTION_HEADER *pSections
- );
- DWORD Reloc( HANDLE hFile, ULONG BaseAddr );
- BOOL RelocFile( PVOID pFile, ULONG BaseAddr );
- DWORD RvaToFileOff( PVOID pFile, DWORD Rva );
- BOOL VerifyPE( PVOID pFile );
- ULONG char2ul(char *lpUlNum);
- int main( int argc, char *argv[] )
- {
- LPCTSTR lpErrMsg;
- HANDLE hFile;
- //
- // Check the arguments
- //
- if( argc != 4 )
- {
- wprintf( L"Usage: /n" );
- wprintf( L"rebase -b baseaddr filepath /n");
- return 1; // indicate argument error
- }
- if( strcmp( argv[1], "-b" ) != 0 )
- {
- wprintf( L"Usage: /n" );
- wprintf( L"rebase -b baseaddr filepath /n");
- return 1;
- }
- //
- // Check the File (existence)
- //
- char *lpFilePath = argv[3];
- hFile = CreateFileA(
- lpFilePath,
- GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- (LPSECURITY_ATTRIBUTES)NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- (HANDLE)NULL );
- if( hFile == INVALID_HANDLE_VALUE )
- {
- lpErrMsg = GetErrMsg();
- wsprintf( L"CreateFile Failed!errorcode = %s", lpErrMsg );
- LocalFree( (HLOCAL)lpErrMsg );
- return 2; // indicate open file error
- }
- //
- // Get the base address
- //
- ULONG ulBaseAddr = char2ul( argv[2] );
- //
- // Reloc the file
- //
- if( Reloc( hFile, ulBaseAddr ) != 0 )
- {
- wprintf( L" Reloc file failed! I'm sorry /n" );
- CloseHandle( hFile );
- return 3; // indicate reloc error
- }
- return 0; // indicate success
- }
- LPCTSTR GetErrMsg(void)
- {
- DWORD dwErrCode;
- LPCTSTR lpErrMsg;
- dwErrCode = GetLastError();
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
- (LPCVOID)NULL,
- dwErrCode,
- MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
- (LPWSTR)&lpErrMsg,
- 0,
- NULL );
- return lpErrMsg;
- }
- DWORD Reloc( HANDLE hFile, ULONG BaseAddr )
- {
- DWORD dwFileSize;
- HGLOBAL pFile; // HGLOBAL = HANDLE = void* = LPVOID
- DWORD dwReturnBytes;
- LPCTSTR lpErrMsg;
- //
- // Read the File to memory
- //
- dwFileSize = GetFileSize( hFile, NULL );
- pFile = GlobalAlloc( GMEM_FIXED, (SIZE_T)dwFileSize );
- if( ReadFile(
- hFile,
- pFile,
- dwFileSize,
- &dwReturnBytes,
- (LPOVERLAPPED)NULL
- ) == 0 )
- {
- lpErrMsg = GetErrMsg();
- wprintf( L"ReadFile failed! error message = %s", lpErrMsg );
- GlobalFree( hFile );
- //
- // indicate read file error.
- //
- return 1;
- }
- //
- // Verify PE file
- //
- if( VerifyPE( pFile ) == FALSE )
- {
- wprintf( L" this is not a PE file /n");
- GlobalFree( pFile );
- return 1; // indicate not pe file
- }
- //
- // Reloc PE file
- //
- if( RelocFile( pFile, BaseAddr ) != TRUE )
- {
- wprintf( L" reloc PE file failed!/n");
- GlobalFree( pFile );
- return 2; // indicate reloc pe file failed;
- }
- //
- // Jmp to the begining of the PE file
- //
- SetFilePointer(
- hFile,
- 0,
- (PLONG)NULL,
- FILE_BEGIN
- );
- //
- // Write back the file
- //
- if( WriteFile(
- hFile,
- pFile,
- dwFileSize,
- &dwReturnBytes,
- (LPOVERLAPPED)NULL
- ) == 0 )
- {
- lpErrMsg = GetErrMsg();
- wprintf( L" WriteFile failed! %s/n", lpErrMsg );
- GlobalFree( pFile );
- CloseHandle( hFile );
- return 3; // indicate write file failed!
- }
- GlobalFree( pFile );
- CloseHandle( hFile );
- printf(" Yes you get it/n" );
- return 0; // indicate success
- }
- DWORD RvaToFileOff( PVOID pFile, DWORD Rva )
- {
- /*++
- Routine Name:
- RvaToFileOffset
- Description:
- Translate the Relative Virtual Address to Raw File Offset
- Arugments:
- File Map; Rva;
- Return:
- File Offset
- --*/
- static DWORD dwSections;
- DWORD i;
- static PIMAGE_SECTION_HEADER pSections;
- ULONG ulDiffer = 0;
- static BOOL bFunExecute = FALSE; // GetSectionInfo should only execute once.(?)
- if( bFunExecute == FALSE )
- {
- dwSections = GetSectionsInfo( pFile, &pSections );
- bFunExecute = TRUE;
- }
- for ( i = 0; i < dwSections; i++ )
- {
- if( (Rva >= pSections[i].VirtualAddress) &&
- (Rva <= (pSections[i].VirtualAddress + pSections[i].Misc.VirtualSize)) )
- {
- //
- // indicate in the this section.
- //
- ulDiffer = pSections[i].VirtualAddress - pSections[i].PointerToRawData;
- break;
- }
- }
- return (Rva - ulDiffer);
- }
- DWORD
- GetSectionsInfo(
- PVOID pFile,
- PIMAGE_SECTION_HEADER *pSections
- )
- /*
- Return number of sections
- Return pointer to sections table
- */
- {
- DWORD dwSections;
- PIMAGE_SECTION_HEADER hSections;
- //
- // Jump to section table
- //
- PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFile;
- PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pFile + pDosHeader->e_lfanew); // e_lfanew + 0x3c
- dwSections = pNtHeader->FileHeader.NumberOfSections; // NumberOfSections + 0x02
- //
- // Allocate the memory for section table
- //
- hSections = (PIMAGE_SECTION_HEADER)GlobalAlloc( GMEM_FIXED, dwSections*sizeof(IMAGE_SECTION_HEADER) );
- //
- // Copy the section table information
- //
- PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(++pNtHeader);
- memcpy( (PVOID)hSections, (PVOID)pSectionHeader, (SIZE_T)dwSections*sizeof(IMAGE_SECTION_HEADER) );
- *pSections = hSections;
- return dwSections;
- }
- BOOL VerifyPE( PVOID pFile )
- {
- PIMAGE_DOS_HEADER pDosHeader;
- PIMAGE_NT_HEADERS pNtHeader;
- pDosHeader = (PIMAGE_DOS_HEADER)pFile;
- if ( pDosHeader->e_magic != 0x5A4D ) // compare with 'MZ'
- return FALSE;
- pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pFile + pDosHeader->e_lfanew); // e_lfanew + 0x3c
- if ( pNtHeader->Signature != 0x00004550 ) // compare with 'PE/0/0'
- return FALSE;
- return TRUE;
- }
- ULONG char2ul(char* lpUlNum)
- {
- ULONG ulSum = 0;
- while(*lpUlNum)
- {
- if(*lpUlNum>='0' && *lpUlNum<='9')
- *lpUlNum = *lpUlNum - '0';
- else if(*lpUlNum>='A' && *lpUlNum<='F')
- *lpUlNum = *lpUlNum - 'A' + 10;
- else
- *lpUlNum = *lpUlNum - 'a' + 10;
- ulSum = ulSum*16 + *lpUlNum;
- lpUlNum++;
- }
- return ulSum;
- }
- BOOL RelocFile( PVOID pFile, ULONG BaseAddr )
- {
- PIMAGE_NT_HEADERS pNtHeader;
- PIMAGE_DOS_HEADER pDosHeader;
- DWORD dwImageBase;
- DWORD pRelocAddr,dwRelocAddr;
- DWORD dwDiffer;
- PWORD pType;
- PIMAGE_RELOCATION pRelocBlock;
- pDosHeader = (PIMAGE_DOS_HEADER)pFile;
- pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pFile + pDosHeader->e_lfanew); // e_lfanew + 0x3c
- dwImageBase = pNtHeader->OptionalHeader.ImageBase;
- dwDiffer = dwImageBase - BaseAddr; // pay attention to the order
- // Get reloc table RVA
- PIMAGE_DATA_DIRECTORY pRelocTable = (PIMAGE_DATA_DIRECTORY)
- pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
- // Get reloc table File Offset
- pRelocBlock = (PIMAGE_RELOCATION)( (PCHAR)pFile + RvaToFileOff( pFile, (DWORD)pRelocTable ) ); // the pRelocTable is file offset?
- do
- {
- pType = &pRelocBlock->Type;
- do
- {
- // Get reloc address's RVA
- if( ( *pType && 0x3000) == 0 )
- {
- if( ( *pType && 0xf000) == 0 )
- continue;
- return TRUE;
- }
- pRelocAddr = pRelocBlock->VirtualAddress + (*pType & 0x0fff);
- // pRelocAddr += dwImageBase;
- // Get reloc address's File Offset
- pRelocAddr = RvaToFileOff( pFile, pRelocAddr );
- // DWORD test = pRelocAddr;
- // Go to the Buffer offset
- pRelocAddr += (DWORD)pFile;
- // Get the reloc address
- dwRelocAddr = *(PDWORD)pRelocAddr;
- // Calculate the new address
- dwRelocAddr -= dwDiffer;
- // Copy to the file
- *(PDWORD)pRelocAddr = dwRelocAddr;
- } while( ++pType < (PWORD)((PCHAR)pRelocBlock + pRelocBlock->SymbolTableIndex) );
- pRelocBlock = (PIMAGE_RELOCATION)((PCHAR)pRelocBlock + pRelocBlock->SymbolTableIndex );
- } while( pRelocBlock->VirtualAddress != 0 );// loop the reloc block entry
- pNtHeader->OptionalHeader.ImageBase = BaseAddr;
- return TRUE;
- }
[代码]重定位文件程序
最新推荐文章于 2022-03-15 23:51:13 发布