還發現在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 可以看出滿足閉包的幾點 閉包的優點 閉包的...