首页
社区
课程
招聘
[原创]2022秋季赛题目提交
2022-10-25 15:42 6945

[原创]2022秋季赛题目提交

2022-10-25 15:42
6945

战队名称:天外星系
战队创建者:geekfire
题目名称:NoLimit
输出提示:key正确则输出提示good!

题目设计说明

本题注册算法通过两段shellcode实现,分别简称为sc1 sc2
算法的核心步骤是根据生成的很简单的迷宫地图和输入的迷宫路径来验证是否能走出迷宫。
其中sc1负责生成迷宫地图,如果检测到调试信息等会生成错误的伪迷宫。

 

SC2负责验证迷宫,如果迷宫验证无误,则会修改提示信息为good!否则为no!
如果key正确则输出提示good! 否则输出no!或者不输出任何提示。

 

另外sc1通过aes 算法加密,私钥的前4个字符需要枚举才能解密,后面的字符被RSA加密。

(1)aes秘钥后部分解密:

给定的rsa算法里面的n可以快速被分解,通过分解n求出rsa私钥,即可解密,得到后部分秘钥为:AllIsNothing。

(2)aes秘钥前四个字符枚举条件 四个字符必须为数字类型

1
2
1 0
0 1

1、把前4个字符任意排列,只要其中一组排列满足:按上表所示,横向 和 纵向 两个字符相加结果要全部相等
2、通过aes秘钥尝试解密sc1,使得sc1解密后执行时不产生异常
枚举通过python + vc代码实现
python负责枚举 vc负责解密sc1并执行
其中vc 部分代码如下:

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
    SetUnhandledExceptionFilter(callback);
    int ScSize = 0;
    string FindScDec;
    string AesKeyPreffix;
    if (argc > 1)
        AesKeyPreffix = argv[1];
    string AesKeySuffix = "AllIsNothing";
    string AesKey;
    string aesIV = "ABCDEF0123456789";//128 bits
    AES aes;
    int size = strlen(FindScEnc) / 2;
    TextToHex(FindScEnc, size);
 
    AesKey = AesKeyPreffix + AesKeySuffix;
    FindScDec = (char*)aes.DecryptCBC((unsigned char*)FindScEnc, size, (unsigned char*)AesKey.c_str(), (unsigned char*)aesIV.c_str());//CBC
    ScSize = FindScDec.size();
    void* ptr = NULL;
 
    ptr = VirtualAlloc(
        NULL,
        ScSize,
        MEM_RESERVE | MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);
    if (ptr == NULL) {
        //printf("Failed to allocate memory: error=%u\n", GetLastError());
        return 1;
    }
    memcpy(ptr, FindScDec.c_str(), ScSize);
    __try{
        ((void(*)())ptr)();
    printf("success!\r\n");
}
   __except (filterException(GetExceptionCode(), GetExceptionInformation()))
    {
 
       printf("the aes preffix %s is error\r\n", AesKeyPreffix.c_str());
    }
    return 0;

把上述代码编译为NoLimit.exe,然后用脚本调用枚举
python 枚举部分代码为:

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
# -*- coding: UTF8 -*-
import os
import threading
import datetime
chrs = '0123456789'
AesPreffix = ''
a=b=c=d=''
AesPreffixS =[]
starttime = datetime.datetime.now()
threads = []
class Getoutofloop(Exception):
    pass
def runsc(AesPreffix):
    cmd = os.popen('NoLimit.exe ' + AesPreffix)
    result = cmd.read()
    print("result:" + result)
    if 'success' in result:
        print('AesPreffix is '+ AesPreffix)
        AesPreffixS.append(AesPreffix)
for a in chrs:
    AesPreffix += a
    for b in chrs:
        AesPreffix += b
        for c in chrs:
            AesPreffix += c
            for d in chrs:
                AesPreffix += d           
                t = threading.Thread(target=runsc, args=(AesPreffix,))
                threads.append(t)
                t.start()
                   #os._exit(0)
                AesPreffix = AesPreffix[:-1]
            AesPreffix = AesPreffix[:-1]
        AesPreffix = AesPreffix[:-1]
    AesPreffix = AesPreffix[:-1]
for t in threads:
    t.join(2)
