最近開始玩某個遊戲的私服,世界各國代理商全倒光之後就有一群人在臺港澳中開了私服,甚至就直接用那個遊戲的名字直接營運.... XD
遊戲主程式有加殼,因為有改過所以沒辦法直接從 section name 或是 exeinfoPE 看出來,後來是 ProtectionId 說他是 VMProtect 2.06(我沒辦法驗證這件事情,基本上他沒開任何 VMProtect 的保護功能)
一開始不知道怎麼脫,x64dbg 配 Win10 的環境也不太好作業,所以就在遊戲跑起來的狀況下 dump memory 然後修 IAT,結果 Win10 因為相容性問題,所以引入了 AcLayers.dll / apphelp.dll ,並且在 PE loader 內去 hook EAT,結果就會讓 Scylla 壞掉
脫殼請在該應用程式支援的最低作業系統版本下進行 XD
總之我就先把這樣的 binary 丟進 IDA 看呀看,後來看到一個 function 在 parse commandline(而且 直接把 GetCommandLineA 為給 sscanf,會 overflow呢 XDDDDD),結果就不小心找到 OEP 了
(VC 編譯出來的 OEP 會是一個 call 緊接著一個 opcode = 0xe9 的 jmp,jmp 的目標裡面會有 GetCommandLineA,接著再往下就會呼叫 WinMain)
後來開了 Windows XP VM,OllyDbg + StrongOD,但是 hardware breakpoint 一直被吃掉,大概是 anti-debug 的功能吧,後來用 PhantOm 也沒辦法處理,後來看到其他 VMP 脫殼都說先 break 在 VirtualProtect (沒辦法,packer 注定要用的 API XDDD),按個幾次 F9 直到看到 protection attribute 是 PAGE_READONLY 為止,現在你的 binary 應該就 decrypt / decompress 完成了,接著去 break OEP,再 F9 就可以 dump 了
接著做出來的 binary 沒辦法執行,會跳 Runtime Error: R6002,查了一下之後在看雪找到解答,Microsoft 的 runtime library 會看某個 section 的 protection attribute,如果可寫就跳過 floating point 相關的 initialization,所以要手動 patch 讓他別跳過(或是也可以設定好正確的 PE section)
最後詳情就請見看雪論壇,照著做patch 完就可以動了!
結論:VMProtection 保護都不開的話基本上脫殼難度只比 asprotect 難一點 XDDDD
看了其他人的分析,在開啟 IAT protection 的狀況下真的很麻煩,不過感覺用 binary instrumentation 的技術去處理 IAT reconstruction 應該蠻有幫助的 XD
SSH Tunnel 有三種工作模式,使用 ssh tunnnel 的好處有:
- 在可能被監聽的網路環境保護未加密連線的安全
- 翻牆
- 一定程度上取代 VPN,是一個比較 light-weight 的解決方案
先定義兩個名詞:
- local: ssh client
- remote: ssh server
在 local listen port A,透過 remote forward 到 host B 的 port C
ssh user@host -L [local_bind_address:]local_port_A:host_B:remote_port_C
example:
ssh user@host -L 8080:10.7.99.8:80
-- 在 local 聽 8080 port,透過 remote 再連到 10.7.99.8:80
在 remote listen port A,透過 local forward 到 host B 的 port C
ssh user@host -R [remote_bind_address:]local_port_A:host_B:remote_port_C
example:
ssh user@host -R 2223:140.112.172.1:23
-- 在 remote 聽 2223 port,透過 local 再連到 telnet protocol 的 ptt
在 local listen port P,建立 socks proxy server
ssh user@host -D [local_bind_address:]local_port_P
example:
ssh user@host -D 7788
-- 在 local 聽 7788 port,會是一個 socks proxy service,連線會透過 remote 再連到目標
真的很賭爛因為別人的 code 有 bug 讓自己花了超久的時間 debug
最近在寫一個 CTF 訓練平台,架構上採用 peewee + bottle.py 進行開發,因為不想花太多時間去學 Flask 和 Django 這種太龐大的架構(加上有些用法自己不見得喜歡),所以打算自幹整個架構
遇到了一個問題是我需要自訂 view 的路徑,翻了一下 code 之後發現我有 template_lookup
這個 keyword argument 可以用,但是不管怎麼嘗試,就是沒辦法讓 bottle.py 去我指定的 path 找 template file,不知道是不是我對 decorator 有誤解,改了老半天,後來又 trace 了一下 bottle.py 的 code,才發現根本不是我的問題.....
TL;DR
def template(*args, **kwargs):
"""
Get a rendered template as a string iterator.
You can use a name, a filename or a template string as first parameter.
Template rendering arguments can be passed as dictionaries
or directly (as keyword arguments).
"""
tpl = args[0] if args else None
# should mixin args into kwargs here
adapter = kwargs.pop('template_adapter', SimpleTemplate)
lookup = kwargs.pop('template_lookup', TEMPLATE_PATH) # <-- template_lookup reads from here
tplid = (id(lookup), tpl)
if tplid not in TEMPLATES or DEBUG:
settings = kwargs.pop('template_settings', {})
if isinstance(tpl, adapter):
TEMPLATES[tplid] = tpl
if settings: TEMPLATES[tplid].prepare(**settings)
elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)
else:
TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
if not TEMPLATES[tplid]:
abort(500, 'Template (%s) not found' % tpl)
for dictarg in args[1:]:
kwargs.update(dictarg) # <-- my template_lookup appears here
return TEMPLATES[tplid].render(kwargs)
mako_template = functools.partial(template, template_adapter=MakoTemplate)
cheetah_template = functools.partial(template,
template_adapter=CheetahTemplate)
jinja2_template = functools.partial(template, template_adapter=Jinja2Template)
def view(tpl_name, **defaults):
""" Decorator: renders a template for a handler.
The handler can control its behavior like that:
- return a dict of template vars to fill out the template
- return something other than a dict and the view decorator will not
process the template, but return the handler result as is.
This includes returning a HTTPResponse(dict) to get,
for instance, JSON with autojson or other castfilters.
"""
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
if isinstance(result, (dict, DictMixin)):
tplvars = defaults.copy()
tplvars.update(result)
return template(tpl_name, **tplvars)
elif result is None:
return template(tpl_name, defaults) # <-- if goes here
return result
return wrapper
return decorator
一般人聽到 CTF 可能會有的反應大概就幾種:「那是什麼?」、「駭客的遊戲?聽起來好可怕」、「蛤?」,加上一個人打 CTF 太孤單,所以來寫這篇文章,向大家介紹 CTF!
所以 CTF 到底是殺小?
Capture The Flag,駭客的搶旗遊戲,Flag
通常就是一串文字,或是要達成指定的目標。
至於這個 Flag
要怎麼拿呢?基本上主辦方會架設一些有漏洞的服務系統,或者是含有漏洞的程式,又或者是把資訊隱藏在檔案裡面,挑戰者要想辦法用駭客攻擊的手法入侵系統,或者想辦法找出或解密藏在檔案或程式內隱藏的 Flag
CTF 的賽制
基本上可以分成四種:
- Jeopardy
- Attack & Defense
- King of Hill
- (CGC)[http://www.cybergrandchallenge.com/]
Jeopardy
Jeopardy 會有多道題目可以解,題目常見類型如下:
misc
綜合題,什麼都有可能,雜七雜八無法分類通常就會算成這個
pwn
目標通常會是一個服務,有漏洞可以打下來,(大多時候)會給你那個 service 的 binary
bin (revsersing)
就是需要逆向工程,不限於執行檔,也遇過各種奇怪的檔案格式
web
就是 Web 啊,不解釋(?)
題型不出幾種:SQL Injection / Command Injection / Cookie / Race Condition,但是思考要很猥瑣才有辦法解題
crypto
密碼學啊不解釋(?)
- RSA 是常考題,在 MMA CTC 2015 看到了 ECC....
- AES 也常常出現
- 各種奇怪的弱 cipher
- 頻率分析
- xor
stego
猜謎!猜謎!猜謎!
有些低品質的 CTF 根本就是在玩猜謎,所有題目有一大半都是 stego 也是有可能的
每一道題目解開都可以拿到一組 Flag
,輸入記分板之後可以換分數!
以上就是關於 Jeopardy 的介紹
Attack & Defense
每一組參賽者要維護一台主機,主機上面會跑多個服務,這些服務是由主辦方設計的,每個都含有漏洞,並且在主機上會放置有Flag
,這組Flag
會在每個回合由主辦發更新一次。
比賽方式
- 入侵其他參賽者維護的主機,偷取
Flag
- 修補自己主機上的漏洞,防止其他參賽者偷取你的
Flag
- 把對手的
Flag
遞交到主辦單位的記分板就可以獲得額外分數 - 如果成功守護自己的
Flag
也會有分數 - 如果自己的
Flag
被偷走則拿不到分數
這樣的比賽模式相較 Jeopardy ,更為接近真實的攻防環境
King of the Hill
跟 Attack & Defense 有點類似,不過每個隊伍一開始不會擁有主機,而要把主辦方提供的主機打下來然後寫入自己的Flag
(例如:改首頁),參賽者要守護已經打下來的主機,不被其他隊伍搶走,每個回合依照擁有主機的數量進行加分。
比起 Attack & Defense ,這是企業每天都真實上演,每天都要面對的狀況,更能模擬和考驗駭客在戰場上的實力
CGC
前陣子由美國國防部下屬單位(DARPA)主辦的 CTF 競賽,可以算是 Attack & Defense 的一種,但是多了一條規定,不可以由人類進行攻擊或修補漏洞,攻擊和修補必須寫程式來自動進行,人腦處理資訊的速度有限,但是電腦很快,把事情交給電腦作會是未來的發展方向
所以我說那個 CTF 戰隊呢?
台灣有不少實力堅強的戰隊、組織在打 CTF ,像是 台大217Lab、HackStuff、BambooFox ...等,都有好手齊聚一堂一起比賽,以前偶爾會跟 HackStuff 一起打比賽,後來比較少聯絡,這些隊伍都很厲害也很頂尖,但是也就只有這幾個隊伍上的了檯面,加上台科和TDoH的戰力都不太夠,而且強大的隊伍都已經夠強大了,加上一個人打CTF實在太無力,又難以拿下名次,所以打算成立一個CTF戰隊來培養實力,尋找戰友!
_____ ___ ____ __ __ ____ _____ _____ _____ _____ _ __ __
| ___/ _ \| _ \ \ \/ / / ___|_ _| ___| |_ _| ____| / \ | \/ |
| |_ | | | | |_) | \ / | | | | | |_ | | | _| / _ \ | |\/| |
| _|| |_| | _ < / \ | |___ | | | _| | | | |___ / ___ \| | | |
|_| \___/|_| \_\/_/\_\ \____| |_| |_| |_| |_____/_/ \_\_| |_|
___ _ ___ __ __
/ __|___ _ __ / |_ _ __ _ | __|/ \ / \ _ _
| (__/ _ \ ' \| | ' \/ _` | |__ \ () | () | ' \ _ _ _ _
\___\___/_|_|_|_|_||_\__, | |___/\__/ \__/|_||_(_|_|_|_)
|___/
Use built-in http
module and ecstatic
for middleware.
First, install ecstatic
npm install ecstatic
And the magic!
var http = require('http'),
ecstatic = require('ecstatic');
http.createServer(ecstatic({root:'./'}))
.listen(8080, '127.0.0.1');
某網站小遊戲加密弱點分析
故事是這樣的,某(N)大(T)學(U)的某系之夜弄了一個網站,上面有幾個 JS + canvas 寫的小遊戲,看到小遊戲我怎麼能夠放過不玩(弄)呢?
先來看看原始 Code
function Encode_orig(t, n) {
var i = 'abcdefghijklmnopqrstuvwxyz0123456789{:}"!@.$%,&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ?',
o = {},
e = i.length;
n %= e, 0 == n && (n = 2);
for (var r = 0; e > r; r++) o[i[r]] = r;
for (var s = t.split("").map(function(t) {
return o[t]
}), r = 0; r < s.length; r++) s[r] = s[r] * n % e;
return s.map(function(t) {
return i[t]
}).join("")
}
存在問題
- map 上的第一個 char 不會被換置
- 完全對稱加密
- key == 1 時,等於原文
- key 空間太小(key %= char_map.length),使得 bruteforce 可能
function Encode(str, key) {
// the map
var char_map = 'abcdefghijklmnopqrstuvwxyz0123456789{:}"!@.$%,&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ?';
key %= char_map.length;
if (key == 0) {
key = 2;
}
return str.split("").map(function(e) {
return char_map.indexOf(e);
}).map(function (e) {
return e * key % char_map.length;
}).map(function(e) {
return char_map[e]
}).join("");
}
function Decode(str, key) {
var char_map = 'abcdefghijklmnopqrstuvwxyz0123456789{:}"!@.$%,&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ?';
var rev_map = Encode(char_map, key);
return str.split("").map(function(e) {
return char_map[rev_map.indexOf(e)];
}).join("");
}
function Bruteforce(str, filter) {
var r = [];
for (var i = 2; i < 80; i++) {
var c = Decode(str, i);
if (!filter || filter(c)) r.push([i, c]);
}
return r;
}
var r = Bruteforce('0pq}SpXpd1YnbYnb9Sbn}t$}Kp,', function (e) {
// JSON data must starts with '{' or '['
return e[0] == '{' || e[0] == '[';
});
console.log('Bruteforce result:\n' + r.join('\n') + '\n');
var key = 12345;
var enc = Encode('abcdefghijklmnopqrstuvwxyz0123456789{:}"!@.$%,&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ?', key);
var dec = Decode(enc, key);
console.log("Key: " + key);
console.log("Encoded: " + enc);
console.log("Decoded: " + dec);
function validate() {
var test_str = [ 'abcdefg', 'asjdfjaklsdf', 'jqjriowjoiasjdf', 'abcdefghijklmnopqrstuvwxyz0123456789{:}"!@.$%,&*()_+ABCDEFGHIJKLMNOPQRSTUVWXYZ?', 'owoasdf123______________' ];
var test_key = [ 1234567, 223457, 123456789, 12343412, 333333334, 2345, 2, 0 ];
var result = true;
test_str.map(function (qq) {
test_key.map(function (pp) {
result = result && ( Encode(qq, pp) === Encode_orig(qq, pp) );
});
});
return result;
}
console.log();
console.log('Testing my implement...');
console.log(validate() ? "Test pass" : "Test failed");
改進建議
- 使用現有 cryptology library
- 加強混淆強度
這幾個小遊戲真的不太好玩
SQL Injection 是怎麼發生的?
這篇文章原本是要寫給學校的老師看的,覺得可以拿來資安科普所以就貼到 Blog 吧!
首先,考慮以下 PHP 程式碼
<?php
function login($user, $pass) {
$sql = "SELECT * FROM `users` WHERE `name` = '$user' AND `password` = SHA1('$pass')";
$user = query($sql);
if (count($user) > 0)
return $user[0];
else
return false;
}
$user = login($_POST['user'], $_POST['pass']);
if ($user !== false)
echo "登入成功:" . $user['name'];
else
echo "登入失敗!";
使用者輸入資料:
user=%27%20or%20%27%27%20%3D%20%27%27%20--&pass=aaaaaaa
解碼後(--
和 #
是 SQL 註解)
user
-> ' or '' = '' --
, pass
-> aaaaaaa
進入 PHP 組合成 SQL 語句
SELECT * FROM `users` WHERE `name` = '$user' AND `password` = SHA1('$pass')
帶入資料後
SELECT * FROM `users` WHERE `name` = '' or '' = '' --' AND `password` = SHA1('aaaaaaa')
由於 ' or '' = '' --
造成一個永遠成立 (某些條件 or True
),就可以繞過驗證登入
另外一些技巧,如:
SELECT * FROM `topics` WHERE `id` = '$id'
帶入
$id
= -1' UNION SELECT * FROM users --
組合後
SELECT * FROM `topics` WHERE `id` = '-1' UNION SELECT * FROM users --'
會造成 id = -1
不存在,select不出任何東西,但是 union select 會撈出別的資料
除此之外,就算是 checkbox
, select
, radio
都有可能修改其 value,所以只要是從 user 出來的資料,一律要經過過濾
推薦閱讀文章:如何正確的取得使用者 IP? (Devcore) (使用者 IP、User-Agent 可以竄改)
身為一個網管,平常的好(ㄜˋ)習(ㄑㄩˋ)慣(ㄨㄟˋ)之一就是看Log
定期看看你的 server 最近又被誰踹了、有哪些攻擊的痕跡、有誰跟你 Say Hello (?
HTTP Access Log
User-Agent
$ log-cat.py "{8}" school-access.log | sort | uniq -c | sort -nr | head -n 16
56428 -
2716 Mozilla/5.0 (X11; U; Linux i686; pt-BR; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15
2569 Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36
2206 Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36
2175 Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:37.0) Gecko/20100101 Firefox/37.0
1444 Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.7) Gecko/2009021910 Firefox/3.0.7
1031 Apache/2.4.7 (Ubuntu) PHP/5.5.9-1ubuntu4.5 (internal dummy connection)
895 Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
698 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:34.0) Gecko/20100101 Firefox/34.0
590 Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)
584 Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
508 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
491 Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0
451 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
431 Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
407 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.91 Safari/537.36
Garena 被駭事件玩家事後處理建議
發生了什麼事?
Garena 遊戲公司遭到惡意入侵,旗下兩款遊戲「Path of Exile 流亡黯道」以及「League of Legends 英雄聯盟」安裝程式被植入惡意程式(PlugX)
是誰幹的?
據目前了解,一個被命名為 Winnti Group
的組織所為,他們在過去曾經攻擊上百個遊戲公司,竊取遊戲原始碼、在遊戲檔案植入惡意程式、竊取使用者密碼等行為
我是不是受害者?
過去四個月內(2014年九月 ~ 2014年十二月)曾經下載並安裝「Path of Exile 流亡黯道」以及「League of Legends 英雄聯盟」者,您很有可能是受害者。
此外,您可以檢查電腦是否存在以下兩個檔案,若有出現,您極為有可能是受害者:
C:\Windows\System32\NtUserEX.dll
C:\Windows\System32\NtUserEX.dat
我該怎麼辦?
- 使用趨勢科技推出的解毒程式進行處理
- 立刻安裝防毒軟體進行全面掃描
- 若您的密碼曾經與 Garena 遊戲公司註冊帳號重複使用者,請立即更改密碼(特別注意 E-mail 與 Facebook 帳號的安全)
附錄
哪裡有好用的免費防毒軟體?
HITCON Freetalk -- OperationGG
結語
請各位遊戲玩家保持警覺,如果防毒軟體說遊戲有毒也請謹慎處理,可將疑似出問題的檔案上傳至 VirusTotal 掃描評估,重要的服務、網站系統請使用不同的密碼(E-mail、Facebook),並且請保持您的電腦所有軟體都有隨時更新,停止使用終止支援的作業系統(例如:Windows XP)、軟體,以保護自身設備的安全。
以上是小弟在HITCON Freetalk現場寫的廢文,最後祝各位玩家遊戲愉快!
WebGoat installing instruction
you can run this tutorial under any debian family distro but not other platform
sudo apt-get install tomcat7 tomcat7-admin
sudoedit /etc/tomcat7/tomcat-users.xml
- edit
tomcat-users.xml
like below sudo service tomcat7 force-reload
- open
http://your-server.net:8080/manager/html
and upload your war file - open
http://your-server.net:8080/WebGoat-X.X
and enjoy your hack. (admin interface will show the path)
tomcat-users.xml configure example
tomcat-users.xml should looks like below
<?xml version='1.0' encoding='utf-8'?>
<!--
...
-->
<tomcat-users>
<!--
...
-->
<role rolename="manager-gui"/>
<user username="admin" password="admin" roles="tomcat,admin-gui,manager-gui,webgoat_user,webgoat_admin"/>
<user username="guest" password="guest" roles="tomcat,webgoat_user,guest"/>
</tomcat-users>
最近發現有 ht editor ,於是想下載編譯來用
無奈奮鬥了半小時還是搞不定,差點就放棄直接載 sourceforge 上的 binary 來用,所幸最後還是搞定了
# if you are not use debian family, install dependency on your own
sudo apt-get install autoconf automake libncurses-dev texinfo byacc flex
git clone --depth 1 https://github.com/sebastianbiallas/ht.git
cd ht
./autogen.sh
./configure
make
make htdoc.h
make
sudo make install
今天被問了奇怪的問題,覺得有價值筆記下來,VBA不解釋
Sub Main()
If MsgBox("Hi, Split sheets to files?", vbYesNo) = vbNo Then Exit Sub
Dim xPath As String
xPath = Application.ActiveWorkbook.Path
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each xWs In ThisWorkbook.Sheets
xWs.Copy
Application.ActiveWorkbook.SaveAs Filename:=xPath & "\" & xWs.Name & ".xls"
Application.ActiveWorkbook.Close False
Next
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "Done! Files are in..." & vbNewLine & Application.ActiveWorkbook.Path
End Sub
有在用VIM的人應該會覺得ESC好遠好難按,Caps Lock根本用不到
或是emacs的使用者應該會覺得Ctrl的位置很不方便
這時候我們就可以把Caps Lock改成ESC或是Ctrl
對於X Window環境我們可以直接用 xmodmap
來解決,至於Mac OS X則要透過Seil這個軟體來解決
X Window
xmodmap -e "keycode 66 = Escape NoSymbol Escape"
Mac OS X
int __cdecl main() // decompiled with IDA
{
char *char_ptr; // edi@2
int val_1; // eax@3
int val_tmp_1; // edx@3
char val_tmp_2; // zf@4
int length; // edi@8
unsigned int counter_1; // eax@9
unsigned __int8 v6; // dl@9
signed int counter_2; // eax@14
unsigned __int8 table_2[8]; // [sp+18h] [bp-824h]@1
unsigned int __table_2_2; // [sp+1Ch] [bp-820h]@1
unsigned __int8 table_1[24]; // [sp+20h] [bp-81Ch]@1
unsigned int __table_1_2; // [sp+24h] [bp-818h]@1
unsigned int __table_2_3; // [sp+28h] [bp-814h]@1
unsigned int __table_2_4; // [sp+2Ch] [bp-810h]@1
char process_buffer[1024]; // [sp+30h] [bp-80Ch]@11
char input_buffer[1036]; // [sp+430h] [bp-40Ch]@2
sub_401C30();
/*
unsigned char map_1[] = {
0x10, 0x7D, 0x33, 0xCE, 0x30, 0xF7, 0x88, 0x3C,
0x23, 0x02, 0x73, 0xC2, 0x3D, 0xDF, 0xF2, 0x5E
};
unsigned char map_2[] = { 0x65, 0x13, 0x00, 0xB8, 0x03, 0xC5, 0xE6, 0x0C };
*/
*(_DWORD *)table_1 = 0xCE337D10u;
__table_1_2 = 0x3C88F730u;
__table_2_3 = 0xC2730223u;
__table_2_4 = 0x5EF2DF3Du;
*(_DWORD *)table_2 = 0xB8001365u;
__table_2_2 = 0xCE6C503u;
while ( 1 )
{
char_ptr = input_buffer;
printf("Enter key to unlock: ");
fgets(input_buffer, 1024, (FILE *)iob /* stdin */);
do {
val_tmp_1 = *(_DWORD *)char_ptr;
char_ptr += 4;
// 這個地方有點特別可以算算看
// unsigned char b = 0x00;
// ~b & (b - 0x01) & 0x80 == 0x80
// 等價於 b ? 0x00 : 0x80
// 推廣到int32_t
val_1 = ~val_tmp_1 & (val_tmp_1 - 0x1010101) & 0x80808080;
} while ( !val_1 );
// 判斷low-part有沒有東西
val_tmp_2 = (unsigned __int16)(val_1 & 0x8080) == 0;
if ( !(val_1 & 0x8080) ) // 如果low-part有東西的話,把hi-part拉到low-part,讓後面繼續判斷
val_1 = (unsigned int)val_1 >> 16;
if ( val_tmp_2 ) // 如果low-part有東西的話 +2
char_ptr += 2;
// 最後其實就是strlen
length = &char_ptr[-((_BYTE)val_1 >= (unsigned __int8)-(_BYTE)val_1) - 3] - input_buffer - 1;
// 基本上這是個無意義操作
input_buffer[length] = 0;
if ( length > 0 )
{
v6 = 0x10; // 注意囉,first byte的xor key是 0x10
// 底下看起來很可怕,而且一次 shift 59 bits有點奇怪,背後的 opcode 是:
// 00403832 sar ecx, 31
// 00403835 shr ecx, 28
// 這裡先說明一下 sar 這個指令, SAR (Shift Arithmetic Right)
// 基本上他做的事情是shift right (shr),但是他會用MSB做填充,即正負不變
// 用於 signed 操作,至於 shr 則是 shitft right ,空位用 0 填充
// sar reg, 31 是有特殊意義的,他會用MSB填滿整個register,
// i.e.: reg = (reg < 0) ? -1 : 0;
// 接下來的 shr ecx, 28 ,串起來就會變成 reg = (reg < 0) ? 0b01111 : 0;
// 這時候 & 0x0F 就變成沒有意義的操作了
// 所以可以化簡成 ((counter_1 + (counter_1 >> 59))) - (counter_1 >> 59)
// counter_1 + (counter_1 >> 59) - (counter_1 >> 59)
// 最後就變成 v6 = table_1[counter_1]
for ( counter_1 = 0; ; v6 = table_1[((counter_1 + (counter_1 >> 59)) & 0xF) - (counter_1 >> 59)] )
{
process_buffer[counter_1] = input_buffer[counter_1] ^ v6;
++counter_1;
if ( length == counter_1 )
break;
}
// first byte 是分開處理的
// first byte = 'e' ^ 0x10 = 'u'
// 另外由此可知,key length 是 8
if ( length == 8 && process_buffer[0] == 'e' )
break; // 這個 break 會出 最外層的 while ( 1 ),就會跳過LABEL_18
}
LABEL_18:
puts("Key error, please retry :)");
}
counter_2 = 0;
while ( 1 )
{
++counter_2; // minium counter_2 is 1
if ( counter_2 > 7 ) // counter_2 -> [1, 7]
break;
// counter_2 永遠小於等於 7 ,所以 & 7 也是無意義操作
// 所以可以知道 input 會先跟 table_1 做 xor 在跟 table_2 比對
// key[1] ~ key[7] 就是 table_1[i] ^ table_2[i] , i -> [1, 7]
if ( process_buffer[counter_2] != table_2[counter_2 & 7] )
goto LABEL_18;
}
puts("Successfully unlock!");
system("pause");
return 0;
}
Key is un3v32n0
Reference: Intel Pentium Instruction Set Reference (Basic Architecture Overview)
#!/bin/bash
if [ $UID -ne 0 ]; then
sudo $0 $*
exit
fi
# Clear default rules
iptables -F
iptables -X
iptables -Z
# Default policy for INPUT
iptables -P INPUT DROP
# Accept for loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow ssh, http
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 8000 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
# Do not drop packet from established connection
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# List
iptables -L -n -v
sudo cp iptables-setup.sh /etc/init.d/
sudo chown root:root /etc/init.d/iptables-setup.sh
sudo chmod 755 /etc/init.d/iptables-setup.sh
# Use your own runlevel, runlevel = 2 for Debian family distro
sudo ln -s /etc/init.d/iptables-setup.sh /etc/rc2.d/S90iptables-setup