首页
论坛
专栏
课程

[原创][代码]重定位程序的实现

2008-11-13 19:28 9312

[原创][代码]重定位程序的实现

2008-11-13 19:28
9312
// 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;  
}  


[挑战]看雪.纽盾 KCTF 2019晋级赛Q3攻击方进行中……,华为P30 Pro、iPad、kindle等你来拿!

最新回复 (7)
newjueqi 7 2008-11-14 15:57
2
0
楼主的代码写得非常规范,学习一个
iilovejuan 2008-11-17 04:40
3
0
看看。。。。。。。。。。。。。。
benyanwk 3 2008-12-8 15:40
4
0
今天翻出以前写一文章,关于重定位表的.附如下:
上传的附件:
greatbob 2008-12-17 12:34
5
0
我现在对重定位还是比较模糊,进一步学习中
bjalq 2009-2-13 00:45
6
0
谢谢LZ,看了你的帖子,才知道自己对PE的结构还是掌握的不行。
今后要多努力了。
也希望LZ多发更多更好的帖子。
ZSYL 2009-6-13 00:25
7
0
学习了.多谢
xinxinqing 2012-11-29 10:01
8
0
if( ( *pType && 0x3000) == 0 )  
            {  
                if( ( *pType && 0xf000) == 0 )  
                    continue;  
                return TRUE;  
            }
上面的&&错误,程序逻辑错误。
应该是用位运算&,否则在实际dll中,有的有问题,我就遇到过。
if( ( *pType & 0xf000) != 0x3000 )  
            {  
                if( ( *pType & 0xf000) == 0 )  
                    continue;  
                return FALSE;  
            }
游客
登录 | 注册 方可回帖
返回