首页
论坛
课程
招聘
[原创]KCTF2020秋季赛 第二题 异常信号 Writeup
2020-11-21 09:07 1018

[原创]KCTF2020秋季赛 第二题 异常信号 Writeup

2020-11-21 09:07
1018

KCTF2020秋季赛 第二题 异常信号 Writeup

程序刚下载下来就被杀了,似乎“来者不善”。试运行下:

1
2
3
4
5
PS C:\Users\admin\Downloads\kctf2020\2> .\CrakMe.exe
Input Serial:
123
 
一个礼貌的开场白还是要的

静态分析,发现有壳,而且壳的代码里比较大,其中的大量的栈上异或编码过的字串和crc32计算代码。纯静态比较难看出什么了,于是转动态。
由于静态没有看出OEP在哪,于是直接运行,然后attach上去,dump出PE文件。此时dump的PE文件主要代码是可以看的,只不过区段信息不正确,入口不对,导入表未修复。继续静态看dump出来的PE文件。从字符串入手,找到了主函数,从而找到了入口在0x402F59,此过程中发现了一些反调试,如:主函数的crc32校验、ZwQueryInformationProcess调用、32位和64位代码执行环境的转换等。然后反调试细看了下,包括壳运行期间起的反调试线程,发现其对于业务流程和算法没有影响,所以并没有过多的纠结,主要分析主函数sub_4012B0。
这部分代码涉及导入函数的不多,可以不用修复导入表,壳将导入函数地址写在了堆上,并用异或操作进行的处理,虽说恢复不难,但没有必要。个别的手动标注下就好。整理代码后,了解到,主函数的主要流程是:

  1. 检查输入格式为大写16进制字串
  2. 检查输入长度不大于360
  3. 将16进制字串转成Int16数字
  4. 将Int16数字作为随机数转成对应的种子数字,取出非负数字
  5. 校验这些非负数字,要求非负数字至少有12个,两两之差唯一及其它一些条件:比如隐藏条件--第一个非负数字为0

所以大概意思是:从0-89(360的输入长度,可取的最大非负数字为89)取12个数字记为n,要求n中的数字两两之差唯一,且n[1]-n[0] < n[11]-n[10]。找到满足条件的12个数后,再将其转换成相应的随机数,这些随机数就是答案了。
手动凑了下,发现11个满足条件的数是比较容易找到的。于是在小伙伴的帮助下,开始以差唯一为突破口,开始暴力搜索。代码如下:

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
def check(n):
    n_len=len(n)
    n_num=(n_len-1)*n_len//2
    t=[]
    for i in range(n_len):
        for j in range(i+1,n_len):
            t.append(n[j]-n[i])
    return len(list(set(t)))==n_num
 
def g(n):
    n_len=len(n)
    t=[]
    for i in range(n_len):
        for j in range(i+1,n_len):
            t.append(n[j]-n[i])
    return t
 
class node:
    def __init__(self,state,lmin):
        self.state=state
        self.lmin=lmin
 
 
def search():
    while len(s)>0:
        x=s.pop()
        base=[i for i in range(x.lmin+1,90)]
        q=list(set(base) - set(g(x.state)))
        for i in q:
            if i > x.lmin:
                y=x.state.copy()
                y.append(i)
                y.sort()
                if check(y):
                    s.append(node(y,i))
                    if len(y)==12:
                        print(y)
                        input('next?')
                    search()
    return
s=[]
t=node([0],0)
s.append(t)
search()

结果:12个非负数为[0, 2, 6, 24, 29, 40, 43, 55, 68, 75, 76, 85],答案为675E7A025B4786190D65933042199F472513AB5E312AB8753E41C40C4A58D023566FDD3A6306E9516F1DF5687B340100D3490E1794621A2EA0793450AD10335CB9273F73C53E4B0AD1555821DE6C64387111704FF61ADE2E0332897D0F4995141B60A12B2877AE42340EBA59402594244D3CD3075953DF1E656AEB357101F84C7E1804648A2F107BC44E1D12A35D2929AF743540BB0B193E93724E6ED4395A05E050661CED677333F97EDC4A

 

由于输入并未超过最大输入长度,且后面加负数对应的随机值对程序校验没有影响,所以还有4个解,分别附加0516、05168B61、05168B61112D、05168B61112D9878。


[培训]12月3日2020京麒网络安全大会《物联网安全攻防实战》训练营,正在火热报名中!地点:北京 · 新云南皇冠假日酒店

收藏
点赞1
打赏
分享
最新回复 (2)
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
YenKoc 活跃值 2020-11-21 17:33
2
0
po叔 yyds
雪    币: 11984
活跃值: 活跃值 (215)
能力值: ( LV15,RANK:2389 )
在线值:
发帖
回帖
粉丝
poyoten 活跃值 22 2020-11-21 23:16
3
0
游客
登录 | 注册 方可回帖
返回