-
-
[原创]看雪CTF 秋季赛 第二题 writeup
-
2017-10-26 22:13 2408
-
这个题目思路极其独特,看似简单的题目,背后居然隐藏了怎么大的秘密。
刚开始打开IDA的时候,代码极其简单,很兴奋,感觉又好像是一道类似签到题。
void sub_401090(){ int v0; // [sp+4h] [bp-8h]@0 int v1; // [sp+8h] [bp-4h]@0 if ( v1 && v0 && v1 != v0 && 5 * (v1 - v0) + v1 == 0x8F503A42 && 13 * (v1 - v0) + v0 == 0xEF503A42 ) --checkcode; }
以及
void sub_4010E0(){ int v0; // [sp+4h] [bp-8h]@0 int v1; // [sp+8h] [bp-4h]@0 if ( v1 && v0 && v1 != v0 && 17 * (v1 - v0) + v1 == 0xF3A94883 && 7 * (v1 - v0) + v0 == 0x33A94883 ) --checkcode; }
只需要将两次的if语句都算正确即可。
6 * a - 5 * b = 0x8F503A42(s1) 13 * a - 12 * b = 0xEF503A42(s2) 18 * a - 17 * b = 0xF3A94883(s3) 7 * a - 6 * b = 0x33A94883(s4)
按照常规的数学运算,a和b是能够通过多个等式求出来的 即使求出来的解不是很准确,但是最多也就最高位上的值不是很准确
a = s4 * 2 - s2 a = s1 + s2 - s3 b = (s1 * 3 - s3) / 2 b = s1 + s4 - s2
通过两中方式求出来的a,b差距很大, 而且看 数值 0xF3A94883 ≈ 0x33A94883 , 0x8F503A42 ≈ 0xEF503A42。
所以说可能是有诈,并且没有说明输入的字符长度为8。
后发现该程序存在栈溢出漏洞,作者可能利用这一点将真正的代码验证端放到之后。并且OD加载的初始位置和这段代码之间的间隔了很多的空数据。 找到空数据结束的位置 0x413131 。 推测可能为程序真正的代码验证块。
0018FF34 0041B08C ASCII "%s" 0018FF38 0018FF3C ASCII "aaaabbbbcccc11A" 0018FF3C 61616161 0018FF40 62626262 0018FF44 63636363 0018FF48 00413131 ctf2017_.004131310018FF4C 00413E3E 返回到 ctf2017_.00413E3E 来自 ctf2017_.00401000
直接覆盖返回地址为00413131 即输入12个字符+11A
之后代码后很多花指令,乱跳转,但是目的都只有一个,是用来验证输入的code。
使用调试软件直接动调将一句一句代码扣下来, 因为全是跳转语句,刚开始在验证的跳转处没有识别出来,然后遇到了挫折。后来发现主要的跳转有一个特点就是跳转很长。
00413131 | 83 C4 F0 | add esp,FFFFFFF0 | 00413150 | 33 C0 | xor eax,eax | eax:"aaaabbbbcccc11A" 00413184 | A3 34 B0 41 00 | mov dword ptr ds:[41B034],eax | 004131BA | 58 | pop eax | 004131EB | 8B C8 | mov ecx,eax | ecx:&"\n\n" 0041321F | 58 | pop eax | 00413254 | 8B D8 | mov ebx,eax | 00413289 | 58 | pop eax | 004132B5 | 8B D0 | mov edx,eax | 004132AD | 8B D0 | mov edx,eax | 004132E2 | 8B C1 | mov eax,ecx | 00413316 | 2B C3 | sub eax,ebx | 00413349 | C1 E0 02 | shl eax,2 | 00413380 | 03 C1 | add eax,ecx | 004133B5 | 03 C2 | add eax,edx | 004133E9 | 2D E2 17 F9 EA | sub eax,EAF917E2 | 00413420 | 0F 85 DD 06 00 00 | jne ctf2017_fpc.413B03 | 00413455 | 03 C1 | add eax,ecx | 00413489 | 2B C3 | sub eax,ebx | 004134BF | 8B D8 | mov ebx,eax | 004134F3 | D1 E0 | shl eax,1 | 00413525 | 03 C3 | add eax,ebx | 00413559 | 03 C1 | add eax,ecx | 0041358F | 8B C8 | mov ecx,eax | 004135C3 | 03 C2 | add eax,edx | 004135F7 | 2D C8 08 F5 E8 | sub eax,E8F508C8 | 0041362E | 0F 85 CF 04 00 00 | jne ctf2017_fpc.413B03 | 00413665 | 8B C1 | mov eax,ecx | 0041365D | 8B C1 | mov eax,ecx | 004136A7 | 2B C2 | sub eax,edx | 004136D8 | 2D 68 3C 0A 0C | sub eax,C0A3C68 | 00413710 | 0F 85 ED 03 00 00 | jne ctf2017_fpc.413B03 | 00413747 | 58 | pop eax | 00413777 | 35 01 81 00 00 | xor eax,8101 | 004137A9 | 8B F8 | mov edi,eax | 004137E2 | 33 C0 | xor eax,eax | 00413817 | AB | stosd dword ptr es:[edi],eax | 0041385C | 58 | pop eax | 0041388E | 50 | push eax | 004138BA | 8B F8 | mov edi,eax | 004138B2 | 8B F8 | mov edi,eax | 004138E6 | 68 69 09 00 4E | push 4E000969 | 0041391F | 58 | pop eax | 004139B5 | 35 3E 0A 01 00 | xor eax,10A3E | 004139EB | AB | stosd dword ptr es:[edi],eax | 00413A1C | 33 C3 | xor eax,ebx | 00413A4D | 35 14 1E 51 22 | xor eax,22511E14 | 00413A82 | AB | stosd dword ptr es:[edi],eax | 00413AB6 | 35 2D 64 61 00 | xor eax,61642D | 00413B83 | 33 05 34 B0 41 00 | xor eax,dword ptr ds:[41B034] | 00413BBB | FF E0 | jmp eax |
核心的代码就是怎么一段, 最后是经过jmp eax 回到输出的位置的。
可以就只分析前面的三个等式,忽略后面的,总结就是怎么三个等式。求三个解。
5 * a - 4 * b + c = 0xEAF917E2(s1) 4 * a - 3 * b + c = 0xE8F508C8(s2) 5 * a - 3 * b - c = 0x0C0A3C68(s3)
先计算出大概值:
c = (s2 - s3) / 2; a = (s2 - c) * 4 - (s1 - c) * 3; b = (s2 - c) * 5 - (s1 - c) * 4; a = 0xf473754a ; b = 0xf26f6630 ; c = 0xee756630;
高位在爆破一下:
for (int i1 = 0; i1 <= 0xff; i1++){ for (int i2 = 0; i2 <= 0xff; i2++){ for (int i3 = 0; i3 <= 0xff; i3++){ int t1 = ((i1 << 24) & 0xff000000) + (0xf473754a & 0xffffffff); int t2 = ((i2 << 24) & 0xff000000) + (0xf26f6630 & 0xffffffff); int t3 = ((i3 << 24) & 0xff000000) + (0xee756630 & 0xffffffff); if ((5 * t1 - 4 * t2 + t3 == s1) && (4 * t1 - 3 * t2 + t3 == s2) && (4 * t1 - 3 * t2 - t3 == s3)){ printf("%x %x %x \n", t1, t2, t3); } } } }
//output: 7473754a 726f6630 6e756630
最后flag为 Just0for0fun11A
出题人的思路真心可以,第一次遇到这种骚操作。
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
赞赏
他的文章
看原图