NSSCTF_reverse_[SWPUCTF 2021 新生赛]re1——[SWPUCTF 2021 新生赛]re2

张开发
2026/4/10 2:06:50 15 分钟阅读

分享文章

NSSCTF_reverse_[SWPUCTF 2021 新生赛]re1——[SWPUCTF 2021 新生赛]re2
目录[SWPUCTF 2021 新生赛]re1[SWPUCTF 2021 新生赛]简简单单的逻辑[LitCTF 2023]世界上最棒的程序员[NSSCTF 2022 Spring Recruit]easy C[SWPUCTF 2021 新生赛]re2[SWPUCTF 2021 新生赛]re1首先先查一下这个exe软件是一个64位程序我们用ida64打开找到可疑的字符串我们点进去看看代码逻辑分析初始密文存储在栈上的Str2区域Str2 3707130418507821947(64位整数)v5 1936864118v6 32051v7 0输入处理读取用户输入的 flag 到Str1将输入中的e(101) 替换为3(51)将输入中的a(97) 替换为4(52)验证将处理后的输入与初始密文比较相同则正确密文解析初始密文在内存中的排列小端序0x3373616273696D7B(Str2)0x5F74695F6B634F(v5需要补全为8字节)0x7D336D(v6v70)将这些十六进制转换为 ASCII注意小端序要反转Str2: 0x3373616273696D7B → 反转字节: 7B 6D 69 73 62 61 73 33→ ASCII: { m i s b a s 3v5: 0x5F74695F6B634F00 → 反转: 00 4F 63 6B 5F 69 74 5F→ ASCII: \0 O c k _ i t _v6: 0x7D336D → 反转: 6D 33 7D→ ASCII: m 3 }我们用脚本跑一下完整代码import struct # 小端序数据 data struct.pack(Q, 3707130418507821947) # Str2 data struct.pack(I, 1936864118) # v5 data struct.pack(H, 32051) # v6 print(密文字节:, data) print(密文ASCII:, data.decode(ascii))得到{mishas3Ock_it_m3}# 已知密文 cipher {34sy_r3v3rs3} # 反向替换3 - e, 4 - a flag cipher.replace(3, e).replace(4, a) print(fFlag: {flag})得到flagNSSCTF{easy_reverse}[SWPUCTF 2021 新生赛]简简单单的逻辑第一步理解加密过程代码大致流程flag xxxxxxxxxxxxxxxxxx list [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25] result for i in range(len(list)): key (list[i]4) ((list[i] 0xf) 4) result str(hex(ord(flag[i]) ^ key))[2:].zfill(2) print(result) # resultbcfba4d0038d48bd4b00f82796d393dfeckey的计算list[i] 4取高 4 位(list[i] 0xf) 4取低 4 位并移到高 4 位这两个相加其实就是交换高 4 位和低 4 位比如470x2F高 4 位0x2低 4 位0xF交换后变成0xF2242。ord(flag[i]) ^ keyflag 字符的 ASCII 值与 key 进行异或结果转为 2 位十六进制字符串拼接起来得到最终密文第二步已知密文密文bcfba4d0038d48bd4b00f82796d393dfec长度 34 个十六进制字符代表 17 个字节对应list长度 17。第三步解密思路加密是异或操作且 key 只依赖于list所以直接逆推即可将密文每 2 个字符转成十进制整数即加密后的字节用同样的方法计算出key用密文字节 ^ key得到 flag 的 ASCII 码转成字符第四步解密脚本完整代码list_data [47, 138, 127, 57, 117, 188, 51, 143, 17, 84, 42, 135, 76, 105, 28, 169, 25] cipher_hex bcfba4d0038d48bd4b00f82796d393dfec # 将十六进制字符串按每2个字符切分 cipher_bytes [int(cipher_hex[i:i2], 16) for i in range(0, len(cipher_hex), 2)] flag for i in range(len(list_data)): # 计算 key高低4位互换 key (list_data[i] 4) ((list_data[i] 0xf) 4) # 异或解密 flag_char chr(cipher_bytes[i] ^ key) flag flag_char print(flag)运行后得到flagNSSCTF{EZEZ_RERE}[LitCTF 2023]世界上最棒的程序员首先查一下是32位的exe软件我们用ida32打开shiftF12直接找到flag最后flag为NSSCTF{I_am_the_best_programmer_ever}[NSSCTF 2022 Spring Recruit]easy C这段代码的逻辑是输入的字符串经过a[i]和a[i] a[i] ^ 2的变换后如果与b相等则正确。我们已知目标数组b是dvxbQd我们需要逆向推导出原始的输入。逆向过程加密过程是a[i]a[i] a[i] ^ 2所以解密需要反过来先用b[i] ^ 2再减 1计算过程b dvxbQd flag for c in b: original (ord(c) ^ 2) - 1 flag chr(original) print(flag)最后flag为NSSCTF{easy_Re}[SWPUCTF 2021 新生赛]re2用ida64打开找到伪代码步骤 1分析代码逻辑目标字符串构造代码中Str2、v5、v6经过小端序打包后是我们需要对比的目标字符串。字符变换规则若输入字符是A/B/a/b则加 24否则减 2。逆向思路根据变换后的字符t反推原始字符c若t - 24是A/B/a/b则c t - 24否则c t 2。步骤 2Python 实现逆向完整代码import struct # 1. 定义代码中的目标值 Str2 7167867335899966585 v5 2070968689 v6 0 # 2. 构造目标字符串小端序打包Q8字节, I4字节, B1字节 target struct.pack(Q, Str2) struct.pack(I, v5) struct.pack(B, v6) flag [] for t in target: if t 0: # 遇到字符串结束符停止 break # 3. 逆向还原原始字符 candidate1 t - 24 if candidate1 in {65, 66, 97, 98}: # 检查是否为 A/B/a/b flag.append(chr(candidate1)) else: flag.append(chr(t 2)) print(Flag:, .join(flag))flag为anss_caesar}NSSCTF{nss_caesar}

更多文章