zoukankan      html  css  js  c++  java
  • 重定位

    1.代码重定位提出

    可执行代码在PE文件中移动到另一个位置时,内容并不变,但如果全局数据位置变了但是某些使用绝对地址定位的操作数的代码将不会改变,这时

    仍然引用目标将会出错.

    例如: 

    0040103B >/$ B8 00304000 mov eax,parseRel.00403000 ; ASCII "test"

     操作数是个绝对地址,如果重定位后这条代码不修改,那么引用的是重定位后的parseRel.00403000 地址.将可能出错

    2.PE文件重定位表原理

    PE文件的默认加载基址被其他文件占用时,如加载dll时,2个dll默认加载到同一个地方,但是后一个如果要加载成功就需要重定位表.

    因此重定位表常常用于dll中

    对于一个地址,它是4B大小,正常来说如果有n个地址需要重定位将需要n*4个字节大小的缓冲来存储这些地址. 但是Windows采用了另一种方式

    存储这些地址: 以一个需要重定位的地址所在的页为单位,且知道该页基址,那么在这个页(4096个字节)中需要重定位的地址只需记录低16bit即可,因为

    这些地址中高16bit都是一样的(其实在这个页中高20bit都是一样的).

    因此保存一个页的重定位信息所需4(页基址RVA)+4(需要重定位的地址个数)+2*n个字节即可.

    重定位表信息存储在OptionHeader的数据目录的第6个字段中: 例如ntdll的重定位位置 :

    在图中该表显示了重定位表的表项IMAGE_BASE_RELOCATION:

    typedef struct _IMAGE_BASE_RELOCATION {
        DWORD   VirtualAddress;  //该页起始RVA
        DWORD   SizeOfBlock;    //该页需要重定位的地址个数
    } IMAGE_BASE_RELOCATION;

    重定位表结构:重定位项结构, 接着是该页的重定位地址信息(2字节),接着是下一个页的重定位项结构,接着是该页的重定位地址信息(2字节).......依次类推如图:

    其中2字节的重定位地址信息的高4bit是重定位类型, 有多种,但只用到了2种:

    0 = IMAGE_REL_ALPHA_ABSOLUTE  无意义,用作对齐

    3=IMAGE_REL_ALPHA_GPREL32    表示双字32bit都需要修正

    于是当高4bit是3时,需要重定位的代码的地址=页基址+映像基址+低12bit

    根据这个地址找到该处代码后即可将其取4字节大小的操作数进行修正.

    3.解析重定位表

     根据以上分析不难写出解析代码:

      1 .386
      2 .model flat,stdcall
      3 option casemap:none
      4 include        windows.inc
      5 include        kernel32.inc
      6 include        msvcrt.inc
      7 includelib    kernel32.lib
      8 includelib    msvcrt.lib
      9 
     10 
     11 .data
     12 addrinfo        db        '重定位基址: 0x%x',0dh,0ah,0
     13 numinfo            db        '重定位地址数量:0x%x',0dh,0ah,0
     14 addrlist        db        '地址列表:',0dh,0ah,0
     15 
     16 tip                db        '请输入文件路径',0dh,0ah,0
     17 errorinfo        db        '错误代码:%d',0dh,0ah,0
     18 noRel            db        '无重定位表',0dh,0ah,0
     19 addritem        db        '0x%x',09h,0
     20 scanfs            db        '%s',0
     21 entercode        db        0dh,0ah,0
     22 .data?
     23 filePath        db        MAX_PATH dup(?)
     24 .code
     25 _RVAToOffset proc _lpFileHead,_dwRVA
     26   local @dwReturn
     27   
     28   pushad
     29   mov esi,_lpFileHead
     30   assume esi:ptr IMAGE_DOS_HEADER
     31   add esi,[esi].e_lfanew
     32   assume esi:ptr IMAGE_NT_HEADERS
     33   mov edi,_dwRVA
     34   mov edx,esi
     35   add edx,sizeof IMAGE_NT_HEADERS
     36   assume edx:ptr IMAGE_SECTION_HEADER
     37   movzx ecx,[esi].FileHeader.NumberOfSections
     38   ;遍历节表
     39   .repeat
     40     mov eax,[edx].VirtualAddress
     41     add eax,[edx].SizeOfRawData        ;计算该节结束RVA,不用Misc的主要原因是有些段的Misc值是错误的!
     42     .if (edi>=[edx].VirtualAddress)&&(edi<eax)
     43       mov eax,[edx].VirtualAddress
     44       sub edi,eax                ;计算RVA在节中的偏移
     45       mov eax,[edx].PointerToRawData
     46       add eax,edi                ;加上节在文件中的的起始位置
     47       jmp @F
     48     .endif
     49     add edx,sizeof IMAGE_SECTION_HEADER
     50   .untilcxz
     51   assume edx:nothing
     52   assume esi:nothing
     53   mov eax,-1
     54 @@:
     55   mov @dwReturn,eax
     56   popad
     57   mov eax,@dwReturn
     58   ret
     59 _RVAToOffset endp
     60 
     61 
     62 LoadPe    proc filename:dword
     63     
     64     LOCAL    hFile:dword
     65     LOCAL    hMap:dword
     66     LOCAL    imageBase:dword
     67     pushad
     68     invoke    CreateFile, filename,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
     69     .if eax==INVALID_HANDLE_VALUE
     70         invoke GetLastError
     71         invoke crt_printf,offset errorinfo,eax
     72         mov eax,0
     73         ret
     74     .endif
     75     mov     hFile ,eax
     76     invoke    CreateFileMapping, hFile,0,PAGE_READONLY,0,0,0
     77     .if eax==INVALID_HANDLE_VALUE||eax==0
     78         invoke CloseHandle,hFile
     79         invoke GetLastError
     80         invoke crt_printf,offset errorinfo,eax
     81         mov eax,0
     82         ret
     83     .endif
     84     mov hMap,eax
     85     invoke    MapViewOfFile,hMap,FILE_MAP_READ,0,0,0
     86     .if eax==0
     87         invoke CloseHandle,hFile
     88         invoke CloseHandle,hMap
     89         invoke GetLastError
     90         invoke crt_printf,offset errorinfo,eax
     91         mov eax,0
     92         ret
     93     .endif
     94     mov imageBase,eax
     95     invoke CloseHandle,hFile
     96     invoke CloseHandle,hMap
     97     popad
     98     mov eax,imageBase
     99     ret
    100 
    101 LoadPe endp
    102 
    103 getRelocInfo proc imageBase:dword
    104     
    105     LOCAL    relocRva:dword
    106     LOCAL    nums:dword
    107     LOCAL    index:dword
    108     LOCAL    sizeofreloc:dword
    109     LOCAL    sizeofall
    110     pushad
    111     mov relocRva,0
    112     mov nums,0
    113     mov index,0
    114     mov esi,imageBase
    115     assume esi: ptr IMAGE_DOS_HEADER 
    116     
    117     mov eax,[esi].e_lfanew
    118     add eax,esi
    119     assume eax: ptr IMAGE_NT_HEADERS
    120     lea ebx,dword ptr [eax].OptionalHeader.DataDirectory[8*5]
    121     mov ebx,dword ptr [ebx+4] ;获取重定位表总大小
    122     mov sizeofall,ebx
    123     mov eax,[eax].OptionalHeader.DataDirectory[8*5].VirtualAddress
    124 
    125     .if eax==0
    126         invoke crt_printf,noRel
    127         mov eax,0
    128         ret
    129     .endif
    130     invoke _RVAToOffset,imageBase,eax
    131     add esi,eax
    132     mov relocRva,esi
    133     invoke crt_printf,offset addrlist
    134     ;至此esi指向重定位表
    135 parse:    
    136     mov edx,dword ptr [esi] ;地址
    137     mov ebx,dword ptr [esi+4] ;大小
    138     
    139     mov sizeofreloc,ebx
    140     mov ecx,sizeofreloc
    141     sub ecx,08h
    142     shr ecx,1
    143     mov nums,ecx    ;获取重定位表项个数
    144 
    145     invoke    crt_printf,offset addrinfo,edx
    146     invoke crt_printf,offset numinfo,nums
    147 
    148     xor edi,edi  
    149     ;output是输出某个重定位表项
    150 output:
    151     
    152     mov edx,index
    153     cmp edx,nums
    154     jnl outputend
    155 
    156     invoke crt_printf ,offset addritem,word ptr [esi+edx*2+8]
    157     inc edi
    158     .if edi == 5
    159         xor edi,edi
    160         invoke crt_printf,offset entercode
    161     .endif    
    162     
    163     lea edx,dword ptr [index]
    164     inc dword ptr [edx]
    165     jmp output
    166     
    167 outputend:    
    168 ;输出完后继续定位到下一个重定位表项,如果超过了总大小则说明没有了
    169     invoke crt_printf,offset entercode
    170     mov index,0    ;将index归0
    171     add esi,sizeofreloc
    172     mov eax,esi
    173     sub eax,relocRva
    174     cmp eax,sizeofall
    175     jnz parse
    176 
    177     
    178     ret
    179 
    180 getRelocInfo endp
    181 start:
    182     invoke    crt_printf,offset tip
    183     invoke    crt_scanf,offset scanfs,offset filePath
    184     invoke LoadPe,offset filePath
    185     .if eax>0
    186         invoke    getRelocInfo,eax
    187     .endif
    188     
    189     
    190     invoke    ExitProcess,0
    191 
    192 end start
  • 相关阅读:
    使用SecureCRTP 连接生产环境的web服务器和数据库服务器
    CSS之浮动
    CSS之定位
    Session的过期时间如何计算?
    浏览器关闭后,Session会话结束了么?
    Spring事务注意点
    Lucene 的索引文件锁原理
    Mysql数据库的触发程序
    记一次jar包冲突
    关于jvm的OutOfMemory:PermGen space异常的解决
  • 原文地址:https://www.cnblogs.com/freesec/p/6669965.html
Copyright © 2011-2022 走看看