mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4mobile wallpaper 5mobile wallpaper 6
2557 字
13 分钟
第二届rdctf逆向Writeup

Hello_Rust#

首先点开exe程序发现

Please input the flag:

于是直接搜索对应字符找到对应主函数

__int64 __fastcall Hello_Rust::main::h72897955569e0b8d(__int64 a1, __int64 a2)
{
_QWORD *v2; // rax
int v3; // r8d
int v4; // r9d
__int64 v5; // rdx
__int64 v6; // rdx
void *v7; // rax
void *v8; // rdx
int v9; // r9d
int v10; // r8d
int v11; // r9d
_QWORD *v12; // rax
void *v13; // rsi
__int64 v14; // rdx
__int64 *v15; // r13
char *v16; // rbp
char *v17; // r9
__int64 v18; // r8
__int64 v19; // rcx
char v20; // r9
__int64 (__fastcall **v21)(size_t *, void *, __int64, _QWORD); // rax
__int64 v22; // r10
__int64 v23; // rdx
__int64 v24; // rcx
unsigned __int8 v25; // al
_BYTE *v26; // rcx
__int64 result; // rax
__int64 v29; // [rsp+30h] [rbp-268h] BYREF
__int64 v30; // [rsp+38h] [rbp-260h]
__int64 v31; // [rsp+40h] [rbp-258h]
const char *v32; // [rsp+48h] [rbp-250h] BYREF
__int64 v33; // [rsp+50h] [rbp-248h]
__int64 v34; // [rsp+58h] [rbp-240h]
size_t Size; // [rsp+60h] [rbp-238h] BYREF
const char *v36; // [rsp+68h] [rbp-230h]
__int64 v37[2]; // [rsp+70h] [rbp-228h] BYREF
__int64 (__fastcall **v38)(size_t *, void *, _QWORD, _QWORD); // [rsp+80h] [rbp-218h]
__int64 v39; // [rsp+88h] [rbp-210h]
__int64 v40; // [rsp+90h] [rbp-208h]
__int64 v41; // [rsp+98h] [rbp-200h]
__int64 v42; // [rsp+A0h] [rbp-1F8h] BYREF
char v43; // [rsp+A8h] [rbp-1F0h] BYREF
__int64 (__fastcall **v44)(size_t *, void *, __int64, _QWORD); // [rsp+B0h] [rbp-1E8h] BYREF
__int64 (__fastcall **v45)(size_t *, void *, __int64, _QWORD); // [rsp+B8h] [rbp-1E0h]
__int64 (__fastcall **v46)(size_t *, void *, __int64, _QWORD); // [rsp+C0h] [rbp-1D8h]
__int64 (__fastcall **v47)(size_t *, void *, __int64, _QWORD); // [rsp+C8h] [rbp-1D0h]
__int64 v48; // [rsp+D0h] [rbp-1C8h]
__int64 v49; // [rsp+D8h] [rbp-1C0h]
char v50; // [rsp+E0h] [rbp-1B8h] BYREF
char v51; // [rsp+E8h] [rbp-1B0h] BYREF
__int64 v52; // [rsp+F0h] [rbp-1A8h]
char *v53; // [rsp+F8h] [rbp-1A0h]
const char *v54; // [rsp+100h] [rbp-198h]
__int64 v55; // [rsp+108h] [rbp-190h]
__int64 v56; // [rsp+110h] [rbp-188h]
__int64 *v57; // [rsp+118h] [rbp-180h]
__int128 v58; // [rsp+120h] [rbp-178h]
__int64 v59; // [rsp+130h] [rbp-168h]
__int64 v60; // [rsp+138h] [rbp-160h] BYREF
_QWORD *v61; // [rsp+140h] [rbp-158h]
__int64 v62; // [rsp+148h] [rbp-150h]
__int64 v63; // [rsp+150h] [rbp-148h] BYREF
void *Src; // [rsp+158h] [rbp-140h]
__int64 v65; // [rsp+160h] [rbp-138h]
void *v66; // [rsp+168h] [rbp-130h] BYREF
__int64 v67; // [rsp+170h] [rbp-128h]
size_t p_Size; // [rsp+178h] [rbp-120h]
__int64 v69; // [rsp+180h] [rbp-118h]
__int64 v70; // [rsp+188h] [rbp-110h]
__int64 v71; // [rsp+198h] [rbp-100h]
__int64 v72[11]; // [rsp+240h] [rbp-58h] BYREF
v2 = (_QWORD *)RNvCs691rhTbG0Ee_7___rustc12___rust_alloc(a1, a2, 8LL, 128LL);
if ( !v2 )
alloc::alloc::handle_alloc_error::h3c5fc2000323952a(a1, a2, 128LL, 8LL);
*v2 = "Please inputtheflag:";
v2[1] = 6LL;
v2[2] = " inputtheflag:";
v2[3] = 1LL;
v2[4] = "inputtheflag:";
v2[5] = 5LL;
v2[6] = " inputtheflag:";
v2[7] = 1LL;
v2[8] = "theflag:";
v2[9] = 3LL;
v2[10] = " inputtheflag:";
v2[11] = 1LL;
v2[12] = "flag:";
v2[13] = 5LL;
v2[14] = " inputtheflag:";
v2[15] = 1LL;
v66 = v2;
v67 = (__int64)v2;
p_Size = 8LL;
v69 = (__int64)(v2 + 16);
v70 = 0LL;
v71 = 0LL;
_$LT$alloc..string..String$u20$as$u20$core..iter..traits..collect..FromIterator$LT$char$GT$$GT$::from_iter::hb4f7ccd8f8c26ef4(
a1,
(unsigned int)v72,
(unsigned int)&v66,
(unsigned int)v72,
v3,
v4);
Size = (size_t)v72;
v36 = (const char *)_$LT$alloc..string..String$u20$as$u20$core..fmt..Display$GT$::fmt::hfdc0cc6c70cf0f9f;
v66 = &unk_1400A20E8;
v67 = 1LL;
v70 = 0LL;
p_Size = (size_t)&Size;
v69 = 1LL;
std::io::stdio::_print::hb423c4c57e4fd8e1(a1, v72, v5, &v66);
Size = std::io::stdio::stdout::h802387c29eff3b4c();
v7 = (void *)_$LT$std..io..stdio..Stdout$u20$as$u20$std..io..Write$GT$::flush::hcff5a89562c9cbf7(a1, v72, v6, &Size);
if ( v7 )
{
v66 = v7;
core::result::unwrap_failed::hf125793ccbd5d840(
a1,
(unsigned int)v72,
22,
(unsigned int)"Failed to flush stdoutsrc\\main.rs",
(unsigned int)&v66,
(unsigned int)&off_1400A2090);
}
v29 = 0LL;
v30 = 1LL;
v31 = 0LL;
Size = std::io::stdio::stdin::hae0488c3f631d306();
if ( (std::io::stdio::Stdin::read_line::h51906b3109204308(a1, v72, &v29, &Size) & 1) != 0 )
{
v66 = v8;
core::result::unwrap_failed::hf125793ccbd5d840(
a1,
(unsigned int)v72,
19,
(unsigned int)"Failed to read line",
(unsigned int)&v66,
(unsigned int)&off_1400A2090);
}
v66 = (void *)v30;
v67 = v30 + v31;
LOBYTE(p_Size) = 0;
_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$GT$::from_iter::he73d87c5766bf13f(
a1,
v72,
&v66,
&Size,
&off_1400A2078);
v66 = (void *)v36;
v67 = (__int64)v36;
p_Size = Size;
v69 = (__int64)&v36[4 * v37[0]];
LOBYTE(v70) = 0;
_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$GT$::from_iter::h3e8df7d6d04c157d(
(unsigned int)&Size,
(unsigned int)v72,
(unsigned int)&v66,
(unsigned int)&Size,
(unsigned int)&off_1400A2078,
v9);
v66 = (void *)v36;
v67 = (__int64)v36;
p_Size = Size;
v69 = (__int64)&v36[4 * v37[0]];
_$LT$alloc..string..String$u20$as$u20$core..iter..traits..collect..FromIterator$LT$char$GT$$GT$::from_iter::hf11d0f788b4382c5(
(unsigned int)&Size,
(unsigned int)v72,
(unsigned int)&v66,
(unsigned int)&v63,
v10,
v11);
v12 = (_QWORD *)RNvCs691rhTbG0Ee_7___rustc12___rust_alloc(&Size, v72, 8LL, 32LL);
if ( !v12 )
alloc::alloc::handle_alloc_error::h3c5fc2000323952a(&Size, v72, 32LL, 8LL);
*v12 = _$LT$Hello_Rust..XorOp$u20$as$u20$Hello_Rust..Operation$GT$::apply::h39ba18a00a5e6aef;
v12[1] = _$LT$Hello_Rust..AddOp$u20$as$u20$Hello_Rust..Operation$GT$::apply::hb8ca4846c60bec8c;
v12[2] = _$LT$Hello_Rust..SubOp$u20$as$u20$Hello_Rust..Operation$GT$::apply::hc33f064d2a20566c;
v12[3] = _$LT$Hello_Rust..IdxXorOp$u20$as$u20$Hello_Rust..Operation$GT$::apply::h6761405cf33cc523;
v60 = 4LL;
v61 = v12;
v62 = 4LL;
v13 = Src;
v66 = Src;
v67 = (__int64)Src + v65;
p_Size = 0LL;
LOBYTE(v69) = 0;
_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..spec_from_iter..SpecFromIter$LT$T$C$I$GT$$GT$::from_iter::h78fb51c0aaaccf06(
&Size,
Src,
&v66,
&v32,
&off_1400A2078);
if ( v34 == 30 )
{
v15 = &v42;
v16 = &v43;
v17 = (char *)v33;
v18 = v33 + 30;
v58 = 0LL;
v59 = 0LL;
Size = (size_t)&unk_1400A20B0;
v36 = "Please inputtheflag:";
v37[0] = 0LL;
v44 = 0LL;
v52 = v33;
v53 = (char *)v33;
v54 = v32;
v55 = v33 + 30;
v56 = 0LL;
v57 = &v60;
v19 = v33;
while ( v17 != (char *)v18 )
{
v53 = v17 + 1;
v20 = *v17;
v14 = v56++;
v21 = (__int64 (__fastcall **)(size_t *, void *, __int64, _QWORD))v57[1];
v22 = (__int64)&v21[v57[2]];
v37[0] = (__int64)v21;
v37[1] = v22;
v38 = v21;
v39 = v22;
v40 = v14 & 3;
v41 = 1LL;
v42 = v14;
v43 = v20;
v17 = v53;
if ( v21 )
{
v41 = 0LL;
if ( (v14 & 3) != 0 )
{
v40 = 0LL;
v21 = (__int64 (__fastcall **)(size_t *, void *, __int64, _QWORD))core::iter::traits::iterator::Iterator::nth::h47ff4efa2abd51fb(
&Size,
v13,
v14 & 3,
v37,
v18,
v53);
if ( v21 )
goto LABEL_26;
v19 = v52;
v37[0] = 0LL;
if ( !v52 )
break;
}
else
{
if ( v21 != (__int64 (__fastcall **)(size_t *, void *, __int64, _QWORD))v22 )
{
v38 = v21 + 1;
goto LABEL_26;
}
v38 = v21;
v39 = v22;
v37[0] = 0LL;
if ( !v19 )
break;
}
v17 = v53;
v18 = v55;
}
}
if ( !v44 || !v49 )
goto LABEL_36;
--v49;
v23 = v48;
if ( v48 )
{
v48 = 0LL;
v21 = (__int64 (__fastcall **)(size_t *, void *, __int64, _QWORD))core::iter::traits::iterator::Iterator::nth::h47ff4efa2abd51fb(
&Size,
v13,
v23,
&v44,
v18,
v17);
if ( !v21 )
goto LABEL_36;
}
else
{
v21 = v46;
if ( v46 == v47 )
{
v14 = (__int64)v45;
v47 = v45;
v21 = v44;
if ( v44 == v45 )
goto LABEL_36;
}
v46 = v21 + 1;
}
v15 = (__int64 *)&v50;
v16 = &v51;
LABEL_26:
v25 = (*v21)(&Size, v13, *v15, (unsigned __int8)*v16);
v26 = (_BYTE *)Size;
v14 = (__int64)v36;
if ( (const char *)Size != v36 )
{
++Size;
LOBYTE(v16) = *v26 == v25;
memcpy(&Size, v13, (size_t)&Size);
if ( (unsigned __int8)_$LT$core..iter..adapters..map..Map$LT$I$C$F$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::fold::h3f0587534a09e2ec(
&Size,
v13,
(unsigned int)v16,
&v66) )
{
v32 = "Congratulations! The flag is correct.";
v33 = 37LL;
Size = (size_t)&v32;
v36 = (const char *)_$LT$$RF$T$u20$as$u20$core..fmt..Display$GT$::fmt::h31fa4d9b908ac590;
v66 = &anon_ad88cb96a3fdcaf8c94331b0da292800_3_llvm_3440038967210771795;
v67 = 2LL;
v70 = 0LL;
p_Size = (size_t)&Size;
v69 = 1LL;
result = std::io::stdio::_print::hb423c4c57e4fd8e1(&Size, v13, v14, &v66);
goto LABEL_40;
}
goto LABEL_39;
}
LABEL_36:
v24 = v52;
if ( !v52 )
goto LABEL_39;
v14 = (__int64)v54;
if ( !v54 )
goto LABEL_39;
goto LABEL_38;
}
v14 = (__int64)v32;
if ( v32 )
{
v24 = v33;
LABEL_38:
RNvCs691rhTbG0Ee_7___rustc14___rust_dealloc(&Size, v13, v14, v24, 1LL);
}
LABEL_39:
v32 = (const char *)&unk_1400A2168;
v33 = 24LL;
Size = (size_t)&v32;
v36 = (const char *)_$LT$$RF$T$u20$as$u20$core..fmt..Display$GT$::fmt::h31fa4d9b908ac590;
v66 = &anon_ad88cb96a3fdcaf8c94331b0da292800_3_llvm_3440038967210771795;
v67 = 2LL;
v70 = 0LL;
p_Size = (size_t)&Size;
v69 = 1LL;
result = std::io::stdio::_print::hb423c4c57e4fd8e1(&Size, v13, v14, &v66);
LABEL_40:
if ( v60 )
result = RNvCs691rhTbG0Ee_7___rustc14___rust_dealloc(&Size, v13, 8 * v60, v61, 8LL);
if ( v63 )
result = RNvCs691rhTbG0Ee_7___rustc14___rust_dealloc(&Size, v13, v63, v13, 1LL);
if ( v29 )
result = RNvCs691rhTbG0Ee_7___rustc14___rust_dealloc(&Size, v13, v29, v30, 1LL);
if ( v72[0] )
return RNvCs691rhTbG0Ee_7___rustc14___rust_dealloc(&Size, v13, v72[0], v72[1], 1LL);
return result;
}

