關於buffer overflow的範例程式,就如同上一篇文章裡面有提到,buffer overflow 主要是利用C++對於陣列大小沒有限制的概念,當你輸入一個過大的數值,回傳值(return value)會被蓋掉,即使你輸入錯誤的數值,你會也因為這樣而成功的登入電腦(或是使某個安全認證通過~~~)
一個好朋友(生魚片)寫了一個範例程式,但是我看了一下總是覺得哪裡怪怪的,因為我記得雖然記憶return value會在記憶體位置之中,但是很難確切抓出function的回傳位置就在變數之後,並且他設定的函數為void,照理說也是無法回傳的才對~所以我大膽猜測他所寫的程式主要是將func的副程式加以執行過後的結果,與我們原先探討的Buffer Overflow有所差異,所以我寫了一個範例程式如下:
在這個範例程式之中,副函示有數個變數宣告,buf[1],*p, r_c 所以記憶體分配方式如下(先宣告的記憶體位址比較後面,後宣告的記憶體位置比較前面):
|
+-----------------------+
| (other variable) |
+-----------------------+
| 指標 p |
+-----------------------+
| (other variable) |
+-----------------------+
| r_c (1 bytes) |
+-----------------------+
| (other variable) |
+-----------------------+
| buf (1 bytes) |
+-----------------------+
| (other data in stack) |
| . |
+-----------------------+
| return address of |
| this function |
| . |
| . |
當你在VC++編輯的時候,若是使用 [F11]來一個階段,一個階段的DEBUG,去一個個參照變數的位置(Address)的時候,你會發現以下的結果
也就是透過指標*p,回傳變數r_c會被該更改到,使得回傳的值變的有誤。
所以這個程式明明不該輸出『System passing 』卻因為回傳值變成r_c所以產生~~~~錯誤造成程式的錯誤
但是你使用 (long)func
不就是在呼叫程式了嗎?而非讓陣列 overflow....
==============================================
這裡讓我澄清一下,
在 add[2]= (long)func;
並不是呼叫函式阿.
只是我觀察到在stack中.存放要return回main函式中的位址,可以透過add[2]來填入,所以我只是把func的address寫入其stack中.達成在func1最後,組合語言ret時.pop出來的返回為指為func1的位址,這樣不也是一樣的原理嗎???
厄.....我只是路過啦
順便發表一下感言.....
這世界上,果然有種世界語言,是我所不懂的啊
啊,雖然你寫的是中文
或簡單的英文單字
但是其中的邏輯與想像
應該就是我大腦缺的那一塊吧
好!!KUSO完畢
由 小貓 發表於 May 15, 2004 12:43 AMto 生魚片~~
我明天在好好試試看
因為那個程式沒有傳回值,所以一直讓我以為不會去抓那個位置
to 小貓
隔行如隔山~~
大概再沒多久,你會在這個地方看到
1011001101111 一堆的機器語言
@__________________@
在此總結一下生魚片與我的程式意義上的不同
我的想法是:
在輸入變數沒有控制大小之下,若是input buf使用array的方式存放,將使某些變數可以寫入可能是回傳的變數,也就是輸入一個比陣列大小還大的資料,會覆蓋到某些可能回傳的變數,使得認證的函示錯誤,進而得到控制權。
生魚片的方法是:
在程式碼中注入一個自己的函示(像是病毒或是後門程式),將其位置放入到陣列以外的位置(回傳值位址)使得函示會自動去執行他。
大致上是這樣,若有不對請糾正 :)
生魚片的方法是:
在程式碼中注入一個自己的函示(像是病毒或是後門程式),將其位置放入到陣列以外的位置(回傳值位址)使得函示會自動去執行他。
我的想法是
我並不是改回傳值位址,而是更改用來存放呼叫此function的function位址,因為我們知道當我們呼叫function的時候會將我們自己程式現在的address存入stack中,等到function執行完畢.電腦在從stack將剛剛我們存放的位址pop出來然後跳回我們自己的程式並繼續往下執行,所以我只是更改存放我們程式位址的地方,將我們程式的位址改成別的函式位址.....我不太懂得解釋了..:P真慘的我..國文要好好學學了!!!
生魚片,我大概瞭解了
你就是更改掉程式裡面儲存程式的位置(將其換成自己函示的位置)(組合語言裡面的 PC與IP 結合出的位置)
讓電腦可以執行你想作的事情
只是我當初想問你,
1.你是怎麼查出來的
2.並且我們很難將這個設為變數傳入不是嗎?
傳入喔..簡單阿...要把自己的函式位址傳入只要將函式的名稱給它就好...
例如傳入一個long就只要給他函式名稱.而不要加()
例如void func(void)這個函式..
要將此函式的位址傳入一個存放一個long的地方
long arr[10];
arr[0] = (long)func;就是把func的位址當作long來存放
至於怎麼查出來的...這..經驗吧..然後就是看組合語言的code阿..:D
看不出來跟buffer overflow有什麼關係
不如叫亂用指標的後果
還有r_c是區域變數 怎麼能return 回去勒.......