2011年5月18日 星期三

重定位程式的實現Code

學習重定位程式非常棒的範例


 


直接上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; 


} 


 


 


沒有留言:

張貼留言