學習重定位程式非常棒的範例
直接上Code給大家學習囉
// 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;
}
沒有留言:
張貼留言