[安洵杯 2019]crackMe

首先查看文件信息,发现是32位无壳程序。

接着用ida32打开查看

最开始打开是这样的:

进入main_0里查看

发现这个似乎有点问题,首先可以知道的是这个输入为unk_41A1E4,然后现在我们先进入这个sub_41100F函数里面看一下。进入到最里层

看到这里有一个*a1=0xC0000005之类的判断,这个C00000005是程序报错会出现的一个返回值,是一个错误类型

这里我们试着运行一下程序

可以看到,程序是无法正确启动的,所以这里程序就会进入这个分支。而这个函数的第四个参数就是我们的输入,说明这里肯定有对输入的处理,接着我们进入函数里面看看

这里a3是等于16的,相当于就是执行了因此sub_4119F0。而a4是我们的输入,接着进入这个函数看看

首先就是将我们的输入分割为四个32位的无符号数据,这里有点像AES,SM4算法的第一步,将128位明文分为4个32位的字

接着我们看一下这个sub_411700函数,这个好像就是传入了输入的结果,看看它在干什么,这里32轮可能可能是SM4了,因为SM4就是32轮循环,然后最后结果X32,X33,X34,X35就是最后的密文。

可以发现,32轮中还需要密钥,那么那个a1+4*v6应该就是密钥了,然后四个v5[v6]对应上面的Xi。进入这个函数

可以看到,a1相当于上面的Xi,这个sub_411760相当于上面的T函数了,而T函数又分为两个步骤,一个是S盒替换还有一个就是L函数循环左移加异或。进入这个函数看看

可以发现,首先是在进行S盒替换,然后就是L函数,看到这里差不多可以实锤SM4算法了,相当于输入第一步就是进行SM4算法,但是我们还是可以进一步看看这个sub_4119A0这个函数,看看它的S盒是不是标准的。

这里直接就是返回,替换也就是这样的

于是我也是去网上找到了SM4算法的S盒,发现和这个基本一致

所以到这里就不用去继续分析下去了,输入就是进行了SM4加密,然后我们返回到我们的main_0函数

接着看到这个sub_411136函数是在干什么

进入到最里面发现是一个比较,这个Str1是我们对输入处理的结果,Str2是最后比较的结果。这里我们对Str1点击X键查看它是怎么来的

然后直接OK,接着就到这里了

浅浅的看一下,发现我们在比较之前对结果还有一个交换的操作,接着我们看一下Str1的这个函数,这个Byte_41A180我猜应该就是输入经过Sm4的结果。

也是同样的,进入到最里层

这里由于有两个Str,为了不混淆,我直接将输入改为input了,这个就是在进行base64加密。然后多了一个sub_4110FF函数,接着看一下这个函数

发现是每次额外加了24,这个也简单,解密就是取下标,然后减去24对64取余即可。就可以还原正常base64加密的结果了

接着我们看一下这个base64表

用X键查看一下引用情况,这里主要是怕动态改变这个表从而影响解密

直接OK,接着就来到了这个地方

发现,这个表被换了,并不是标准的base64编码表。而是被改了,但是改的不多,只是将大小写交换了一下位置而已。这里看到还有一个Handler,不知道是干什么的,进入看看

这个好像是补充了我们前面的Sm4算法缺失的密钥,因为前面我们只是猜测那个结果是密钥,但是并不知道密钥怎么来的,这个函数应该就是专门产生密钥的,这里也可以看出密钥应该就是where_are_u_now?。接着进入这个sub_411172这个函数看看它是不是在搞密钥拓展

可以看到这个函数和SM4算法的密钥拓展运算基本一致。这里四个常数FK没有以明文给出,而是存储在这个byte_417A68里面,然后也是用32轮循环来拓展加密32轮每一轮需要的密钥。这里26的dword_417A78里面存储的就是CK了。这个也是32个固定的值。而且还挺有特点的,每两个相邻的字节之间相隔7,相当于就是第一个字节为07,第二个就是07+7也就是0D这样的。

接着我们进入这个sub_4114E0里面看看是不是对应上面的T函数。这个T函数也是和前面的差不多,首先替换,然后一个L函数循环左移异或。

接着我们回到这个函数的外层

可以看到,这个第9行还有一个东西,我们进去看看里面是什么

没想到,搞了一圈还回来了。说明刚刚那个函数应该是在这个函数之前进行的,然后返回到这个函数。

看到这里,整个流程基本是差不多了,这里也是把密钥生成搞懂了,然后密钥也有了,所以整个流程就是先对输入进行Sm4加密,然后加密结果进行base64加密。这里需要注意的就是base64的表换了,还有结果加了24.

下面先去提取一个str2的结果,要开始解密了

这里两个!应该相当于两个=

这里直接给出最后的脚本

s2="1UTAOIkpyOSWGv/mOYFY4R!!"
s=''
for i in range(0,len(s2),2):
    s+=s2[i+1]+s2[i]    #交换结果前后两位
# print(s)
table="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"   #手动替换了
# print(len(s))
s1=''
for i in s:
    if i=='!':
        s1+='='
    else:
        t = table.index(i)
        s1+=table[(t-24)%64]
print(s1)

还原的思路也很简单,先还原最后的结果,然后还原表,最后根据索引还原原索引结果。最后输出。

最后得到这么一串结果,这里这个结果是正常base64加密的后的结果,就是没有加24的结果。然后我们复制这个表就可以去cyberchef解密了

首先是base64解密,然后Sm4解密。这里注意两点,第一个就是base64的表需要换成上面那个。然后就是sm4的密钥为utf-8然后mode选nopad.

最后这个output套上flag就是最后的结果了。

这个题目主要就是考察对sm4算法的理解,以及base64。如果是真正比赛的时候应该就没必要搞这么透彻了,看到那些特征值就可以直接去试结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值