[問題] Buffer overflow 和 Instruction address

看板C_and_CPP作者 (疾風)時間15年前 (2010/12/08 11:30), 編輯推噓7(7031)
留言38則, 8人參與, 最新討論串1/4 (看更多)
遇到的問題(Question): 我要先誠實的說,這是作業文 我自己的作業文 但是題目我看了兩天了,只處理解決了一部分的問題 所以想請大家給我一點意見或是提示 (題目: http://isis.poly.edu/courses/cs392-f2010/labs/HW6.pdf ) 餵入的資料(Input): 餵入一串字元 希望的正確結果(Expected Output): 如果輸入的字元少於24個沒事,超過24個要避免overflow 只能印出 x is 0 不能印出 x is 1 跑出來的錯誤結果(Wrong Output): 我解決了overflow的部分 但是還是會印出x is 1 開發平台(Platform): (例: VC++, Gcc, OpenGL, Linux, ...) win7 64bit + code::blocks + GCC 程式碼(Code): (請善用置底文標色功能) #include <stdio.h> #include <stdlib.h> //BEGIN:A program to illustrate buffer overflow //vulnerability void func(char *str) { char buffer[24]; int *ret; //strcpy(buffer,str); <--原來程式用的函式 /**以下我是我改的部分**/ int temp; temp = sizeof(buffer) - 1; //printf("%d\n",temp); strncpy(buffer,str,temp); //<--避免overflow的函式 buffer[23]='\0'; puts(buffer); ret = buffer + 12; //<--改了沒用,不知道為什麼這樣用,from網路 (*ret) += 8; //<--why is it 8?? 用來改pointer,似乎沒用 /************************/ } int main(int argc, char **argv) { int x; x = 0; func(argv[1]); x = 1; printf("x is 1\n"); printf("x is 0\n"); } //END 補充說明(Supplement): 題目有兩個部分 第一題小題是如果可以修改原始碼 那要怎麼避免overflow 第二小題則是不能修改原始碼 只能執行他 那要怎麼避免overflow 我覺得最讓我不知道怎麼處理的部分是 執行完func這個function之後 回到main裡面 要跳過 x = 1; 和 printf("x is 1\n"); 在執行程式的過程中我們可以直接去抓instruction的address嗎? 然後我們可以直接修改這個address?? 所以執行完func之後可以直接跳回main的printf("x is 0\n"); ?? 我目前只想出第一小題的overflow怎麼解決 第2小題還沒想 請大家給我一點意見和提示 謝謝大家 -- 我不是宅 我只是比較居家 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 108.6.66.40

12/08 11:43, , 1F
可以修改function的回傳值型態嗎?
12/08 11:43, 1F

12/08 11:46, , 2F
沒事 別管我
12/08 11:46, 2F

12/08 12:35, , 3F
快去看第五戒
12/08 12:35, 3F

12/08 13:12, , 4F
先把stdout導出讓他印完之後再自己印?
12/08 13:12, 4F

12/08 14:36, , 5F
你就在 func 裡面, 從 buffer 之前往前印值
12/08 14:36, 5F

12/08 14:36, , 6F
看看哪個是 stack 上的 return stack pointer
12/08 14:36, 6F

12/08 14:36, , 7F
看不出來的話可以多 call func 幾次
12/08 14:36, 7F

12/08 14:37, , 8F
知道 offset 之後再去改
12/08 14:37, 8F

12/08 14:50, , 9F
ret=buffer+12這行錯了,因為還是在buffer裡面
12/08 14:50, 9F

12/08 14:52, , 10F
第二小題在linux下倒是有很簡單的做法,用LD_PRELOAD
12/08 14:52, 10F

12/08 14:56, , 11F
用64bit要加16而不是加8,不過不是你那種做法就是了
12/08 14:56, 11F

12/08 14:56, , 12F
我想第二題應該是想要用 buffer overrun 塞爛 stack 作答
12/08 14:56, 12F

12/08 14:57, , 13F
LD_PRELOAD 又是另一種邪惡的東西了 XD
12/08 14:57, 13F

12/08 15:00, , 14F
用buffer當基準點也是很冒險的,因為不能保證緊鄰frame
12/08 15:00, 14F

12/08 15:00, , 15F
pointer
12/08 15:00, 15F

12/08 15:01, , 16F
這次作業我真的完全沒有頭緒,資料也都是上網查的
12/08 15:01, 16F

12/08 15:02, , 17F
真的想不到所以才來發文問問看
12/08 15:02, 17F

12/08 15:07, , 18F
parameter--ret addr--frame pointer--local var
12/08 15:07, 18F

12/08 15:08, , 19F
左邊是高位址,右邊是低位址,compiler可能會在fp跟
12/08 15:08, 19F

12/08 15:09, , 20F
印出來東西之後 怎麼判斷是不是return stack pointer?
12/08 15:09, 20F

12/08 15:09, , 21F
又來如何修改那個pointer呢??
12/08 15:09, 21F

12/08 15:10, , 22F
local之間塞東西,local var擺放順序視complier的參數
12/08 15:10, 22F

12/08 15:10, , 23F
如果你 call func 好幾次, 每次會加一定值的, 就有可能是
12/08 15:10, 23F

12/08 15:11, , 24F
而定,你首先要做的是確定buffer跟ret addr的相對位址
12/08 15:11, 24F

12/08 15:11, , 25F
因為如果 call 好幾次, 每次 return value 都會到下個指令
12/08 15:11, 25F

12/08 15:11, , 26F
原po得學學debugger怎麼用
12/08 15:11, 26F

12/08 15:12, , 27F
這時候把 ret 移到跳動的那個, 幫他加一個 inst 的長度
12/08 15:12, 27F
我的確不太會debug 所以我才想要學 不管這是不是作業 如果是我在網路上找到這些資料 我也會想知道要怎麼解決 很感謝大家的回答,雖然我還是不知道怎麼用 XD 話說我的code::blocks不讓我debugger 真囧 改ret真的是改到return 的 address嗎?? 還是覺得很奇怪 ※ 編輯: rock1985 來自: 108.6.66.40 (12/08 15:33)

12/08 15:34, , 28F
你可以用ollydbg,界面很簡單
12/08 15:34, 28F

12/08 15:35, , 29F
如果ret有正確指到ret addr就能改
12/08 15:35, 29F

12/08 15:56, , 30F
gdb.exe 現在抓得到嗎?? 我好像沒有這個檔案
12/08 15:56, 30F

12/08 15:57, , 31F
還是要自己抓東西回來生成??
12/08 15:57, 31F

12/08 15:58, , 32F
code::blocks裝好應該就會有gdb可以用了吧?
12/08 15:58, 32F

12/08 16:12, , 33F
printf("x is 1"); exit(1); XD
12/08 16:12, 33F

12/08 22:32, , 34F
我的code::blocks 沒辦法 debugger一整個怪 = =a
12/08 22:32, 34F

12/08 22:35, , 35F
ollydbg呢
12/08 22:35, 35F

12/09 03:21, , 36F
ollydbg可以用,不過看不太懂他列出來的東西
12/09 03:21, 36F

12/09 03:52, , 37F
我大概有個底知道要怎麼處理
12/09 03:52, 37F

12/09 03:52, , 38F
但是對於stack的分析還是有點陌生,可以再給我一點提示嗎
12/09 03:52, 38F
我現在用debug去看 一些東西的記憶體位置 但是還不知道要怎麼看return address是存在stack的哪個位置 #include <stdio.h> #include <stdlib.h> //BEGIN:A program to illustrate buffer overflow //vulnerability void func(char *str) { char buffer[24]; int *ret; char *tmp; //strcpy(buffer,str); /**以下我是我改的部分**/ int temp; temp = sizeof(buffer) - 1; //printf("%d\n",temp); //ret = buffer; strncpy(buffer,str,temp); buffer[23]='\0'; puts(buffer); tmp=buffer; printf("%p: %c (0x%x)\n", tmp, *tmp, *(unsigned int *)tmp); while(tmp<buffer+23) { printf("%p: %c (0x%x)\n", tmp, *tmp, *(unsigned int *)tmp); tmp++; } /***********************/ } int main(int argc, char **argv) { int x; x = 0; //func(argv[1]); func("123456789876543212345678987654321"); x = 1; printf("x is 1\n"); printf("x is 0\n"); } //END 這是我現在測試用的程式碼 http://0rz.tw/st47M 圖是我跑debug的情況,請大家再多給我一點提示 我大概知道要怎麼處理 請大家在跟我說一下怎麼處理或是去抓stack的狀態 謝謝 ※ 編輯: rock1985 來自: 128.238.241.120 (12/09 05:01) ※ 編輯: rock1985 來自: 128.238.241.120 (12/09 05:32)
文章代碼(AID): #1C_lkznP (C_and_CPP)
文章代碼(AID): #1C_lkznP (C_and_CPP)