首页
社区
课程
招聘
[原创]KCTF2020秋季赛 第二题 异常信号 Writeup
发表于: 2020-11-21 09:07 4587

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

2020-11-21 09:07
4587

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

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

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

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

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

PS C:\Users\admin\Downloads\kctf2020\2> .\CrakMe.exe
Input Serial:
123
 
一个礼貌的开场白还是要的
PS C:\Users\admin\Downloads\kctf2020\2> .\CrakMe.exe
Input Serial:
123
 
一个礼貌的开场白还是要的
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()
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

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 2
支持
分享
最新回复 (2)
雪    币: 2677
活跃值: (5340)
能力值: ( LV10,RANK:177 )
在线值:
发帖
回帖
粉丝
2
po叔 yyds
2020-11-21 17:33
0
雪    币: 13713
活跃值: (2851)
能力值: ( LV15,RANK:2663 )
在线值:
发帖
回帖
粉丝
3
2020-11-21 23:16
0
游客
登录 | 注册 方可回帖
返回
//