ctf

nactf-writeup

ctf题解

Posted by gxkyrftx on September 19, 2019

1 reverse

1.1 cliche_crackme

mac os环境编译得,没法动态调试

1.1.1 start

__int64 start()
{
  void *v0; // ST30_8
  __int64 result; // rax
  char sn; // [rsp+40h] [rbp-30h]
  __int64 v3; // [rsp+68h] [rbp-8h]

  v0 = calloc(667uLL, 4uLL);
  scanf("%s", &sn);
  result = sub_100000DB0(
             (void (__fastcall *)(__int64, __int64))sub_100000D00,
             (unsigned int (__fastcall *)(__int64, void *))sub_100000C80,
             (unsigned int (__fastcall *)(__int64))sub_100000BA0,
             (unsigned int (__fastcall *)(__int64))sub_100000C10,
             (__int64)&sn,
             (__int64)v0);
  if ( __stack_chk_guard == v3 )
    result = 0LL;
  return result;
}

1.1.2 result函数

__int64 __fastcall sub_100000DB0(void (__fastcall *a1)(__int64, __int64), unsigned int (__fastcall *a2)(__int64, void *), unsigned int (__fastcall *a3)(__int64), unsigned int (__fastcall *a4)(__int64), __int64 sn, __int64 a6)
{
  unsigned int (__fastcall *v6)(__int64); // ST28_8
  __int64 sn_copy; // ST18_8
  __int64 v9; // [rsp+10h] [rbp-30h]
  unsigned int (__fastcall *v10)(__int64); // [rsp+20h] [rbp-20h]

  v6 = a3;                                      // 第三个函数
  v10 = a4;                                     // 第四个函数
  sn_copy = sn;
  v9 = a6;                                      // 指向一个地址
  a1(a6, sn);
  if ( v6(sn_copy) && v10(v9) && a2(v9, &unk_100001040) )
    printf("Congratz - You have earned it!");
  else
    printf("%s", "You've got to do better");
  return 0LL;
}

根据执行流程,分析a1,也就是第一个函数,sub_100000D00,内容如下

1.1.3 sub_100000D00

__int64 __fastcall sub_100000D00(__int64 a1, const char *a2)
{
  __int64 result; // rax
  int j; // [rsp+0h] [rbp-20h]
  int i; // [rsp+4h] [rbp-1Ch]
  int v5; // [rsp+8h] [rbp-18h]
  int v6; // [rsp+Ch] [rbp-14h]

  v6 = strlen(a2);
  v5 = 0;
  for ( i = 0; i < v6; ++i )
  {
    for ( j = i + 1; j < v6; ++j )
      *(_DWORD *)(a1 + 4LL * v5++) = a2[j] + a2[i];
  }
  result = a1;
  *(_DWORD *)(a1 + 2668) = 0;
  return result;
}

主要功能,将sn做变换,放入内存

接下来看v6(sn_copy),也就是sub_100000BA0

1.1.4 sub_100000BA0

_BOOL8 __fastcall sub_100000BA0(__int64 a1)
{
  signed int i; // [rsp+4h] [rbp-18h]
  int v3; // [rsp+8h] [rbp-14h]

  v3 = 0;
  for ( i = 0; i < 37; ++i )
    v3 += *(char *)(a1 + i);
  return v3 == 3504;
}

将sn的每一位,加一个数,然后整体相加=3504

接下来看v10(v9),也就是sub_100000C10

1.1.5 sub_100000C10

_BOOL8 __fastcall sub_100000C10(__int64 a1)
{
  signed int i; // [rsp+4h] [rbp-18h]
  int v3; // [rsp+8h] [rbp-14h]

  v3 = 0;
  for ( i = 0; i < 667; ++i )
    v3 += *(_DWORD *)(a1 + 4LL * i);
  return v3 == 126144;
}

这次传入的参数是将sn做变换,放入内存的值,然后检测这些值相加之后,是否=126144

1.1.6 sub_100000C80

最后看a2(v9, &unk_100001040),也就是 第二个函数sub_100000C80,参数是内存中的地址和从unk_100001040开始的一些值,部分如下

