资讯详情

CTF逆向总结(二)

CTF 逆向总结

CTF 逆向总结

题目类型总结:

汇编操作总结:

ASCII码表类总结:

反向、脚本总结:

总结栈、参数、内存、寄存器:

函数类总结:

IDA等软件类总结:

算法总结:

浏览器操作:

特殊语法积累:

非EXE文件类型

bugku 逆向入门:(实际TxT不能直接运行的文件)

攻防世界parallel-comparator-200:(.c文件、大小写字符转换算法、函数积累、相同或0算法积累、线程操作积累、不能直接操作、伪随机数加密算法)

攻防世界tt3441810:(实际TXT文件,不能直接运行,出乎意料flag、可打印字符过滤算法积累)

main函数主逻辑分析(C语言)

不能正常工作EXE文件类型:

攻防世界的csaw2013reversing2:(操作乱码,int3.断点调查,函数积累,不能直接运行。

main算法逻辑平铺类型:

攻防世界逆向入门题Hello, CTF:(简单比较)

攻防世界open-source:(argv[]外部调用输入参数)

攻防世界logmein:(地址小端存储和正向)

BUUCTF的reverse2:(原flag简单操作)

攻防世界666:(函数逻辑封装,函数名称暗示)

p id="%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8CReversing-x64Elf-100%EF%BC%9A%EF%BC%88%E5%87%BD%E6%95%B0%E9%80%BB%E8%BE%91%E5%B0%81%E8%A3%85%E3%80%81%E5%9C%B0%E5%9D%80%E5%B0%8F%E7%AB%AF%E5%AD%98%E6%94%BE%E4%B8%8E%E6%AD%A3%E5%90%91%E3%80%81%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E7%AE%97%E6%B3%95%E7%A7%AF%E7%B4%AF%EF%BC%89-toc" style="margin-left:80px;">攻防世界Reversing-x64Elf-100:(函数逻辑封装、地址小端存放与正向、二维数组算法积累)

攻防世界EasyRE:(栈地址连续小字符串变量、栈中过渡变量反序字符串、/x7f截断字符串、运算符优先级注意)

攻防世界re-for-50-plz-50:

攻防世界IgniteMe:(函数逻辑封装、大小写字符转换算法)

攻防世界zorropub:(伪随机数加密算法、md5加密/解密算法、代码截断重写、函数积累、exe爆破传参、遍历字符加2算法积累)

main函数与迷宫结合类型:

攻防世界maze:(高低位分割数、函数逻辑封装、迷宫结合)

攻防世界easy_Maze:(迷宫结合、地址连续小数组、题目描述暗示、环境准备函数、IDA动态调试、GDB动态调试、IDA的Hex View图热键)

main函数与游戏结合类型:

攻防世界gametime:(游戏通关生成flag、)

main函数与数学算法结合:

攻防世界notsequence:(杨辉三角算法、函数逻辑封装、IDA对char型(byte)的4*计数)

攻防世界SignIn:(RSA加密/解密算法、函数积累、字符ASCII码做索引、ASCII码表相关、RSA的ASCII字符整数16进制拆分转换算法)

攻防世界ReverseMe-120:(base64加密/解密算法、可变参数混淆、寄存器传参、函数名称暗示、冗余中定关键代码、函数积累、数组首地址变化遍历字符串算法积累)

main函数中嵌入大量冗余代码,拆分代码混淆:

攻防世界Newbie_calculations:(非预期行为、不能直接运行、题目描述暗示、栈地址连续小数组、c语言写脚本、不同系统的特殊数、负数作循环条件)

攻防世界testre:(函数逻辑封装、冗余中锁定关键代码、base58加密算法、)

函数逻辑封装类型:

攻防世界的no-strings-attached:(函数名称暗示,GDB动态调试,小端)

攻防世界answer_to_everything:(函数名称暗示、函数逻辑封装、出人意料的flag、题目描述暗示)

攻防世界secret-galaxy-300:(函数名称暗示、题目描述暗示、字符串拆分算法积累)

攻防世界simple-check-100:(IDA动态调试、GDB动态调试)

攻防世界re1-100:(函数逻辑封装、出人意料的flag、非预期行为)

攻防世界elrond32:(argv[]外部调用输入参数符合条件、函数逻辑封装、递归调用算法)

攻防世界babymips:(多层加密操作、函数逻辑封装、移位算法积累、取限制位数算法、奇数偶数判断算法)

main函数中有与本地文件相关的操作类型:

攻防世界getit:(IDA动态调试、GDB动态调试)

攻防世界key:(不能直接运行、多层交叉引用查看、OD动态调试、寄存器传参、同地址变量、动调验证值猜想、冗余中锁定关键代码、运算符优先级注意、大量判断少赋值的字符串比较算法、不用输入类型)

main函数中有与本地环境变量相关的操作类型:

攻防世界catch-me:(不能直接运行、不用输入类型、main函数主逻辑平铺、冗余中锁定关键代码、运算符优先级注意、IDA动态调试、小端转大端存储算法)

main函数主逻辑分析(C++)

main函数中嵌入大量冗余代码,拆分代码混淆:

攻防世界dmd-50:(函数积累、地址小端存放与正向、md5加密/解密算法、出人意料的flag)

攻防世界crazy:(函数名称暗示、地址赋值算法积累、非预期行为、出人意料的flag)

main函数逻辑平铺:

攻防世界re2-cpp-is-awesome:(字符ASCII码做索引、函数逻辑封装、argv[]外部调用输入参数符合条件、align错误反汇编、模板复制操作)

攻防世界reverse-for-the-holy-grail-350:(冗余中锁定关键代码、模板赋值操作、多层加密、倍数条件算法积累、地址差值操作、超位数循环截取算法、正向爆破)

攻防世界easyCpp:(函数积累、函数逻辑封装、lambda自定义函数、IDA动态调试、动调验证值猜想、斐波那契数列算法)

无main函数分析(C语言)

主逻辑平铺一函数内:

攻防世界Mysterious:(地址小端存放与正向,出人意料的flag)

攻防世界流浪者:(多层交叉引用查看、函数逻辑封装、范围算法积累、函数积累)

攻防世界srm-50:

攻防世界hackme:(可变参数混淆、随机抽取比较、取限制位数算法)

无伪代码分析汇编:

攻防世界之76号:(F7和F8交叉使用、函数逻辑封装、寄存器传参、switch正向代入推导)

带壳题目类型

工具直接脱壳类型:

攻防世界simple-unpack脱壳:(工具脱壳)

攻防世界Windows_Reverse1:(工具脱壳、不能直接运行、寄存器传参、地址差值+数组组合遍历字符串、字符ASCII码做索引、ASCII码表相关)

> 和 % 运算符算法积累、正向爆破)">攻防世界Replace:(工具脱壳、解题逆向模板、>> 和 % 运算符算法积累、正向爆破)

