重定位表详解
重定位表對于EXE文件是沒有必要的,因為EXE程序是第一個被載入內(nèi)存的模塊。而DLL卻是必須需要重定位信息的,因為DLL不一定加載到它默認(rèn)的ImageBase上。重定位表作為一個單獨的區(qū)塊放到區(qū)塊表中,其名字一般為.reloc。
PE文件通過將所有可能的修改的數(shù)值存放到一個數(shù)組里,以一種統(tǒng)一的方式進(jìn)行修正。
每個重定位信息以一個IMAGE_BASE_RELOCATION開始,采用類似頁分割的方式,由許多重定位塊組成,每個塊是4KB的大小。
IMAGE_BASE_RELOCATION結(jié)構(gòu)如下
VirtualAddress是要修正的數(shù)據(jù)的基地址。
SizeOfBlock是該重定位結(jié)構(gòu)的大小,重定位結(jié)構(gòu)的大小是不定的,在SizeBlock后面緊跟著的就是一個TypeOffset數(shù)組,一個大小是2字節(jié),其中高4位代表修正的類型,低16位是修正的偏移。它的大小與VirtualAddress相加就是要修正的RVA地址。當(dāng)出現(xiàn)一個_IMAGE_BASE_RELOCATION結(jié)構(gòu)體的值全為0時,表明重定位表結(jié)束。
重定位是DATA_DIRECTORY的第6項。
TypeOffset高4位的可能取值:
IMAGE_REL_BASED_DIR64 出現(xiàn)在64位的PE文件中。對于x86而言,所有的基址重定位類型都是IMAGE_REL_BASED_HIGHLOW。并且在一組重定位信息結(jié)束的地方會出現(xiàn)IMAGE_REL_BASED_ABSOLUTE用于對齊操作。
下面來實戰(zhàn)下。
跳到重定位開始處。
其VirtualAddress是0x1000,重定位結(jié)構(gòu)的大小是0x10,也就是說,后面跟著的TypeOffset數(shù)組的個數(shù)是(0x10 - 2 * sizeof(DWORD)) / sizeof(TypeOffset),即4個。
重定位數(shù)據(jù)分別是
- 30 0f
- 30 23
- 00 00
- 00 00
很明顯的看出最后兩個是用于對齊而用的,所以真正有用的是前兩個TypeOffset,他們的類型是3,說明類型是IMAGE_REL_BASED_HIGHLOW,所以我們知道了要修正的數(shù)據(jù)位置為0x100f,0x1023,換算成文件偏移也就是0x60f,0x623。
所以執(zhí)行PE文件前,Loader會遍歷重定位表,找到要修正的數(shù)據(jù),然后用 (實際映像地址-默認(rèn)基址)+該重定位數(shù)據(jù)地址。
補充,之所以TypeOffset只需要12位即可表示x86下的線性地址,是因為我們說了,重定位塊是以頁為單位的,而一頁是4KB,也就是12bit,故我們僅用12位表示偏移即可,高4位就空出來,微軟很聰明的用余下四位干了其他的事情
總結(jié)
- 上一篇: 锐捷linux网卡,CentOS 7安装
- 下一篇: AI2019下载Adobe Illust