PE文件格式--------------重定位

一、关于重定位

1、直接寻址指令需要重定位。如:mov eax, dword ptr [4000c0h]

注意:call 401000h 是相对寻址,不需要重定位。

请问 call [401000h]需要重定位吗?

2、重定位需要的信息:重定位地址、实际装载地址、建议装载地址。

二、重定位数据结构

IMAGE_ BASE_RELOCATION struct

  VirtualAddress           dd         ;重定位内存页首地址RVA

  SizeOfBlock               dd         ;重定位块大小,包含本结构在内的大小

IMAGE_BASE_RELOCATION ends 

1、该结构后面紧跟的是word型的重定位项。

2、重定位地址的 RVA = VirtualAddress + word型重定位项的低12位

3、word行重定位项的高4位表示重定位类型,一般常见的值为0和3

高4位值 常量表示 含义
0 IMAGE_REL_BASED_ABSOLUTE 使块按照32位对齐,位置为0
1 IMAGE_REL_BASED_HIGH 高16位必须应用于偏移量所指高字16位
2 IMAGE_REL_BASED_LOW 低16位必须应用于偏移量所指低字16位
3 IMAGE_REL_BASED_HIGHLOW 全部32位应用于所有32位
4 IMAGE_REL_BASED_HIGHADJ 需要32位,高16位位于偏移量,低16位位于下一个偏移量数组元素,组合为一个带符号数,加上32位的一个数,然后加上8000然后把高16位保存在偏移量的16位域内
5 IMAGE_REL_BASED_MIPS_JMPADDR 资料不详
6 IMAGE_REL_BASED_SECTION 资料不详
7 IMAGE_REL_BASED_REL32 资料不详

4、重定位项数 = (SizeOfBlock - 4 - 4) / 2

5、重定位块结束,以IMAGE_BASE_RELOCATION结构的VirtualAddress值为0结束。因此若映像加载00400000h,则代码加载地址为00401000h

6、示例:

(1)运行界面

 

(2)代码processpefile_reloc.asm

;======================
;pe文件重定位表
;by 紫陌
;======================
;======================
;数据段
;======================
.data?


.const
szErrNon    db '没有重定位信息', 0
szBaseReloc   db '重定位首地址:%08X    重定位大小:%08X', 0dh, 0ah, 0
szTitleBlock  db '================重定位块(%08X)(累计大小%08X)=============', 0dh, 0ah, 0
szBlock    db '重定位内存页首地址(%08X):%08X', 0dh, 0ah
      db '重定位块大小(%08X):%08X', 0dh, 0ah, 0
szEntry    db '重定位项(%08X):%04X', 0dh, 0ah, 0

;======================
;代码段
;======================
.code

_ProcessPeFile_Reloc proc _lpImageBase
 local @szBuf[512]:BYTE
 local @dwRelocSize:DWORD
 local @dwEntryNum:DWORD
 local @dwTotalSize:DWORD
 
 pushad
 
 ;********************
 ;从数据目录取重定位首地址和大小
 ;********************
 mov edi, _lpImageBase
 assume edi:ptr IMAGE_DOS_HEADER
 add edi, [edi].e_lfanew
 assume edi:ptr IMAGE_NT_HEADERS
 mov ecx, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC * sizeof IMAGE_DATA_DIRECTORY].isize
 mov @dwRelocSize, ecx
 mov edi, [edi].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC * sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
 .if !edi
  invoke lstrcpy, addr szShowMsg, addr szErrNon
  invoke SetWindowText, hRichEdit, addr szShowMsg
  jmp _overpos
 .endif
 ;*******************
 ;将RVA转为文件偏移
 ;*******************
 invoke _RvaToOffset, _lpImageBase, edi
 add eax, _lpImageBase
 mov edi, eax
 assume edi:ptr IMAGE_BASE_RELOCATION
 ;*******************
 ;显示重定位首地址和大小
 ;*******************
 invoke wsprintf, addr @szBuf, addr szBaseReloc, edi, @dwRelocSize
 invoke lstrcpy, addr szShowMsg, addr @szBuf
 invoke SetWindowText, hRichEdit, addr szShowMsg
 ;*******************
 ;循环显示重定位块
 ;*******************
 mov @dwTotalSize, 0
 .while TRUE
  .break .if [edi].VirtualAddress == 0
  ;****************
  ;重定位块累计大小
  ;****************
  mov ecx, @dwTotalSize
  add ecx, [edi].SizeOfBlock
  mov @dwTotalSize, ecx
  invoke wsprintf, addr @szBuf, addr szTitleBlock, edi, @dwTotalSize
  invoke lstrcat, addr szShowMsg, addr @szBuf
  ;****************
  ;重定位头
  ;****************
  invoke wsprintf, addr @szBuf, addr szBlock, \
   addr [edi].VirtualAddress, [edi].VirtualAddress, \
   addr [edi].SizeOfBlock, [edi].SizeOfBlock
  invoke lstrcat, addr szShowMsg, addr @szBuf
  ;****************
  ;重定位项
  ;****************
  mov ecx, [edi].SizeOfBlock
  sub ecx, 8
  shr ecx, 1
  mov @dwEntryNum, ecx
  mov esi, edi
  sub esi, 8
  .while ecx
   mov @dwEntryNum, ecx
   lodsw
   movzx eax, ax
   invoke wsprintf, addr @szBuf, addr szEntry, esi, eax
   invoke lstrcat, addr szShowMsg, addr @szBuf
   mov ecx, @dwEntryNum
   dec ecx
  .endw
  ;*****************
  ;显示重定位块
  ;*****************
  invoke SetWindowText, hRichEdit, addr szShowMsg
  ;*****************
  ;取下一个重定位块
  ;*****************
;  mov ecx, @dwRelocSize
;  sub ecx, [edi].SizeOfBlock
;  mov @dwRelocSize, ecx
  add edi, [edi].SizeOfBlock
 .endw
_overpos:
 assume edi:nothing
 popad
 ret

_ProcessPeFile_Reloc endp

 

posted on 2012-05-10 08:38  紫 陌  阅读(1742)  评论(0编辑  收藏  举报

导航