常常聽到一些hacker或者病毒利用軟體的一類漏洞,叫做buffer overflow或者stack over run,然後可以達到入侵的目的,這些執行的結果往往是為了跳到特定的位址執行某些程式碼。啥是特殊位置?buffer overflow跟stack overrun是為了啥?
以前聽得很模糊,對linux的loader跟process有了解之後,大概可以解釋這種行為的意圖,先看網路上抓來的兩張圖片,一張是virtual process的空間配置是意圖,另外一張是process各資料區段的示意圖
一般來說,hacker想要存取的是kernel space的地方,因為畢竟user space的權限不大,進入kernel space就比較可以隨心所欲,但是一般而言,是無法直接存取kernel space的;此時就是必須利用如heap之類的空間,讓寫入的資料超出本來該寫入的地方,並且寫到kernel space上;又或者想把辦法蓋掉text的程式碼,讓他跳至特定的kernel space內,去執行一些意想不到的code
c string由於沒有邊界檢查,是最常被用來突破的點,但是現在防範的手法已經愈來愈高明了,邊界檢查也是愈來愈嚴苛,可能會規範heap的大小範圍,一旦範圍超出規定的上限或者下限位址,程式就當掉
當然還是有百密一疏的時候,畢竟防禦的人要擋下所有攻擊,但是進攻方只要找到一個突破的點,難易程度也是不對稱的。
當然話說回來,不是只有這種入侵手法,這只是最常見的。
2013年1月18日 星期五
linux上的stack frame
有些文章介紹了stack frame,大多提到的是對應x86底層的實作,即使有些OS跟組合語言的概念,但是還不是很能理解,慢慢的追蹤組合語言才了解了大概,這邊寫下幾個容易混淆的地方
這裡呼叫的function叫做caller,被呼叫的稱為callee,比方說main(caller)呼叫foo(callee)
其實intel並沒有規定這樣stack實作模式,之所以會變成這樣,主要是根據ABI的規範
上面的行為可以透過objdump, gdb中的info register, x來觀察
這裡呼叫的function叫做caller,被呼叫的稱為callee,比方說main(caller)呼叫foo(callee)
- %ebp是stack frame的底部,%esp是stack frame的頂部
- 但是%ebp是在高位址,但是%esp是在低位址
- 增加local variable的時候,%esp向低位址減少
- 存取parameters的時候卻是向著高位址前進,比方%ebp+8, %ebp+12,存取的是上一個caller的stack frame
- 存取local variable使用的是%esp-0x04這種格式,這就是存取自身的stack frame
- 一般function開頭push %ebp是為了保留上一個stack frame的位址,等到後面可以回復,跟著就把callee的%ebp設定為caller的%esp,接著sub 0x10,%esp,表示未local varabiles配置空間
- 注意組合語言call, leave, ret對register的影響,回傳值是透過%eax傳遞
其實intel並沒有規定這樣stack實作模式,之所以會變成這樣,主要是根據ABI的規範
上面的行為可以透過objdump, gdb中的info register, x來觀察
2013年1月17日 星期四
C++的mangle與debug
其實稍微懂得loader的人都知道這個機制,也就是避免名稱空間碰撞的機制,用於C++也可以避免兩個不同class但是有相同的member function名稱碰撞的問題,但設這樣來說,在gdb內很喜歡用的b function_name如何使用?
先把namgle後的名稱找出來,使用之前nm可以列出,如果還不確定,可以使用c++filt轉出prototype,c++filt之所以可以反轉,乃是因為namgle是有規則的(好像有點廢話)
比方說code如下
class foo{
int a,b;
public:
void func(int x,int y);
};
void foo::func(int x,int y){
a=x;
b=y+2;
}
int main(void){
foo f1, f2;
printf("f1:%p, f2: %p\n",&f1,&f2);
f1.func(5,1);
f2.func(-4,2);
return 0;
}
找出foo這個function在被namgle之後的名稱可以用
nm name | grep foo | c++filt
或者
nm -C name | grep foo
可以看到名稱為_ZN3foo4funcEii
進入gdb,這下子就可以用b *_ZN3foo4funcEii來設定break point了,跟之執行run
停止後gdb很好心的印出了function call的prototype,會發現多了一個this,這也是C++的object pointer來源
先把namgle後的名稱找出來,使用之前nm可以列出,如果還不確定,可以使用c++filt轉出prototype,c++filt之所以可以反轉,乃是因為namgle是有規則的(好像有點廢話)
比方說code如下
class foo{
int a,b;
public:
void func(int x,int y);
};
void foo::func(int x,int y){
a=x;
b=y+2;
}
int main(void){
foo f1, f2;
printf("f1:%p, f2: %p\n",&f1,&f2);
f1.func(5,1);
f2.func(-4,2);
return 0;
}
找出foo這個function在被namgle之後的名稱可以用
nm name | grep foo | c++filt
或者
nm -C name | grep foo
可以看到名稱為_ZN3foo4funcEii
進入gdb,這下子就可以用b *_ZN3foo4funcEii來設定break point了,跟之執行run
停止後gdb很好心的印出了function call的prototype,會發現多了一個this,這也是C++的object pointer來源
2013年1月16日 星期三
GDB指令筆記
留一下備忘錄
commands #breakpoint
...
...
end
在中斷點中斷時執行的指令
define #command
...
...
end
document
...
...
end
可以用來設定指令,比方說
define li
x/10i $pc
end
document li
list machine instruction
end
help li則是印出指令說明
使用core file當作gdb的輸出的時候,必須加上-s exec_file或者在進入gdb後file exec_file,才可以載入symbol table
attach pid將某個process加入gdb模式,使用detach離開
參考資料:
http://www.study-area.org/cyril/opentools/opentools/debug.html
- break/b : 設定break point,break main, break 10, break test.C:10
- run/r : 執行
- backtrace/bt : 列印出stack frame, bt 10, bt full 10
- print/p : 列印出變數數值
- info register : 列印出regiseter內容
- next/n : step by step
- step/s : step into
- continue/c : 繼續執行
- watch expression : 監視變數
- delete # : 刪除break point或者 watch point
- set variable var=expression : 設定變數內容
- generate-core-file
- info proc : 印出在/proc內容
- break #breakpoint if condition : 設定中斷點條件
- condition #breakpoint condtion : 為中斷點設定條件
- condition #breakpoint : 取消中斷點的條件
- clear : 清除所有中斷點
- disable : 暫停使用所有中斷點
- enable : 啟用中斷點
- info b : 列出所有中斷點
- set history/show history : 顯示出使用過的指令
- set history save/show history save : 儲存使用過的指令
- source file_name : 載入設定檔案
commands #breakpoint
...
...
end
在中斷點中斷時執行的指令
define #command
...
...
end
document
...
...
end
可以用來設定指令,比方說
define li
x/10i $pc
end
document li
list machine instruction
end
help li則是印出指令說明
使用core file當作gdb的輸出的時候,必須加上-s exec_file或者在進入gdb後file exec_file,才可以載入symbol table
attach pid將某個process加入gdb模式,使用detach離開
參考資料:
http://www.study-area.org/cyril/opentools/opentools/debug.html
2013年1月14日 星期一
你一天寫多少source code?
LOC(lines of codes)雖然是一個非常不精準的指標,卻也是一個非常好用的指標,我大概計算過,我每天只能產出100行程是,跟大多數的人差不多,就是第一天就可以生產五百到一千行,然後開始debug,一個星期大概只有一天拿來寫code,跟著有兩三天用來檢視設計跟重新規劃code(我不大喜歡看到兩個同樣的code blocks),有兩三天用來debug,結果平均下來就只有一百行勉強算是bug-free(畢竟現實專案沒有人可以宣稱他的code是bug-free的)
講了一堆,如何計算code?簡單的方式有
find . \( -name '*.h' -or -name '*.c' \) -exec cat "{}" ";" | wc -l
講了一堆,如何計算code?簡單的方式有
find . \( -name '*.h' -or -name '*.c' \) -exec cat "{}" ";" | wc -l
其實更廣泛的工具有,他支援多種語言
http://cloc.sourceforge.net/
uCLinux--如果沒有...
最近剛剛拜讀完人家,一些在linux底下的loader的機制,也就是牽涉到如何載入share lib跟OS如何分配管理elf程式的部分,回想uCLinux到底有何不同,想不到真的大大不同!!我把uClinux想簡單了
底下是另外一篇解釋uCLinux跟一般linux不一樣的地方,過去總是以為簡單的沒有MMC跟浮點數(floating point)
http://www.linuxjournal.com/article/7221
因為沒有MMU,就不支援Virtual Memory(VM),在這一節上,想不到會有許多差異
直覺,沒有VM,那麼記憶體應該是直接攤在記憶體中,且應該是連續的
因為沒有MMU,過去2^n配置記憶體,考慮到環境,也不可行,必須改用其他演算法,免得有記憶體破碎的問題
Heap要自己管理,也就是可能直接深入kernel,由kernel控制
沒有fork(),讓我實在意外,uCLinux只有提供vfork,使用 vfork() 會使得 parent process suspend 直到child process結束或執行exec()為止。@@a multi-process認知都有點不一樣了,我看muti-thread就更不用想了
只支援 flat executable format (bFLT), 這有兩種型態:
一、code text & data 都是 relocatable
二、使用 PIC 碼 (Position Independent Code)只有部份 data 需要 relocation 即可。
其中第二項衍生出 XIP (eXecute In Place) ,就是程式可以直接在 ROM上面執行的方式,因為 ROM 是 read only,可以被多個 instance share 使用。在這裡似乎uCLinux佔到了一點便宜,因為位址是固定的,外加用事read-only,那麼從新定位code text變成沒有必要的事情,也就是不用plt.got這個表了。可是事情也沒那麼樂觀,因為不是所有的硬體平台都支援PIC orz
回想想用gcc -shared 選項表示使用loading time relocate,但無法幫你在 bFLT格式中製作shared library。 這裡只提一個重要概念,shared library 必須是 XIP ,否則在每個uClinux application 都會產生一份 copy --- 這種情形比 static linking還要糟糕!
底下是另外一篇解釋uCLinux跟一般linux不一樣的地方,過去總是以為簡單的沒有MMC跟浮點數(floating point)
http://www.linuxjournal.com/article/7221
因為沒有MMU,就不支援Virtual Memory(VM),在這一節上,想不到會有許多差異
直覺,沒有VM,那麼記憶體應該是直接攤在記憶體中,且應該是連續的
因為沒有MMU,過去2^n配置記憶體,考慮到環境,也不可行,必須改用其他演算法,免得有記憶體破碎的問題
Heap要自己管理,也就是可能直接深入kernel,由kernel控制
沒有fork(),讓我實在意外,uCLinux只有提供vfork,使用 vfork() 會使得 parent process suspend 直到child process結束或執行exec()為止。@@a multi-process認知都有點不一樣了,我看muti-thread就更不用想了
只支援 flat executable format (bFLT), 這有兩種型態:
一、code text & data 都是 relocatable
二、使用 PIC 碼 (Position Independent Code)只有部份 data 需要 relocation 即可。
其中第二項衍生出 XIP (eXecute In Place) ,就是程式可以直接在 ROM上面執行的方式,因為 ROM 是 read only,可以被多個 instance share 使用。在這裡似乎uCLinux佔到了一點便宜,因為位址是固定的,外加用事read-only,那麼從新定位code text變成沒有必要的事情,也就是不用plt.got這個表了。可是事情也沒那麼樂觀,因為不是所有的硬體平台都支援PIC orz
也就是說,在uCLinux底下開發程式要注意的點比一般的linux程式還要多的限制,不是簡單換個distribution那樣而已,也不是簡單的抽換到glibc這個lib
2013年1月1日 星期二
node.js體驗完畢
看圖說故事,外殼已經寫好(對決大多數美工能力不強的programmer,就這樣簡單的畫面吧)
希望達到的功能姑且可以名為:方便日記 現在手機在拍照的時候往往可以用GPS記錄當下拍照的位置,所以回家只要上傳之後,server side/cloud side自動幫忙找出拍照地點,並且完成地名、日期以及描述,這些資料當然通通來自於網頁上,下面則是可以讓使用者瀏覽自己已經上傳的照片。也就是不用動手就可以寫完一篇遊記XD當然在不考量版權的問題之下
核心也完成了beta版本,大致效果如下,只要傳進參數loc的經緯度位置,就可以幫忙找出一些可能的地點,在localhost server效果也還可以
想不到一上傳到雲端伺服器,結果竟然大相逕庭,主要是回傳資料少上取多...真的不知道是在網路的哪個環節被截斷了。
以上就是體驗node.js完成的功能,心得有兩點
希望達到的功能姑且可以名為:方便日記 現在手機在拍照的時候往往可以用GPS記錄當下拍照的位置,所以回家只要上傳之後,server side/cloud side自動幫忙找出拍照地點,並且完成地名、日期以及描述,這些資料當然通通來自於網頁上,下面則是可以讓使用者瀏覽自己已經上傳的照片。也就是不用動手就可以寫完一篇遊記XD當然在不考量版權的問題之下
核心也完成了beta版本,大致效果如下,只要傳進參數loc的經緯度位置,就可以幫忙找出一些可能的地點,在localhost server效果也還可以
想不到一上傳到雲端伺服器,結果竟然大相逕庭,主要是回傳資料少上取多...真的不知道是在網路的哪個環節被截斷了。
以上就是體驗node.js完成的功能,心得有兩點
- node.js在流程控制上還要加強,非同步傳輸是node.js的強項,但是同時也不好控制,導致現在有許多async的套件,但是對於層層疊套的async呼叫其實幫助只到一定的程度,有許多套件使用preparse或者precompile處理,但是我有點不大喜歡,如果出了一個coffee script之類的又另當別論,不過我想短時間不容易做到
- 要把我想要的功能做得很完美,恐怕也是很困難,中間牽涉到網路爬蟲、語意分析、地理位置處理,本來還想用圖片比對,後來發現前兩者就已經很難了,只好先擱置了。另外拿jquery parse網頁並不是一個好主意,畢竟他是操作網頁tag為主,而且是自己產生的網頁比較能控制,拿來控制分析其他人網頁,往往是case by case
體驗玩node.js就可以回到嵌入式系統了XD
訂閱:
文章 (Atom)





