【攻防世界】ereere
收获
熟悉伪代码中的 Base64 和 RC4,以及快速编写脚本
识别伪代码中的
strlen()
函数
思路
根据 Strings 页面定位到主函数 sub_400BC8()
得到主函数内容:
v3 是用户的输入,大概率就是 flag,v3 首先经过了函数 sub_41A6E0(v3)
的处理,跟进
得到 sub_41A6E0()
的内容:
结合中间一个循环的特点:
while ( 1 )
{
LABEL_7:
if ( ((*(_DWORD *)a1 - 16843009) & ~*(_DWORD *)a1 & 0x80808080) != 0 )
{
if ( !*a1 )
return (char *)(a1 - v1);
if ( !a1[1] )
return (char *)(a1 - v1 + 1);
if ( !a1[2] )
return (char *)(a1 - v1 + 2);
if ( !a1[3] )
return (char *)(a1 - v1 + 3);
}
a1 += 4;
}
这个函数的作用应该是计算字符串的长度,即 strlen()
然后函数 sub_4009DC()
对 v3 进行了处理,继续跟进:
在函数最开始,首先调用了 sub_400864()
,跟进:
可以看到两个 256 的 for 循环(十六进制的 0x100 就是十进制的 256)
并且第一个 for 循环仅赋值,第二个 for 循环有 swap 操作
再结合 sub_4009DC()
后面部分的一个 for 循环、余 256、一个 swap 操作和一个异或操作
可以明显得知这是 RC4 算法的特征sub_400864()
做 s 盒的初始化操作,即 rc4_initsub_4009DC()
做加解密操作,即 rc4_crypt
根据 RC4 算法的特点,可知 byte_4A0860[]
为 s_box
,aFlag1233213211[]
为 Key
同时得到 aFlag1233213211[]
的内容:flag{123321321123badbeef012}
回到主函数 sub_400BC8()
中,在 RC4 算法之后,函数 sub_400550()
又对 v3
做了处理,跟进:
发现多次对数组 aZyxwvutsrqponm[]
的索引操作,且 aZyxwvutsrqponm[]
的内容:
ZYXWVUTSRQPONMLKJIHGFEDCBAabcdefghijklmnopqrstuvwxyz/+9876543210
,神似 Base64 的密码表
再结合每次赋值的偏移操作,如:*(_BYTE *)(v13 + v3)
等
以及 if 判断语句中:
if ( i < 2 )
{
*(_BYTE *)(v13 + v11) = aZyxwvutsrqponm[(16 * *v8) & 0x30];
*(_BYTE *)(v13 + v11 + 1) = 61;
v6 = v11 + 2;
v10 = v11 + 3;
*(_BYTE *)(v13 + v6) = 61;
break;
}
在 i < 2
的条件下,存在两次赋值 ‘=’ 的操作 (61 是 ‘=’ 的 ASCii 码)
这些都是 Base64 加密的特点,可以推知函数 sub_400550()
是一个更换了原始码表的 Base64 算法
也就是说,本题是将 flag 进行 RC4 加密后,再进行更换码表的 Base64 加密,最终加密结果为:ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ==
先进行更换码表的 Base64 解密,再进行 RC4 解密,即可得到 flag
脚本
Python(引用库)
import base64
from Crypto.Cipher import ARC4
key = "ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ=="
string1 = "ZYXWVUTSRQPONMLKJIHGFEDCBAabcdefghijklmnopqrstuvwxyz/+9876543210" # string1表示更换后的码表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" # string2表示原始码表
Str = base64.b64decode(key.translate(str.maketrans(string1, string2))) # Base64解密,bytes型
aFlag1233213211 = "flag{123321321123badbeef012}"
flag = ARC4.new(bytes(aFlag1233213211, encoding='utf-8')).decrypt(Str)
print(flag)
Python(完整实现)
import base64
flag = ""
key = "ScDZC1cNDZaxnh/2eW1UdqaCiJ0ijRIExlvVEgP43rpxoxbYePBhpwHDPJ=="
string1 = "ZYXWVUTSRQPONMLKJIHGFEDCBAabcdefghijklmnopqrstuvwxyz/+9876543210" # string1表示更换后的码表
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" # string2表示原始码表
print("Base64还原: ", key.translate(str.maketrans(string1, string2))) # 将 key 还原成初始码表加密后的结果
Str = base64.b64decode(key.translate(str.maketrans(string1, string2))) # Base64解密,bytes型
print("Base64解密: ", Str)
byte_4A0860 = []
aFlag1233213211 = "flag{123321321123badbeef012}"
# rc4_init
for i in range(256):
byte_4A0860.append(i)
v4 = 0
v3 = 0
for j in range(256):
v5 = byte_4A0860[j]
v3 = (v5 + v3 + ord(aFlag1233213211[int(j % len(aFlag1233213211))])) & 0xff
byte_4A0860[j] = byte_4A0860[v3]
byte_4A0860[v3] = v5
v4 = v4 + 1
if v4 >= len(aFlag1233213211):
v4 = 0
print("s_box:", end=" ")
for j in range(256):
print(byte_4A0860[j], end=" ")
print()
# rc4_crypt
v4 = 0
v3 = 0
for k in range(len(Str)):
v3 = (v3 + 1) & 0xff
v4 = (byte_4A0860[v3] + v4) & 0xff
v5 = byte_4A0860[v3]
byte_4A0860[v3] = byte_4A0860[v4]
byte_4A0860[v4] = v5
flag += chr(Str[k] ^ byte_4A0860[(byte_4A0860[v3] + byte_4A0860[v4]) & 0xff])
print(flag)
结果
flag{RC_f0ur_And_Base_s1xty_f0ur_Encrypt_!}