// XorOp
char __fastcall apply(__int64 a1, __int64 a2, __int64 a3, char a4) {
return a4 ^ 0x37;
}
// AddOp
__int64 __fastcall apply(__int64 a1, __int64 a2, __int64 a3, int a4) {
return (unsigned int)(a4 + 20);
}
// SubOp
__int64 __fastcall apply(__int64 a1, __int64 a2, __int64 a3, int a4) {
return (unsigned int)(a4 - 5);
}
// IdxXorOp
char __fastcall apply(__int64 a1, __int64 a2, char a3, char a4) {
return a4 ^ a3; // a3 是索引
}

之后直接看校验发现v34 == 30,加密后的flag是unk_1400A20B0处的数据

之后根据主函数逻辑写解密脚本

# 加密后的数据(30字节)
encrypted = [
0x65, 0x58, 0x3e, 0x57, 0x71, 0x8f, 0x4d, 0x72, 0x02, 0x88,
0x5a, 0x3a, 0x43, 0x47, 0x6d, 0x3b, 0x43, 0x44, 0x6d, 0x60,
0x68, 0x48, 0x6d, 0x24, 0x68, 0x57, 0x2b, 0x2b, 0x5b, 0x91
]
# 解密
flag = []
for i, c in enumerate(encrypted):
op = i % 4
if op == 0:
flag.append(chr(c ^ 0x37)) # 逆XorOp
elif op == 1:
flag.append(chr((c - 20) & 0xFF)) # 逆AddOp
elif op == 2:
flag.append(chr((c + 5) & 0xFF)) # 逆SubOp
elif op == 3:
flag.append(chr(c ^ i)) # 逆IdxXorOp
print('Flag:', ''.join(flag))

