Often times you will need to decipher a language which you can not find on google, or is encrypted in some way. I have made up a language for you to decipher. What is the output of this program?
有人設計了一種程式語言,並寫了一支只有五行的程式,希望你去分析這支程式會輸出什麼內容。
BEGIN notr.eal
CREATE int AS 2
DESTROY int AS 0
ANS var AS Create + TO
out TO
- 首先第一行
BEGIN notr.eal,看到BEGIN很自然地會想到傳統程式語言的function head - 最後一行
out TO,必然會想到C++的cout等print功能,可以猜測最後一行就是輸出TO變數 - 接著分析第二行
CREATE int AS 2,看到CREATE int就會理解為建立一個整數型態變數名稱AS且初始值為2 - 第三行
DESTROY int AS 0我認為比較不容易分析,首先假設這裡是刪除變數AS,但從第四行看到AS仍然有被使用到,於是採用第二種假設,DESTROY為減法,所以變成AS = AS - 0 - 第四行
ANS var AS Create + TO一開始沒有什麼頭緒,第一種假設,這裡的+ TO是串接一個字串TO,也就是AS = AS + TO,第二種假設,不管ANS var跟+的意義,單純假設TO = AS - 嘗試內容中的關鍵字組合,TO、20、20TO、2TO、AS、ANS、var等皆錯誤,經過以上粗體字的思路後,得到答案為2
function notr.eal
variable named 'AS' = 2
AS = AS - 0
variable named 'TO' = AS
print TO
後來試著搜尋其他人的想法,看到其中一種想法是當作組合語言來思考
- 第一行一樣是function宣告
- 第二、三行將其理解為PUSH變數2、0到名為
AS的stack裡面 - 第四行是將
AS的變數POP兩個出來放到TO,此時TO = 02也就是2 - 輸出變數
TO
function notr.eal
PUSH 2 into AS
PUSH 0 into AS
POP two values into TO
print TO
參考他人思路後,可以看到對於第一行及最後一行的理解大部分人應該都是差不多的,關鍵分析主要仍然在二三四行。由於題目只有給五行的範例程式,難以分析出此程式語言的詳細語法規範,因此可以推測這是在考我們分析的同時發揮一點想像力,也並不需要全部依照關鍵字的英文意義去推論,在這個網站上過於死板的黑客過程只會讓自己心態炸裂。
<?php
if (isset($_GET['name']) && isset($_GET['email'])) {
$user = mysql_real_escape_string($_GET['name']);
$email = mysql_real_escape_string($_GET['email']);
$result= mysql_fetch_assoc(mysql_query("SELECT `email` FROM `members` WHERE name = '$user'"));
$reply = false;
if ($email == $result['email'])
{
$reply = true;
}
} else {
$reply = false;
}
echo ($reply) ? 1 : 0;
?>The script's filename is vrfy.php Make the script reply 1. Use the relative path. You don't know any users or emails.
給你一段php程式碼並告訴你它的檔案名稱是vrfy.php,希望你讓這段程式碼印出1
- 看到程式碼出現
$_GET關鍵字,就知道跟GET request method有關,首先修改網站網址路徑找看看有沒有這個網頁,但是找不到。 - 看到
mysql_query(),嘗試在變數中使用SQL injectionvrfy.php?name=or1=1/*&email=or1=1/*,嘗試放入亂數、字串vrfy.php?name=a&email=a,以上測試於HackThisSite輸入答案皆錯誤 - 既然沒有給我網頁測試,那我就自己放到網站上去跑,測試發現
vrfy.php?name=a&email=a可以印出1,但並不是題目想要的答案 - 搜尋論壇得到標準答案為
vrfy.php?name=&email=,發現論壇也有人說答案應該不唯一 - 修改網站程式碼,嘗試將變數印出並觀察變化
<?php
if (isset($_GET['name']) && isset($_GET['email'])) {
$user = mysql_real_escape_string($_GET['name']);
$email = mysql_real_escape_string($_GET['email']);
$result = mysql_fetch_assoc(mysql_query("SELECT `email` FROM `members` WHERE name = '$user'"));
$reply = false;
echo "\$_GET['name']=" . $_GET['name'] . '<br>';
echo "\$_GET['email']=" . $_GET['email'] . '<br>';
echo gettype($user) . ' $user=' . ($user ? 'true' : 'false') . '<br>';
echo gettype($email) . ' $email=' . ($email ? 'true' : 'false') . '<br>';
echo gettype($user) . ' $user=' . $user . '<br>';
echo gettype($email) . ' $email=' . $email . '<br>';
echo gettype($result) . " \$result=" . $result . '<br>';
echo gettype($result['email']) . " \$result['email']=" . $result['email'] . '<br>';
if ($email == $result['email'])
{
$reply = true;
}
} else {
echo "\$_GET['name']=" . $_GET['name'] . '<br>';
echo "\$_GET['email']=" . $_GET['email'] . '<br>';
$reply = false;
}
echo ($reply) ? 1 : 0;
?>$user = mysql_real_escape_string($_GET['name']);
$email = mysql_real_escape_string($_GET['email']);
mysql_real_escape_string()使用前需要先建立MySQL連線,否則執行失敗回傳False
if ($email == $result['email'])
{
$reply = true;
}
NULL == NULL在php為True,在其他程式語言或系統上不一定相同
似乎是因為兩年沒有碰php,三年沒碰mysql,我竟然沒有在第一時間發現mysql_query()之前沒有建立MySQL連線,就直接做了SQL injection測試。這一題如果硬要下去猜的話其實有很高的機會猜出正確答案,但要了解整個前因後果仍然需要具備一點php的概念。裡面使用的跳脫字元處理函數mysql_real_escape_string()過去從未使用過,透過官方使用手冊了解在php7.0以後正式移除功能。而NULL == NULL更是第一次碰到的觀念,搜尋相關資料的同時也找到了False == False為False的觀念,著實學到了不少東西。
Often times you will need to decipher a language which you can not find on google, or is encrypted in some way I have made up a language for you to decipher. This is slightly harder. What is the output of this program? This is a REAL language with REAL rules. This is practice for obfustication or encrypted functions.
{user types 6,7}
BEGIN F.ake
var int as in
int var as in
out var int
分析上方的語言會輸出什麼內容。
- 本題與上一題FindaFake 1為類似的分析題,因此首先參考上一題與本題語法上的相似之處。
BEGIN notr.eal
CREATE int AS 2
DESTROY int AS 0
ANS var AS Create + TO
out TO
- 依照個人分析的想法,上方
CREATE int AS 2以及DESTROY int AS 0的宣告代表著int型態的CREATE與DESTROY分別被指派2與0的數值。 - 依此類推,本題
var int as in與int var as in分別代表int型態的var變數與var型態的int變數,指派的數值皆為in。 - 根據本題程式上方
{user types 6,7}判斷,6與7為本題的輸入,因此判斷前面所提到的in代表input的意思,分別為6與7。 - 將
var與int變數所輸入的6與7兩個數值,按照out的順序輸出,即為答案67。
本題與上一題相同,只能在短短幾行的程式中推測出程式的意思,在一開始的時候,由於沒有注意到最上方{user types 6,7}使用者輸入這一行,而被交錯混雜的int與var所混淆,但在注意到之後,由於in所代表的input非常好辨認,所以一下就試出答案了;本題需要一些能突破框架的思維能力,只要不過度執著於題目中的文字,便能順著input找到本題的答案。
Notice: do not use sed -r. This only works for linux. Instead use sed -E.
Sam wants certain users to be able to run limited commands from a PHP page. He created a function called safeeval to run these commands. However on one page he neglected to use safeeval and instead used eval(). Safeeval will fail if a command given should not run. Sam then created a shell script to fix the error.
Sam's uname is: freeBSD 6.9
Here is the script:
<?php
include ('safe.inc.php');
if ($access=="allowed") {
eval($_GET['cmd']);
if (!empty($_GET['cmd2'])) {
eval($_GET['cmd2']);
}
}
?>
Here is his shell script (for freeBSD):
#!/bin/sh
rm OK
sed -E "s/eval/safeeval/" <exec.php >tmp && touch OK
if [ -f OK ]; then
rm exec.php && mv tmp exec.php
fi
Fix the incorrect line in the shell script (and use the SAME spacing).
Sam不小心在一個頁面中使用了eval()而不是safeeval(),因此寫了一個shell script來解決這個問題。 本題的要求為修復上方shell script的錯誤,由於解題的方式為shell script的修正,因此將對於本題shell script的語法進行說明以及除錯。
#!/bin/sh:首行的#!宣告這個script所使用的shell,後面接著/bin/sh即為shell的路徑。
rm OK:移除名為OK的檔案
sed -E "s/eval/safeeval/" <exec.php >tmp && touch OK
sed:為stream editor,有著對資料特定的字串進行新增、刪除、取代等等的功能。
-E:參數可連接多個sed script,若只有一個sed script則可省略。(經過測試,解答不需要此參數也能通過)
"s/eval/safeeval/":此指令中的s為substitute的縮寫,其功能為將他之後的第一個字串eval用下個字串safeeval代替,要被代替的字串可以用reguler expression來表示。
<exec.php:sed支援std input,此行將exec.php作為其stdin作為輸入。
>tmp:將sed編輯過後的檔案輸出到tmp的檔案中。
&&:在左邊指令的執行結果回傳為true後(即執行成功),才會執行右邊的指令。
touch OK:touch的功能可以建立檔案以及修改檔案、目錄等的時間戳記,在此沒有參數的用法中,若檔案不存在,便會建立一個空白的新檔案。
本行指令的目的為,當sed更改檔案成功之後,便建立一個名為OK的檔案。
if [ -f OK ]; then
rm exec.php && mv tmp exec.php
fi
由於前面的指令,OK只會在sed完成修改後生成,在這裡使用[ -f OK ]來檢查OK是否存在,若存在便將原本的exec.php用更改後的tmp取代,mv tmp exec.php則是用來將tmp的檔名改為exec.php。
本題shell script的核心為sed的取代功能,而在本題中,"s/eval/safeeval/"缺少了一個flag,若執行本指令,sed只會取代所搜尋到的第一個字串,因此需要在其後方加上g,即"s/eval/safeeval/g"。
因此此題解答為sed -E "s/eval/safeeval/g" <exec.php >tmp && touch OK。
本題有著對於shell script以及sed語法認識的需求,而在查詢本題的種種語法後,認識並瞭解了許多新的語法,以及其豐富的組合用法,使我獲益良多。
This site is run by a new sysadmin who does not know much about web configuration The script is located at http://moo.com/moo.php Attempt to make the script think you are authed by entering the correct URI. Here is the script (me.php):
<?php
$user = $_GET['user'];
$pass = $_GET['pass'];
if (isAuthed($user,$pass))
{
$passed=TRUE;
}
if ($passed==TRUE)
{
echo 'you win';
}
?>
<form action="me.php" method="get">
<input type="text" name="user" />
<input type="password" name="pass" />
</form>
<?php
function isAuthed($a,$b)
{
return FALSE;
}
?>
- 首先看到題目上說的,題目是說要我們修改程式碼,讓這個 script 只有 author 才能進入正確的 URI
- 再看到程式碼中有
isAuthed的if條件,然後又是這個php中,所以我就去嘗試將網址的後面再加上條件,答案即為
http://moo.com/moo.php?passed==TRUE
php 中常見傳送資料的方法:使用 POST 跟 GET 的方法來傳遞資料
- POST方法
- 傳送的值藉由 POST 請求 HTTP 發送,將資料放在訊息主體內進行傳送
- 請求並不會被 cache 紀錄
- 對資料長度沒有限制
- 比 GET 更安全,較適合用來傳送隱密性高資料
- POST 傳值是運用 PHP
$POST['xxx']的變數接收
- GET方法
- 傳送的值藉由 GET 請求 URL 發送,將資料放在 header 內進行傳送 (網址看的到)
- 請求會被 cache 紀錄
- 依瀏覽器規定資料受到 QueryString 長度限制
- 安全性較低,較適合用來檢視資料
- GET 傳值是運用 PHP
$_GET['xxx']的變數接收
題目描述
- 前情概要:Kirk 隊長編寫 Perl 腳本給其他人使用
- 腳本功能:自動執行日誌紀錄,讓其他人能key進去並存檔
- 腳本問題:日誌只能記錄一個,會自動刪除過往所有日誌
- 修復要求:使日誌可以全部保存(修改程式碼)
- 按下F12看code發現有好幾個超連結(hp.php / print.html / open.html)
看到超連結當然就是點下去啦 - 進去超連結找尋有用資訊
- hp.php 看起來沒什麼幫助
- print.html 看起來語法也都對,先看下一個
- open.html 有找到相關資訊
- 在open.html中找到與題目相關的內容 觀察到題目上第二行 open 的 code
open(STARTREKLOG, '>/var/log/startrek');其中的 > 與網頁中的一段敘述有相關,仔細閱讀後發現 open 有不同模式
>orNULLmode:read 模式(讀取文件)<mode:write模式(截斷清空文件再創建新的文件)>>mode:write模式(打開文件並 append 在後面)
由以上可推測出,由於Kerk隊長使用錯誤的open模式,才導致文件一直只能保存最後一筆的紀錄,所以我將open的模式從 > 改成 >> 得到答案是
open(STARTREKLOG, '>>/var/log/startrek');第一次接觸 perl ,也算蠻幸運有觀察到有用訊息,一開始題目就回答正確,也學習到 perl open()這個函式含有許多不同的模式,不僅上述說的幾點,還有像是前方加上加號的 +> 模式等等,學習到不少東西。
So Bill Gates was tired of VisualBasic and now did some Perl, too bad; this script has a security flaw that allows everyone access to the company records! Fix the flaw for him!
比爾蓋茨厭倦了VB,他現在想做些perl,但不幸運的是,這個腳本有點缺陷,就是會允許所有人進入這個系統!請幫忙修好它!
#!/usr/bin/perl
chomp(my $User = `/usr/bin/whoami`);
print "Checking your access level...\n";
if ($User == 'BillGates')
{
print "Authorized! Here are the company records:\n" . `cat /home/BillGates/CompanyRecords.db`;
die("Closing...\n");
}
die("You're not authorized!\n");
- 首先根據題目文字的意思,這段code應該是某個地方有一點瑕疵,並且正式因為這個瑕疵會讓所有人都可以得到系統權限,接著仔細看下代碼,發現有一個if語句會根據條件成立與否進行不同的操作。
- 接著分析下代碼:首先第一行是說獲得系統中的主機名稱,然後賦值給
$User這個變量,第二行是說打印"檢查你的存取級別"這句話,第三行進入if語句判斷:如果$User == 'BillGates',那麼你將登陸成功,獲得存取權限,否則會打印"你沒有權限"這句話。 - 因為題目是說所有人都會得到權限所以我猜應該問題出在
$User == 'BillGates'這句話上面,即這個式子一定是true,下面的登錄成功語句一定會顯示。 - 接著我分析思考下
$User == 'BillGates'這句話為什麼一定會是true,我聯想到python中的is語句和==是不一樣的,在python中,is用來判斷是不是同一個內存對象,而==用來判斷2個對象之間的值是否相同。基於這個啟發,我想到可能是$User == 'BillGates'中=是不是不對,因為通常==都是用來判斷數值大小的嘛,使用==的話可能會造成兩邊都演變成一樣的數值? - 然後我查了下資料,發現perl中字符串比較的話,是使用
eq語句而不是說使用==來比較,而題目中這個明顯是不對的,要用eq來替換。 - 但是我思考了下,即使使用
==來比較字符串,為什麼一定會是true呢?哪怕兩邊根本不一樣啊。我查了相關文獻,了解到在perl中,如果用==來比較字符串,則字符串兩邊都會轉化為數值0,所以不管兩邊字符串是什麼,最終結果都會是true。
更改$User == 'BillGates'這段代碼,把==改成eq,在輸入框中輸入完整的$User eq 'BillGates'這句代碼,然後回車就會顯示成功。
因為搜索資料時發現很多語言都會出現 字符串比較 和 常規數值比較 的不同方法,所以查閱相關知識做了一個小的總結:
Java中:
==比較的是變量之間的內存地址
equals比較的是兩變量的內容
所以通常都用equals比較字符串內容,數字一般用==來比較
C#中:
==操作比較的是兩個變量的值是否相等,對於引用型變量表示的是兩個變量在堆中存儲的地址是否相同,即棧中的內容是否相同
equals操作表示的兩個變量是否是對同壹個對象的引用,即堆中的內容是否相同。
Python中
is的作用是用來檢查對象的標示符是一致,也就是比較兩個對象在內存中的地址是否一樣
==用來檢查兩個對象是否相等
C++中
==是判斷引用是否相同
equals()指的是值是否相同。
小小的語法錯誤可能會導致整個系統的安全性變得完全不可靠,所以在學習一門語言的時候需要學的比較細,比較扎實猜可以。
You have to give input to a C program which gives you the length of the string. How would you crash it? here is the function: 您必須將輸入提供給C程序,該程序可以提供字符串的長度。您將如何讓它崩潰?
void blah(char *str)
{
char lol[200];
strcpy(lol, str);
}
- 首先這個題目要求我們輸入一個字符串,然後讓它崩潰,而題目又特別提到字符串長度的問題。
- 接著我看了下程式:這是壹個C的標準程式函式,返回viod類型,接受壹個字符串str,然後設定壹個list lol[200],然後copy這個str到lol中
- 接著我先嘗試看下有沒有語法錯誤。仔細找了找發現沒有返回物件,所以加了壹句
return lol;,但是驗證並不成功。 - 接著我仔細看下,覺得長度問題是這個題目特別強調的,看了下程式碼,認為
char lol[200];這一句限定了長度必須200個位元,那如果str超過200長度,是否就會崩潰呢,再者,題目就是要求崩潰,所以我嘗試輸入壹個長度210的string嘗試下(1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111),輸入後發現顯示go on成功。
輸入一個長度200+的字符串就好了,然後回車就會顯示成功。
設計程式的時候需要考慮異常情況,否則壹旦輸入不合理就不能正常運營,而且我有感受到很多問題都是小小的程式設計不嚴謹導致的。
