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
接下来等待安装即可
- 还有一种安装方法:
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