UnravelMFC

XNUCA实在是太难了,连这个XNUCA做出来人数最多的一题我都做了接近两天才弄出来,还是太菜了。

本题是一个MFC题有输入框但无论你怎么输入,始终无法点击那个确认按钮,我也是醉了这个地方,后面就在import表中找到GetWindowTextW,GetDlgItemTextW函数下断但始终没断下来,后面于是换了个思路用xspy工具扫它找到它几个button所对应的函数,然后下断。

image-20201103154713519

定位了三个函数,其中断在了sub_5A13A0这个函数,终于发现里面有个判断长度的地方

image-20201103154956457

但恶心的是你的输入框最多只允许你输入0x3f长度,所以不管你怎么输入都过不了这个判断。这也难怪窗体上那个确认键无法触发了,将这个判断patch掉,就能顺利来到了sub_5A1080这个函数,前面一大串都是些无用的函数,直到这个判断

image-20201103160415658

里面有一个很奇怪的字符,进去看了以下就是flag正确,以UTF-16LE的格式存储的,难怪string不出来

image-20201103160556235

到这里基本上就能确定关键函数的位置了,第一个判断函数是做了一个RC4加密,把亦或的key dump出来就行,然后又做了个魔改base64(函数好像做了控制流平坦化,这个要调试才能看出来)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
key=[0x40,0x28,0xb6,0x5c,0xd3,0x84,0x5c,0x1a,0xe0,0x18,0xfd,0x3f,0x5d,0xce,0xf6,0xbb,0x3d,0x46,0x43,0x82,0x7a,0xa9,0x5c,0xe3,0xe4,0x48,0xfd,0xa5,0xb9,0x39,0x7b,0xd4,0xfe,0xfe]
#input[:0x1b]^key
#base64encode()
from z3 import *
import base64
import string
print(len(key))
str1 = "$HM%/NEX,79PBN\C/BQLVSW,*/'8T#UMC4%EG@@@,.%5"

string1 = "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ab"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tmp=base64.b64decode(str1.translate(str.maketrans(string1,string2)))
print(len(tmp))
flag=""
for i in range(0x21):
flag+=chr(tmp[i]^key[i])
print (flag)
#Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dl

这就是前半段的解,第二个函数先是判断你的第二段的首字符是不是“f”,然后将你的输入做了一个DWORD小端转换,之后就是做了一个魔改的TEA加密但这个加密只改了delta,其它像运算过程是没改的,后面就到了比较部分了,这又是一个坑人的地方。它将最后的生成的密文分成4段64位,res[0],res[1],res[2],res[3],其中res[1]==0xDF3634AE2F9970FF。

image-20201103162005697

然后下一步判断是一个加减法运算

1
2
3
(res[2]-res[0]==0x3F66B755B4490579)
(res[3]+res[0]==0x1162F924623D2CAE0)
(res[3]-res[2]==0x7C3C71F1B295D77F)

image-20201103162842110

从判断函数上看res[3]+res[0]==0x162F924623D2CAE0,但后面通过这个解出来的值再做TEA解密有不可见字符,经过其他的师傅提醒才发现这里会有一个溢出,所以进一位尝试发现这样才有可行解,最终解出来是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from z3 import *
s=Solver()
x=Int('x')
y=Int('y')
z=Int('z')
s.add(y-x==0x3F66B755B4490579)
s.add(z+x==0x1162F924623D2CAE0)
s.add(z-y==0x7C3C71F1B295D77F)
print s.check()
print s.model()
key1=[0xD9610D02, 0x2AADA57D, 0xA37537F1, 0xC29E3913]
key2=[0xD5942CE8, 0x608CCE66, 0x6D593422, 0x21E5D6F2]
key3=[0xED3A9235, 0x9DAD62C4, 0x3856641B, 0x71F75B9D]
key4=[0xDCDEDAE8, 0xEAD2D1A0, 0xBAC4F564, 0xDA4772AC]
res1: 0x2D46347F 0x5E79F6F4

res2: 0xDF3634AE 0x2F9970FF

res3: 0x6CACEBD5 0x12C2FC6D

res4: 0xe8E95DC6 0xC558D3EC

再用魔改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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <stdio.h>  
#include <stdint.h>

//加密函数
void encrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
uint32_t delta = 0x9e3779b9; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
} /* end cycle */
v[0] = v0; v[1] = v1;
}
//解密函数
void decrypt(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0x2433B95A<<5, i; /* set up */
uint32_t delta = 0x2433B95A; /* a key schedule constant */
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
for (i = 0; i<32; i++) { /* basic cycle start */
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
} /* end cycle */
v[0] = v0; v[1] = v1;
}
void get_byte(uint32_t t)
{
char tmp[4];
int i;
for (i = 0; i < 4; i++)
{
tmp[i] = (t >> (8 * i)) & 0xff;
}
for (i = 0; i < 4; i++)
{
printf("%c", tmp[i]);
}
}
int main()
{
uint32_t v[8] = { 0x2D46347F,0x5E79F6F4,0xDF3634AE,0x2F9970FF,0x6CACEBD5,0x12C2FC6D,0xe8E95DC6,0xC558D3EC }, k[16] = { 0xD9610D02, 0x2AADA57D, 0xA37537F1, 0xC29E3913, 0xD5942CE8, 0x608CCE66, 0x6D593422, 0x21E5D6F2,0xED3A9235, 0x9DAD62C4, 0x3856641B, 0x71F75B9D,0xDCDEDAE8, 0xEAD2D1A0, 0xBAC4F564, 0xDA4772AC };
int i;
for (i = 0; i < 4; i++)
{
decrypt(&v[2 * i], &k[4 * i]);
printf("解密后的数据:%x %x\n", v[2*i], v[2*i+1]);
}
for (i = 0; i < 8; i++)
{
get_byte(v[i]);
}
getchar();
return 0;
}
#f1cUlt_foR_THe_r0Ok1E_t0_REver5e

拼在一起就是

Fr4nk1y_MfC_l5_t0O_ComPIeX_4nd_dlff1cUlt_foR_THe_r0Ok1E_t0_REver5e

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2022 llx-moon
  • Visitors: | Views:

请我喝杯咖啡吧~