【CTF-RE】[ctf.show]re2
“勒索病毒”的逻辑是把flag.txt经rc4加密后的内容输出至enflag.txt
加密后的enflag.txt已经提供(加密的内容大概就是flag),又由于rc4是对称加密,目标是找到密钥。
main函数:
充值函数内部:
char __cdecl sub_401A70(char *inputS, char *Str1)
{
char v3; // [esp+0h] [ebp-E4h]
signed int i; // [esp+D0h] [ebp-14h]
signed int v5; // [esp+DCh] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_40B027);
v5 = strlen(inputS);
for ( i = 0; i < v5; ++i )
Str1[i] += inputS[i] ^ 0x1F;
if ( !strcmp(Str1, "DH~mqqvqxB^||zll@Jq~jkwpmvez{") )// str1原始为0,异或回去是[Warnning]Access_Unauthorized
print("充值成功.\n", v3);
else
print("Error!\n", v3);
return *Str1;
}
其中的str1已在main函数里memset为0了。
所以可以反推出来应该输入的inputS,_注意运算优先级+-
>^
>+=
def decrypt(encrypted_str):
# 初始化解密后的字符串
decrypted_str = []
# 遍历加密字符串的每个字符
for char in encrypted_str:
# 解密逻辑:Str[i] = (Str1[i] - Original_Str1[i]) ^ 0x1F
# 假设 Original_Str1 的初始值为全零(即 0)
decrypted_char = (ord(char) - 0) ^ 0x1F
# decrypted_char = ord(char) - ord(char) ^ 0x1F -的优先级高于^
decrypted_str.append(chr(decrypted_char))
# 将字符列表拼接成字符串并返回
return ''.join(decrypted_str)
# 测试解密函数
if __name__ == "__main__":
# 加密后的字符串
encrypted_str = "DH~mqqvqxB^||zll@Jq~jkwpmvez{"
# 调用解密函数
decrypted_str = decrypt(encrypted_str)
# 输出解密结果
print("解密后的字符串:", decrypted_str)
解密后的字符串: [Warnning]Access_Unauthorized
有了密钥和密文,即可得到原文了
既可以把enflag.txt复制成flag.txt,再加密,相当于两次异或获得到原内容;也可以通过特定工具输入密钥和密文。
比较坑的一点,给出的enlag.txt以ANSI编码,复制到flag.txt建议直接复制文件重命名;到工具中复制也建议直接读取文件,或复制为HEX。而新输出的flag又是UTF-8
Latin1编码原来就是ISO-8859-1,向下兼容ANSI,而ANSI作为ASCII的扩展。
RC4内部:
int __cdecl sub_4014E0(char *inputString, int a2, int a3, FILE *FlagTXT, FILE *ENflagTXT)
{
char v6; // [esp+0h] [ebp-D8h]
int strLen; // [esp+D0h] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_40B027);
strLen = strlen(inputString);
TwotoOne(a2, (int)inputString, strLen); // 第二个参数写入第一个参数
Zeroto255(a3); // a3写入0到255
RC4_KSA(a3, a2); // (目标数组,密钥数组)。用来伪随机打乱目标数组
RC4_PRGA(a3, FlagTXT, ENflagTXT); // 从FlagTXT逐字节读入
// 结合随机后的a3异或,生成加密字节
// 写入EnflagTXT
fclose(FlagTXT);
fclose(ENflagTXT);
return print(aE, v6);
}
总之是通过input的密钥,把flag.txt加密到enflag.txt中