来源网站:
buuctf网址:buuoj.cn
江西师大计算机信息工程学院风信子工作室2023新生娱乐赛:fctf.jxnusec.cn
随着网络安全问题重要性的不断提升,逆向的操作也日益提上了议程,本期我们就来聊一下有逆向分析(找flag)方面的一些相关操作。
首先,我们先来看一下2023新生娱乐赛的题目
打开这个网站,你会看到这个界面:
下拉界面,找到>>>_REVERSE(逆向)
本期文章在本网站上讲解的题目是:xor,我的flag怎么不对,【简单】有趣的运算,令人心动的key,upxxx,EzSMC,FlowerDance。
(1),xor
xor,异或运算,这个是位运算中的一种(其余几种在最后有补充)
若存在两个输入A,B将要就行异或运算,那么就会有以下几种情况(不妨设输出结果为F):(在位运算当中,异或运算的符号记为^)
A=1,B=1,F=0;1^1=0
A=1,B=0;F=1;1^0=1
A=0,B=1,F=1;0^1=1
A=0,B=0,F=0;0^0=0
通过上面的描述,我们不难发现:异或运算是可逆的,因此我们就可以对即将逆向的程序进行分析(IDA的使用我会单独补充进行讲解)
由于我们在网站上找到的文件格式为C语言文档的格式,用编辑C语言的软件打开(本人比较推荐Dev c++)打开以后发现为一下界面:
在上方我们知道,异或运算是可逆的,可以进行一下改动(之后我们将这一类通过改动找flag的程序叫做脚本)
a,将需要输入的这行操作使它无效;
b,添加输出字符串;
得到以下结果:
运行结果如下:
FCTF{You_Are_Great_Xor_is_Very_Easy}就为该题的解(也就是我们所谓的flag)
(2),我的flag怎么不对
许多初学者在找到flag{xxx}字样的字符串的时候会不假思索的认为这个就是我们要找的flag,但是事实上有的并不是这个题目的真正的flag。
将该程序用IDA打开
可以看到,有一部分的函数我们并没有见过,甚至有一些并非是函数名,要注意甄别。
再IDA上面显示出的代码为伪C代码,并且若它的函数名称完全正确是可以将其复制粘贴到编译软件上面进行编译运行。
在分析过程中我们可以看到该代码对正确的flag进行了一定的“骚操作”,也就是replace函数里面有以下变换:
通过按R我们可以让这些数字显出原形:(ps:在if和input后面的数值为该字符的ASCII码的值)
通过变换我们可以将原先我们不清楚的变换形式搞明白:
我们就可以将原先的fake_flag变成real_flag了;
原先的fake_flag:
FCTF{This_is_Fake_Flag}
经过更改的real_flag:
FCTF{Th1s-1s-F@ke-Fl@g}
(3),【简单】有趣的运算
对于萌新选手,这个【简单】是相对的,但是只要掌握了一系列的手段以后就可以将其迎刃而解;
将该程序用IDA打开以后,我们就会发现
该伪C代码存在着一定的运算。若想要将这个代码的flaga逆向分析出来,那么运算就得逆向操作。举一个简单的例子,若你希望运算1+1的值为多少,那么逆向运算就是运算2-1的值为多少一个道理。
我们可以通过编写脚本的方法来将这个代码的flag进行分析;
将+运算改为-运算,将一些对我们解出真实flag的题目无关的代码去除,我们得到了一下脚本:
编译运行结果为:
本代码的真实flag为FCTF{Rev3rse_1s_fun_hahaha}
(4),令人心动的key
当我们需要开锁的时候,必须要有钥匙来打开。当然,在我们解锁(找flag)的时候,没有钥匙(key)就不可能打开锁。
完全不知所措,这个时候我们就应该仔细分析每一条语句所包含的意思和逻辑思路。
我们发现,有一个strcpy()函数,也就是字符串复制地址的函数例如:
strcpy(array Name1,array Name2)可以理解为将array Name2的地址复制到array Name1的地址上面。需要注意的是,array Name1要有足够的长度,否则不能输入所拷贝的字符。
另一个值得注意的地方,就是它的encode()函数,不过需要注意的是,这个encode()函数在c语言里面并没有内置的函数,需要自己定义一个;
//encode()函数是python语言里面的一种字符串方法,用于将字符串编码为指定的编码格式。格式如下:
string.encode(encoding='UTF-8',errors='strict')
其中,string
是要编码的字符串,encoding
是指定的编码格式,默认为UTF-8
,errors
是指定编码错误处理的方式,默认为strict
。
gets()函数 会读取整行输入行,直至遇到换行符,然后丢弃换行符,储存其余字符,并在字符末尾添加一个空字符使其成为C字符串。常和 puts()函数 配对使用。//
我们点开进去以后可以发现如下的运算模式:
那么问题来了,我们如何判断哪一个是a1,哪一个是a2?
不难发现,这个函数和a1具有很大关联,那我们就从a1开始看起。
在伪C代码里面,get(&v5[9])是指从v5[9]的位置开始取地址,这样一来既不会把之前的地址取代,也不会造成混乱
通过for循环和上方的encode函数的分析判断,我们可以推断出v5为key, v4为flag。其中a2[i]是经过运算的v4的成果。
那么我们就需要将这个flag进行逆运算。
事实上遇到这样的问题的时候,通过脚本的分析我们就可以将问题迎刃而解。
对此,我写了本题目的第一个脚本:
但是我们运算的结果却是这样子的
这就说明我们的代码分析的思路出现了问题;
解析过程不对,一切都白费;
经过逆运算,我们可以知道后续的flag的输入是将内容输入在了第八位之后的位置,也就是第九位开始进行入位;
因此我们做出如下改动:
运算结果为:
FCTF{Welc0me_t0_Rev3rse}
(5)upxxx
像平时一样,我们为了让我们的贵重物品不被拿走,我们都会将我们的东西所在柜子里面;类似的,我们若想将我们所需要的信息保护起来,那么我们就要将其进行加壳操作;因为我们的工作是从逆向分析方向出发,也就是脱壳(具体操作要领我后续会有说明)
进过脱壳以后将其用IDA打开我们看到了如下的界面:
将几个变量更改名字(N),Str改名为input,Str2改名为data;点击merge函数进去分析:
我们会看到一下的运算和操作,也就是说,这个函数将我们所需的flag进行一定的运算之后,就变成了这个样子
FBRCw?*XQ'u^iK,rYNho_g_e]c[v
是不是乍一看有点看不懂?没事,我也一样。
我们看到,上一个for循环对我们的a1(也就是我们的字符串没有任何影响,所以我们可以忽略掉)仅仅只是计算长度而已。
看第二个for循环,我们看到,在break下面一行的运算,就是我们所要分析的核心部分,也是将我们需要的flag进行变形的环节(或者说是操作)
那么,搓脚本!
运行结果如下:
此题flag为:
FCTF{D0_Y0u_kN0w_Upx_hahaha}
(6)EzSMC
当我们将所需要的文件打开之后,我们会发现我们看到的代码并不是我们所期望的类型,这是因为我们所需要编译的环境被花指令弄乱了,因此我们需要对其进行修复和重新识别;这个也是我们所需要进行操作的内容,
其详细步骤如下;
1. Edit>Patch program>change byte
2. 将e8修改为90(nop)
也可以快捷键ctrl+n直接nop
3. nop完可能被认为是数据
需要按c重新识别为代码
需要注意:花指令一般都是32位的,因为这样子可以方便写内敛汇编。
不过当我们打开的时候会发现我们需要的main函数并不存在于我们的这个选项里,那么我们就可以点击左侧的蓝框,ctrl+f然后输入main回车
你会看到这样的一个代码:
都是乱码,这是因为我们程序的指令里面出现了花指令,让ida很难识别出来,那么,我们就应该修改它的花指令来达到我们的目的。
回到最开始的界面,我们就可以发现有两个被标红的指令,这就是花指令,想要除去,就按照上方的步骤进行。注意,下方还有一个花指令。
可以先按F5看看自己的代码有没有显示出来,若没有显示,那么返回到main函数的起始位置
按p,让ida进行重新识别
左侧的函数框上就会出现新的_main函数的选项,点开以后代码就是以下形式
错脚本干嘛?愣着啊!
可以看出来,这个和那一题令人心动的key有着异曲同工之妙,那么,我们就可以对上述代码进行脚本分析。(以后分析代码的时候尽量将脚本写出来,方便以后复盘和复习)
注意,脚本的分析代码是要自己搓出来的而不是代码一开始就会给你这个完整的脚本。