攻防世界Windows_Reverse2:(专业脱壳工具、大小写字符转换算法、16进制转10进制算法、遍历字符加1算法积累、同地址变量、base64加密/解密算法、多层加密操作)

攻防世界easyre-153:(函数积累、线程操作积累、IDA伪代码生成优化)

手动脱壳类型:

攻防世界crackme:(ESP脱壳定律、设立硬件访问断点、OD手动脱壳操作、工具脱壳、导入表修复)

攻防世界BabyXor:(ESP脱壳定律、OD动态调试、OD手动脱壳操作、导入表修复、函数逻辑封装、函数积累、环境准备函数、不用输入类型、正向爆破、地址差值操作、for空执行循环遍历字符串)

花指令题目类型(代码与数据混合)

自定义函数自修改:

攻防世界BABYRE:(函数名称暗示、IDA热键重新反汇编、IDA动态调试、栈地址连续小数组)

2021年10月广东强网杯,REVERSE的simplere:(迷宫结合、base64加密/解密算法、)

2021年9月广州羊城杯,REVERSE的RE-BabySmc:(函数积累、移位算法积累、IDA热键重新反汇编、单层交叉引用查看、base64加密/解密算法、正向爆破)

系统函数函数自修改:(HOOK,通常两次修改系统函数,一次改成自定义机器码,一次改回正常)

攻防世界EASYHOOK:(非预期行为、函数积累、手动机器码)

攻防世界梅津美治郎:(函数积累、非预期行为、环境准备函数、IDA动态调试、int3断点考察)

地址运算动态跳转:

攻防世界serial-150:(IDA热键重新反汇编、nop修补垃圾代码、动态地址运算处理、F7和F8交叉使用)

安卓java类逆向分析

java逻辑平铺:

攻防世界Guess-the-Number:(代码截断重写)

JS类逆向分析

