首页
社区
课程
招聘
[原创]看雪.京东 2018CTF-第十三题分析
2018-7-11 12:02 2757

[原创]看雪.京东 2018CTF-第十三题分析

2018-7-11 12:02
2757
IDA载入后发现有2个TlsCallback函数,初步看这两个函数,没发现特别的东西,暂时不管,先分析下main的代码。
一、main函数
1、获取输入sn,并判断sn长度如果不是10,则输出key error错误提示。(条件一)
2、调用401CE0函数,将sn字符串转换成一个64位16进制数称为keyValue,同时要求输入的字符必须在"0123456789ABCDEF"范围内。(条件二)
      输入"123456789A",将转换成为0x9A78453412。
3、将64位16进制数,拆分成2个double数称为 keyValue_x和 keyValue_y,分别为低4字节和高6字节,为:0x3412000000000000, 0x9A78560000000000。
4、调用4015E0函数将上面的2个double数经过了一系列的浮点运算获得一个双精度值称之为:newKeyValue。同时判断上面的两个双精度数必须在
      1.0 和10.0之间(条件三)
5、将 newKeyValue格式化成字符串 newKeyString,并要求 newKeyString [1]必须是小数点。(条件四)
6、将 newKeyString[0]、 newKeyString[2]、 newKeyString[3]字符减去0x30,并将它们的平方和作为输入调用403360函数,在其内部进行了一系列的浮点
      运算,并将运算结果赋给 newKeyValue2。
7、判断 newKeyValue2 不小于15.5。(条件五)
8、要求 keyValue的第五位必须为0。 (条件六)
9、 (keyValue_x+ keyValue_y -  newKeyValue) <0.003。 (条件七)
满足上面的7个条件则输出“Congratulation”表示成功。
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  double v3; // xmm1_8
  __int64 v4; // rdx
  __int64 v5; // rax
  __int64 v6; // rdx
  __int64 v7; // rax
  __int64 v8; // rdx
  __int64 v10; // rax
  __int64 v11; // rax
  double v12; // xmm1_8
  __int64 v13; // rax
  int newKey1; // [rsp+20h] [rbp-198h]
  char v15; // [rsp+24h] [rbp-194h]
  char Format[4]; // [rsp+30h] [rbp-188h]
  char v17; // [rsp+34h] [rbp-184h]
  double v18; // [rsp+40h] [rbp-178h]
  double low4Byte_newKey; // [rsp+50h] [rbp-168h]
  double high5_newKey1; // [rsp+58h] [rbp-160h]
  double low4Byte_newKey_1; // [rsp+60h] [rbp-158h]
  double high5_newKey1_1; // [rsp+68h] [rbp-150h]
  __int64 v23; // [rsp+70h] [rbp-148h]
  __int64 v24; // [rsp+78h] [rbp-140h]
  __int64 v25; // [rsp+80h] [rbp-138h]
  __int64 v26; // [rsp+88h] [rbp-130h]
  char inputKey[256]; // [rsp+90h] [rbp-128h]
  int v28; // [rsp+190h] [rbp-28h]

  sub_401F00(*(__int64 *)&argc, (__int64 *)argv);
  v15 = 0;
  memset(inputKey, 0, sizeof(inputKey));
  v17 = 0;
  low4Byte_newKey = 0.0;
  high5_newKey1 = 0.0;
  low4Byte_newKey_1 = 0.0;
  high5_newKey1_1 = 0.0;
  v18 = 0.0;
  v28 = 0;
  newKey1 = 0;
  *(_DWORD *)Format = 0;
  v23 = 0LL;
  v24 = 0LL;
  v25 = 0LL;
  v26 = 0LL;
  sub_401790();
  sub_401C50((__int64)&v28, (__int64)inputKey, v4, 252);
  v5 = 0LL;
  do
  {
    v6 = (byte_408D00[v5] ^ 0x19) - (unsigned int)v5;
    *((_BYTE *)&v23 + v5) = (byte_408D00[v5] ^ 0x19) - v5;
    ++v5;
  }
  while ( v5 != 16 );
  printf(Format, inputKey, v6, &v23);
  Format[0] = byte_408D70 ^ 0x25;
  Format[1] = (byte_408D71 ^ 0x25) - 1;
  scanf(Format, inputKey, inputKey, Format);
  if ( strlen(inputKey) != 10 )                 // 条件1:长度为10
  {
    v7 = 0LL;
    do
    {
      v8 = (byte_408D10[v7] ^ 0xF) - (unsigned int)v7;
      *((_BYTE *)&v23 + v7) = (byte_408D10[v7] ^ 0xF) - v7;
      ++v7;
    }
    while ( v7 != 16 );
    goto LABEL_6;
  }
  if ( (unsigned int)charToHex((__int64)Format, (__int64)inputKey, (__int64)&newKey1, (__int64)inputKey, 10) != 5 )// 将输入转换成整数
  {
    v10 = 0LL;
    do
    {
      v8 = (byte_408D20[v10] ^ 0x21) - (unsigned int)v10;
      *((_BYTE *)&v23 + v10) = (byte_408D20[v10] ^ 0x21) - v10;
      ++v10;
    }
    while ( v10 != 16 );
    goto LABEL_6;
  }
  HIWORD(low4Byte_newKey) = newKey1;            // "1234" --> 3412000000000000 
  low4Byte_newKey_1 = low4Byte_newKey;
  *(_WORD *)((char *)&high5_newKey1 + 5) = HIWORD(newKey1);
  HIBYTE(high5_newKey1) = v15;                  // 123456789A --->9A78560000000000
  high5_newKey1_1 = high5_newKey1;
  sub_4015E0((__int64)Format, (__int64)inputKey, &v18, &low4Byte_newKey);// if ( v17 <= 1.0 || v17 >= 10.0 || (v18 = v8[3], v18 <= 1.0) || v18 >= 10.0 )
  Format[0] = byte_408D72 ^ 0x12;
  Format[1] = (byte_408D73 ^ 0x12) - 1;
  Format[2] = (byte_408D74 ^ 0x12) - 2;
  sprintf(Format, inputKey, Format, inputKey, *(_QWORD *)&v18, v18, v3, v18);
  if ( inputKey[1] != '.' )
  {
    v11 = 0LL;                                  // Ohhh.Try again
    do
    {
      v8 = (byte_408D40[v11] ^ 0x3F) - (unsigned int)v11;
      *((_BYTE *)&v23 + v11) = (byte_408D40[v11] ^ 0x3F) - v11;
      ++v11;
    }
    while ( v11 != 16 );
    goto LABEL_6;
  }
  v12 = (double)(inputKey[3] - 0x30) * (double)(inputKey[3] - 0x30);
  if ( sub_403360(
         (__int64)Format,
         (__int64)inputKey,
         (double)(inputKey[0] - 0x30) * (double)(inputKey[0] - 0x30)
       + (double)(inputKey[2] - 0x30) * (double)(inputKey[2] - 0x30)
       + v12,
         v12) <= 15.5
    || newKey1 & 0xF0000 )
  {
    v13 = 0LL;
  }
  else
  {
    v13 = 0LL;
    if ( COERCE_DOUBLE(COERCE_UNSIGNED_INT64(low4Byte_newKey_1 + high5_newKey1_1 - v18) & xmmword_409080) < 0.003 )
    {
      do                                        // Congratulation
      {
        v8 = (byte_408D50[v13] ^ 0x47) - (unsigned int)v13;
        *((_BYTE *)&v23 + v13) = (byte_408D50[v13] ^ 0x47) - v13;
        ++v13;
      }
      while ( v13 != 16 );
      goto LABEL_6;
    }
  }
  do
  {
    v8 = (byte_408D60[v13] ^ 0x37) - (unsigned int)v13;// comeon go on
    *((_BYTE *)&v23 + v13) = (byte_408D60[v13] ^ 0x37) - v13;
    ++v13;
  }
  while ( v13 != 16 );
