首页
论坛
课程
招聘
[原创]KCTF2021秋季赛第9题 万事俱备
2021-12-9 02:34 16454

[原创]KCTF2021秋季赛第9题 万事俱备

2021-12-9 02:34
16454

E语言,IDA+E-Decompiler,定位关键函数sub_4010CB
图片描述
里面会释放7z.exe和ctf.7z,而后用7z.exe去解压ctf.7z,得到python27.exe和check.py,最后调用python27.exe check.py
图片描述
校验逻辑全部在check.py中,发现是字节码
运行python27.exe,重命名为check.pyc,import一下,然后dir看有哪些东西
图片描述
可以hook函数,打印入参和返回值

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
import check
#input
'''
05C1930A146B0FC3
8E6E67F357338CC7912F3161CBAC4273
'''
from check import *
 
def funcA(A,B):
    print("A-----------GO")
    print(A,B)
    ret = O00(A,B)
    #print(ret)
    print(A,B)
    print("A----------END")
    return ret
 
def funcB(A,B,C):
    print("B-----------GO")
    print(A,B,C)
    print(A.encode('hex'))
    ret = O00OooOOo0O(A,B,C)
    print(ret.encode('hex'))
    print("B----------END")
    return ret
 
def funcC(A,B):
    print("C-----------GO")
    print(A,B)
    ret = OO0oo0(A,B)
    print(ret)
    print("C----------END")
    return ret
 
def funcD(A,B):
    print("D-----------GO")
    print(A,B)
    ret = o00oo0(A,B)
    print(ret)
    print("D----------END")
    return ret
 
def funcE(A,B):
    print("E-----------GO")
    print(A,B)
    ret = oOO0o00Oo(A,B)
    #print(ret)
    print("E----------END")
    return ret
 
check.O00 = funcA
check.O00OooOOo0O = funcB
check.OO0oo0 = funcC
check.o00oo0 = funcD
check.oOO0o00Oo = funcE
 
check.O0ooo0()

图片描述
算法上半,猜测是个RC4,求出最后的xor就可
图片描述
图片描述
得到xor key 1b4ff4d1f9f35895b40aeca5539cba0a
算法下半,验证猜出D函数是个rot,需要调试python27.exe
下断所有的PyNumber,PyInt,PyLong类函数,只调用B函数减少干扰,根据程序运行,做好log输出信息,参考https://docs.python.org/2.7/c-api/number.html了解api参数等
图片描述
图片描述
下条件断点PyInt_FromLong,rcx==数字(这里下断了0xf188),ret时会创建一个Python对象,偏移量0x10是这个数字,硬件断点跟踪,可以追踪对这个数字执行的逻辑,理论上可以还原算法
图片描述
图片描述
图片描述
结果群里有人 hint
图片描述
也做过今年春季赛第7题,感觉很像,只是改了下数字顺序,按照现在已经逆向出的算法,求数组输入顺序
拿出以前的脚本改改了

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include<stdio.h>
#define int unsigned int
 
int rol(int num,int i){
    return (num << (i%16) | num >> ((16-i)%16))&0xffff;
}
 
int ror(int num,int i){
    return (num >> (i%16) | num << ((16-i)%16))&0xffff;
}
void dec(unsigned short*a,int r,unsigned short* p){
    int t[110];
    int x1=p[0]^p[1];//a[4]^a[5]
    int x2=p[2]+p[3];//a[2]+a[3]
    int x3=p[4]-p[5];//a[1]-a[0]
    int x4=rol(p[6]^p[7],r);//a[6]^a[7]
    t[1]=x2;
    t[2]=x1;
    t[3]=x3&0xffff;
    t[4]=t[1]&t[2];
    t[0]=~t[2]&0xffff;
    t[5]=t[0]&t[3];
    t[12]=t[4]|t[5];
    t[6]=(t[12]&0XFFFF)*t[2];
    t[7]=t[6]>>r;
    t[8]=t[7]+0X18;
    t[9]= t[3] ^ (t[8] & 0XFFFF);
    t[10]=t[8]&t[12];
    t[11]=t[9]|t[10];
    a[0]=p[5]-t[8];
    a[1]=x3+a[0];
    a[2]=p[3]+t[9];
    a[3]=p[2]-t[9];
    a[4]=p[1]^t[11]^0X0000;
    a[5]=p[0]^t[11]^0X0000;
    a[6]=ror(p[7],r)^t[12];
    a[7]=ror(p[6],r)^t[12];
#if 0
    for(int i=0;i<13;i++){
        printf("%.8x ",t[i]);
    }
    printf("\n");
#endif
 
}
int main(){
    for(int x=0;x<16;x++){
        unsigned char p1[16]={0};
        unsigned char t[16]={0};
        //char s[16]={0x4b,0x43,0x54,0x46,0x00,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x11,0x10};
        char* s="KCTF@021GoodLuck";
        unsigned short r[8]={0};
        unsigned short s2[8]={0};
        printf("%.1x::",x);
        for(int i=0;i<8;i++){
            s2[i]=s[2*i+0]+s[2*i+1]*256;
        }
        dec(r,x,s2);
        for(int i=0;i<8;i++){
            t[2*i+0]=r[i]%256;
            t[2*i+1]=r[i]>>8;
        }
        //4546 4330 3733 3530 4132 4445 4530 3333
        // for(int i=0;i<8;i++){
        //  p1[2*i+0]=t[(6-i*2)%16];
        //  p1[2*i+1]=t[(5-i*2)%16];
        // }
        int shuffle[]={2,1,4,3,6,5,0,7};
        for(int i=0;i<8;i++){
            printf("%.2X",t[shuffle[i]*2]);
            printf("%.2X",t[shuffle[i]*2+1]);
        }
        printf("\n");
    }
}

寻找最后比较的输出,提供的注册码是直接比较了username,猜测KCTF用00补全,没猜对,只好测一下
username输入KCTF,serial用提供的,
CheatEngine搜索提供的username
找到应该比较的字符串是KCTF@021GoodLuck
图片描述
算法爆破会有16个结果,输进去观察发现rot中参数是9,使用第9个结果 B645EB508058BC1B67BA9F5D1346E8AD
图片描述
图片描述
B645EB508058BC1B67BA9F5D1346E8AD和之前的key xor
图片描述
得到AD0A1F8179ABE48ED3B073F840DA52A7,即为正确答案
图片描述


【公告】 讲师招募 | 全新“预付费”模式,不想来试试吗?

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回