os.system('taskkill /f /im %s' % 'NoLimit.exe')
#print(AesPreffixS)
str = ''
lastresult = []
try:
    for p in AesPreffixS:
        for i in range(0,4):
            a = p[i]
            for j in range(0,4):
                if j == i :
                    continue
                b = p[j]
                for k in range(0,4):
                    if k == j or k == i:
                        continue
                    c = p[k]
                    for l in range(0,4):
                        if l == k or l == j or l == i:
                            continue
                        d = p[l]
                        str = a + b + c + d
                        #print(str)
                        num = ord(str[0]) + ord(str[1])
                        if num == ord(str[2]) + ord(str[3]) and num == ord(str[0]) + ord(str[2]) and num == ord(str[1]) + ord(str[3]):
                            if p not in lastresult:
                                lastresult.append(p)
                            break;
                            #raise Getoutofloop()
except Getoutofloop:
    pass
print('AesPreffix:')
print(lastresult)
endtime = datetime.datetime.now()
print('time:%ds' % (endtime - starttime).seconds )

枚举完成大概不到3分钟,结果如下:
result:
AesPreffix:
['1441', '1010', '2222', '2424', '3773', '4646']
time:133s
得到6个结果,6个前缀对应的解密后的sc1分别为:

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
1441
    test edi,ebx
    jl 1C8D88FFFDD//该跳转不执行
    fdiv st(0),st(1)
    ret
 
2222
 
        ret
 
2424
 
    xor cl,byte ptr ds:[rbx+19]
    ret
 
3773
    ret
 
4646
    adc ch,al
    ret
 
1010
    call 1D18DAF0004
    接着:
    1D18DAF0004:    inc eax
                    pop rdi
                    mov ecx,10107B1
                    xor ecx,1010101
                    add rdi,1E
                    xor esi,esi
                    cld
                    mov al,byte ptr ds:[rdi]
                    cmp al,11
                    cmove eax,esi
                    stosb
                    loop 1D18DAF0019
                    push rbx
                    push rsi
                    push rdi
                    push r12
                    push r13
                                        ... ...

除了1010外 其他都都是执行两三条汇编指令后就返回了
这时可以判断Aes秘钥为1010AllIsNothing

(3)解密了sc1后 sc1负责生成迷宫

过了一些调试和一部分条件后生成真实迷宫如下:

1
2
3
4
5
6
7
8
9
10
01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01
01 01 01 01 01 01 01 01 01 01
00 00 00 00 01 01 01 01 01 01
01 01 01 00 01 01 01 01 01 01
01 00 00 00 00 00 00 01 01 01
01 00 01 01 01 01 00 01 01 01
01 00 00 00 00 01 00 00 00 01
01 01 01 01 00 01 00 01 01 01
01 01 01 01 00 01 01 01 01 01

其中00 表示可以通过的路径
然后sc2 负责验证迷宫路径是否正确
路径的坐标为:

1
30 31 32 33 43 53 52 51 61 71 72 73 74 84 94

(4)key的组成

1、用来解密的rsa私钥
2、AES秘钥前4个字符
3、路径长度
4、路径坐标
最后key 为:

1
1BDF5752B86533B0EF0C488375EBFE389163712709D3FEE35C7679A1AB7A8E697366227CAF168C99DD7F110100F303132334353525161717273748494

(5)最后留了一个干扰项

有个求解方程的逻辑,实际上无解,就算解出来了也会输出no!


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2022-12-11 12:03 被kanxue编辑 ,原因:
上传的附件:
收藏
点赞2
打赏
分享
最新回复 (5)
雪    币: 32410
活跃值: (18730)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2022-11-14 16:10
2
0
第十题 两袖清风
雪    币: 32410
活跃值: (18730)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2022-12-9 08:02
3
0

ThTsOD发现一解1BDF5752B86533B0EF0C488375EBFE389163712709D3FEE35C7679A1AB7A8E697366227CAF168C99DD7F11010173031324351525354555661717273746676777884948694



98k团队:

1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F201220122012201220122012201201


1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F201320132013201320132013201301


1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F201120112011201120112011201101


1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F101110111011101110111011101101


1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F102110211021102110211021102102


最后于 2022-12-9 13:09 被kanxue编辑 ,原因:
雪    币: 32410
活跃值: (18730)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2022-12-9 13:08
4
0
摸鱼划水打酱油  11:33:19
012345678901234567890123456789012345678901234567890123456789012345678901234567890123449941010201020102010201020102010201020

  11:33:20
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234499412102010201020102010201020102010201020
雪    币: 32410
活跃值: (18730)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2022-12-11 11:08
5
0
000000000000000000000000000000000000000000000000000000000000000000000000000000000000B88880F101102030405060706050403020102

0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0124301010E1021120312031203140516071809
雪    币: 32410
活跃值: (18730)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2022-12-14 15:35
6
0



得分: 179.69*0.4984209207=89.56

游客
登录 | 注册 方可回帖
返回