第十八届信息安全大赛 && 第二届长城杯 - re
字数 718 2025-08-22 12:22:30
RC4加密与逆向分析实战教学
1. RC4加密算法基础
RC4是一种流密码算法,由Ron Rivest在1987年设计,广泛应用于SSL/TLS等协议中。
1.1 RC4算法原理
RC4算法包含两个主要部分:
- 密钥调度算法(KSA):初始化S盒
- 伪随机生成算法(PRGA):生成密钥流
1.2 Python实现示例
from Crypto.Cipher import ARC4
# 加密示例
key = b"testkey"
plaintext = b"example data"
cipher = ARC4.new(key)
ciphertext = cipher.encrypt(plaintext)
# 解密示例
cipher = ARC4.new(key) # 需要重新初始化
decrypted = cipher.decrypt(ciphertext)
2. 逆向分析中的RC4识别
在逆向工程中,识别RC4算法的特征:
-
初始化阶段:
- 256字节的S盒初始化
- 明显的密钥调度循环
-
加密/解密阶段:
- 两个指针(i,j)的更新
- 字节交换操作
- 异或操作
3. 题目分析
3.1 加密流程分析
题目中发现的加密流程:
- 使用RC4加密(密钥为"testkey")
- 对结果进行相邻字节异或处理(从后向前)
3.2 解密脚本
from Crypto.Cipher import ARC4
# 加密后的数据
data = [
0x96, 0x8F, 0xB8, 0x08, 0x5D, 0xA7, 0x68, 0x44, 0xF2, 0x64,
0x92, 0x64, 0x42, 0x7A, 0x78, 0xE6, 0xEA, 0xC2, 0x78, 0xB8,
0x63, 0x9E, 0x5B, 0x3D, 0xD9, 0x28, 0x3F, 0xC8, 0x73, 0x06,
0xEE, 0x6B, 0x8D, 0x0C, 0x4B, 0xA3, 0x23, 0xAE, 0xCA, 0x40,
0xED, 0xD1
]
key = b"testkey"
cipher = ARC4.new(key)
data = cipher.decrypt(bytes(data))
# 逆向相邻异或操作
data = bytearray(data)
for i in range(len(data)-2, -1, -1):
data[i] ^= data[i+1]
print(bytearray(data).decode())
3.3 题目提示
- 正确的flag长度为22
- 第13位为'4'
- 字符编码算法(Base64)
4. 爆破方法
当无法直接逆向时,可以采用爆破方法:
4.1 单字节爆破示例
import subprocess
exe_path = './re.exe'
table = {}
chartable = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{}="
for i in chartable:
process = subprocess.Popen(f"{exe_path} flag{i}",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
out = stdout.decode()
if out[8:] == '':
print("No output")
continue
v = int(out[8:], 16)
if v in table:
print(f"Duplicate value {v} for {i}")
table[v] = i
with open('flag', 'rb') as f:
data = f.read()
flag = ''
for i in data:
flag += table[i]
print(f"final {flag}")
5. 高级逆向技巧:Hook技术
5.1 Python Hook示例
class Symbol:
def __init__(self, name):
self.name = name
def __eq__(self, other):
print(f"Comparing {self.name} and {other:08x}")
if isinstance(other, Symbol):
return self.name == other.name
return self.name == other
import rand0m
tempcheck = rand0m.check
temprand0m = rand0m.rand0m
def mycheck(flag):
print("Checking flag: ", flag, end=" -> \n")
result = tempcheck(flag)
print("Result: ", result)
return result
def myrand0m(x):
print("\tRandom: ", x, end=" -> ")
result = temprand0m(x)
print(f"\tResult: ({result[0]:08x}, {result[1]:08x})")
result = (Symbol(f"{result[0]:x}"), Symbol(f"{result[1]:x}"))
return result
rand0m.check = mycheck
rand0m.rand0m = myrand0m
flag = "1234567890abcdef1234567890abcdef"
print(rand0m.check(flag))
5.2 分析输出
通过Hook可以观察到:
- check函数将每8个hex字符传入rand0m函数
- 返回两个结果,第二个结果用于比较验证
6. 复杂算法逆向
6.1 算法分析
def myrand0m(x):
x = int(x, 16)
t2 = x >> 5
x1 = x << 4
t4 = x1 & 0xFA3AFFFF # 通过输入0xFFFFFFFF确定
t5 = x >> 28
t6 = t4 | t5
return t6
6.2 爆破脚本
final2 = [0x98d24b3a, 0xe0f1db77, 0xadf38403, 0xd8499bb6]
flag = [0x812287f3, 0xd4a30f74, 0x8023a126, 0x78810880]
# 0xA3A -> 1010 0011 1010
# 0xFFA3AFFF
base = "101000111010"
idx = [1, 3, 4, 5, 9, 11]
flag_str = [[] for i in range(4)]
for z in range(4):
for i in range(2**6):
test = flag[z]
i_str_bin = format(i, '06b')
for j in range(6):
test = test | (int(i_str_bin[j]) << (23 - idx[j]))
r = rand0m.rand0m(f"{test:08x}")
if r[0] == final2[z]:
print(f"idx: {z} Testing: {i_str_bin} -> {test:08x}: {test:032b}")
flag_str[z].append(f"{test:08x}")
print(flag_str)
7. 总结
- RC4识别:寻找256字节S盒初始化和密钥调度循环
- 加密后处理:注意额外的处理如相邻异或等
- 爆破技巧:当逆向困难时,考虑单字节爆破
- Hook技术:动态分析程序行为
- 复杂算法:通过输入特殊值(如全F)确定掩码参数
最终flag格式:flag{MTczMDc4MzQ2Ng==}(Base64编码)