-
-
[原创]看雪CTF2016第20题原作者解析
-
发表于: 2016-12-11 22:09 3265
-
作者简介:网名brichfire,职业看门大叔,爱好密码、数论、登山、下海……看雪CTF2016活动开始才初步学习程序逆向破解,出题之前才恶补反逆向技术。
题目设计思路:
1、 通过函数表隐藏调研过程,增加静态分析的难度。
DWORD (*pfunc[8]) (char *);
int (*pfunc4[4]) (void);
2、通过3种反调试手段增加动态分析难度。
超时退出线程
CheckRemoteDebuggerPresent
int 3,调试状态下进入无解的校验函数。
3、验证算法
N(11)阶幻方扣掉对角线的10个数据,该数据由用户输入数据查表覆盖,当N行、N列、2N条循环斜对角线之和相等的条件下验证成功。(出题的时候考虑N取更大值、甚至扣掉更多的数据,但是为了让破解者更加方便,也为了避免多解的情况只取了N为11,抠掉10个数)。
题目破解步骤:
1、 将下处反调试的影响去除,nop掉该指令,或者改为or esi, 1,否则进入无解的校验函数。
2、 去除下图中调试超时退出的代码,或者将jle改成jmp
3、 去除CheckRemoteDebuggerPresent反调试退出代码,将第一个jnz改为nop,将第二个jnz改为jmp(第二个其实可以不修改)。
4、 去除int 3反调试,将int 3的指令0xcc改为0x00,原来exception触发0x80000003异常,修改后触发0xc0000005异常,将异常处理的cmp ecx, 80000003h修改为cmp ecx, c0000005h。此时去除了int 3的反调试。
去除反调试之后调试状态下的exception执行后能够执行到如下代码
Call edx的值取决于ecx,ecx来自如下代码:
无反调试情况下ecx不应该去参与or 2运行,但应该参与or 1的运行,可以猜测ecx就应该为1,且需要构造输入使input[1]%4 == 1成立。ecx为1时执行到0x401500位置的check代码。
5、 校验
Sub_0x401500处的函数是校验代码,校验算法是一个N阶幻方,就是将1,2,3,……,N*N这些数填入一个N*N的方阵,使得N行、N列、2N条循环对角线之和相等。本题中N取11,并且已经将大部分数据填好,剩下的Table[i][i] (i从0到9)位置由用户输入查表生成。N为大于2的素数时,N阶幻方可通过如下公式生成,不知道公式可以由无需填充的右斜对角线计算得到和,再计算需要填充的位置:
Table[i][j] = ((2*i+j+3)%N)*N + (2*i-j+N+1)%N + 1; ( i, j 选自 0,1,2,……N-1)
校验矩阵如下
标注出来的位置实际应该为: 0x23,0x45,0x67,0x10,0x32,0x54,0x76,0x1f,0x41,0x63
这些值通过table_410ee0[input[i]]获得,根据下图数据,推断出input[i]依次为:
0x43,0x6d,0x4a,0x46,0x39,0x32,0x6f,0x52,0x63,0x75, 对应字符为:CmJF92oRcu
最后附上去除反调试之后的程序RmCrackMe和原程序CrackMe。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!