一、前言
闲来无事,刷刷ctf题
二、题目: level0
1、下载好题目后,拖入到kali中去,用 file
和 checksec
查看一下,可以发现该程序是 64位
,只开了 NX
保护,如下图所示:
2、拖入到 IDA
中去,发现在 main
函数中打印出信息后就调用了 vulnerable_function
函数,跟进 vulnerable_function
函数,可以发现 read
函数处为栈溢出漏洞,并且可以得知该 buf
数组距离 ebp
为 0x80
个字节,如下图所示:
3、通过 IDA
,可以发现程序中存在一个名为 callsystem
的函数,可以直接 getshell
,有了这个加上上面的偏移量,就可以直接编写 exp
, exp
执行结果如下图所示:
三、题目: level2
1、下载好题目后,首先使用 file
和 chseksec
,可以发现程序是 32
位并且开了 NX
的,如下图所示:
2、拖入到 IDA
当中去,可以发现程序首先调用 vulnerable_function
函数后就打印一串字符串就结束了,跟进到 vulnerable_function
中去,可以发现 read
存在栈溢出,并且 buf
距离 ebp
为 0x88
,如下图所示:
3、上面我们找到了 buf
距离 返回地址
的偏移量(0x88+4),仔细观察,我们可以发现存在 _system
函数可以 getshell
,跟进去该函数后,可以发现,需要传入字符串 /bin/sh
作为参数才能 getshell
,使用快捷键 shift+F12
调出字符串界面,发现了该字符串,那么我们的 payload
应该为 0x8C * b'A' + p32(_system函数地址) + p32(0) + p32(/bin/sh字符串地址)
(PS:这里之所以有一个 p32(0)
,是因为我们正常调用一个函数时,栈从高到底的结构为:参数 返回地址 ebp,所以这里我们需要提供一个虚假的返回地址以模拟正常的调用过程),最后 exp
执行结果如下图所示:
四、题目: string
1、下载好题目后,拖入到kali中去,用 file
和 checksec
查看一下,可以发现该程序是 64位
,如下图所示:
2、将程序拖入到 IDA
中去,在 main
函数中,首先调用 alarm
函数设置了 0x3C
秒后关闭程序,然后给变量 v4
申请了 8个字节
的空间,并且给 v4[0]
赋值为 68
、 v4[1]
赋值为 85
,之后就是调用 puts
函数打印一些信息,然后就调用 sub_400D72
函数,并且将 v4
数组作为参数传入,之后 main
函数就结束退出了,如下图所示:
3、跟进 sub_400D72
中去,该函数首先要求输入一个名字,如果长度小于等于 0xC
,则创建一个角色,然后依次调用 sub_400A7D
、 sub_400BB9
、 sub_400CA6
函数,否则就退出,如下图所示:
4、跟进到 sub_400A7D
中去,该函数只有输入 east
才能正常返回,如下图所示:
5、接着跟进到 sub_400BB9
中去,该函数首先要求我们输入一个数字,如果输入的数字为 1
,则进入一个 if
里面去,在该 if
块里面,首先要求输入一个数字,然后要求输入一串字符串,紧接着该函数直接将该字符串作为参数传入到 printf
函数中去了,很明显的格式化字符串漏洞,如下图所示:
6、接着分析一下 sub_400CA6
,该函数首先调用 puts
函数打印一些信息,然后判断参数数组 a[0]
是否等于 a[1]
,如果相等,则申请一片空间,然后通过 read
函数获取用户输入写入到刚刚申请到的空间中,然后把该空间中的值作为一段代码执行,而这里的参数数组就是 main
函数的 v4
数组,如下图所示:
7、有了上面的分析,可以很明显得出解题的方法,首先利用格式化字符串漏洞,将 v4[0]=v4[1]
,然后写入 shellcode
来 getshell
,首先我们来寻找一下偏移量,执行程序,输入名字之后,输入 east
,然后输入 1
,之后输入 payload
测试偏移量,从下图可以看出,偏移量为 8
,如下图所示:
8、有了偏移量,就可以写 exp
了,但这里有一个小坑, __isoc99_scanf
函数这里前几个字节没办法直接作为地址写入(PS:事后对比了其他师傅的wp,发现 IDA
反编译出来的内容都有点不同,不知道是不是这个原因),这里使用代码中前面输入那个地址,偏移量为 7
,在上面的图片中已标注,执行 exp
,结果如下图所示:
五、题目: guess_num
1、首先下载好题目,拖入kali中查看一下基础信息,可以发现为 64位
的程序,如下图所示:
2、拖进 IDA
中,发现程序首先生成了一个随机种子,然后调用 gets
函数获取输入,典型的栈溢出漏洞,但前面保护全开,也没法直接覆盖返回地址来 rce
,往下接着看,要求用户练着猜10次并且全部正确就可以得到 flag
,前面存在一个栈溢出,虽然没办法来 rce
,但可以用来覆盖随机化种子,有了种子,我们就可以直接提前计算出来随机值,而 gets
输入距离种子偏移量为 0x20
,如下图所示:
3、直接使用c算出随机值,然后 nc
连接上去即可得到 flag
(PS:不知道我的python脚本为啥一直得不到flag,这里就直接简单粗暴的nc连接了),如下图所示:
六、题目: get_shell
nc
连接即可,如下图所示:
七、题目: int_overflow
1、还是首先拖入到 kali
中查看一下基础信息,可以发现是 32
位的程序,如下图所示:
2、运行一下程序,没发现什么有意思的东西,拖入到 IDA
中去,根据运行时的字符串,定位到了 main
函数中去,分析一下 main
函数,就是一个登录流程,没什么可疑的地方,如下图所示:
3、跟进到 login
函数中去,可以发现最多可以输入 0x199
大小的密码,其余地方也没什么可疑的,如下图所示:
4、跟进到 check_passwd
函数中去,首先可以发现当中的 v3
变量大小是一字节,然后程序将密码字符串的大小赋值给了 v3
,之后判断 v3
是否小于3,大于8,如果是,就退出,否则就打印信息并将密码拷贝到 dest
数组中去,结合题目名的提醒,可以发现这里存在整数溢出漏洞,可以绕过其对 v3
的判断,然后栈溢出覆盖返回地址,如下图所示:
5、那么 v3
等于多少时能绕过喃,这里 v3
只有一个字节大小,所以我们只需要使我们输入的密码长度的最后一个字节为 4,5,6,7,8
之中的一个即可,这里密码最多可输入 0x199
字节,写一个判断脚本跑一下所有可能,如下图所示:
6、这里选择第一个 260
,接下来我们还需要偏移量, IDA
已经给出了,为 0x14
到 ebp
,那么我们覆盖 0x18
字节之后即可覆盖返回地址,在该程序中,还存在一个直接获取 flag
的函数 what_is_this
,我们直接将返回地址覆盖为这个函数地址即可拿到 flag
, exp
执行结果如下图所示:
八、题目: cgpwn2
1、下载好题目之后,拖入 kali
中简单查看一下程序信息,可以发现该程序为 32位
,并且开了 NX
,如下图所示:
2、将程序拖入到 IDA
中,首先查看 main
函数,该函数没什么可疑的,如下图所示:
3、跟进到 hello
函数中去,可以发现在函数末尾调用了 gets
函数,很明显的栈溢出,并且从 IDA
反编译的结果我们可以知道数组 s
距离 ebp
为 0x26
,也就是说 0x26 + 4
个字节的偏移量后即可覆盖到返回地址,如下图所示:
4、因为题目开了 NX
,没办法在栈上直接部署 shellcode
来执行,仔细观察,我们发现提供了 system
函数,但是没有提供 /bin/sh
字符串,我们只要想办法制造一个 /bin/sh
字符串即可 getshell
,在 hello
函数中,程序还调用了 fgets
函数获取输入储存到 name
变量中,查看 name
位置可以发现 name
位于 bss
段中,那么 exp
的思路就是首先在程序调用 fgets
处输入 /bin/sh;
字符串,然后再调用 gets
函数处溢出覆盖返回地址为 system
函数地址, exp
执行结果如下图所示:
九、题目: level3
1、下载好题目,拖入到 kali
中去,查看一下程序的基本信息,可以发现程序为 32位
的,并且开了 NX
,如下图所示:
2、将程序拖入到 IDA
中去,首先看一下 main
函数, main
函数首先调用了一个 vulnerable_function
函数,然后就是调用了 write
输出信息到控制台中,没什么存在漏洞的地方,如下图所示:
3、跟进到 vulnerable_function
函数中去,可以发现该函数调用的 read
函数存在栈溢出,并且 IDA
已经计算出来 buf
距离 ebp
为 0x88
,那么覆盖 0x88 + 4 = 0x8C
个字节之后即可覆盖返回地址,如下图所示:
4、仔细观察该程序,可以发现没有 system
等现成的函数可以让我们直接 getshell
,但是存在 libc
和已经调用过的 write
函数,并且题目还给了 libc.so
文件,那么思路就很明显了,首先栈溢出调用 write
函数输出 write
函数的地址,进而获取到 libc
的基地址,因为 libc.so
中存在 system
函数和 /bin/sh
字符串的偏移地址,加上基地址就可以得到对应的绝对地址,之后再栈溢出调用 write
时将返回地址设置为 vulnerable_function
函数的首地址,再次栈溢出覆盖返回地址为前面计算出的 system
的绝对地址即可 getshell
, exp
执行结果如下图所示:
十、题目: cgfsb
1、下载好题目,拖入到 kali
中去,查看一下程序的基本信息,可以发现程序为 32位
的,并且开了 NX
,如下图所示:
2、拖入到 IDA
中去,可以发现程序首先要求我们输入一个名字,然后输入一串信息,之后直接将信息作为传入到了 printf
函数里面去了,典型的格式化字符串漏洞,之后则判断 pwnme
变量是否等于 8
,如果等于 8
,则输出 flag
,如下图所示:
3、经过上面的分析,那么解题的思路就很明显了,利用格式化字符串漏洞将 pwnme
变量修改为 8
即可。那么现在需要确定两个东西,一个是偏移量,另一个是 pwnme
变量的地址,仔细观察可发现, pwnme
变量不是函数局部变量,而是 bss
段的一个变量,双击变量名即可获得地址,至于偏移量怎么确定,这么不过多叙述了,不明白的可以看我上一篇文章https://www.cnblogs.com/aWxvdmVseXc0/p/15734510.html ,这里计算出来偏移量为 10
,如下图所示:
4、最后 exp
执行结果如下所示:
十一、题目: hellopwn
1、下载好题目,拖入到 kali
中去,查看一下程序的基本信息,可以发现程序为 64位
的,并且开了 NX
,如下图所示:
2、拖入到 IDA
当中,进入到 main
函数,会发现程序首先输出一些信息,然后调用 read
函数获取输入,之后比较 dword_60106C
变量是否等于 0x6E756161
,如果相等,这调用 sub_400686
函数,跟进 sub_400686
函数,会发现该函数作用为输出 flag
,如下图所示:
3、有了上面的分析,那么解题的思路就很明显了,利用 read
函数溢出覆盖 dword_60106C
变量为 0x6E756161
,仔细观察一下,会发现 unk_601068
变量增长 4
个字节到 dword_60106C
,既偏移量为 4
,最后 exp
执行结果如下图所示:
十二、相关链接
题目和 exp
的 github
链接:https://github.com/windy-purple/XCTF_PWN
Original: https://www.cnblogs.com/aWxvdmVseXc0/p/15828313.html
Author: windy_ll
Title: XCTF pwn新手区解题记录
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685226/
转载文章受原作者版权保护。转载请注明原作者出处!