奶龙爱喝花茶#

先拿exeinfo看一眼发现没加壳,之后直接搜字符串

Input flag:

本打算定位到主函数,却发现里面充斥各种反反汇编代码混淆

0x411BE5: call loc_411BEB
0x411BEB: add [esp], 0Ch ; 修改返回地址
0x411BF0: retn ; 跳转到 0x411BF6

这种技术通过修改栈上的返回地址来隐藏真正的代码流程,使 IDA 无法正确识别函数边界。 实际执行路径从 0x411BF6 开始:

0x411BF6: lea eax, [ebp-18h] ; 获取 key 地址
0x411BF9: push eax
0x411BFA: call 0x4119F0 ; 调用 key 初始化函数

修复前 修复后

之后发现需要修复的太多了于是,只修复了部分关键函数,直接看加密逻辑

最后梳理后

输入 (24字节)
分成 3 个 8 字节块
每块转换为 2 个 DWORD (小端序)
预处理
TEA 加密
存储结果

解密脚本

import struct
def tea_decrypt(v0, v1, key):
"""TEA 解密"""
delta = 0x9E3779B9
sum_val = (delta * 32) & 0xFFFFFFFF
for i in range(32):
v1 = (v1 - (((key[3] + (v0 >> 5)) ^ (sum_val + v0) ^ (key[2] + ((v0 << 4) & 0xFFFFFFFF))))) & 0xFFFFFF
v0 = (v0 - (((key[1] + (v1 >> 5)) ^ (sum_val + v1) ^ (key[0] + ((v1 << 4) & 0xFFFFFFFF))))) & 0xFFFFFF
sum_val = (sum_val - delta) & 0xFFFFFFFF
return v0, v1
def rol(val, r_bits, max_bits=32):
return ((val << r_bits) | (val >> (max_bits - r_bits))) & ((1 << max_bits) - 1)
def ror(val, r_bits, max_bits=32):
return ((val >> r_bits) | (val << (max_bits - r_bits))) & ((1 << max_bits) - 1)
# 正确的 TEA 密钥(动态计算得到)
key = [0xFD56276F, 0x725BE59E, 0x03F240A5, 0xEA6E72F5]
# sub_411E20 使用的数组
v3 = [0x12345678, 0x9ABCDEF0, 0x0FEDCBA9, 0x87654321]
# 密文
ciphertext = [0x2E06E9DC, 0x11469DD0, 0x481028F0, 0x83FB8766, 0x2EBBAB8C, 0xBC51B3AF]
# Step 1: 计算加密后的期望值
encrypted_input = []
for i in range(6):
idx = i & 3
shift = (5 * i + 3) & 0x1F
mask = rol(v3[idx], shift) ^ 0xDEADBEEF
enc = mask ^ ciphertext[i]
encrypted_input.append(enc)
# Step 2: TEA 解密
decrypted_blocks = []
for i in range(3):
v0 = encrypted_input[i*2]
v1 = encrypted_input[i*2+1]
p0, p1 = tea_decrypt(v0, v1, key)
decrypted_blocks.append((p0, p1))
# Step 3: 逆向预处理
flag_bytes = b''
for p0, p1 in decrypted_blocks:
orig_v0 = p0 ^ 0xA5A5A5A5
orig_v1 = ror(p1, 7) ^ 0x3C3C3C3C
flag_bytes += struct.pack('<I', orig_v0)
flag_bytes += struct.pack('<I', orig_v1)
print(f"Flag: RDCTF{{{flag_bytes.decode()}}}")

