前言:学习笔记
深入刨析,打好基础~
常规:下载 解压 查壳
32位>>> 32IDA Pro 打开。
常规:先查找字符串 再进入main()函数
main():
进入func:(我们复制func代码在sublime进行分析<<<<因为func看着比较复杂。)
程序分析:
第一部分:(注意点就是v7~v10的字节数)
第二部分:(考察对指针:p 取地址:& 取值:* 的理解)
第三部分:(验证)
程序流程:
① 输入字符串,必须是ACTF{} +flag 的格式
② 遍历数组,判断 flag[i] 是否属于大写小写字母 if T >>> 执行对应的加密算法
【不属于。则不进行任何操作。】
③ 遍历数组。判断加密后的flag[i] 是否等于v12[i] if F>>>return flag[i]【结束程序,表明错了】
④ 打印 printf("You are correct!"); 说明>>>正常退出,flag正确。
C逆向脚本:
脚本思路:
从后往前推。【逆向reverse嘛。】
原程序中第二个while只用于验证,所以不重要。
重点是对第一个while的逆推。
FF>>>(正向的while循环 写成C代码的样式如下:v1[i]是我们要求的flag。通过加密算法变成了v12.)
因为加密后的结果为v12(已知)。
进行逆推(以大写为例)。
① v12[i] 先减去 65 变成 (v12[i] -51)%26
② 因为” ( ) 【运算优先级】 “,所以先逆括号里面的>>> (v12[i] + 51)%26
我用X代替(v12[i] + 51)
③ 这时候需要小心。 X 的值分为两种情况:(该怎么解释->>>逆向%26 。。。T^T)
A 当 X =>65(A)时 不用做任何矫正。【因为其范围就在大写字母之内】
B 当 X <65(A)时 则需要加上余数26 【为了确保其范围在大写字母之内】
问题一:为什么能够确保在大写字母之内?:
【原因:首先v12[i]属于大写字母,先 减65 ‘A’ 再 加51 结果会> 90 'Z' ??只能是( 结果① =>65 || 结果②<65 )】
问题二:为什么要确保在大写字母之内?:请看 FF的内容。
题外话:取余 以及 取模。
脚本:
验证:
flag{Cae3ar_th4_Gre@t}。
总结:
最大的难点在于对 %26的理解与处理、其次对 p & *的理解运用、以及char int 所占字节数等。
%处理:
◎①若指定范围,例如本题矫正依据情况而定.
②若未指定,直接抄原代码.例如<buu-pyc>.◎
>>>若逆向结果在指定范围,则不需要进行矫正。
>>>若逆向结果在指定范围之外,则需要加上【%X】的【X】进行矫正。
if (v12[i] > 64 && v12[i] <= 90)//大写字母的范围
{
v12[i] = v12[i] - 65 + 51;//运算的值可能在范围内,也可能不在范围内。
if (v12[i]< 65) //对不在范围内的值进行矫正。
{
v12[i] += 26;
{
拓展:^处理。
假设:(具体依据情况而定)
原 : for (int i = 0; i < strlen(FLAG) - 1; i++)
{
FLAG[i] ^= FLAG[i + 1]; //该位与后一位进行异或。 最后一位不异或
}
则逆: for (int i = strlen(FLAG) - 1; 1 <= i; i--)
{
flag[strlen(FLAG) - 1] ^= FLAG[i]; //最后一位不异或,从后往前,异或还原。
}
目前学习掌握的两种运算逆向。(继续学习)