LitCTF-2023-Reverse

世界上最棒的程序员

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}

当前页面链接: https://www.hyhforever.top/litctf-2023-reverse/
如果您对本文内容有所意见或者建议,欢迎评论。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