LABEL_6:
  printf(Format, inputKey, v8, &v23);
  return 0;
}

二、获取SN
一共有7个条件,不想分析浮点运算了。利用下面4个条件爆破sn,具体如下:
1、长度为10
2、必须是"0123456789ABCDEF";
3、转换的2个双精度数值必须大于1.0小于10.0 其中1.0对应的为 0x3FF0000000000000,10.0对应为0x4024000000000000。因此要求输入的
      keyValue_x取值范围为0x3FF1和0x4024之间, keyValue_y取值范围为0x3FF000和402400之间。
4、 keyValue的第5位为0,也就说明上面的递增步长是0x10。
脚本如下:
import subprocess
import sys
pname ="NNCrackme.exe"
def getSn():
	a=['0','0','0','0','0','0','0','0','0','0',0]
	i =0x3FF1
	while i<0x4024:
		print('i='+ str(hex(i)))	
		temp = i&0x000f
		a[1]= (i&0x000f)
		a[0]= ((i&0x00f0)>>4)
		a[3]= ((i&0x0f00)>>8)
		a[2]= ((i&0xf000)>>12)
		j = 0x3FF010
		while j<0x402400:
			a[5]= (j&0x00000f)
			a[4]= ((j&0x0000f0)>>4)
			a[7]= ((j&0x000f00)>>8)
			a[6]= ((j&0x00f000)>>12)
			a[9]= ((j&0x0f0000)>>16)
			a[8]= ((j&0xf00000)>>20)
			k =0
			keystr = ''
			while k <10:
				keystr=keystr+str(hex(a[k]))[2:].upper()
				k=k+1		
			print(keystr)
			arg =keystr
			io = subprocess.Popen(pname,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
			ret=io.communicate(input=arg)
			res = ret[0].decode()[0:]
			print(res)
			if(res.find('Congratulation')>=0):
				print("the flag is:%s"%keystr)
				return
			else:
				j=j+0x10
		i=i+1
	return
getSn()		
			
爆破结果如下:
F13F802140
Input your KEY:Come on, go on
F13F902140
Input your KEY:Come on, go on
F13FA02140
Input your KEY:Come on, go on
F13FB02140
Input your KEY:Come on, go on
F13FC02140
Input your KEY:Come on, go on
F13FD02140
Input your KEY:Come on, go on
F13FE02140
Input your KEY:Congratulation
the flag is:F13FE02140

flag = F13FE02140

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-7-11 12:08 被oooAooo编辑 ,原因:
收藏
点赞2
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回