攻防世界secret-string-400:(函数名称暗示、JS控制台操作、涉及虚拟机、字节码相关操作)

python逆向分析

pyc文件反编译:

攻防世界re4-unvm-me:(逆向解题模板、md5加密/解密算法、)

攻防世界handcrafted-pyc:(函数积累、涉及虚拟机、代码截断重写、字节码相关操作)

D语言逆向分析(.d后缀)

攻防世界deedeedee:

RC4解密脚本:

INT3断点:

ESP脱壳定律:


非预期行为:

指解题中出现与预想结果不符合的一系列非预期行为,这基本说明了在中间或前面存在其他自己还没分析的操作。

不同系统的特殊数:

指解题中遇到考察特定位数系统中特定的数的真实值的时候,需要辨认出对应的值才能继续解题。如:32位系统中100000000就是0了

冗余中锁定关键代码:

从后往前看,就是确定比较关键对象,从该对象开始排除其他无关变量,一步步找出与该对象有关的其它变量,最后串起找到的所有相关变量,然后开始逆向分析。

题目类型总结:

题目描述暗示:

指题目给出的描述中有解题的大方向思路,以及对解题过程中出现的一些疑惑点的解释。

不能直接运行:

指解题中下载的附件无法正常运行,这种文件通常不需要用户输入,可能是对外界本机环境又要求,需要文件相关操作等。也可能是脱壳后地址混乱,需要修复导入表或梳理地址,还有可能是算法混淆,增加了运算时间。

不用输入类型:

指解题中遇到程序在没有用户输入情况下直接执行,这种不用输入的程序都是直接利用程序外部的一些东西来作为条件继续执行的,如本地环境,文件读取等。这需要我们修改程序外的一些东西,来符合程序的执行。

游戏通关数生成flag:

指与游戏相关的可执行文件中,不是存储型flag,而是与用户输入相关的生成型flag,且以通关数生成flag。通常这种类型的题目改一下判断条件就可以全部通关获取flag了。

迷宫结合:

指解题过程中有类似于迷宫的每一步不能碰点或每一步必须符合在1维或多为字符串上的落点,如:*A**********.***.....**.....***.*********..*********B**

这称之为与迷宫结合类型。算法走迷宫过于耗时,通常整理出迷宫维数后手动来走。

涉及虚拟机:

指解题中设计了个虚拟机,虚拟机的指令和数据来自预定义加载的大量字节码或数字。其实现原理是根据不同的字节码转换代码函数,进行特定的操作。通过调试和输出承接转换后代码的变量,可以呈现出代码的最终样式,有了代码就可以进行进一步解题了。

字节码相关操作:

指在涉及自定义虚拟机的题目类型中只能对字节码进行相关操作来把预定义字节码往代码方向进一步转换。

如:通过用bytes函数把字节码直接转换为字节串。因为bytes函数是以字节序列二进制的形式表示字节串,以字节为单位。可能对得上字节码吧。如:print(bytes(字节码列表).split(b’\x00’))

又如:python反编译中要把二进制字节码写入文件中,再通过相关工具反编译才能得到代码。

多层加密操作:

指解题中原代码逻辑中出现不止一层加密操作,多层加密之间可能彼此有特殊关联,逆向时需要反向一层层来解密,理清每一层解密的关系。

线程操作积累:

指解题代码中设计多线程的交叉,阻塞,共享内存等操作,由于线程知识积累较少,所以每次都要积累。

汇编操作类总结:

int3断点考察:

int 3是断点的一种,代码执行到此处会抛出异常,伪代码中通常会有__debugbreak()函数。因为这不是我们在OD之类的调试器下的断点,所以OD之类的调试器不会处理该断点的异常,而是交给系统处理,而系统的处理方式往往是强制退出。所以我们在动态调试中要改为nop,不然后面的代码就没法执行。

手动机器码:

指解题过程中遇到类似自修改代码的操作。

如HOOK原型:

byte_40C9BC = 0351;

dword_40C9BD = (char *)sub_401080 - (char *)lpAddress - 5; ;跳转到sub_401080地址处

这样写是因为汇编语言JMP address被编译后会变成机器指令码,E9 偏移地址,偏移地址=目标地址-当前地址-5(jmp和其后四位地址共占5个字节)。所以前面直接用E9,这里直接用偏移地址就省去编译生成机器码那一步。

ASCII码表类总结:

字符ASCII码做索引:

指解题中遇到如:*v1 = byte_402FF8[(char)v1[v4]]; 之类的字符做数组索引的表达式。

其中v1[v4]逐个取input_flag的单个字符,这个字符的ascii码作为偏移继续在byte_402FF8[]数组中寻址。(PS:这不是Python中list.index()函数可以用字符查找对应索引!)

ASCII码表相关:

指解题中遇到.data数据节中跟踪变量数组时显示的有大量0FFh这种不可识别字符后又有连续的可打印字符。

因为ASCII编码表里的可视字符就得是32往后了, 所以凡是位于32以前的数统统都是迷惑项,都会被显示成0FFh甚至乱码,不会被索引到的。然后后面32之后就有连续的字符串,这种就是ASCII码表。

逆向、脚本类总结:

解题逆向模板:

第一步确定Flag字符数量,第一个红框处得到flag数量是35。

第二步找到已确定的比较字符串作为基点来反推flag字符。

第三步找出逻辑中与flag直接相关的部分,该部分可以正向爆破或者从尾到头的反向逻辑。然后找到与flag没有直接关联的部分,该部分无需逆向逻辑,直接正向流程复现即可。

正向爆破:

指解题中采用枚举正向爆破的方法,让flag中的每一个字符遍历常用的字符(ascii码表中32-126),带入原伪代码中加密算法(不用逆向),如果成功,就把这个flag存入。

exe爆破传参:

指解题中能够枚举出所有符合条件的输入,但是对正确输入后程序进行的一系列操作不想正向逻辑复现。这是我们可以使用python的subprocess模块通过循环和线程给exe文件批量传入枚举出的所有符合条件的输入,然后检测输出结果是否符合即可。

C语言写脚本:

指解题中对于不需要逆向逻辑的单纯去除冗余代码算法的题目,需要仿写去除冗余代码后的逻辑,由于只是仿写,所以原本的伪代码很难用python复现,这时就需要复制粘贴修改成C语言脚本了。

代码截断重写:

指解题中在有较完整源代码的情况下flag生成与用户输入无关,而且源代码逻辑平铺,代码量少,没有过多函数封装,则可以单独截断提取出flag生成的函数或逻辑,然后运行截断程序输出flag。

出人意料的flag:

指在题目中获取到了flag,但是这个flag可能长得不像flag,或者flag还要经过进一步的脑洞处理,而不是常规的解密处理。

栈、参数、内存、寄存器类总结:

栈地址连续小数组:

指一些本来应该是大数组的变量被IDA识别成分割成两个或多个连续地址的小数组来使用,可以通过查看栈中的地址排列或循环中的循环数大于单个数组空间来发现,也是需要更加细致才能分析出来。

栈地址连续小字符串变量:

指一些本来应该是大字符串的单个变量被IDA识别成分割成两个或多个连续地址的小字符串变量来使用,可以通过查看栈中的地址排列来发现,也是需要更加细致才能分析出来。

同地址变量:

指IDA生成的伪代码中,多个不同名字的变量实际上指向了同一个地址。所以会遇到操作这个变量,取传入另一个变量的现象,这通常具有很大迷惑性,需要我么双击查看栈中的地址才行。

栈中过渡变量反序字符串:

指一些题目本来取输入的字符串变量的最后一位,但是IDA插入了过渡变量来使分析变得困难,如v5 = (char *)&v11 + 7;这里v11就是过渡变量,指向输入字符串input_flag的第16位,所以这里v5指向输入字符串input_flag的最后一位,栈中地址又是从下到上,高位到低位的,所以反序操作标志是v6 = *v5--;

地址小端存放与正向:

指字符串数字等在内存中是反向存放的,如v7 = ‘ebmarah’,如果用地址来取的话要反向,如果用数组下标来取的话才是正向。

高低位分割数:

指一些本来应该是两个小类型变量的数被IDA识别成一个大类型然后分成高位和低位来使用,需要更加细致才能分析出来。

可变参数混淆:

指解题中IDA伪代码显示出来的参数数量超出,不符合逻辑,也不知道多附加了什么操作。查看反汇编才发现并没有传入那么多的参数,原伪代码中之所以有那么多参数是因为C语言的可变参数的特性,有些参数显示了但是并没有用上。

地址差值+数组组合遍历字符串:

指解题中遇到地址减地址的操作如:v4 = input_flag - v1; 然后通过数组组合如:v1[v4]。

