先看**:
pop.c
extern int stack[512];
extern int top;
int pop()
push.c
extern int stack[512];
extern int top;
void push(int v)
main.c
#include int stack[512];
int top=0;
void main(int n,void * a)
正常編譯時使用gcc -c -g pop.c push.c main.c,然後使用objdump -ds 檢視反彙編:
objdump -ds pop.o
int pop()
27:5d pop %ebp
28:c3 ret
可以看出top的訪問位址都是0。
使用gcc pop.o push.o main.o -o main,然後使用 objdump -ds main檢視反彙編
extern int top;
int pop()
可以看到top的位址已經被硬編碼為0x804a028。
gcc -g -fpic -c pop.c push.c,使用objdump -ds pop.o檢視反彙編
extern int stack[512];
extern int top;
int pop()
上面訪問top需要經過2步驟:
eax = ecx[0]
eax = exa[0]
和一般編譯方式不同,它使用的間接位址訪問top資料。
將這些物件檔案鏈結成為動態庫
gcc -shared -o libstack.so push.o pop.o,然後察看libstack.so的反彙編
000004b8 :
extern int stack[512];
extern int top;
int pop()
比較pop.o可以看出:
top的位址儲存位置由原來的ecx[0]改變為ecx[-12]
另外也能看出stack的位址儲存位置由原來的ecx[0]改變為ecx[-4]
編譯可執行檔案並執行
htm@htm:~/test/testlink$ gcc main.o -lstack -o main -l.
htm@htm:~/test/testlink$ ./main
./main: error while loading shared libraries: libstack.so: cannot open shared object file: no such file or directory
編譯時指定了libstack.so的查詢路徑,但執行時卻找不到這個檔案。
ldd命令能夠模擬程式執行,查詢需要的動態鏈結檔案。
htm@htm:~/test/testlink$ ldd main
linux-gate.so.1 => (0xb77d5000)
libstack.so => not found
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7614000)
/lib/ld-linux.so.2 (0xb77d6000)
對於找不到動態庫可以修改ld_library_path環境變數或者/etc/ld.so.conf檔案,也可以將路徑直接寫入可執行檔案中:
htm@htm:~/test/testlink$ gcc -lstack -l. main.c -o main -wl,-rpath,/home/htm/test/testlink/
htm@htm:~/test/testlink$ ldd main
linux-gate.so.1 => (0xb77d6000)
libstack.so => /home/htm/test/testlink/libstack.so (0xb77d1000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7612000)
/lib/ld-linux.so.2 (0xb77d7000)
注意-l只能告訴編譯器在**找到庫檔案,但是執行時庫檔案在**需要環境變數或者配置檔案或者查詢執行檔案中的rpath
使用wl,rpath後,利用readelf可以檢視到main檔案中多了一些資訊
htm@htm:~/test/testlink$ readelf -d main
dynamic section at offset 0xf18 contains 22 entries:
tag type name/value
0x00000001 (needed) shared library: [libstack.so]
0x00000001 (needed) shared library: [libc.so.6]
0x0000000f (rpath) library rpath: [/home/htm/test/testlink/]
0x0000000c (init) 0x804840c
0x0000000d (fini) 0x804864c
0x6ffffef5 (gnu_hash) 0x80481ac
0x00000005 (strtab) 0x80482e0
0x00000006 (symtab) 0x80481f0
0x0000000a (strsz) 188 (bytes)
0x0000000b (syment) 16 (bytes)
0x00000015 (debug) 0x0
0x00000003 (pltgot) 0x8049ff4
0x00000002 (pltrelsz) 40 (bytes)
0x00000014 (pltrel) rel
0x00000017 (jmprel) 0x80483e4
0x00000011 (rel) 0x80483dc
0x00000012 (relsz) 8 (bytes)
0x00000013 (relent) 8 (bytes)
0x6ffffffe (verneed) 0x80483bc
0x6fffffff (verneednum) 1
0x6ffffff0 (versym) 0x804839c
0x00000000 (null) 0x0
使用這種技術,可以為指定程式新增後門。
程式執行時,遇到動態庫提供的介面或者變數,程式會跳轉到動態聯結器/lib/ld-linux.so.2,在其中完成動態鏈結的過程,並呼叫或者訪問變數。
linux 動態庫的生成和使用
1.動態鏈結庫是程式執行時載入的庫,當動態鏈結庫正確安裝後,所有的程式都可以使用動態庫來執行程式。動態鏈結庫是目標檔案的集合,目標檔案在動態鏈結庫中的組織方式是按照特殊方式形成的。庫中函式和變數的位址是相對位址,不是絕對位址,其真實位址在呼叫動態庫的程式載入時形成。2.動態鏈結庫的名稱有別名 son...
Linux下動態庫生成和使用
1.動態鏈結庫是程式執行時載入的庫,當動態鏈結庫正確安裝後,所有的程式都可以使用動態庫來執行程式。動態鏈結庫是目標檔案的集合,目標檔案在動態鏈結庫中的組織方式是按照特殊方式形成的。庫中函式和變數的位址是相對位址,不是絕對位址,其真實位址在呼叫動態庫的程式載入時形成。2.動態鏈結庫的名稱有別名 son...
Linux 使用gcc生成靜態庫和動態庫
首先,庫是一種可執行 的二進位制形式,可以被作業系統載入記憶體執行。在linux下分為兩種,靜態庫和共享庫 動態庫 對比兩者的區別如下 庫的種類 描述優點 缺點靜態庫 目標檔案的簡單集合,linux下以.a作為字尾,程式編譯時載入 程式所需庫被載入後不會發生跨平台不相容等類似的問題 由於所需的 被載...