Skip to content

0x01. 玩转ELF符号

liyansong2018 edited this page Jan 5, 2025 · 3 revisions

ELF符号是一个重要概念,可以指函数名也可以指变量名,elfspirit提供了-B-D参数,用于解析和修改符号。例如对于以下代码,可以使用elfspirit提供的编辑模块,修改符号,达到控制流劫持的目的。

void main() {
    func1();
    getchar();
}

修改导入符号

此代码引用两个外部函数,通过-D可以看到动态链接的符号

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ elfspirit parse -D main.bin
 [+] .dynsym table
     [Nr]    Value Size Type     Bind     Vis       Ndx Name                
     [ 0] 00000000    0 NOTYPE   LOCAL    DEFAULT     0                     
     [ 1] 00000000    0 FUNC     GLOBAL   DEFAULT     0 func1               
     [ 2] 00000000    0 FUNC     GLOBAL   DEFAULT     0 __libc_st[...]      
     [ 3] 00000000    0 NOTYPE   WEAK     DEFAULT     0 _ITM_dere[...]      
     [ 4] 00000000    0 FUNC     GLOBAL   DEFAULT     0 getchar             
     [ 5] 00000000    0 NOTYPE   WEAK     DEFAULT     0 __gmon_start__      
     [ 6] 00000000    0 NOTYPE   WEAK     DEFAULT     0 _ITM_regi[...]      
     [ 7] 00000000    0 FUNC     WEAK     DEFAULT     0 __cxa_finalize

使用编辑模块,可以直接修改符号

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ elfspirit edit -D -i1 -j6 -s"func2" main.bin 
func1->func2

这时,再运行目标程序,我们发现函数func1已被替换为func2

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ LD_LIBRARY_PATH=./ ./main.bin 
Hello, this is func2.

修改导出符号

案例中的函数所在的库文件hello.so提供了func1func2的实现

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ elfspirit parse -D hello.so
 [+] .dynsym table
     [Nr]    Value Size Type     Bind     Vis       Ndx Name                
     [ 0] 00000000    0 NOTYPE   LOCAL    DEFAULT     0                     
     [ 1] 00000000    0 NOTYPE   WEAK     DEFAULT     0 _ITM_dere[...]      
     [ 2] 00000000    0 FUNC     GLOBAL   DEFAULT     0 puts                
     [ 3] 00000000    0 NOTYPE   WEAK     DEFAULT     0 __gmon_start__      
     [ 4] 00000000    0 NOTYPE   WEAK     DEFAULT     0 _ITM_regi[...]      
     [ 5] 00000000    0 FUNC     WEAK     DEFAULT     0 __cxa_finalize      
     [ 6] 00001119   26 FUNC     GLOBAL   DEFAULT    14 func1               
     [ 7] 00001133   26 FUNC     GLOBAL   DEFAULT    14 func2

同样可以按照之前所述的直接修改符号的方法控制执行流,但是这里,我们使用另外一种方式达到函数劫持的目的,即修改符号指向的地址

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ elfspirit edit -D -i6 -j0 -m"0x1133" hello.so 
1119->1133

修改完成后,运行目标程序,会发现函数func1已经替换为func2

jerry@jerry-virtual-machine:~/elfspirit/examples/01_play_symbol$ LD_LIBRARY_PATH=./ ./main.bin 
Hello, this is func2.

设计思想

如果新的符号值长度小于原先符号,则直接将符号对应位置的字符串进行替换即可。但是,如果新符号过长,直接替换会导致字符串表后面的字符被覆盖。因此,在不重新链接的情况下,需要将整个字符串表移动到文件最后,扩充整个节的大小。

Clone this wiki locally