您的位置:首页 > 编程语言

[代码]重定位文件程序

2008-11-12 20:21 281 查看
// 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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: