[安洵杯 2019]crackMe

发布时间 2023-07-08 09:05:02作者: h40vv3n

[安洵杯 2019]crackMe

将exe文件放入ida打开后,首先按shift+F12查看字符串,发现了base64的编码表和一串疑似经过加密/编码处理过后的字符串

image-20230703150255400

此时推测该字符串不是由正常base64编码得来,可能进行了换码操作,因此点进引用了该编码表的地方

image-20230703150416870

此时发现该函数对base64的编码表进行了大小写转换的操作,然后下面提示hook成功,此时推测程序在运行过程中的流程发生了变化

继续点进Handler进行分析

image-20230703151107616

发现将一串关键的字符串传入了v2当中,然后执行了sub_411172()函数,我们点进去继续进行分析

image-20230703151743457

结合资料发现这是SM4加密,而且刚刚传入v2的值是密钥,我们接着向下分析

image-20230703151940397

经过加密之后,程序执行了系统函数SetUnhandledExceptionFilter,查询资料得知该函数的作用是当程序发生异常则会执行参数中指向的函数,推测程序在运行到此处之前会出现异常,然后程序会进入TopLevelExceptionFilter函数之中,目的应该是隐藏这个函数的调用,我们点进该函数分析

image-20230703152351947

该函数首先对Str2进行了相邻两位换位操作,点击查看后发现变换完之后就是之前所说的疑似进行编码/加密过后的字符串

image-20230703152615131

接下来就是一个对Str1的赋值操作,我们点进去进行分析

image-20230703152853210

发现该流程正是base64的编码过程,不过有些不太一样,我们仔细查看后发现,将后面填充的“=”变成了“!”,而且下方还执行了一个函数sub_4110FF(),点进去查看

image-20230703153147138

发现最后有一个移位的操作,这里可以理解为将变换后的base64编码表再循环左移了24位

在给Str1赋值之后,我们接着在分析sub_411136()函数

image-20230703153525843

发现该函数最后判断Str1是否与Str2相等

此时推测程序的流程为:用户的输入→SM4加密→换码base64编码→与Str2比较

因此我们首先要得到SM4加密之后的密文:

str2 = '1UTAOIkpyOSWGv/mOYFY4R!!'
old_base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
temp = []
new_base = [0 for i in range(64)]
for i in range(len(old_base)):
    if old_base[i].isalpha():
        if old_base[i].isupper():
            temp.append(old_base[i].lower())
        else:
            temp.append(old_base[i].upper())
    else:
        temp.append(old_base[i])
for i in range(len(temp)):
    new_base[(i+64-24)%64] = temp[i]

print(''.join(new_base))

这样就得到了变化之后的base64编码表

image-20230703160243621

通过工具解码后得到了加密之后的密文(此处注意将“!”替换为"=")

image-20230703160430415

之后再编写SM4解密脚本得到flag,完整解题脚本如下:

from pysm4 import encrypt, decrypt
str2 = '1UTAOIkpyOSWGv/mOYFY4R!!'
old_base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
temp = []
new_base = [0 for i in range(64)]
for i in range(len(old_base)):
    if old_base[i].isalpha():
        if old_base[i].isupper():
            temp.append(old_base[i].lower())
        else:
            temp.append(old_base[i].upper())
    else:
        temp.append(old_base[i])
for i in range(len(temp)):
    new_base[(i+64-24)%64] = temp[i]

print(''.join(new_base))

miwen = '0x'+'59 D0 95 29 0D F2 40 06 14 F4 8D 27 69 06 87 4E'.replace(' ','')
key = 'where_are_u_now?'
key_temp = ''
print(miwen)
for i in range(len(key)):
    key_temp += (hex(ord(key[i])))
print('0x'+key_temp.replace('0x',''))
miwen_num = 0x59D095290DF2400614F48D276906874E
key_num = 0x77686572655f6172655f755f6e6f773f

mingwen = bytes.fromhex(hex(decrypt(miwen_num, key_num))[2:]).decode() 
print('flag{'+mingwen+'}')

因此flag为:flag{SM4foRExcepioN?!}