HGAME2019-Say-Muggle-Code a.k.a. SMC

首先SMC,使用python脚本:

1
2
3
4
5
6
7
8
i=0x603000
key=123
while 1:
PatchByte(i,Byte(i)^key)
i+=1
key+=1
if i == 0x603200:
break

要求输入的flag长度为39,并且格式为hgame{}。

同时把括号内的内容分为两半,前面一半用check1检验,后面一半用check2检验。

check1:

每个字符异或0xe9后与data1比较,所以可以直接逆运算:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
data1=[0xDE,
0xD1,
0xD8,
0x8C,
0x8F,
0xD9,
0xDF,
0xDE,
0xDF,
0x8C,
0xD8,
0xDA,
0x8C,
0xDC,
0xDD,
0xD8,]
print ''.join([chr(i^0xe9) for i in data1])

结果为781ef0676e13e541

check2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
_DWORD *__fastcall encrypt(__int64 a1, _DWORD *a2)
{
_DWORD *result; // rax
int v3; // [rsp+10h] [rbp-10h]
signed int i; // [rsp+14h] [rbp-Ch]
signed int j; // [rsp+18h] [rbp-8h]

v3 = 0;
for ( i = 0; i <= 31; ++i )
{
result = (_DWORD *)0x9E3779B9LL;
v3 -= 0x61C88647;
for ( j = 0; j <= 3; j += 2 )
{
*(_DWORD *)(a1 + 4LL * j) = *(_DWORD *)(4LL * j + a1)
+ ((*(_DWORD *)(4 * (j + 1LL) + a1) + v3) ^ (16 * *(_DWORD *)(4 * (j + 1LL) + a1) + *a2) ^ ((*(_DWORD *)(4 * (j + 1LL) + a1) >> 5) + a2[1]));
result = (_DWORD *)(4 * (j + 1LL) + a1);
*result += (*(_DWORD *)(4LL * j + a1) + v3) ^ (16 * *(_DWORD *)(4LL * j + a1) + a2[2]) ^ ((*(_DWORD *)(4LL * j + a1) >> 5)
+ a2[3]);
}
}
return result;

TEA。

解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdint.h>
#include <stdio.h>
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], v2=v[2],v3=v[3], sum=0xC6EF3720, i;
uint32_t delta=0x9e3779b9;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
v3 -= ((v2*16) + k2) ^ (v2 + sum) ^ ((v2>>5) + k3);
v2 -= ((v3*16) + k0) ^ (v3 + sum) ^ ((v3>>5) + k1);
v1 -= ((v0*16) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1*16) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
}
v[0]=v0; v[1]=v1; v[2]=v2; v[3]=v3;
}
int main()
{
uint32_t flag[4]={0xbdba0e28,0x38d1cd98,0x3ab63e63,0x535e9dac};
uint32_t key[4]={0x5b3e0f37,0x0c3b0d3d,0x5d6e5f3a,0x31390d38};
decrypt(flag,key);
for (int i=0;i<4;i++)
{
printf("%x ",flag[i]);
}
return 0;
}

然而并没有得到正确的后半部分23333


鬼知道当时哪里搞来的flag和key……

看了大佬的wp之后才发现自己flag和key完全不对orz

正确的flag直接从data2处取就行了。

key的话是利用6-22位异或,然而我一直不知道哪里出了错,只有第一位和和第二位是正确的。后来通过dalao的key反推发现,异或只在"781ef0676e13e541"上进行,但是我写脚本时却利用了异或之后的值继续异或,这也是只有一二位正确的原因。

正确flag与key:

1
2
key[4] = {0x54090f37,0x01065603, 0x02545301, 0x05015056};
flag[4] ={0xd240f52f,0x728cca9d,0xb6379fd3, 0xfba1a736};

改正后跑出后半部分:
64313964 66656265 31633236 66363439

都是16进制,转换为字符得到:
d91debef62c1946f

最终flag:hgame{781ef0676e13e541d91debef62c1946f}

简直回到了高中做数学题的时候,知道怎么做但是最后答案不对,还一直不到哪里错了orz

文章目录
|