首页
社区
课程
招聘
[原创]看雪CTF2016 第8题分析
2016-11-16 22:31 2112

[原创]看雪CTF2016 第8题分析

2016-11-16 22:31
2112
直接扔 idaq64 里面,在sub_140001910()函数里 F5得到:
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

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回