这里V1作为地址和v4作为数组v1[v4]执行的是v1+v4的操作,就是v4+v1=input_flag。因为数组a[b]本质就是在数组头地址a加上偏移量b来遍历数组的,所以这里是一种遍历input_flag的新操作。

寄存器传参:

指解题中涉及寄存器作为参数传入,但是有时候IDA无法反汇编出寄存器参数的传入。解题中发现异常如:传入参数为input_flag,但是比较的却是另一个变量,这时就可能是寄存器传参了,要通过查看汇编代码来发现。

/x7f截断字符串:

/x7f可以阻断字符串,在IDA中会把一个长字符串分隔成两行的短字符串。如:xIrCj~<r|2tWsv3PtI /x7f zndka

argv[]外部调用输入参数符合条件:

指解题中需要使用命令行传入参数。

如:int main( int argc, char *argv[] )

$./a.out testing1 testing2

应当指出的是,argv[0] 存储程序的名称,argv[1] 是一个指向第一个命令行参数的指针,*argv[n] 是最后一个参数。如果没有提供任何参数,argc 将为 1,否则,如果传递了一个参数,argc 将被设置为 2。

地址差值操作:

指解题中用数组、字符串首地址、寄存器等地址类或栈地址类的差值来进行操作,有时直接用地址差值做循环条件。此类型可以双击IDA查看栈地址,也可以看IDA陈列在函数上面的类型定义中的esp和ebp相对偏移地址来算出地址差值。特别的rsi源地址寄存器是相当于rsp寄存器的。

函数类总结:

函数逻辑封装:

指关键逻辑被封装成自定义函数,需要自己双击跟进并总结出函数作用,需要通过动态调试验证猜想的作用。

函数名称暗示:

指题目给出的自定义函数名称有含义,可以概括该函数的大致作用,来给总结函数作用提出一些方向性的指导。

函数积累:

指题目中有没做笔记的函数需要终点重温和积累一下。

环境准备函数:

指在用户输入命令之前,是系统程序运行时的自执行代码,是为程序渲染环境做前期准备用的,没有必要弄懂它。如easy_Maze中的step_0和step_1是为程序做迷宫地图的,设计迷宫算法,弄懂它与解题没有太大关系,而且前期准备环境的算法函数也不会有故意出错的地方来设考点,毕竟考点是走迷宫。

lambda自定义函数:

指C++类解题中遇到lambda表达式了,这是C++自定义函数的关键字,函数名入口在前面紧接着std的部分那里,不同常规的C++长模板类名最后一个才是关键函数。不过前面的不过直接双击lambda也是可以跟踪的。

C++函数名前置:

指C++类型解题中,C++长模块关键类名函数中的关键函数名不是常规的在最后面,而是在最前面的std::xx中,除了C++自定义函数之外,C++有很多函数名都在前面std::xx处。最后面通常会有operator运算符搭配在一起。

IDA等软件类总结:

GDB动态调试:

指使用GDB来进行ELF文件的动态调试。

IDA动态调试:

指使用IDA来进行ELF或windows文件的动态调试。

IDA热键重新反汇编:

指解题中必须使用IDA热键对处理过或未处理的的错误反汇编代码重新分析,以至生成新的正确的反汇编代码,常用的有U取消代码定义、C重新定义反汇编、P重新生成函数等,多用在混淆和花指令区。

IDA热键a生成数组:

指解题中对IDA零散的单个字符可以使用热键a生成数组,即长字符串。如果中间没有截断,则可以正常生成字符串。

IDA对char型(byte)的4*计数:

指解题中虽然IDA伪代码显示的 i 是 int 型,但是计算的时候通常会变成 4*i ,这通常会具有干扰性,所以我们要知道这是IDA默认把 i 当成byte类型即可,4*i 和 int 型的 i 是一样的。

单层交叉引用查看:

指在解题中只能确定一些少量的被调用函数,这些函数可能是自定义函数也可能系统函数。通过IDA的function call或Ctrl+x操作来查看改函数被谁调用,从而找到主逻辑所在的函数。

多层交叉引用查看:

指在解题中一开始获得的是比较深层次的被调用函数,需要多次查看交叉引用才能锁定最终的主逻辑所在函数。

IDA的Hex View图热键:

指在IDA的Hex View图右键菜单data format可以调成固定byte类型和有无符号类型。如调成4bytes和signed即可用±1简化显示。

align错误反汇编:

指IDA反汇编过程中自动把多个0判断成对齐操作了,然后会影响数据的分段和脚本的编写。如:align 8是因为前面dd 24h中本来是db 24 0 0 0 然后后面一个双字是dd 0 也就是db 0 0 0 0,IDA把这连着的7个0当成了间隔,那上一个数和下一个数间隔就是8了,所以IDA生成了align 8。我们只要鼠标右键undefine或把上面的dd 24改一下数据大小即可重定义align 8,重新生成数据了。

nop修补垃圾代码:

指花指令类型的题目中地址运算动态跳转情况下,被跳过的指令没有任何用处。但是代码和数据混杂在一起是无法重新F5反汇编生成函数的,垃圾代码中必须用0X90的nop填补才行。用脚本批量填补时通过U键查看垃圾代码的标志指令作为垃圾代码判断条件即可。

动态地址运算处理:

指花指令类型解题中遇到地址运算动态跳转类的反静态汇编模糊代码,如:jz short near ptr loc_400A54+1。需要协助IDA反汇编代码,通过用U取消错误的400A54代码段的定义,然后在400A55处用热键C重新生成反汇编代码后,前面jz short near ptr loc_400A54+1会直接变成jz short near ptr loc_400A55。

F7和F8交叉使用:

指花指令类型解题中不知道断点下在哪里,只能直接运行程序后在输入的地方按下暂停键来先把输入函数定位出来。但是由于输入函数是导入库的函数,所以这时会暂停在0x7开头的导入表地址处,直接单按F8或F7会发现陷入死循环的状态跳不出来,只有F7和F8交叉按才会慢慢跳出到0x4开头的真正代码处。

设立硬件访问断点:

指解题中遇到手动脱壳类型,如利用ESP脱壳定律手动脱壳。这时要根据ESP脱壳定律需要设立对应大小的硬件访问断点,使程序主代码解压后停在OEP处。

OD手动脱壳操作:

指手动脱壳中通过其它操作找到了程序主代码解压后的入口点OEP,然后通过OD插件OllyDump来脱壳当前调试的进程。

工具脱壳:

值传统的用工具压缩的文件,可以直接用工具来解压缩,即脱壳。

专业脱壳工具:

指用工具脱壳中如果exeinfope中有推荐的专业脱壳工具,则直接使用专业的工具。像万能脱壳工具这些可能会生成错误的伪代码,会造成解题错误,所以有专业的工具最好使用专业的工具。

导入表修复:

指加壳类题目中脱壳后程序出现错误,这通常是导入表出错。此时需要用importREC修复导入表,因为ImportREC是内存转储,所以要在程序运行时才能判断导入的库。

IDA伪代码生成优化:

指IDA反汇编生成伪代码中会像c语言的各种编辑器中采取的release版优化输出一样,汇编代码会因为O2优化而与源代码有较大差异。

如固定跳转中会发现ida不可能运行到的代码干脆不进行反编译,甚至如果后面代码操作和上面的处理没关系的话也不会反汇编上面的代码。

解决方法就是把固定跳转的地方用0x90的nop替换掉,注意保持指令大小不变。

动调验证值猜想:

指解题中对某个关键变量的取值或函数功能进行大致的猜想,然后这需要通过动态调试在该位下断点后查看结果是否符合猜想。

验证函数功能时记住在函数外追踪全局变量变化,而不是在函数内追踪局部变量。

双击追踪变量值的时候记住变量类型大小要对得上,有时候变量设置成正确类型大小后会显示一个地址,变量值全在地址内,而不是在双击追踪的.data地址处

算法类总结:

main算法逻辑平铺:

指主要算法代码都在main函数中,不涉及解题算法之外的其它操作,而且代码逻辑平铺、显而易见,没有把关键逻辑分成自定义函数形式,不需要频繁跟进函数。

范围算法积累:

指解题中有涉及用户输入的范围内判断以及逆向算法时对于范围处理的过程中值得注意和积累的地方。如:Str[i] > 90 || Str[i] < 65

地址赋值算法积累:

指解题中涉及对关键字符串如用户输入字符串的操作,原代码中会先把输入字符的地址赋值给变量,即让一个变量指向输入字符串然后再开始修改,这是两步操作,需要辨认。

二维数组算法积累:

