Linux kernel function / system call hijacking

想要 hijack 某個 Linux kernel 的 function ,所以開始了這次的搜尋。

Linux kernel 各部分之間的 function 呼叫有2種,一種是直接把要呼叫的 function header file include 進來,如果是在同一個檔案當然也不需要 include。另一種是呼叫 exported function ,允許外部呼叫的 function 在定義之後會加上 EXPORT_SYMBOL(function_name) ,這個 function 的記憶體位址就可以從 kernel symbol table 找到(symbol table 裏面不只有 function ,也有變數)。外部呼叫是指 kernel 的其他部分還有 kernel module ,外部呼叫時會去 symbol table 找位址再進行呼叫(應該吧)。

所以只要修改 symbol table 的內容,就可以 hijack 特定的 function,讓他去找我們自己定義的位址的 function 去呼叫了。不對

但是一般 kernel symbol table 是唯讀的,看一下 /proc/kallsyms 的內容,第一欄是記憶體位址,第二欄是屬性(是否可讀寫等等,標籤代表的意義請 man nm),第三欄是變數或函式名稱。

system call table 裏面存了所有 system call 的記憶體位址,它的 symbol 叫做 sys_call_table ,在大部分的 Linux 上面應該是 R (唯讀)需要先解除 page write protection 才能修改。(其他參考)HTC Android kernel 的 sys_call_table 標籤居然是 T ,意思好像是可讀寫?

syscall table 裏面存了所有 syscall 的進入點(記憶體位址),用 sys_call_table[CONSTANT] 的方式可以找到特定 syscall 的進入點,像是如果要找 fork() 的進入點,就這樣寫:sys_call_table[__NR_fork]__NR_fork 這些 constant 定義於 unistd.h ,依處理器架構會有不同。上面連結的那兩篇有如何 hijack syscall 的教學。

後來發現我要的不是 syscall hijacking ,而是 kernel function hijacking ,我搞混了這兩個。syscall 是 userspace 程式和 kernel 溝通的界面,一般來說都是由應用程式呼叫;kernel function 是 kernel 內部的函式,提供給其他 kernelspace (可能在 kernel 或是 kernel module )的函式調用,又有是否 export 之分,有 export 的 function 在宣告後會加上 EXPORT_SYMBOL(function_name) ,它的位址就在 symbol table 找得到。

要 hijack kernel function 似乎要牽涉到一些 shellcode… 而且是 platform-specific ,還有待研究。(順帶一看

搜尋的過程當中找到這幾個問答:

發現若不是要 hijack 的話,基本的 debug 可以透過 kprobe

 

產生 SSH key 給 Bitbucket/Github 使用

首先當然是弄個帳號:https://bitbucket.org

它讓我很感動的就是竟然有 OpenID 登入!

跟 Github 類似,他也可以直接用 SSH key 來認證,也可以用 HTTPS,不過我猜用 HTTPS 大概每次都要輸密碼吧,不像 ssh-add 一下就可以解鎖整個 session 。

原理簡單來說就是你有私鑰在本機,然後把公鑰放在你想要登入的機器上面(通常是放在那臺機器你的家目錄底下的.ssh/authorized_keys ),你想要登入的時候只要擁有私鑰就可以登入了(當然如果有 Passphrase 的話還是得輸入正確才能使用私鑰)。

而且還可以在本機下 ssh-add ,然後它就會問你你的私鑰 Passphrase ,只要輸入這一次,直到你登出本機之前你就可以一直使用私鑰而不需要每一次都輸入 Passphrase 了。

ssh-keygen, ssh, ssh-add 這些 utility 在 Linux 上絕對有,Mac 上應該也有。可憐的 Windows ,連這種小功能都沒有內建,還要用 putty ……

接下來就實際開始做啦

首先產生一組SSH公鑰/私鑰對:

$ ssh-keygen -t rsa -b 2048

當然想要金鑰長度更長我也不反對啦…… -b 參數調高一點就好了。

然後他會問你金鑰要放在哪裏,建議還是在檔名後面加個識別。

Enter file in which to save the key (/home/pellaeon/.ssh/id_rsa): /home/pellaeon/.ssh/id_rsa_bitbucket

設定 Passphrase ,就是通關密語,每一次用這個金鑰的時候就要輸入才能使用。最好還是設定一下,不要留空白

Enter passphrase (empty for no passphrase):

出現以下這些訊息就是成功產生了,id_rsa_bitbucket 是私鑰,要保管好,不要隨便複製/提供給別人,權限最好設成600。id_rsa_bitbucket.pub 是公鑰。

Your identification has been saved in /home/pellaeon/.ssh/id_rsa_bitbucket.
Your public key has been saved in /home/pellaeon/.ssh/id_rsa_bitbucket.pub.

產生完成了,接下來做一些小設定,讓 ssh 指令在連某一些地址的時候自動用特定的私鑰。打開 ~/.ssh/config ,我的設定是這樣的:

# Github
Host github.com
HostName github.com
User git
IdentityFile /home/pellaeon/.ssh/id_rsa_github
# Bitbucket
Host bitbucket.org
HostName bitbucket.org
User git
IdentityFile /home/pellaeon/.ssh/id_rsa_bitbucket

意思就是連到 github.com 的時候會自動用 ‘git’ 這個使用者還有 id_rsa_github 這個私鑰嘗試登入;
而連到 bitbucket.org 的時候會自動用 ‘git’ 這個使用者還有 id_rsa_bitbucket 這個私鑰嘗試登入;
連綫到這兩臺之外的機器的時候,就會嘗試用你目前在本機已經登入的使用者名稱,還有預設的私鑰 id_rsa 來嘗試登入。

Nice, huh?