第一步 查壳。该题是32位且无壳,直接拖入ida。
第二步 找到main界面,按tab键进入如图界面,第一个main()点进去没有什么东西。本题主要跟进func
第三步 进入后
分析一下
- strcpy(v12, "Qsw3sj_lz4_Ujw@l"); - 将字符串 "Qsw3sj_lz4_Ujw@l" 复制到变量 v12 中。
- printf("Please input:"); - 打印提示信息,要求用户输入。
- scanf("%s", &v2); - 从标准输入读取一个字符串到变量 v2。
- result = v2; - 将 v2 的值赋给 result。
- 接下来的代码块是一系列嵌套的 if 语句,用于检查 v2 到 v11 的值是否依次为 'A', 'C', 'T', 'F', '{', '}'。如果所有条件都满足,程序将继续执行内部的代码块。
- v1[0] = v7; v1[1] = v8; v1[2] = v9; v1[3] = v10; - 将变量 v7 到 v10 的值分别赋给数组 v1 的前四个元素。
- *(_DWORD *)&v12[17] = 0; - 将 v12 数组中索引为 17 的位置的整数值设置为 0。
- while ( *(int *)&v12[17] <= 15 ) - 开始一个循环,循环条件是 v12[17] 的整数值小于等于 15。
- 在循环内部,有两个 if 条件判断,用于对 v1 数组中的字符进行转换:
(1)如果字符是大写字母 (ASCII 65-90),则进行一定的计算后调整其值。
(2)如果字符是小写字母 (ASCII 97-122),则进行另一种计算调整其值。
- ++*(_DWORD *)&v12[17]; - 每次循环结束时,将 v12[17] 的整数值加 1。
- 循环结束后,再次将 v12[17] 的整数值设置为 0,并开始另一个循环,检查 v1 数组中的字符是否与 v12 中相应位置的字符相匹配。
- 如果所有字符都匹配,最后打印 "You are correct!"。
红色圈出的部分可以看出是凯撒密码加密类型,原因是当偏移量为13位的时候,凯撒密码又叫回转密码(ROT13):明文加密得到密文,密文再加密就会得到明文(因为偏移量为13位,一共26个字母,加密两次就会回到明文了)
我们用计算偏移量进行逆向倒推出flag
先看大写字母
偏移量n=(-51)-(-64)+65-64=14
再看小写字母
偏移量n=(-79)-(-64)+97-64=18
有关凯撒密码的知识可参考以下两篇文章:
凯撒密码原理(加解密)_实现凯撒密码的移位置换-CSDN博客
凯撒密码(Python)_python凯撒密码-CSDN博客
第四步 编写脚本。
分析一下脚本:
flag="Qsw3sj_lz4_Ujw@l"
- 定义一个名为flag
的字符串变量,存储了待处理的字符串。result=[]
- 初始化一个空列表result
,用于存储转换后的字符。flag1=""
- 初始化一个空字符串flag1
,用于最后的字符串拼接。循环遍历
flag
中的每个字符i
:- 如果字符
i
是大写字母(ASCII 值在 65 到 90 之间),则对其进行一个特定的数学变换:先将其 ASCII 值减去 65,再减去 14,取模 26 后加上 65,最后转换回字符。这个过程是对字符进行一个特定的偏移。 - 如果字符
i
是小写字母(ASCII 值在 97 到 122 之间),则进行类似的变换,但偏移量是 18。 - 如果字符
i
不是字母,则直接添加到result
列表中。
- 如果字符
使用另一个循环遍历
result
列表中的每个元素,并将它们拼接到flag1
字符串中。print("flag{"+flag1+"}")
- 打印出处理后的字符串,格式为flag{...}
。
得到flag
flag{Cae3ar_th4_Gre@t}