UPX#

首先通过exeinfo发现有upx魔改壳

[Tampared file] x64 UPX v3.9 - 5.0 - [4.24]
Don't try: upx.exe -d option

发现UPX特征字段都被改成小写了

之后使用Python脚本修复:

with open("original.exe", "rb") as f:
data = bytearray(f.read())
# 修复签名和段名
data[0x3E0:0x3E4] = b'UPX!' # upx! -> UPX!
data[0x1F8:0x1FC] = b'UPX0' # upx0 -> UPX0
data[0x220:0x224] = b'UPX1' # upx1 -> UPX1
with open("fixed.exe", "wb") as f:
f.write(data)

修复后使用标准UPX工具成功脱壳

分析脱壳后程序发现是一个魔改AES加密(有额外的XOR)

解密脚本

SBOX = [0x63, 0x7c, 0x77, 0x7b, ...] # 标准AES S-Box
INV_SBOX = [0] * 256
for i in range(256):
INV_SBOX[SBOX[i]] = i
def inv_mix_columns_modified(state):
# 关键:先撤销XOR 0x7C
state = bytes([b ^ 0x7c for b in state])
# 然后执行标准InvMixColumns
# ... 标准实现 ...
return result
def decrypt_block(ciphertext, expanded_key):
state = ciphertext
state = add_round_key(state, expanded_key[160:176])
for round in range(9, 0, -1):
state = inv_shift_rows(state)
state = inv_sub_bytes(state)
state = add_round_key(state, expanded_key[round*16:(round+1)*16])
state = inv_mix_columns_modified(state) # 使用修改版
state = inv_shift_rows(state)
state = inv_sub_bytes(state)
state = add_round_key(state, expanded_key[0:16])
return state
# 解密
key = b'rDctf_AES_key_16'
ciphertext = bytes.fromhex('341359569651ffae3ed8d2b53be64b3452ba52e9a684b4ef4f39d5bcb1bb68b0')
expanded_key = key_expansion(key)
pt1 = decrypt_block(ciphertext[:16], expanded_key)
pt2 = decrypt_block(ciphertext[16:], expanded_key)
print("Flag:", (pt1 + pt2).decode())
# Output: RDCTF{MixColXor7C_AES_Rev_2026!}