0000000100001040  D7 00 00 00 CC 00 00 00  DD 00 00 00 CF 00 00 00
0000000100001050  E4 00 00 00 BD 00 00 00  D1 00 00 00 9D 00 00 00
0000000100001060  DD 00 00 00 DC 00 00 00  C8 00 00 00 D1 00 00 00
0000000100001070  CE 00 00 00 9A 00 00 00  9A 00 00 00 C8 00 00 00
0000000100001080  D5 00 00 00 99 00 00 00  DD 00 00 00 C8 00 00 00
0000000100001090  99 00 00 00 CF 00 00 00  C8 00 00 00 E0 00 00 00
00000001000010A0  99 00 00 00 DB 00 00 00  D4 00 00 00 C8 00 00 00
00000001000010B0  E0 00 00 00 9D 00 00 00  DC 00 00 00 C8 00 00 00
00000001000010C0  D2 00 00 00 DD 00 00 00  A8 00 00 00 E6 00 00 00
00000001000010D0  D1 00 00 00 E2 00 00 00  D4 00 00 00 E9 00 00 00
00000001000010E0  C2 00 00 00 D6 00 00 00  A2 00 00 00 E2 00 00 00
00000001000010F0  E1 00 00 00 CD 00 00 00  D6 00 00 00 D3 00 00 00
0000000100001100  9F 00 00 00 9F 00 00 00  CD 00 00 00 DA 00 00 00
0000000100001110  9E 00 00 00 E2 00 00 00  CD 00 00 00 9E 00 00 00
0000000100001120  D4 00 00 00 CD 00 00 00  E5 00 00 00 9E 00 00 00
0000000100001130  E0 00 00 00 D9 00 00 00  CD 00 00 00 E5 00 00 00
0000000100001140  A2 00 00 00 E1 00 00 00  CD 00 00 00 D7 00 00 00
0000000100001150  E2 00 00 00 AD 00 00 00  EB 00 00 00 D7 00 00 00
0000000100001160  C9 00 00 00 DE 00 00 00  B7 00 00 00 CB 00 00 00
0000000100001170  97 00 00 00 D7 00 00 00  D6 00 00 00 C2 00 00 00
0000000100001180  CB 00 00 00 C8 00 00 00  94 00 00 00 94 00 00 00
0000000100001190  C2 00 00 00 CF 00 00 00  93 00 00 00 D7 00 00 00
_BOOL8 __fastcall sub_100000C80(__int64 a1, __int64 a2)
{
  signed int v3; // [rsp+0h] [rbp-1Ch]

  v3 = 0;
  while ( v3 < 666 )
  {
    if ( *(_DWORD *)(a1 + 4LL * v3) == *(_DWORD *)(a2 + 4LL * v3) )
      ++v3;
  }
  return v3 >= 666;
}

比较内存中的值是否相等

总共四个check。

思路就是根据unk_100001040,恢复flag,666*4=0xA68,选定字节从0x100001040到0x100001AA8的数据,

1.1.7 解线性方程组

接下来考虑解37元方程的解法,考虑z3求解器求解

  • 安装z3
git clone https://github.com/Z3Prover/z3.git
cd z3/
cd scripts/
python scripts/mk_make.py --prefix=/usr --python --pypkgdir=/usr/local/lib/python2.7/dist-packages #--prefix参数是用户目录,--pypkgdir是python包存在磁盘上的位置
make
sudo make install

接下来等待安装即可

1569333145236

  • 还有一种安装方法:
pip install z3-solver

然后写脚本求解

#!/usr/bin/env python
from z3 import *

