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

 

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

 

    hFileCreateFileA(  

                    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 pFileDWORD 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

 

 

arrow
arrow
    全站熱搜

    殘月影 發表在 痞客邦 留言(0) 人氣()