ELF檔案的「匯出表」 延遲繫結

2021-10-02 05:26:04 字數 2504 閱讀 3451

還發現在ida在顯示elf的匯入表時沒有顯示匯入函式所在的庫檔案

並沒有顯示_libc_start_main( )、puts( )函式所在的庫檔案,感覺elf檔案的重定位好神秘。

顯示依賴3個檔案:

linux-gate.so.1檔案      可以看到載入位址屬於linux核心空間,整個檔案系統中也搜尋不到這個檔案(慢慢搞明白這個檔案作用吧)

/lib/ld-linux.so.2檔案     是乙個軟連線,指向動態連鏈結器,動態鏈結器在作業系統載入完可執行檔案後,接過控制權從自身的入口位址(動態鏈結器也是乙個共享庫)開始一系列自身的初始化工作,並對可執行檔案進行動態鏈結,完成之後把控制權交給可執行檔案的入口位址,elf程式正式執行。這個動態鏈結器其實也是就是.interp節區的那個字串:

/lib/i386-linux-gnu/libc.so.6檔案     也是乙個軟連線,連線到同目錄下的libc-2.23.so檔案,用ida開啟可以看到裡面匯出了_libc_start_main( )、puts( )函式

匯入函式的位置找到了,那麼elf檔案中是如何定義匯入表的呢?

elf檔案規定:

.got節區用來儲存全域性變數的位址值

.got.plt用來儲存匯入函式的位址值

.rel.dyn存放對全域性變數的修正資訊

.rel.plt存放對匯入函式的修正資訊

先看一下.rel.dyn、.rel.plt節區的內容:

對於r_386_jump_slot型別,只需要把函式位址直接填入對應記憶體即可(其他的重定位型別有不同的位址計算方法)

可以看到在記憶體偏移0x0804a00c存放著puts( )函式位址、偏移0x0804a010存放著_libc_start_main( )函式位址

我們再看一下檔案中.got.plt節區的內容:

有沒有注意到內容不一樣,為什麼???

因為elf檔案引用的外部函式使用了延遲繫結,具體**流程如下:

.text 0x0804832c:	call   0x80482f0 <__libc_start_main>

.plt 0x080482f0: jmp dword ptr ds:0x804a010

.plt 0x080482f6: push 0x8 序號

.plt 0x080482fb: jmp 0x80482d0

gdb中無法反彙編的**

.plt 0x80482d0: push dword ptr ds:0x804a004 模組id

.plt 0x80482d6: jmp dword ptr ds:0x804a008 _dl_runtime_resolve()函式位址

因為使用了延遲繫結第一次呼叫_libc_start_main( )函式時,會轉到.plt  0x080482f0:    jmp    dword ptr ds:0x804a010指令處,由於是第一次呼叫0x0x804a010記憶體處應該是檔案中的原始值0x080482f6(這樣就一致了);

呼叫 _dl_runtime_resolve( )函式,結合入棧的模組id和序號中找到_libc_start_main( )函式位址,呼叫並把這個位址填入0x804a010記憶體處(覆蓋掉原始檔中的初始值0x080482f6,和ida顯示的值就對應了),這樣第二次呼叫_libc_start_main( )函式時,直接就跳到函式處,不用再用_dl_runtime_resolve( )函式尋找了。

貼上gdb除錯的**:

0x080482d0處記憶體反彙編失敗,只能在od中修改二進位制值檢視**了(唉!能用的辦法都用上了):

最後,如果要在linux下顯式呼叫外部函式、變數,需要使用以下4個函式:

void * dlopen( const char * pathname, int mode);

void * dlsym(void * handle,const char * symbol);

char * dlerror(void); // 返回錯誤資訊,成功返回null

int dlclose (void *handle);

ELF檔案 重定位表

重定位 relocation 是把符號引用與符號定義鏈結到一起的過程 比如,當程式呼叫乙個函式時,將從當前執行的指令位址處跳轉到乙個新的指令位址處去執行 然而在編寫程式的過程中,只需要指明所要呼叫的函式名 即符號引用 即可,然後,在重定位過程中,動態鏈結器會把函式名與函式實際所在的位址 即符號定義 ...

php的延遲靜態繫結

先說下定義 就是把本類在定義階段固定下來的表示式或者變數,改在執行階段才決定。這個是為了解決下面 的問題才引入的 class parents class child extends parents echo child render parents可以看到我們使用self關鍵字只能夠訪問到該類中的靜...

Python中的延遲繫結

延遲繫結出現在閉包問題中。下面我們看乙個閉包的例子 def gen mul n defmul x return n x return mul double gen mul 2 double value double 6 print double value 可以看出滿足閉包的幾點 閉包的優點 閉包的...