指解题中涉及二维数组,用户输入与二维数组要取的下标相关,逆向时要明确是二维数组逻辑以及一维在哪里确定,举例如: *(char *)(v3[i % 3] + 2 * (i / 3)) - *(char *)(i + a1) != 1,(char *)(v3[i % 3] 确定了一维,+ 2 * (i / 3))继续在一维上面取字符串对应位,然后和*(char *)(i + a1) 字符串数组比较且要满足 = 1

数组首地址变化遍历字符串算法积累:

指解题中需要对数组进行赋值,但是数组首地址一直在变化,如:v7++ 。赋值的时候就会出现不断给v7[-1]赋值的现象,因为数组首地址一直往后移动了。但是像ebp一样的基址并没有移动,所以最后的比较不影响。

遍历字符加1算法积累:

指解题中遇到对变量每次加1的算法公式的新形式,如结合移位操作的加1算法,v3+=2 v7=v3 >> 2,加1算法通常与字符串遍历相结合。

遍历字符加2算法积累:

指解题中遇到对变量每次赋值 2 个字符的算法公式的新形式。

如:%02x,x 表示以十六进制形式输出,02 表示不足两位,,前面补0输出,如果超过两位,则以实际输出。

sprintf(&s1[2 * i], "%02x", (unsigned __int8)v11[i])的意思是把相当于char的__int8的两位输出到&s1[2*i]中,也就是一次输出两个__int8(char)类型的v11[i]到s1的偶数地址中,所以也相当于遍历赋值。

for空执行循环遍历字符串:

指解题源代码用空执行的for循环 i ,当 i 没有字符值时就会跳出循环,是一种遍历字符的新操作,通过地址差值用来计算字符串地址长度。

如:for(i=a1; *i; ++i)

; #空操作执行

字符串拆分算法积累:

指解题中IDA对多个连续的字符串按打乱的顺序以下标的方式分别按多组赋值,这种字符串拆分赋值的方式需要动态调试或耐性的一个个跟踪分析才能梳理清楚。

相同异或为0算法积累:

指解题中遇到特定异或为0的条件则可以采用上面的定律。如: *result = (108+argument[1]) ^ argument[2] = 0 即 argument[2]=(108+argument[1]) 因为相同异或才为0

可打印字符过滤算法积累:

指解题中遇到flag等关键字符在内的混杂的大量字符中,要通过多层过滤来一步步生成flag的算法,可打印字符范围内可用算法如:if ord(i)>=32 and ord(i)<=125:

大小写字符转换算法:

指解题中有一些算法范围波动比较少,看似逻辑相关,实际上只是大小写的ASCII值转换而已。

递归调用算法:

指解题中遇到函数内递归调用自己,传入参数也会在调用时修改的算法,当需要用python仿写递归算法时可以通过超范围的循环来实现递归,因为设置同样的条件,递归不满足时仿写的循环也会退出。

杨辉三角算法:

指解题中遇到对传统数学杨辉三角算法的代码实现,辨认的特征是通过关键代码判断是否符合杨辉三角算法的特性,如:在一维中用(n*(n+1)/2的前n行总数来遍历到特定行,又如:2^n来求第n行的和等。通常涉及等差、等比数列。

斐波那契数列算法:

指解题中涉及传统数学斐波那契数列算法的代码实现,用的是fib(j)的斐波那契数列函数直接生成,遇到该函数时要懂得辨认题目考察的内容与斐波那契数列相关。

>> 和 % 运算符算法积累:

指解题中遇到 >> 和 % 运算符的操作。>> 运算符其实是不带余数的除法 / 算法,单取整数部分。% 运算符其实是不带整数的求余运算,单取余数部分。

如: v6 = (v5 >> 4) % 16 是除以16后的整数部分, v7 = ((16 * v5) >> 4) % 16 是乘16后除16再取16内的余数,也就是直接取16内的余数。一个取整数,一个取余数,所以他们的逆向算法就是16 * v6 + v7

(既然v5 >> 4相当于v5除以16取整数部分,是不带余数的除法 / 算法。顺带说一下,v5 & 0xf 相当于v5除以16取余数部分,是完全的求余%算法,这里0xf是4位所以为16。)

移位算法积累:

指解题中遇到类似base64实现的位移动操作考点,特别注意4 * input_flag[i]这种向右移动的乘法变式,这其实是

2<<input_flag[i]操作,更关键的是逆向时也要注意限制位数为8位的 &0xff 。

运算符优先级注意:

指解题中应该要准确判断长运算式的优先级顺序,写脚本中也应该尽可能使用括号来固定优先级,否则会出现结果的错误。

负数作循环条件:

指解题中遇到负数作循环条件的情景需要明白这不是死循环,而是正数大循环。如:while(-1) ,在32位里 -1 就是 FFFFFFFF,就是100000000 - 1。所以这一下子就转正了!如果是while(-a2),所以就循环100000000 - a2次。

随机抽取比较:

指在解题中以随机数做基准,取各个对应的字符进行比较。其实就是在相同的字符中取随机但同样的位来比较,所以逆向是要顺序取。

取限制位数算法:

指解题中遇到源代码有__int8这样的限制,这是取前8位,python中可以使用&0xff这种方法,因为&在Python中是逻辑与运算,所以与的时候就保留了前8位,如:flag+=chr((v12^v15)&0xff)。取前16,32位都可以套用这个方法。

RSA的ASCII字符整数16进制拆分转换算法:

十六进制数组0~F中,有操作将输入的flag字符传入,以字符ASCII码操作后的结果为索引取十六进制内的数。

如:byte_202010[flag >> 4]和byte_202010[flag & 0xFF]。

一个整数一个余数你会发现这是把输入字符变成两个分开的十六进制存储起来,比如输入字符 ‘1’ ,它的整数是49,49除16的整数是3,余数是1,在byte_202010下标中分别对应3和1,构成的31就是字符 '1’的ASCII的十六进制形式,只不过是分开的十六进制,3 1 共两个字节。

base64加密/解密算法:

指题目中存在加密,,而且是传统的base64加密算法,需要自己去辨认算法的特点,能够在做题中判断出来。

md5加密/解密算法:

指解题中存在加密,而且是传统的md5加密算法,需要自己去辨认算法的特点,能够在做题中判断出来。

base58加密/解密算法:

指解题中存在加密,而且是传统的base58加密算法,右移位 >> 6和 >> 8,一个模58,一个除58是base58加密的关键。需要自己去辨认算法的特点,能够在做题中判断出来。

RSA加密/解密算法:

指解题中存在加密,而且是传统的RSA加密算法,需要自己去辨认算法的特点,能够在做题中判断出来。

奇数偶数判断算法:

原代码逻辑中出现 i&1 的判断,这其实是判断奇数还是偶数来的,以后遇到要懂得辨析。

倍数条件算法积累:

指解题中对输入flag的固定距离或倍数位做操作如:1、4、7。2、5、8。0、3、6。这种位数,通常的算法有除法符号除去非余数,如:3*(v3/3)==v3 和 ++v11==3 以及 v11 == 2这种类型。

超位数循环截取算法:

指解题中循环条件超过了输入flag的位数,从而照成循环结果会超出flag的长度。但是因为循环条件是符合逻辑的,而且不会因为位数超出就乱了结果,也就是说前面flag位数范围内还是符合flag生成的,所以这种题目最后都会有一个flag位数截取,来截取出flag位数内符合条件的前面的字符。

switch正向代入推导:

指解题中IDA生成的伪代码中有关键逻辑是switch的,那这部分无需逆向逻辑,直接正向推导每个满足case条件的字符即可,同迷宫一样都是手动。

16进制转十进制算法:

指解题中对于要求输入16进制数或者原本就存在16进制数中有让转为10进制数的操作。如v10=v16-55,v10=v16-'0'。

16进制范围A~F,减去55之后就是变成了实数的10 ~15。16进制范围0 ~9减去字符'0'之后就变成了实数0 ~9。

所以就是0 ~ F分别对应实数的0 ~15之所以减得不同是因为ASCII表中0 ~ 9和A ~ F并不相连。

IDA循环左右移动算法:

指花指令类型解题中数据变指令的修改是需要左右移动的,当我们选择静态修补的时候,就需要顺着原程序中自修改逻辑来左右移动或更进一步操作。

附上循环左右移动代码:

def ROR(i,index): #循环右移

tmp = bin(i)[2:].rjust(8,"0")

for _ in range(index):

tmp = tmp[-1] + tmp[:-1]

return int(tmp, 2)

def ROL(i,index): #循环左移

tmp = bin(i)[2:].rjust(8, "0")

for _ in range(index):

tmp = tmp[1:] + tmp[

标签: 305v105kx2电容1v69连接器300v105jcbb电容

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台