[0xFA-2021] [AdWorld] game
你将学习的:
- 如何使用x64dbg / ollydbg
- 动态调试基础
- jmp指令
x64dbg/ollydbg 是什么?
x64dbg和ollydbg是常用的windows平台下的动态调试工具,大家可以在52pojie论坛或者下载ollydbg,x64dbg可以直接百度搜索下载,其中x64dbg是开源免费供大家使用的,这里以x64dbg来作示例。
x64dbg窗口
使用x64dbg打开一个.exe文件就会有如下主要界面
- 反汇编窗口显示反汇编指令,其中eip所指向的地方就是当前程序运行所只执行到的地方。
- 内存窗口显示了程序运行时的所有内存情况,以16进制展示,ASCII行列显示的就是16进制直接对应的ASCII编码,也许有意义也许毫无意义。
- 堆栈窗口显示了堆栈情况,至于堆栈是什么,大家可以暂且忽略不计,只要记得它是堆栈窗口就可以了
- 寄存器窗口,同样寄存器是什么大家现在也不着急了解,在后续的课程上会有专门的讲解,目前大家知道它显示的是寄存器的状态即可。
我该怎么做?
无论何时,直接打开一个文件一探究竟都是最快地了解一个程序的方式。 直接在存放文件目录下右键在此处打开windows terminal,或者在此处打开cmd/powershell(或者直接运行) 推荐大家在windows应用商店下载windows terminal程序,非常方便。 我们只要输入 ./ 然后按tab键补全即可。不用自己输入这么多字符串。
运行之后,根据英文提示可以看出这是一个小游戏,只要依次输入正确的数字就会得到flag
描述翻译 来玩一个游戏 n是等的序号,m是一个灯的状态 如果m是第N个灯的状态,他就是亮的,否则他就是暗的 一开始所有的灯都是关闭状态 现在你可以输入一个n来关闭其中一个的状态 但是你要注意一点,如果你改变第N个灯笼的状态,第N-1个和第N+1的状态也会随之改变。 当所有的灯都是开亮的,flag就会出现
不难发现这个小游戏可以并不一定需要破解的方法得出正确的答案,只要你想明白了游戏的规则,就可以正常地通过游戏的考验获得flag,这当然是可行的!但作为一个逻辑不是很好的同学,我怎么可能能靠浅薄的数学技巧解得答案呢?让我们想一想如何通过破解的方法来获得答案吧。
程序逻辑
让我们想一想没有获得flag和获得flag的流程: 提示语->输入N次->没有获得flag->继续输入直至获得flag 提示语->输入N次->输出正确flag。
我们想要的只是flag而不是复杂繁琐的输入,我们是不是可以通过某种手段让程序执行时直接跳转到输出正确flag呢?显然这是可以做到的。
反汇编
01 什么是反汇编?
前面我们简单的让大家认识了x64dbg的界面,让我们来多讲一点关于反汇编的知识。 一个可执行文件究竟是什么呢?为什么一个可执行文件 *.exe会有内存大小呢?不知道大家有没有思考过这个问题,但这里我们需要有个简单的认识。可执行文件也不过是一些01的组合,也就是所谓的机器语言,数字0和1是占用内存的,而一个程序是不可能只有一个机器语言指令构成,它有大量的机器语言组成,所以一个exe文件有大有小,这和生成这个exe文件的源码有关。同时恰好机器语言和汇编语言有着一一对应的关系,又恰好程序运行时挂载在内存上,所以我们可以通过反编译这些01组成的机器语言来获得汇编语言。 上面的概念对大家来说还是太超前了,在没有学习完就去了解这些知识必然是非常枯燥且痛苦的,大家都学过英语,可以这么类比: 1/0=26个字母,一串1/0(机器语言)=一串单词,汇编=单词的意思。如果我们看到一串字母"CQUPT",你自然会想起这是重庆邮电大学,而如果你看到一串"PTCUQ"你自然也说不出他的意思。对于计算机而言也是如此,一个程序就像一篇英语文章,它有许多字母组成,而其中的字母按照一定规则又组成一个个单词,而一个个单词按照一定顺序就是作者要表达出的意思。计算机运行一个程序就像我们阅读一份报纸,拿在了手里,自然就可以知道上面写的字母是什么,自然可以知道每一个单词是什么,只不过汇编语言是非常抽象、难以阅读的。
02 JMP指令
在这里大家会学习一个比较超前的知识,JMP指令。JMP指令是jump的缩写,就如同它的中文释义一样,它有跳转的意思。在C语言中goto就有和jmp一样的功能。它是无条件跳转,只要运行到jmp指令就执行跳转,跳转执行到目标代码,然后执行。 它的语法为:
jmp Adress
Adress为你想要跳转的地址。
怎么修改程序运行时的代码?
在x64dbg中我们只要右键,选择汇编就可以在当前位置修改汇编代码。 大家可以随意的尝试,即便改错了也没有什么关系,重新运行时修改的代码就会消失。
初见思路
之前我们在程序逻辑块分析了程序的基本逻辑, 程序输出提示信息->用户输入->如果正确输出flag。 不难发现,只要我们 使用JMP指令让游戏直接跳转到输出flag的字符串的部分就可以输出字符串,而避免了要自己玩游戏而获得答案的步骤。 也就是将程序流程修改为: 程序提示输出系信息->输入->直接跳转到输出flag
01_找到输出提示字符串的部分。
还记得我们在IDA中是怎么做的吗? 我们使用了搜索字符串的功能,在x64dbg中我们也有类似的步骤。 我们可以在反汇编界面右键 菜单里找到搜索字符串 我们会看到类似这样的界面,很容易发现几个关键的字符串 “”done!!! the flag is :“” ““Play a game\nThe n is the serial number of the lamp,and m is the state of the lamp\nIf m of the Nth lamp is 1,it’s on ,if not it’s off\nAt first all the lights were closed\n”” 与我们直接运行程序时看到的一些提示性字符串,我们在提示性字符串的行右键,切换断点类型,来下断点,断点是什么呢?断点和我们自己写程序时用IDE下的断点是一样的,程序运行到断点时就会暂停运行。 接下来我们点击向右箭头,就可以继续运行程序。 我们可以点击向下箭头来单步执行,也可以点击右拐向下步过。 我们一直步过。 会看到程序一个一个输出字符串。 我们继续步过。
步过到这里时就不能再继续步过了,原因很简单,程序需要我们提供一个输入来继续执行,很明显0xFB96D4的函数是输入函数。我们在这个地方下一个断点,右键选择断点或者F2都可以下断点。 我们随便输入一个数字按下回车会发现,EIP向下继续了。EIP指向的地方就是程序当前执行到的地方。 接着我们一直按步过,会发现程序会梅开二度再次来到 想到思路了没有?
我们只要在这里修改程序的流程,让程序直接跳转到输出flag的函数就可以作弊获得flag。 我们在字符串窗口赋值"…flag is "的地址 或者你可以记下来是0xFBE968 然后我们在输入函数的后面进行汇编。 修改成功就会是这样子: 接着我们随便输入一个数字,一直步过运行,你就会看到程序跳转到输出flag的过程,一直按步过,或者直接按左上角的 程序就会一直运行下去,最后你会得到flag:
结语:
非常抱歉这次的wp提交的有点晚,各位学弟没能及时得到解析就要马上做下一道题。非常抱歉!!! 我不是一个好学长┭┮﹏┭┮,对不起。 这次的任务相比上次要难的多,因为大家是第一次接触动态调试、汇编语言,也是第一次接触x64dbg。 只要跟着步骤一步一步来,最终能成功的输出flag就已经足够啦! 即便是跟着教程来,我相信大多数人也会很懵逼,不要紧,即使是我写这个wp也是反反复复重新运行了好多次,不要灰心。
最后,非常抱歉!!!!
写的比较仓促,也没有很好地讲解所有的知识点,见谅。
|