secret=[0xD7,0xCC,0xDD,0xCF
,0xE4,0xBD,0xD1,0x9D
,0xDD,0xDC,0xC8,0xD1
,0xCE,0x9A,0x9A,0xC8
,0xD5,0x99,0xDD,0xC8
,0x99,0xCF,0xC8,0xE0
,0x99,0xDB,0xD4,0xC8
,0xE0,0x9D,0xDC,0xC8
,0xD2,0xDD,0xA8,0xE6
,0xD1,0xE2,0xD4,0xE9
,0xC2,0xD6,0xA2,0xE2
,0xE1,0xCD,0xD6,0xD3
,0x9F,0x9F,0xCD,0xDA
,0x9E,0xE2,0xCD,0x9E
,0xD4,0xCD,0xE5,0x9E
,0xE0,0xD9,0xCD,0xE5
,0xA2,0xE1,0xCD,0xD7
,0xE2,0xAD,0xEB,0xD7
,0xC9,0xDE,0xB7,0xCB
,0x97,0xD7,0xD6,0xC2
,0xCB,0xC8,0x94,0x94
,0xC2,0xCF,0x93,0xD7
,0xC2,0x93,0xC9,0xC2
,0xDA,0x93,0xD5,0xCE
,0xC2,0xDA,0x97,0xD6
,0xC2,0xCC,0xD7,0xA2
,0xE0,0xDA,0xEF,0xC8
,0xDC,0xA8,0xE8,0xE7
,0xD3,0xDC,0xD9,0xA5
,0xA5,0xD3,0xE0,0xA4
,0xE8,0xD3,0xA4,0xDA
,0xD3,0xEB,0xA4,0xE6
,0xDF,0xD3,0xEB,0xA8
,0xE7,0xD3,0xDD,0xE8
,0xB3,0xF1,0xE1,0xBA
,0xCE,0x9A,0xDA,0xD9
,0xC5,0xCE,0xCB,0x97
,0x97,0xC5,0xD2,0x96
,0xDA,0xC5,0x96,0xCC
,0xC5,0xDD,0x96,0xD8
,0xD1,0xC5,0xDD,0x9A
,0xD9,0xC5,0xCF,0xDA
,0xA5,0xE3,0xCF,0xE3
,0xAF,0xEF,0xEE,0xDA
,0xE3,0xE0,0xAC,0xAC
,0xDA,0xE7,0xAB,0xEF
,0xDA,0xAB,0xE1,0xDA
,0xF2,0xAB,0xED,0xE6
,0xDA,0xF2,0xAF,0xEE
,0xDA,0xE4,0xEF,0xBA
,0xF8,0xBC,0x88,0xC8
,0xC7,0xB3,0xBC,0xB9
,0x85,0x85,0xB3,0xC0
,0x84,0xC8,0xB3,0x84
,0xBA,0xB3,0xCB,0x84
,0xC6,0xBF,0xB3,0xCB
,0x88,0xC7,0xB3,0xBD
,0xC8,0x93,0xD1,0x9C
,0xDC,0xDB,0xC7,0xD0
,0xCD,0x99,0x99,0xC7
,0xD4,0x98,0xDC,0xC7
,0x98,0xCE,0xC7,0xDF
,0x98,0xDA,0xD3,0xC7
,0xDF,0x9C,0xDB,0xC7
,0xD1,0xDC,0xA7,0xE5
,0xA8,0xA7,0x93,0x9C
,0x99,0x65,0x65,0x93
,0xA0,0x64,0xA8,0x93
,0x64,0x9A,0x93,0xAB
,0x64,0xA6,0x9F,0x93
,0xAB,0x68,0xA7,0x93
,0x9D,0xA8,0x73,0xB1
,0xE7,0xD3,0xDC,0xD9
,0xA5,0xA5,0xD3,0xE0
,0xA4,0xE8,0xD3,0xA4
,0xDA,0xD3,0xEB,0xA4
,0xE6,0xDF,0xD3,0xEB
,0xA8,0xE7,0xD3,0xDD
,0xE8,0xB3,0xF1,0xD2
,0xDB,0xD8,0xA4,0xA4
,0xD2,0xDF,0xA3,0xE7
,0xD2,0xA3,0xD9,0xD2
,0xEA,0xA3,0xE5,0xDE
,0xD2,0xEA,0xA7,0xE6
,0xD2,0xDC,0xE7,0xB2
,0xF0,0xC7,0xC4,0x90
,0x90,0xBE,0xCB,0x8F
,0xD3,0xBE,0x8F,0xC5
,0xBE,0xD6,0x8F,0xD1
,0xCA,0xBE,0xD6,0x93
,0xD2,0xBE,0xC8,0xD3
,0x9E,0xDC,0xCD,0x99
,0x99,0xC7,0xD4,0x98
,0xDC,0xC7,0x98,0xCE
,0xC7,0xDF,0x98,0xDA
,0xD3,0xC7,0xDF,0x9C
,0xDB,0xC7,0xD1,0xDC
,0xA7,0xE5,0x96,0x96
,0xC4,0xD1,0x95,0xD9
,0xC4,0x95,0xCB,0xC4
,0xDC,0x95,0xD7,0xD0
,0xC4,0xDC,0x99,0xD8
,0xC4,0xCE,0xD9,0xA4
,0xE2,0x62,0x90,0x9D
,0x61,0xA5,0x90,0x61
,0x97,0x90,0xA8,0x61
,0xA3,0x9C,0x90,0xA8
,0x65,0xA4,0x90,0x9A
,0xA5,0x70,0xAE,0x90
,0x9D,0x61,0xA5,0x90
,0x61,0x97,0x90,0xA8
,0x61,0xA3,0x9C,0x90
,0xA8,0x65,0xA4,0x90
,0x9A,0xA5,0x70,0xAE
,0xCB,0x8F,0xD3,0xBE
,0x8F,0xC5,0xBE,0xD6
,0x8F,0xD1,0xCA,0xBE
,0xD6,0x93,0xD2,0xBE
,0xC8,0xD3,0x9E,0xDC
,0x9C,0xE0,0xCB,0x9C
,0xD2,0xCB,0xE3,0x9C
,0xDE,0xD7,0xCB,0xE3
,0xA0,0xDF,0xCB,0xD5
,0xE0,0xAB,0xE9,0xA4
,0x8F,0x60,0x96,0x8F
,0xA7,0x60,0xA2,0x9B
,0x8F,0xA7,0x64,0xA3
,0x8F,0x99,0xA4,0x6F
,0xAD,0xD3,0xA4,0xDA
,0xD3,0xEB,0xA4,0xE6
,0xDF,0xD3,0xEB,0xA8
,0xE7,0xD3,0xDD,0xE8
,0xB3,0xF1,0x8F,0xC5
,0xBE,0xD6,0x8F,0xD1
,0xCA,0xBE,0xD6,0x93
,0xD2,0xBE,0xC8,0xD3
,0x9E,0xDC,0x96,0x8F
,0xA7,0x60,0xA2,0x9B
,0x8F,0xA7,0x64,0xA3
,0x8F,0x99,0xA4,0x6F
,0xAD,0xC5,0xDD,0x96
,0xD8,0xD1,0xC5,0xDD
,0x9A,0xD9,0xC5,0xCF
,0xDA,0xA5,0xE3,0xD6
,0x8F,0xD1,0xCA,0xBE
,0xD6,0x93,0xD2,0xBE
,0xC8,0xD3,0x9E,0xDC
,0xA7,0xE9,0xE2,0xD6
,0xEE,0xAB,0xEA,0xD6
,0xE0,0xEB,0xB6,0xF4
,0xA2,0x9B,0x8F,0xA7
,0x64,0xA3,0x8F,0x99
,0xA4,0x6F,0xAD,0xDD
,0xD1,0xE9,0xA6,0xE5
,0xD1,0xDB,0xE6,0xB1
,0xEF,0xCA,0xE2,0x9F
,0xDE,0xCA,0xD4,0xDF
,0xAA,0xE8,0xD6,0x93
,0xD2,0xBE,0xC8,0xD3
,0x9E,0xDC,0xAB,0xEA
,0xD6,0xE0,0xEB,0xB6
,0xF4,0xA7,0x93,0x9D
,0xA8,0x73,0xB1,0xD2
,0xDC,0xE7,0xB2,0xF0
,0xC8,0xD3,0x9E,0xDC
,0xDD,0xA8,0xE6,0xB3
,0xF1,0xBC]

solver=Solver()
X = [BitVec('x_%s' % i, 8) for i in range(37)]
count1 = 0
for i in range(37):
    for j in range(i+1, 37):
        solver.add(X[i] + X[j] == secret[count1])
        count1 += 1
        if (count1 == 666):
            break

check1 = 0
for i in range(37):
    check1 += X[i]
solver.add(check1 == 3504)


check2 = 0
count2 = 0
for i in range(37):
    for j in range(i+1, 37):
        check2 += X[i] + X[j]
        count2 += 1
        if (count2 == 666):
            break
solver.add(check2 == 126144)

if solver.check() == sat:
    flag = ""
    m = solver.model()
    for i in range(37):
        flag += chr(m[X[i]].as_long())
    print(flag)

得到flag

1569411547526


本文访问量: