XCTF-pwn-hello_pwn
这几天在尝试入门,学习pwn的知识点,这是我关于pwn入门做的第一道题目,学习pwn需要很多的前置知识,并且需要一些环境,这里大概描述一下需要什么
- 拥有
C语言基础 - 看懂简单的汇编代码
- 拥有一些
python基础,需要使用到pwntools - 拥有
linux的基础,能够正常使用linux终端 - 简单熟悉
ida
拥有上面的基础后,还需要一些pwn的环境:
python环境ida free或者ida pro: 注意ida free是免费的,不过在反汇编成C语言代码的时候需要联网pwntools安装- 安装
pwndbg linux基础命令的使用gcc、checksec
对上述简单的了解以后,就可以进行简单的pwn题目了,在网上搜课的时候,大多数的师傅都说pwn的漏洞并不是很多,但是需要深入了解,入门难的原因时前置的知识要求高,虽然写这篇博客的时候,我也不太清楚为什么这个题目应该这样做,但是照着题目一点一点的做,不会的在网上搜,一点一点的就会变强,加油!
进入正题,首先我们启动靶机环境,然后题目给我们也提供了一个附件可以下载,这就是靶机端口上运行的服务

我们首先需要下载提供的附件,然后对该附件进行分析,最后得到想要的flag
下载后先使用mv命令将文件改名

然后使用file查看文件属性

上述中重要的信息有:
- 该文件是一个
64架构的ELF可执行文件 - 该文件使用的库文件是
动态链接(dynamically linked)
接着使用checksec命令查看该文件的安全保护机制,在最新版中需要使用--file=指定文件名,可以使用--help查看呢

这些安全机制还没有搞明白,慢慢学,但是比葫芦画瓢要知道这个步骤很重要
接着尝试运行一下该文件,手动的尝试分析,或者说感觉一下这个软件的功能

注意:有些时候在网上下载的ELF 可执行文件是没有执行权限了,使用ls -l可以看到文件是否有可执行(x)的权限,如果没有,使用chmod +x 文件名可以给该文件执行的权限
通过上述的分析,我们该程序进入的时候会输出~~ welcome to ctf ~~和lets get helloworld for bof一段内容,这些不重要,重要的是该程序接受了我们用户的输入,一般程序出问题,都是对用于的输入没有进行严格的过滤和限制,导致程序出现漏洞或者bug,所以这里输出就是我们需要研究的地方
有了上述思路,使用ida free将flag文件打开,由于第一次,这里详细记录一下打开过程

上述图中有三个选项:
New就是打开一个新的程序分析Go就是打开之前已经分析过的程序分析- 第三个还没学,暂时不了解
我们选择New然后调转到下面的页面

这是我们只需选择一个文件即可,这里选择flag文件,Open

然后会进入该页面

我们知道,有很多类型的可执行文件,例如windows中的exe、dll,这里就是选择可执行程序的类型,一般情况下,ida会自动分析程序的类型进行自动选择,这里我们可以不改变,点击OK即可
现在已经在分析flag程序了

该页面就是一个软件最基本的样式,占用页面最多的最多的就是汇编代码区域,这些都是ida分析该软件的特征模拟出的程序伪代码。在左侧显示该程序中执行代码,调用函数的基本流程。
摁下f5,ida会将汇编代码转换为C语言代码

上述,在C语言基础中,我们知道程序运行所有的内容主要在main函数中,所以这里我们找到main函数查看该程序的运行逻辑
{
alarm(0x3Cu);
setbuf(stdout, 0LL);
puts("~~ welcome to ctf ~~ ");
puts("lets get helloworld for bof");
read(0, &unk_601068, 0x10uLL);
if ( dword_60106C == 1853186401 )
sub_400686();
return 0LL;
}
上述中C语言的read()函数常用于读取文件描述符中的内容,常用的三个参数read(文件描述符,指针地址,大小),那么上述代码中0代表读取标准输入的值,也就是键盘输出的值,将输出的之复制给unk_601068这个变量的指针中,输入的内容大小最大为0x10uLL也就是十六进制16个字节uLL代表数据类型为无符号的长长整形
在下方进行了一个if语句的判断,如果dword_60106C变量的之和1853186401相等,那么执行sub_400686()函数,我们双击sub_400686()函数查看该函数的内容。

该函数会字节输出flag.txt的内容,这里我们知道,unk_601068是我们可以控制的,我们双击unk_601068该变量在内存中的地址

出上图中可以看出,unk_601068和dword_60106C之差了四行,也就是四个字节,也可以使用计算器手动计算

这里一共可以获取我们输入的字节数为16个,所以这里可以利用read()溢出,
- 输出四个无用值占位,然后输出
1853186401就可以替换dword_60106C变量的值, - 在
if调用dword_60106C变量时调用的是该变量的内存地址,也就是0x60106C, - 然而这个内存地址的值已经被我们
unk_601068变量的值通过read()函数溢出更改为1853186401, - 最后该程序判断
dword_60106C的值等于1853186401,输出flag
所以我们得思路就是连接靶机运行该脚本,然后输入四个aaaa,然后输入1853186401就对了

但是遗憾是,并没有获得flag,这里我们需要使用pwntools中的p32()函数获取我们传入的字符

可以看到为aaun,再次连接靶机,输入aaaaaaun即可获得flag

这里有一个疑问还有没有解决,为什么手动输入1853186401不行,虽然大概知为什么是错的,但是没有得到证实,不清楚其原理,这让我很难受。

浙公网安备 33010602011771号