本文共 1159 字,大约阅读时间需要 3 分钟。
在NJUPT2019 ctf比赛过程中我遇到这样一题。
==Difficulty: easy==
flag格式NCTF{.*}此题单纯考察调试flag一调就出哦~~~==Author QQ: 1403517540==
这题目一看很简单就一个名为debug的文件,用ida pro打开看看。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224104307722.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
找到关键代码,就是把输入的flag和一个名为*s的指针执向的字符串进行比较,然后比较成功就显示flag正确。
检查了一下*s的内存位置。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224104427422.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
发现它在main函数里面,偏移位是-210H,那么接下来我们用gdb来调试这个程序。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224110951312.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
等到程序要求我们输入flag的时候按下ctrl+c给予程序中断信号,然后gdb就会进入控制模式,我们可以在这里输入命令查看栈信息。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224111106844.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
输入backtrace(简写bt)可以打印函数到目前为止调用的栈。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019122411122724.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
可以看到__libc_start_main函数所在栈帧是6
注意到其中,main=0x555555554ae6,这个就是我们main函数的基址,很多同学问为什么要这么做,实际上,在linux里面执行main函数的时候是由__libc_start_main来执行的(甚至main函数没有一个独立的栈帧,是和__libc_start_main共享的),因此要找到main函数的栈基址,就要把断点设置在main函数这里,然后查看esp的内容
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224115500508.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
输入 b *0x555555554ae6设置断点
然后再输入run,让程序重新运行。
重新运行就会断点断在main函数开头,此时输入info r查看寄存器的值
![在这里插入图片描述](https://img-blog.csdnimg.cn/2019122412334690.png)
可以看到rsp的值是0x7fffffffe168,同时结合ida pro里面的汇编代码可以判断,0x555555554ae6存放的是push rbp命令。
sub esp 8mov [esp] rbp
那么这个0x7fffffffe168值是存储rbp的地址加上8,那么就可以得到rbp的地址是0x7fffffffe160,对应ida里面的偏移0
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224124954712.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
加上之前得到的变量地址偏移是-210H,那么我们可以判断flag藏在0x7fffffffe160-210的位置也就是0x7FFFFFFFDF50
此时输入c,让程序恢复运行,在要输入flag的时候继续按ctrl+C中断,然后输入tele 0x7FFFFFFFDF50就可以得到flag。
此时再输入c,把程序恢复运行,输入你刚才得到的flag就可以验证是否正确。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224125458888.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
当然,这样看main函数的地址其实还是有点麻烦,更简单的办法是info file命令
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224150810303.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
我们可以看到这里面entrypoint的值是0x5555555546f0
这个段号就是对应ida里面的.text段的开头
![在这里插入图片描述](https://img-blog.csdnimg.cn/20191224151000485.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZqaDE5OTc=,size_16,color_FFFFFF,t_70)
此时可以算出偏移为0x555555554000然后后面的代码只要加上偏移地址即可。
转载地址:http://pistd.baihongyu.com/