南京大学计算机基础(四)踩坑笔记
第六周 缓冲区溢出章节
bang问题:
- 每次输入的id将影响getbuf中的堆栈位置,用-u 12的ebp和-u 123的ebp位置就不一样。
- 注意汇编代码中不能出现a0(代表换行符),如果地址有a0就将它随便改改就行了(a0改为a8-0x8)。
- 注意gdb如果不能重定向,可能是因为你修改了gdbinit:https://stackoverflow.com/questions/78832654/why-my-gdb-cant-read-the-file-by-stdin-very-weird?noredirect=1#comment138988527_78832654
rumble问题:
仔细分析汇编和栈的调用,这道题挺难的!【搞了我3个小时,真的别只用gdb,用ida静态结合gdb动态才是正解。】
- 用ida标一标,其中的write_here是为了随机地址防止你直接push的。write_here存储的字符串是你大写的cookie值,比如我-u 1234的cookie是0x6eecf91d,那么这里就是"6EECF91D"。
- 然后注意的是memcmp比较的是地址,所以你getbuf中应该push一个地址。
- 缓冲区的输入应该长成这样,注意到我的"6EECF91D"的十六进制是0x43454536 0x44313946【注意要颠倒过来】。
- 然后push %esp表示当前地址。
- 注意到栈帧中第一个参数是$ebp+8,所以你要压入一个“返回地址”,我这里压的是0x11111111占位。
Boom问题:
这个最简单了,注意到旧ebp覆盖便会自动返回正确ebp了。
如果你想试试别的方法,可以用push 旧ebp,然后将ebp指向当前esp,然后leave ret.
为什么会有第二种方法呢?它能多考验一下你对栈帧的理解【滑稽🤪】【好吧,其实一开始没想到可以直接覆盖ebp...】
KABOOM问题
首先要了解以下概念,csdn里面有几个csapp的讲解好像都是错的:
- .text代码段不可编辑【所有有.plt】,所以返回地址一定是固定的。
- 这个问题是“每次调用test时将栈随机增长”,所以test栈帧和getbuf栈帧之间的距离仍然是固定的【试想一下如果改成每调用一个函数都随机增长🤪】
- getbuf栈帧的旧ebp会被覆盖,但是esp和ebp位置也能被推导出来:
- 当leave的时候,esp+4
- 当ret的时候,esp+4
- 所以如果我getbuf中ebp和旧ebp距离是48,那么只需要esp+40就可以。
- 因为getbufn走到ret的时候,我们修改过的返回地址并不确定,所以我们需要nop-sledge,也就是用nop一路滑一直滑倒我们的恶意代码:
- 有些博主都讲错了,并不是跳转到缓冲区开拓的最大起始地址,而是应该最大起始地址加一个数,保证能跳到nop雪橇里面【比如我这里0x556839e1是buf起始地址,我的buf数组长度为735字节】:
最后来个nice job 奖励自己凌晨三点还在学习我最喜欢的计算机~~~
真好玩啊,我对逆向挺感兴趣的~~~
【明天有讨厌的数学考试,但是我什么都不会,因为我只有考试才去上课,其他时间都狠狠地翘了......所以明天一天肯定不能把剩下一点学完咯😭】
第七周 elf章节
不学了,数学没意思,套公式算算算,太无聊了。、
开学!
phase1
跟着视频就能做,我这里是0x79+0x60[data节位置].
phase2
phase2其实有点难,哪怕有视频跟着,因为容易出奇怪的小错误。
心在滴血,搞了整整两个小时,踩坑的点在于:
- put和strcmp都要的是char*,所以不能直接push字符串(网上有教程居然直接跳到put执行,我不建议,这一章节本不应该破坏执行顺序的)
- 字符串的顺序问题,注意小端方式,但是在hexedit中是可以正序的(不懂的自己踩坑就知道了🤪)
- 学号是字符串,不要传个$0x11111111
- call的时候偏移地址是算的下一个地址,切记切记......
如上图,我的字符串验证是"yKSPHJa",A函数地址如果是x,call的下一条为2f,设a=x-2f那么-a=~a+1.
不想改了,应该是ebp,esp之类哪里忘了还回去......
Phase3
这道题有点难,因为我对switch跳转表不熟。
基础知识:
- 跳转表在.rodata节中,然后跳转表里面存的是地址的偏移地址。
- 在.o文件中的跳转表地址和可执行文件链接后是不一样的,但是相对偏移地址是一样的。
我尽量讲清晰点:
可以用ida的y键修改HexRays识别错误的char数组范围,我们可以发现这段代码其实相当好理解:
然后汇编里面发现跳转表位于.rodata偏移0x4的地方:
而.rodata节位于0x29c,所以跳转表起始地址为:0x29c+0x4=0x2a0。
现在我们就只修改第一个做个例子,本来Linkbomb输出是:
我们可以用gdb动态分析,发现经过-0x41过后,第一个是0x13,也就是19,那么跳转表中是四字节地址,那么19*4=76=0x4c,那么跳转表起始地址加上0x4c:0x2a0+0x4c=0x2e4,我们可以用hexedit发现0x2e4的地址是:0x000000a5
说明要跳转到这个偏移.text节的a5位置(我的.text节是0x34):
那么0x34+0xa5=0xd9,在hexedit的对应位置即可找到同样的字节码:
我将38修改为31,那么再linkbomb应该是1开头(和先前不一样):
成功(只看第一个)!:
Phase4
:
我认为最难的一章,为什么?因为你一开始不能用gdb动态调试,在ida中也很难静态分析。你必须对重定位表有所了解,然而,mooc南京大学的老师似乎并没有怎么介绍重定位表.....
我画张图帮助大家理解(应该没人比我的这个更细了吧?):
所以从编译到链接的整个流程是这样的:
- 首先,编译器将人能看懂的预处理.i文件编译成.s汇编文件。当它看到一个变量(准确来说应该是符号,比如函数名也叫符号啊),他就把它丢到对应的节里面,用symtab记录位置【比如上文的0x0320+0x20】
- 然后呢,你光记录了位置,但是以后怎么知道哪里需要它呢?于是就把具体位置丢到.rel节中。
- 接着,该后人“链接器”登场了。它先逐个扫描文件的symtab,将所有在该文件中未定义的符号都放入Undefined(未定义)中,将所有定义了的符号放入Defined中。
- 然后就是消消乐的时间,如果最终U集合还有剩下的,就会报错!熟悉的ld开头报错!
- 如果全部符号都有定义,那就开始重定位吧!查阅.rel节,由于.text节也被整合在一起了,所以也要计算相关位置,最后把最终位置填在代码空缺的地方
我可讲的真好🤪
于是,我没做出来,我也不知道喵的哪里错了,搞了我一晚上了,心太累了。
不知道哪个填错了,好烦,越做不出来越烦,根本不想分析代码.....
放个链接,未来我想做了再回来做......
强行完结!!!!撒花(▽)
本文来自博客园,作者:muyiGin,转载请注明原文链接:https://www.cnblogs.com/muyiGin/p/18343777