XCTF pwn新手区解题记录
一、前言
闲来无事,刷刷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