世界上最棒的程序员
Shift+F12,在全局字符串中查找到 flag
ez_XOR
使用 32 位 IDA 打开,F5 查看伪代码
可以看到存在字符串输入后进行异或,异或是可逆性的
跟进查看 XOR 函数的内容,很明显是每个字符和 9 进行异或
s='E`}J]OrQF[V8zV:hzpV}fVF[t' for i in s: print(chr(ord(i)^9),end='') #LitCTF{XOR_1s_3asy_to_OR}
enbase64
F5 查看伪代码
可以看到输入字符串长度是 33,然后进入 Base64 加密,最后再进行 check
由于 Source 不是标准的 Base64 表,这个可以在 Base64 函数里看到有个 Basechange,对表做了修改
可以让 AI 跑一个脚本,注意了这里有一位是没有赋值的,也就是 v3 [33]
v3 = [ 16, 34, 56, 7, 46, 2, 10, 44, 20, 41, 59, 31, 51, 60, 61, 26, 5, 40, 21, 38, 4, 54, 52, 47, 3, 11, 58, 48, 32, 15, 49, 14, 37, 0, 55, 53, 24, 35, 18, 25, 33, 43, 50, 39, 12, 19, 13, 42, 9, 17, 28, 30, 23, 36, 1, 22, 57, 63, 8, 27, 6, 62, 45, 29 ] source = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" for i in range(48): # 创建一个临时列表,用于存储置换后的字符 temp = [''] * 64 # 遍历索引数组,按照索引交换字符 for j in range(64): temp[j] = source[v3[j]] # 将临时列表赋值给原始字符串 source = ''.join(temp) # 直接将列表转换为字符串 print(source) #gJ1BRjQie/FIWhEslq7GxbnL26M4+HXUtcpmVTKaydOP38of5v90ZSwrkYzCAuND
进入赛播厨师,换表就能得到 flag
snake
附件给的是一个 pyc 文件,不能用 IDA 来进行反编译
在 Python 中,每个.pyc 文件(即 Python 字节码文件)都包含一个魔术数字(Magic Number)来识别版本兼容性。当我们尝试加载一个.pyc 文件时,Python 会检查文件中的魔术数字是否与当前
解释器版本匹配。如果不匹配,就会引发 Bad Magic Number 错误。
查看文件头发现什么都没有
结合文件名的 37,猜测 python 版本应该是 3.7
反编译后可以看到,分数超过 1000 就有 flag
直接复制他的代码会乱码,指定编码也没用
细看他的赋值逻辑是有问题的,后值在使用前值的时候,前值是已经被修改过的,这样就会导致不准确
flag = [ 30, 196, 52, 252, 49, 220, 7, 243, 3, 241, 24, 224, 40, 230, 25, 251, 28, 233, 40, 237, 4, 225, 4, 215, 40, 231, 22, 237, 14, 251, 10, 169 ] for i in range(0, len(flag), 2): temp=flag[i] flag[i] = flag[i + 1] ^ 136 flag[i + 1] = temp ^ 119 # 将结果转换为字节并解码为字符串 decoded_flag = bytes(flag).decode(errors='ignore') print(decoded_flag) #LitCTF{python_snake_is_so_easy!}
程序和人有一个能跑就行了
这个 sub_4015A0
函数可以让 AI 进行分析,符合 RC4 加密的特征
在底部代码里存在逻辑错误,无论是否比较成功,都会输出 U are right?
可以打个断点看看过程
使用 windows 的 debugger
这里是一些 IDA 的使用技巧
多次步过之后发现一段字节,可能是密文
.text:00475BBA mov byte ptr [esp+83h], 8Dh .text:00475BC2 mov byte ptr [esp+84h], 6Ch ; 'l' .text:00475BCA mov byte ptr [esp+85h], 85h .text:00475BD2 mov byte ptr [esp+86h], 76h ; 'v' .text:00475BDA mov byte ptr [esp+87h], 32h ; '2' .text:00475BE2 mov byte ptr [esp+88h], 72h ; 'r' .text:00475BEA mov byte ptr [esp+89h], 0B7h .text:00475BF2 mov byte ptr [esp+8Ah], 43h ; 'C' .text:00475BFA mov byte ptr [esp+8Bh], 85h .text:00475C02 mov byte ptr [esp+8Ch], 7Bh ; '{' .text:00475C0A mov byte ptr [esp+8Dh], 85h .text:00475C12 mov byte ptr [esp+8Eh], 0DEh .text:00475C1A mov byte ptr [esp+8Fh], 0C1h .text:00475C22 mov byte ptr [esp+90h], 0FBh .text:00475C2A mov byte ptr [esp+91h], 2Eh ; '.' .text:00475C32 mov byte ptr [esp+92h], 64h ; 'd' .text:00475C3A mov byte ptr [esp+93h], 7 .text:00475C42 mov byte ptr [esp+94h], 0C8h .text:00475C4A mov byte ptr [esp+95h], 5Fh ; '_' .text:00475C52 mov byte ptr [esp+96h], 9Ah .text:00475C5A mov byte ptr [esp+97h], 35h ; '5' .text:00475C62 mov byte ptr [esp+98h], 18h .text:00475C6A mov byte ptr [esp+99h], 0ADh .text:00475C72 mov byte ptr [esp+9Ah], 0B5h .text:00475C7A mov byte ptr [esp+9Bh], 15h .text:00475C82 mov byte ptr [esp+9Ch], 92h .text:00475C8A mov byte ptr [esp+9Dh], 0BEh .text:00475C92 mov byte ptr [esp+9Eh], 1Bh .text:00475C9A mov byte ptr [esp+9Fh], 88h .text:00475CA2 call memcmp
然后让 AI 跑一个脚本即可
from Crypto.Cipher import ARC4 # 密钥和密文 key = b'litctf' ciphertext = bytes([0x8D, 0x6C, 0x85, 0x76, 0x32, 0x72, 0xB7, 0x43, 0x85, 0x7B, 0x85, 0xDE, 0xC1, 0xFB, 0x2E, 0x64, 0x07, 0xC8, 0x5F, 0x9A, 0x35, 0x18, 0xAD, 0xB5, 0x15, 0x92, 0xBE, 0x1B, 0x88]) # 创建RC4解密器 cipher = ARC4.new(key) # 解密 plaintext = cipher.decrypt(ciphertext) # 输出结果 print(plaintext.decode('utf-8', errors='ignore')) #LitCTF{welcome_to_the_litctf}
debase64
题目是和 Base64 相关的
首先注意到 v15 的长度必须是 20
sub_401520
这个函数的功能类似于对 v13 进行解密,然后结果存到 v4 中
最后对比 v4 的内容是否正确,这里可以看到比较的步长是 2,而那几个数字可以使用十六进制表示,从而分成两个部分
对 v6 打个断点进行调试
可以注意到 18ED 才是 6381,所以十六进制的两个字节需要置换
import base64 data=[0x46, 0xed, 0x18, 0x96, 0x56, 0x9E, 0xd2, 0x72, 0xb2, 0xb3, 0x80, 0x70] bytes_encoded = bytes(data) decoded_bytes = base64.b64encode(bytes_encoded).decode('utf-8') print(decoded_bytes) #Ru0Yllae0nKys4Bw
但是加密结果需要每四个字节进行逆序,看别人的文章似乎是伪代码中的 Base64 加密过程并不标准,也或许是因为程序的大端序存储。
根据题目描述进行 MD5 爆破,得到 flag
from hashlib import md5 import string s = "Y0uReallyKn0wB4s" for i in string.printable: test = s + i + "===" if md5(test.encode()).hexdigest() == "5a3ebb487ad0046e52db00570339aace": print(test) break #NSSCTF{Y0uReallyKn0wB4s3===}
For Aiur
使用 64 位 IDA 进行反编译,能够看出似乎是由 pyinstaller 进行打包的 EXE 文件
反编译工具
对 Probee.pyc
进行反编译,从 ch 中引入了 check 函数
这里有个注意点,需要使用 python3.8 版本,不然会找不到这个 ch 文件
enc = [ 98, 77, 94, 91, 92, 107, 125, 66, 87, 70, 113, 92, 83, 70, 85, 81, 19, 21, 109, 99, 87, 107, 127, 65, 65, 64, 109, 87, 93, 90, 65, 64, 64, 65, 81, 3, 109, 85, 86, 80, 91, 64, 91, 91, 92, 0, 94, 107, 66, 77, 94, 91, 92, 71 ] def check(num): flag = 'LitCTF{' if num % 2 == 0 and num % 4 == 0 and num % 6 == 0 and num % 8 == 0 and num % 12 == 0 and num % 13 == 11: k = str(num) for i in range(len(enc)): flag += chr(ord(k[i % len(k)]) ^ enc[i]) flag += '}' print(flag) check(24) #LitCTF{Pylon_OverCharge!!_We_Must_construc7_addition4l_pylons}