先说结论:本题通过动态调试得到flag至少有两种解法。
最简单的解法是:断下两处比较指令
第一处cmp:
Error, please try again
上方的cmp esi,edi
(用于比较flag长度)
第二处cmp:
mov eax,dword ptr ds:[edx]
cmp eax,dword ptr ds:[ecx]
(用于比较flag内容)
第一步
获取flag长度
依据往年的Windows初级题,题目中一定会先比较flag长度,今年仍然如此。
首先将程序拖入Ollydbg中,运行到答案输入提示,如下图所示:
右击-智能搜索-中文搜索引擎,进入后在Please input password
下面果然能够发现两个不同的错误提示: Error, please try again
和Wrong password, please try again
,如下图所示:
我们先进入并查看Please input password
到Error, please try again
这一段区间的代码,如下图所示:
在这一段代码内可以观察到4个比较指令,其中有3个比较指令的比较值是明文,明文比较值分别为0x10
0x10000
0x1F
,坑就在这里,这里是与往年最大的不同。你可以尝试这三个比较值,会发现这三个比较的值都不是flag的长度。
于是,回头看代码,发现距离Error, please try again
还有一个最近的比较指令cmp esi,edi
用于比较esi寄存器和edi寄存器中的值,我们还没有考虑这一比较指令。
我们在该cmp esi,edi
指令处下上断点,在程序中我们输入123456
(共6
位)作为提交答案尝试,运行结果如下图所示:
可以发现,程序将esi寄存器中的00000006
与edi寄存器中的0000001B
进行了比较。经过多次测试,可以确定esi寄存器中的值是程序中输入答案的位数,并与正确答案预期位数0000001B
进行比较。
因此,我们可以确定因此我们可以确定正确flag答案位数为27
位。
第二步
进军flag
确定flag位数为27
位之后,我们以123456789012345678901234567
(共27
位)作为提交答案尝试,成功跳过了Error, please try again
逻辑。
法一
我们发现Error, please try again
下方有一个循环体会逐字符进行一些解密操作(见法二),其中ecx寄存器和edi寄存器充当累加器的作用,只有当比较累加器的值刚好达到0000001B
时才会跳出循环体,如下图所示:
这个地方法一无需操作,是另一种解法,见法二。
我们在下方Success! Congratulations!
之前可以看到一处相似的逻辑:
mov eax,dword ptr ds:[edx]
cmp eax,dword ptr ds:[ecx]
在该逻辑中,只有比较成立(即两值相等)才会跳出循环体执行后续代码,如下图所示:
我们在该cmp eax,dword ptr ds:[ecx]
指令处下上断点,flag就会直接在ECX寄存器中出现,如下图所示:
最后的最后:程序还会比较提交的答案前4
位是否为fl@g
,如下图所示:
法二
在法一中我们发现:
imul eax,edx,0x41C64E6D
......
add byte ptr ds:[ecx-0x1],al
cmp edi,esi
jnz short 【2025春.001A24D0
这一部分代码在执行解密操作,非常可疑。
已经确认cmp edi,esi
这一行只是普通的计数累加器,我们看到上一行add byte ptr ds:[ecx-0x1],al
仍然在进行加解密操作,可以推断add byte ptr ds:[ecx-0x1],al
这一行可能是加解密操作核心逻辑的最后一行,我们在这一行下上断点。
这一行共有两个元素ds:[ecx-0x1]
和a1
,观察之后发现ds:[ecx-0x1]
嫌疑很大,很有问题。
我们选中该行,右击ds-数据窗口中跟随地址,如下图所示:
不断继续运行,神奇的一幕出现了:
(再继续执行一步就可以得到完整的flag了)
彩蛋
AI都会解: