样本
链接:https://pan.baidu.com/s/1oafdvTCEB2-PiVURHAmt1w?pwd=ldah
提取码:ldah
解题过程
题目有提示,静态分析真的可以得到key吗?猜测需要动态分析
首先运行一下
使用peid检测,发现软件未加壳,使用IDA打开,Ctrl+F12查看字符串,发现please input your flag
点进去查看交叉引用
跟进去,F5查看伪代码,下面是我重命名的伪代码
在这里首先会检测是否开启了Debugger,后续调试的时候需要patch掉,然后根据输入进行加密,这里最关键的就是j_encrypt_and_write_to_memory这个函数,这里第二个函数是输入,第三个长度,最后一个是加密后写入的地址,具体分析跟进去,
这里有很明显的RC4加密特征,看代码可以看到最后一个参数是加密值写入的地址,这点可以在动态调试时验证,在这个函数中,需要找到RC4的加密密钥,因为RC4是对称加密,这个sub_411127是随机数的生成函数,使用chatGPT放进去问一下,a1:表示密钥的起始地址。
a2:表示密钥的长度。
a3:表示 S-Box 的起始地址,因此动态调试的时候重点跟踪第一个和第二个参数就可以得到加密的密钥,
返回去继续看,执行完这个函数后
使用memcmp将&unk_41B018和encryptedFlag地址指向的数据进行比较,相等就win。至此动态分析阶段思路清晰,
1.跟踪sub_411127函数的第一个和第二个参数,拿到密钥
2.跟踪memcmp的第一个参数,拿到需要比较的值,然后解密
使用x64dbg打开程序,开始调试,搜索字符串,定位到下图位置
打下断点,在RC4加密函数F7跟进去往下找,找到sub_411127函数的位置,打个断点,然后执行,在右侧查看参数
可以看到密钥的地址长度为16,右键跳到内存窗口
得到密钥01 E5 D5 40 C3 D5 76 36 FE 66 2D 05 C9 FB 50 E7
继续执行 到memcmp位置断下
同样的方法,拿到加密的数据,然后编写python脚本进行解密
import codecs
def ksa(key):
key_length = len(key)
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % key_length]) % 256
s[i], s[j] = s[j], s[i]
return s
def rc4_decrypt(key, ciphertext):
s = ksa(key)
i = j = 0
plaintext = bytearray()
for byte in ciphertext:
i = (i + 1) % 256
j = (j + s[i]) % 256
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) % 256]
plaintext.append(byte ^ k)
return plaintext
# 密钥和加密数据的十六进制表示
hex_key = "01E5D540C3D57636FE662D05C9FB50E7"
hex_ciphertext = "DE1C22271DAEAD65ADEF6E414C3475F1165050D448696D93361C863BBBD04C91"
# 将十六进制密钥和加密数据转换为字节
key = codecs.decode(hex_key, "hex")
ciphertext = codecs.decode(hex_ciphertext, "hex")
# 使用密钥解密数据
plaintext = rc4_decrypt(key, ciphertext)
# 输出解密结果
print("解密后的数据:", plaintext)
解密成功