本文已在看雪論壇發佈。
工具:RadAsm,010 Editor,LordPE。
源碼
.386
.model flat,stdcall
option casemap:none
include msvcrt.inc
includelib msvcrt.lib
.data
szText db 'welcome', 0ah, 00h
szPause db 'pause', 00h
.code
main:
push offset szText
call crt_printf
add esp, 4
push offset szPause
call crt_system
add esp, 4
ret
end main
end
輸出一句“welcome”,然後執行system(pause)
。
運行
然後。用010Editor打開,開啓重定位。
關於這兩個屬性,文件頭中的IMAGE_FILE_RELOCS_STRIPPED
是去除重定位信息的意思,可選頭中的IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
是動態基址的意思,前者置0,不去除信息;後者置1,開啓動態基址。
再次用OD加載。
可以看到,加載基址變了,但是兩個字符串還有兩個函數的地址還是沒有變,導致程序不能運行。下面就要添加重定位信息,讓它們一塊改變。
添加重定位信息
要分清楚區段和數據目錄表的關係。添加重定位信息要修改的是數據目錄表下標爲5那一項,不是添加.reloc
區段(而且添加了也沒法加載)。區段是規定了屬性,真正用來找到重定位信息的是數據目錄表。
在PE中找個位置,我選擇了700H,然後計算它的RVA。
根據LordPE,700H位於rdata段,RVA==700h-600h+2000h==2100h
。
我們有兩個字符串和兩個函數需要重定位,也就是4個WORD
,加上兩個DWORD
,大小SizeOfBlock == 10H
。數據目錄表中的size還要算上結尾兩個0,所以是12h.
//
// Based relocation format.
//
typedef struct _IMAGE_BASE_RELOCATION {
DWORD VirtualAddress; //RVA
DWORD SizeOfBlock;
// WORD TypeOffset[1]; //end with [00 00]
} IMAGE_BASE_RELOCATION;
struct {
WORD Offset:12; //lower 12 bit relocation offset
WORD Type:4; //higher 4 bit relocation type value : Based relocation types above
}TypeOffset;
因爲我們的程序是32位,所以重定位項的最高位Type
爲3(IMAGE_REL_BASED_HIGHLOW
),64位的PE通常爲A(IMAGE_REL_BASED_DIR64
)。
根據第一張OD加載截圖,VirualAddress==1000H
,4個偏移分別爲001h, 007h, 00fh, 015h
。
這樣,重定位信息就完成了。
00000700: 00 10 00 00 10 00 00 00 01 30 07 30 0F 30 15 30
再次用OD加載看一下。
4個位置的opcode都有了下劃線,說明有重定位,運行也沒有問題。