ezbase#

无壳且逻辑非常简单

  • 读入输入串 Buffer
  • sub_1400117D0 做前向异或: buf[i] ^= buf[i+1] ,最后一字节不变
  • sub_140011890 用自定义 Base64 字表编码
  • 与内置字符串 Str2 比较,相同则输出 Correct!

自定义 Base64 字表:

QWERTYUIOPASDFGHJKLZXCVBNMabcdefghijklmnopqrstuvwxyz0123456789+/

内置 Str2 :

YgcBTj0DKQPLX11ebUgIby0VW1KKGKxzBlhTKgFEKQXRWgYeV2omLXXqaJXTaUhfV2wtJwdeB2g5CwXEYwQQBI0=

解法思路:先用自定义字表把 Str2 解码为字节流,再从末尾逆推还原原串(因为正向是 buf[i] ^= buf[i+1] ,所以逆向是 orig[i] = t[i] ^ orig[i+1] )

解密脚本

import base64
alphabet = b"QWERTYUIOPASDFGHJKLZXCVBNMabcdefghijklmnopqrstuvwxyz0123456789+/"
std = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
trans = bytes.maketrans(alphabet, std)
enc = b"YgcBTj0DKQPLX11ebUgIby0VW1KKGKxzBlhTKgFEKQXRWgYeV2omLXXqaJXTaUhfV2wtJwdeB2g5CwXEYwQQBI0="
raw = base64.b64decode(enc.translate(trans))
n = len(raw)
orig = bytearray(n)
orig[-1] = raw[-1]
for i in range(n - 2, -1, -1):
orig[i] = raw[i] ^ orig[i + 1]
print(orig.decode())

ezpy#

有点懒得说了,直接pyinstxtractor.py 对 exe 进行解包,之后反编译pyc文件

发现是一个RC4加密

key = b"nailong"
target =bytes.fromhex("2ef01fece0420e0e3d2179e97f26eeab020a32ef51e2a73b2ab6d550196858fa89cf284397df709afc")

解密脚本

from binascii import unhexlify
def rc4(data: bytes, key: bytes) -> bytes:
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % len(key)]) & 0xFF
s[i], s[j] = s[j], s[i]
i = j = 0
out = bytearray()
for b in data:
i = (i + 1) & 0xFF
j = (j + s[i]) & 0xFF
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) & 0xFF]
out.append(b ^ k)
return bytes(out)
key = b"nailong"
target = unhexlify("2ef01fece0420e0e3d2179e97f26eeab020a32ef51e2a73b2ab6d550196858fa89cf284397df709afc")
print(rc4(target, key).decode())
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

第二届rdctf逆向Writeup
https://chaojixin.ren/posts/第二届rdctf逆向wp/
作者
超級の新人
发布于
2026-01-31
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
Sample Song
Sample Artist
封面
Sample Song
Sample Artist
0:00 / 0:00