动态调试工具的使用
做了这么久的pwn
之后又得兼顾一下re
了哈哈哈。废话不多说,这周学了动态调试器的使用,并且轻松解出了那几道题目。
linux
下的动态调试器都知道,gdb
永远的神,windows
的动态调试器就比较各色了,ollydbg
,x32dbg
,x64dbg
。这里我用的是后两个调试器,ollydbg
听师傅们说是不更新了还是咋地也不知道,所以就用了x32和x64dbg
,其实看了一下界面都差不多的。
动态调试注意的就是下断点,改值这一系列操作,让程序按照你想的执行。比如有一个函数就是直接输出flag
,但是它直接又没有完全直接给你,那怎么办?我直接改eip
去执行那个函数不就ok了?与pwn
不一样,pwn
我要通过漏洞去执行,这个的话文件控制权限和这台计算机的权限全部在我手上,它怎么运行我说的算,对不对?那么接下来看几道例题,这个不是说只有动调能做,但是会动调一定比不会的占优势,这是真的。
xctf-game
下载文件并且根据它的描述可以看到是一个32位PE文件且是一个类似游戏的程序,逻辑很简单,输入序列然后通过它函数的判断就可以让程序输出flag
。但是
这个函数不仅复杂,直接从这里破解可以但是比较难,要从外面实现又比较苛刻那么此时我们开启动调然后直接改eip执行这个函数。
x32dbg打开查看内存映射,发现textbss的基址是0x101000
而在IDA里,此段的基址是0x401000
很清楚了,他们之间偏移了0x300000
的地址大小,在IDA里面的所有地址减去0x300000
就可以得到在x32dbg
里的对应地址。然后注意改eip
遵循的原则应该是首先保证栈尽量平衡,并且修改的幅度尽量不大。根据这个原则以及x32dbg
给我们程序一开始的断点。
我们把栈顶的值修改成我们要跳转的地方,并且将eip
向下调3个语句之后就能直接执行输出flag
的语句而不用玩它设计的破游戏了。首先那个函数在IDA里面的地址是0x457ab4
,那么在x32dbg
里面这个地址就是0x157ab4
。我们先把栈顶修改成这个,再把eip
改成 0x77661b78
这里需要注意的是,由于我们破坏了它的栈,因此尽量避免去执行那些函数,遇到尽量跳过。
这里我们不选择执行printf
函数,因为试过就知道由于之前破坏了栈帧会导致不可预估的错误发生,正确做法就是把eip
改到call
那个之后。
其实直接改eip
也一样的,我那种只是改的其中一种方式。
然后下面还有一个prinf
函数我们也选择不执行,在printf
之前下个断点然后F9运行你就可以看到flag
了。
然后返回游戏一看,啥也没有,但是我已经知道了flag
,hhh。
1 | flag:zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t} |
xctf-csaw2013reversing2
题目已经说了运行就可以拿flag
,但是运行发现弹出来的窗口是乱码,IDA反汇编并且反编译之后检查main
函数。
1 | c |
这也太狗了,还会检测在不在调试器中,在的话我还索性不输出了?
跟进去0x41000
函数去看发现有对msgbox
输出的flag
做了点手脚,那么就猜测可能这个部分是用来算正确的flag
的,那么我们的顺序应该是先执行那个函数再输出flag
才对。所以一开始我们改eip
执行0x41000
函数。
直接改了eip
发现并不好使,那么我们就要再main
函数里面直接调用main
函数的代码了。发现还是不行之后,发现int3
指令一直再阻挡,因此把这个指令nop
掉。发现可以直接执行那个函数,执行完了之后发现还是要退出程序,那么我们就得寻找输出这个flag
的函数,为什么我们不能像上面那个题那样,直接能看到变量的值?
问得好,我也不知道qwq,只能在线寻师傅解决这个疑问了。
可以看到这边又两个调用messagebox函数,那么到底选择哪一个,回头看代码里就会发现咱们的messagebox传了四个参数,那么对比一下发现下面的messagebox才是传了四个参数的函数调用,那么我们把eip改到传参那边,运行执行跳出消息框得到flag
1 | flag:flag{reversing_is_not_that_hard!} |