rctf2018_magic

Author Avatar
Xzhah 10月 14, 2018
  • 在其它设备中阅读本文章

RCTF2018_MAGIC

好久没发博了,大三破事太多了。。。估计这一年打CTF的时间不会太多了

不过,网鼎杯决赛和misty当队友这个事足够我吹一年了233(虽然我全程划水?)

时间戳爆破

首先要有一个对的时间戳才能进入下一步,且这个函数在main函数之前执行

这个可以用trace window追踪输出定位函数

然后爆破的话,我们就用iathook把magic.exe的时间戳验证函数调用出来爆破就行了,给力

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<windows.h>
#include<string.h>
typedef __int64 (* main_t)();
#define TIME_IAT 0xa38c
#define CHECK_IAT 0x2268
#define CHAT_1 0x5020
int the_time=1526720400;
__time64_t mygets(__time64_t *the_time_tmp)
{
return the_time;
}
void changeIAT(UINT64* iat, UINT64 newVal) //64位的函数实际地址为8字节,ida里time最后是[0x40a38c]里存着这个实际地址
{
DWORD oldProtect;
VirtualProtect(iat, sizeof(DWORD), PAGE_EXECUTE_READWRITE, &oldProtect);//保护内容就4字节
*iat = newVal;
VirtualProtect(iat, sizeof(DWORD), oldProtect, &oldProtect);
}
int main()
{
printf("ok?");
char chat_tmp[256]={0};
HMODULE hMod = LoadLibraryA("magic.dll");
PBYTE pBase=(PBYTE)hMod;
memcpy(chat_tmp,pBase+CHAT_1,256);
if (pBase == NULL)
{
printf("cannot LoadLibrary");
auto err = GetLastError();
printf("%d",err); //193错误就是dll错误,有可能是位数不对 ,126错误是找不到dll
return -1;
}
UINT64* timeiat = (UINT64* )(pBase + TIME_IAT);
changeIAT(timeiat, (UINT64)&mygets);
main_t check_time=(main_t)(pBase + CHECK_IAT);
while (TRUE)
{
//printf("%d\n",the_time);
if (check_time() == 0)
{
memcpy(pBase+CHAT_1,chat_tmp,256);//里面的chat_1有一个chat_1^=rand()的运算,每次跑完会变 我们要还原它
the_time++;
}
else{
printf("the time is %d\n",the_time);
break;
}
}
return 0;
}

有个坑就是64位的函数地址是8字节,呵呵,我被DWORD坑了好久

1.png

RC4

标准rc4,不表了

2.png 3.png 4.png

这里特别迷的一个事就是,我边写注释IDA边给我删注释,我写到最后一行一看,前面的全没了?

重写IDA,刻不容缓

VM

虽然有点不必要,但是可以先打印出每次的指令。。。其实看数组就知道了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from idaapi import *
from idc import *
import os
AddBpt(0x402a46)
print "[+] breakpoint at 0x403e65..."
StartDebugger("","","")
for i in range(0,60):
GetDebuggerEvent(WFNE_SUSP|WFNE_CONT, -1)
#print 'run No. %d' % i
eax = GetRegValue('EAX')
if(eax != 0):
print '[+] ' + hex(eax)

自从做了HCTF2018的level2.。。。再做这个我感觉舒服多了

逻辑如下

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
58
59
regs[1]存放的是unk_405320 regs[2]存放的是rc4加密后的输入
regs[3]=0
regs[4]=0x1a
regs[0] = 0x66
ip-2e跳到这
regs[5]=regs[2]
regs[5]+=regs[3]
regs[5]=*regs[5]
regs[6]=0xcc
regs[5]+=regs[6]
regs[6]=0xff
regs[5]&=regs[6]
regs[5]^=regs[0]
regs[0]=~regs[0] %256
regs[6]=regs[5]
regs[5]=regs[1]
regs[5]+=regs[3]
regs[5]=*regs[5]
dword_409060=5
dword_409064=6
regs[5]=regs[5]==regs[6]
if(regs[5]): ip+2
else : break
regs[3]+=regs[5]
regs[5]=regs[3]
regs[5]=regs[5]==regs[4]
if !regs[5] : ip-2e
10101111
else ip+1
break

z3脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from z3 import *
s=Solver()
regs1=[0x89, 0xC1, 0xEC, 0x50, 0x97, 0x3A, 0x57, 0x59, 0xE4, 0xE6, 0xE4, 0x42, 0xCB, 0xD9, 0x08, 0x22, 0xAE, 0x9D, 0x7C, 0x07, 0x80, 0x8F, 0x1B, 0x45, 0x04,0xe8]
regs2=[BitVec('n%d'%i,8)for i in range(0x1a)]
regs4=0x1a
regs0=0x66
for i in range(0x1a):
s.add((regs2[i]+0xcc)&0xff^regs0==regs1[i])
regs0=~regs0
s.check()
flag=s.model()
flag_rc4ed=[]
for i in range(0x1a):
flag_rc4ed.append((flag[regs2[i]].as_long()))
print hex((flag[regs2[i]].as_long()))
print flag_rc4ed

然后把得到的flag_rc4ed带入rc4函数得到@ck_For_fun_02508iO2_2iOR}

把这个一输入,可以看到有rctf{h的形状。(据说非近视眼看不到)

5.png

后面

可能后面会写一些入坑区块链的东西?大三CTF的时间要减少了。。傻逼学院不认信安竞赛的加分我佛了,可能大三会多一些开发的经历吧。。。希望顺利。当然开发多了对逆向也有帮助,不止一个大哥如是说到。那么,calm down and move on!