-
-
[原创]看雪CTF2016 第8题分析
-
发表于: 2016-11-16 22:31 2457
-
直接扔 idaq64 里面,在sub_140001910()函数里 F5得到:
注册输入的形式是:
在 sub_1400014B0()里F5得到:
也就是
*(&dword_140025CC0 + v8 + 4i64 * v9 + v9) + v5 * dword_140025D24 要等于 3 * v5 才能正确。
v5也就是sub_1400014B0(int a1, __int64 a2)传入的参数a1, 也是sub_140001300(int)的返回值.
设 *(&dword_140025CC0 + v8 + 4i64 * v9 + v9) 为 Y, 那么得到算式:
y可以动态调试中获得,dword_140025D24也可以动态调试中获得。
输入一个假的注册码1A1122。
动态调试,在sub_1400014B0函数里得 Y 和 dword_140025D24的值。
Y=0x3c, dword_140025D24=2, 代入式子中得到:
参数? 使sub_140001300(?)的函数返回等于 0x3c。
抠出 sub_140001300()函数 F5后的代码,组织成暴力计算器:
计算得到值是 3600。
那么注册码是 3600A1122。
同样也可以这种方法行到其它的注册码,输入假注册码 1A4433,得到:
Y=0x3D, dword_140025D24=2, 然后计算得721, 那么注册码是:721A4433。
于是得到许多:
int sub_140001910() { ... sub_140001200("注册码:"); sub_1400012B0("%dA%s", &v3, &v4); ... v0 = sub_140001300(v3); if ( v0 ) { sub_1400014B0((unsigned int)v0, &v4); ... } return ...; }
注册输入的形式是:
%dA%s
在 sub_1400014B0()里F5得到:
void __fastcall sub_1400014B0(int a1, __int64 a2) { ... v34 = a1; ... v5 = v34; ... v33 = "恭喜你注册成功!\n"; if ( *(&dword_140025CC0 + v8 + 4i64 * v9 + v9) + v5 * dword_140025D24 != 3 * v5 ) v33 = (const char *)&unk_140021F90; sub_140001200(v33); ... }
也就是
*(&dword_140025CC0 + v8 + 4i64 * v9 + v9) + v5 * dword_140025D24 要等于 3 * v5 才能正确。
v5也就是sub_1400014B0(int a1, __int64 a2)传入的参数a1, 也是sub_140001300(int)的返回值.
设 *(&dword_140025CC0 + v8 + 4i64 * v9 + v9) 为 Y, 那么得到算式:
Y + sub_140001300() * dword_140025D24 =3* sub_140001300()
Y +f() * dword_140025D24 = 3*f()
y可以动态调试中获得,dword_140025D24也可以动态调试中获得。
输入一个假的注册码1A1122。
动态调试,在sub_1400014B0函数里得 Y 和 dword_140025D24的值。
sub_1400014B0 ..... 000000013F7818A7 | 48 63 C6 | movsxd rax,esi | 000000013F7818AA | 49 63 D6 | movsxd rdx,r14d | 000000013F7818AD | 48 8D 0C 90 | lea rcx,qword ptr ds:[rax+rdx*4] | 000000013F7818B1 | 48 03 D1 | add rdx,rcx | 000000013F7818B4 | 48 8D 05 05 44 02 00 | lea rax,qword ptr ds:[13F7A5CC0] | 000000013F7818BB | 8B 0D 63 44 02 00 | mov ecx,dword ptr ds:[13F7A5D24] | dword_140025D24 =2 000000013F7818C1 | 0F AF CF | imul ecx,edi | 000000013F7818C4 | 03 0C 90 | add ecx,dword ptr ds:[rax+rdx*4] | Y=3c 000000013F7818C7 | 8D 04 7F | lea eax,dword ptr ds:[rdi+rdi*2] | 000000013F7818CA | 3B C8 | cmp ecx,eax | 000000013F7818CC | 48 8D 0D A5 06 02 00 | lea rcx,qword ptr ds:[13F7A1F78] | 000000013F7818D3 | 74 07 | je crackme.13F7818DC | ...
Y=0x3c, dword_140025D24=2, 代入式子中得到:
0x3c+ 2*f()=3*f()
f()=0x3c
参数? 使sub_140001300(?)的函数返回等于 0x3c。
抠出 sub_140001300()函数 F5后的代码,组织成暴力计算器:
#include <stdio.h> signed __int64 sub_140001300(signed int a1) { unsigned int v1; // er9@1 signed int v2; // er11@1 signed int v3; // er8@1 signed int v4; // er10@1 __int64 v6; // rax@8 v1 = 0; v2 = a1; v3 = 1; v4 = 0; if ( a1 == 874 || a1 == 987654321 ) return 0xFFFFFFFFi64; if ( a1 ) { do { ++v4; a1 /= 10; } while ( a1 ); if ( v4 < 1 ) goto LABEL_10; } else { v4 = 1; } v6 = (unsigned int)v4; do { v3 *= 10; --v6; } while ( v6 ); do { LABEL_10: ++v1; if(v1 > 46341) return 0; } while ( (signed int)(v1 * v1) % v3 != v2 ); return v1; } int main(void) { __int64 s=0; int i; i=0; while(i>=0) { s=sub_140001300(i); if(s==0x3C) { printf("%d\n",i); break; } i++; } return 0; }
计算得到值是 3600。
那么注册码是 3600A1122。
同样也可以这种方法行到其它的注册码,输入假注册码 1A4433,得到:
Y=0x3D, dword_140025D24=2, 然后计算得721, 那么注册码是:721A4433。
于是得到许多:
7616A2 6116A233 204A4321
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
看原图
赞赏
雪币:
留言: