初识gdb的使用与数组越界
开始做ISCTF的真题
girlfriend
题目难度:简单
题目描述:你能记住你女朋友的生日嘛?
首先先点评一下,出题人出这个题缝合了两个关卡,把栈溢出,ret2text和数组越界全都考察了一遍,我认为出的水平非常高,符合新生赛要求
当然这么简单的一个题我居然想了一天,也确实是见识少了
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
1 | __int64 vuln() |
canary保护关
NX保护开
PIE关

存在system和bin/sh字符串,而且可以直接getshell
1 | void __fastcall amaze() |
结合本题是除签到以外的第一道pwn题,因此把方向定到了ret2text和栈溢出
利用栈溢出实现任意写
下面来具体分析程序
第一关考察了利用栈溢出实现任意写,以下是第一段payload
1 | payload = 0x28 * b'\x00' |
我们必须要通过strcmp函数关于s1和admin字符串的比较才能进入vuln函数,但是我们无法通过直接写的方式把admin字符串写到s1里,那我们就要利用栈溢出,先通过read覆盖buf,40个,即0x28个字节,然后会溢出到s1,通过栈溢出实现任意写
需要注意的是admin后面跟了三个\x00,因为strcmp(a, b)是逐字节比较a和b,直到遇到第一个\x00才停止,\x00也是字符串结束的标志。admin为5个字节,因此我们最好补充三个\x00凑够8个字节,当然一个\x00有时候也可以
数组越界
进vuln函数开始第二关,我们需要关注的是定义了一个大小为5字节的数组v1,以及定义了局部变量i
然后有一个循环,scanf让我们可以读进long类型的整数,这里需要注意,我们通过这种方式输入的必须是十进制整数,因此我们需要把后门函数的十六进制地址手动转化成十进制的。并且这里用p64打包也是不可以的
v1[i]需要引起我们的注意,这里就涉及到了数组越界的知识
关于数组越界,可以参考下面的文章
总之,程序给v1的内存大小只有五个字节,当我们将其改为v1[6]时,我们就可以往栈上写东西了
我们的思路是,先一次输入5个数,比如1,1,1,1,1,第六次时输入6,为什么要输入6,是因为此时的栈大概是这样的
[高地址]
RIP
RBP
i
v[4]
v[3]
v[2]
v[1]
v[0]
[低地址]
我们输入6后,将会把i覆盖成6,这个时候就能出现a[6],同时循环也不会结束,(如果我们写入1,循环不会继续进行),由于i小于7,i会继续加1,这就有第七次写入的机会
我们必须要知道,这个循环不会因为我们的输入而停止,只要i小于等于7,循环一定是会进行的,并且一定会进行8次
我们可以通过gdb调试一下
1 | from pwn import * |

通过gdb调试,我注意到一个很有意思的事,我明明没有覆盖到rbp,但是rbp指针指向的地址里却有个1

这是没有开始覆盖前的栈,可以看到确rbp天然存了一个1,这就让我们不需要再覆盖rbp了,因此直接加上后门函数的地址即可
1 | from pwn import * |








