2019浙江省大学生网络与信息安全竞赛决赛部分WriteUp
0x01 前言
這次比賽PWN爺爺沒有去,去了OPPO的線下賽,所以最后只拿到了前十靠后的名次。不過還是拿到了省一等獎,也算沒有留下什么遺憾。
0x02 萬能密碼
通過名字就可以知道這題考察的是最基本的SQL注入知識點(diǎn)。
通過對題目環(huán)境的測試可以發(fā)現(xiàn),這是基于盲注的POST注入,閉合雙引號即可,登陸即可拿到flag
payload
admin"#0x03 貳零肆捌
題目是一個2048的游戲,大概就是分?jǐn)?shù)多于一定的值即可,這邊可以選擇玩到輸?shù)臅r候抓包,修改分?jǐn)?shù)。我這邊是直接修改js代碼,另score的初始值等于15001,然后玩到死亡,就獲得了flag
0x04 逆轉(zhuǎn)思維
emmmm題目環(huán)境我這邊沒有保留,大概題目邏輯是
第一步
file_get_contents($_GET(txt))===“welcome to the zjctf”,大概是這個,我們要讓這個條件成立,我一開始想到的是遠(yuǎn)程文件包含,就是在我這邊部署一個包含這個內(nèi)容的文件,讓題目環(huán)境訪問我們開放的端口,后來發(fā)現(xiàn)因?yàn)槭蔷€下局域網(wǎng),沒辦法遠(yuǎn)程文件包含
然后比賽后半段才在我以前拉取下來的wiki的docker里面找到一個data協(xié)議。
利用payload繞過
第二步
題目有第二個參數(shù)file,大概是include()這個file,題目提示我們要包含useless.php
同時有一個判斷是file參數(shù)不能傳入flag,也就是我們不能直接包含flag.php
利用php://filter協(xié)議讀取這個useless.php
構(gòu)造payload讀取useless.php
得到useless.php
<?php??class Flag{//flag.php??public $file;??public function __tostring(){??if(isset($this->file)){??echo file_get_contents($this->file);?echo "<br>";return ("HAHAHAHAHA");}??}?? }???>
第三步
最后一個參數(shù)是password,php代碼里面有反序列化這個傳入的值,所以只要讓最后反序列化出來的file等于flag.php就好了。
構(gòu)造payload
得到flag
0x05 佛洛依德
這邊有幸保留了題目
題目源碼
#!/usr/bin/env?python #?-*-?coding:?utf-8?-*-__author__?=?'seclab' __copyright__?=?'Copyright???2019/08/20,?seclab'import?hashlib,?random,?signaldef?truncated_hash(message,?k):return?hashlib.sha512(message).digest()[-k:]def?floyd(code,?k=3):m0?=?Nonem1?=?Noneturtle?=?truncated_hash(code,?k)hare???=?truncated_hash(turtle,?k)while?turtle?!=?hare:turtle?=?truncated_hash(turtle,?k)hare???=?truncated_hash(truncated_hash(hare,?k),?k)turtle?=?codepre_period_length?=?0while?turtle?!=?hare:m0?????=?turtleturtle?=?truncated_hash(turtle,?k)hare???=?truncated_hash(hare,?k)pre_period_length?+=?1if?pre_period_length?is?0:print(code,?"Failed?to?find?a?collision:?code?was?in?a?cycle!")return?floyd(get_random_code())period_length?=?1hare?=?truncated_hash(turtle,?k)while?turtle?!=?hare:m1??=???harehare?=?truncated_hash(hare,?k)period_length?+=?1return?(m0,?m1,?truncated_hash(m0,?k),?k)def?get_random_code(length=3):char_set?=?"ABCDEFGHIJKLMNOPQRSTUVWXYZ"pw?=?""for?i?in?range(length):next_index?=?random.randrange(len(char_set))pw?=?pw?+?char_set[next_index]return?pwdef?welcom():signal.alarm(5)print( r'''_____?_?????????????????_?????____????????????????_???? |??___|?|?___??_???_??__|?|???/?___|_?__?__?_??___|?|?__ |?|_??|?|/?_?\|?|?|?|/?_`?|??|?|???|?'__/?_`?|/?__|?|/?/ |??_|?|?|?(_)?|?|_|?|?(_|?|??|?|___|?|?|?(_|?|?(__|???<? |_|???|_|\___/?\__,?|\__,_|???\____|_|??\__,_|\___|_|\_\|___/???????????????????????????????????????????????????? ''')def?main():welcom()flag?=?open('./flag',?'r').read()code?=?get_random_code()m0,?m1,?code,?k?=?floyd(code)print("Your?m0?is:{:s}".format(m0.encode("hex")))m1?=?raw_input("Please?input?m1:").rstrip("\n")try:m1?=?m1.decode("hex")if?(m0?!=?m1)?and?(truncated_hash(m0,?k)?==?truncated_hash(m1,?k)):print(flag)exit(1)except?Exception?as?e:passprint("Fail,?bye!")exit(1)if?__name__?==?"__main__":main()通過代碼邏輯我們可以知道,這邊就是給我們m0,然后要我們輸入正確的m1,然后才給我們flag。
解題思路
我首先關(guān)注到的是這個函數(shù)
def?get_random_code(length=3):char_set?=?"ABCDEFGHIJKLMNOPQRSTUVWXYZ"pw?=?""for?i?in?range(length):next_index?=?random.randrange(len(char_set))pw?=?pw?+?char_set[next_index]return?pw從get_random_code函數(shù)可以看出,主要功能是獲得長度為3的字符串,字符是A~Z的。
所以通過這個長度為3,可以發(fā)現(xiàn)是很容易爆破出m0和m1對應(yīng)的字典的。
構(gòu)造字典腳本如下。
import hashlib, random def truncated_hash(message, k):return hashlib.sha512(message).digest()[-k:] def get_random_code(length=3):char_set = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"pw = ""for i in range(length):next_index = random.randrange(len(char_set))pw = pw + char_set[next_index]return pw def floyd(code, k=3):m0 = Nonem1 = Noneturtle = truncated_hash(code, k)hare? ?= truncated_hash(turtle, k)while turtle != hare:turtle = truncated_hash(turtle, k)hare? ?= truncated_hash(truncated_hash(hare, k), k)turtle = codepre_period_length = 0while turtle != hare:m0? ? ?= turtleturtle = truncated_hash(turtle, k)hare? ?= truncated_hash(hare, k)pre_period_length += 1if pre_period_length is 0:print(code, "Failed to find a collision: code was in a cycle!")return floyd(get_random_code())period_length = 1hare = truncated_hash(turtle, k)while turtle != hare:m1? =? ?harehare = truncated_hash(hare, k)period_length += 1return (m0, m1, truncated_hash(m0, k), k) #code = get_random_code() #print(code) #m0, m1, code, k = floyd(code) #print(m0, m1, code, k) m0=[] m1=[]table="ABCDEFGHIJKLMNOPQRSTUVWXYZ" code=[] for i in table:for j in table:for k in table:code.append(i+j+k)m00, m11, code1, k = floyd(i+j+k)m0.append(m00)m1.append(m11)f=open("shuju.txt",'a')?print(len(code)) print(len(m0)) print(len(m1)) f.write("dict = {") for i in range(len(m0)):f.write(m0[i].encode("hex")+":"+m1[i].encode("hex")+",\n") f.write("}") f.close()最后處理一下生成的字典,然后獲取服務(wù)器上的m0,對應(yīng)我們字典中的m1,發(fā)送給服務(wù)器即可得到flag
dict={} from pwn import * #context.log_level ="debug" sh=remote("172.16.0.103",10011) sh.recvuntil("is:") crypto1 = sh.recvline()[:-1] print("~~~~:",crypto1)sendm1=dict[crypto1] print("sendm1",sendm1) sh.recvuntil("m1:") sh.sendline(sendm1)sh.interactive()
0x06?簡單逆向
首先第一步拿到APK,使用Jeb反編譯
通過觀察發(fā)現(xiàn)getFlag是加載進(jìn)來的一個.so文件
找到這個.so文件,用ida反編譯
沒有什么難點(diǎn),就直接明文給你flag了
0x07?清廉校園
首先拿到一張圖片,一開始嘗試了挺多圖片隱寫。。。后來才發(fā)現(xiàn),原來圖片的最后直接有明文的flag信息。是一個凱撒加密的東西
首先全部移位39得到@JC:FT=ELCOME:OHD;SECLABV
然后通過對flag格式的判斷,是ZJCTF開頭的,發(fā)現(xiàn)無意義的字符距離正確的是相差58位,然后對無意義的字符移位58得到有意義的flag字符串,比較坑的是最后還要全部小寫,才是正確的flag
正確的flag為welcometohduseclab
0x08 反推蟒蛇
首先題目給了一個pyo文件,其實(shí)一開始看到還是比較絕望的,因?yàn)楦杏X自己應(yīng)該沒有反編譯的工具。后來好不容易才在自己的學(xué)習(xí)記錄里面找到曾經(jīng)有試過本地反編譯pyc
使用kali自帶的uncompyle6,也有可能是我以前裝的
指令如下
得到的encrypt.py源碼為
# uncompyle6 version 3.3.5 # Python bytecode 2.7 (62211) # Decompiled from: Python 2.7.15+ (default, Nov 28 2018, 16:27:22)? # [GCC 8.2.0] # Embedded file name: encrypt.py # Compiled at: 2017-07-11 05:19:27 from random import randint from math import floor, sqrt _ = '' __ = '_' ____ = [ ord(___) for ___ in __ ] _____ = randint(65, max(____)) * 255 for ___ in range(len(__)):_ += str(int(floor(float(_____ + ____[___]) / 2 + sqrt(_____ * ____[___])) % 255)) + ' 'print _ # okay decompiling encrypt.pyo我這邊是現(xiàn)對這些下劃線進(jìn)行了處理
大概邏輯是這樣的
這邊題目還給了我們一個flag.enc的文件
57, 183, 124, 9, 149, 65, 245, 166, 175, 1, 226, 106, 216, 132, 224, 208, 139, 1, 188, 224, 9, 235, 106, 149, 141, 80這個就是flag經(jīng)過加密后的內(nèi)容了。
通過分析代碼邏輯,我們可以發(fā)現(xiàn),max(b)一定是}的ascii值,然加密后的值一定是最后一個80.通過這個其實(shí)我們可以確定一個值,randint(65,?max(b))的值可以確定,通過排除一個大于}的ascii的值,確定為102
也就是說我們確定了a的值為102*125
這樣其實(shí)我們就可以確定每一個字母對應(yīng)的加密后的值了
構(gòu)造對應(yīng)關(guān)系腳本
最后得到flag加密前的值
zjctf{ThisRandomIsNotSafe}
總結(jié)
以上是生活随笔為你收集整理的2019浙江省大学生网络与信息安全竞赛决赛部分WriteUp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQLi-LABS(21~25a关详解)
- 下一篇: 区块链之智能合约入门