【八芒星计划】静态编译劫持fini_array

24 篇文章 1 订阅

引用:

https://www.freebuf.com/articles/system/226003.html
https://bbs.pediy.com/thread-259298.htm


前言

直接先说使用方法:
fini_array[1]放想要调用的地址addrA,fini_array[0]放__libc_csu_fini的地址,就可以无限调用addrA
也可以用来栈迁移
fini_array[0]放leave,ret,fini_array[1]放ret
 

概括一下,大致的做法就是先将fini_array[0]改为__libc_csu_fini,将fini_array[1]改为main
然后构造rop链在fini_array[2]上(fini_array+0x10)
最后再将fini_array[0]改为leave_ret,fini_array[1]改为ret
 

在这里插入图片描述

//libc_start_main函数原型
__libc_start_main(main,argc,argv&env,init,fini,rtld_fini)

用gdb调试main函数的时候,不难发现main的返回地址是__libc_start_main也就是说main并不是程序真正开始的地方,__libc_start_main是main的爸爸
然鹅,__libc_start_main也有爸爸,他就是_start也就是Entry point程序的进入点啦,可以通过readelf -h

其中,Entry point address: 0x401a60就是_start的地址

rdi <- main
 
rcx <- __libc_csu_init    //在main函数前执行
 
r8 <- __libc_csu_fini    //在main函数后执行

fini:

.text:0000000000402CB0 fini            proc near               ; DATA XREF: start+F↑o
.text:0000000000402CB0 ; __unwind {
.text:0000000000402CB0                 push    rbp
.text:0000000000402CB1                 lea     rax, unk_4B80C0
.text:0000000000402CB8                 lea     rbp, off_4B80B0  ;把fini_array的地址放入rbp
.text:0000000000402CBF                 push    rbx
.text:0000000000402CC0                 sub     rax, rbp        ; rax=0x10
.text:0000000000402CC3                 sub     rsp, 8
.text:0000000000402CC7                 sar     rax, 3          ; rax=2
.text:0000000000402CCB                 jz      short loc_402CE6
.text:0000000000402CCD                 lea     rbx, [rax-1]    ; rbx=1
.text:0000000000402CD1                 nop     dword ptr [rax+00000000h]
.text:0000000000402CD8
.text:0000000000402CD8 loc_402CD8:                             ; CODE XREF: fini+34↓j
.text:0000000000402CD8                 call    qword ptr [rbp+rbx*8+0] ; 先call1,再call0
.text:0000000000402CDC                 sub     rbx, 1          ; rbx=0
.text:0000000000402CE0                 cmp     rbx, 0FFFFFFFFFFFFFFFFh ;-1比较
.text:0000000000402CE4                 jnz     short loc_402CD8 ; 如果不相等
.text:0000000000402CE6
.text:0000000000402CE6 loc_402CE6:                             ; CODE XREF: fini+1B↑j
.text:0000000000402CE6                 add     rsp, 8
.text:0000000000402CEA                 pop     rbx
.text:0000000000402CEB                 pop     rbp
.text:0000000000402CEC                 jmp     sub_4911EC
.text:0000000000402CEC ; } // starts at 402CB0
.text:0000000000402CEC fini            endp

fini_array:

.fini_array:00000000004B80B0 _fini_array     segment para public 'DATA' use64
.fini_array:00000000004B80B0                 assume cs:_fini_array
.fini_array:00000000004B80B0                 ;org 4B80B0h
.fini_array:00000000004B80B0 off_4B80B0      dq offset sub_401BB0    ; DATA XREF: .text:0000000000402C6C↑o
.fini_array:00000000004B80B0                                         ; fini+8↑o
.fini_array:00000000004B80B8                 dq offset sub_401620
.fini_array:00000000004B80B8 _fini_array     ends

这里保存了两个函数指针,分别是fini_array[0]和fini_array[1],参照fini的汇编,是先执行1,再执行0
 
 

看注释应该足够过一遍了,如果还是没懂的话建议配套上面的引用里的文章看

最后提一嘴mov和lea的差别:

mov:

对于变量,加不加[]都表示取值;

对于寄存器而言,无[]表示取值,有[]表示取地址。
lea:

对于变量,其后面的有无[]皆可,都表示取变量地址,相当于指针。

对于寄存器而言,无[]表示取地址,有[]表示取值。

也就是mov加[]是地址,lea加[]是值
 

注意:

1) MOV指令中的源操作数绝对不能是立即数和代码段CS寄存器; 
(2) MOV指令中绝对不允许在两个存储单元之间直接传送数据; 
(3) MOV指令中绝对不允许在两个段寄存器之间直接传送数据; 
(4) MOV指令不会影响标志位

 
来自:

https://blog.csdn.net/fengyuanye/article/details/85715565

一、Memory Monster II

https://blog.csdn.net/carol2358/article/details/106319203

总结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值