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

 

转载于:https://www.cnblogs.com/guanlaiy/archive/2012/05/10/2493672.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值