2013-02-09 43 views
9

Tôi đang tìm hiểu về tràn bộ đệm và đang cố gắng tạo ra bộ đệm. Tôi có mã này:Biên dịch C để cho phép tràn bộ đệm

#include <stdio.h> 

char *secret = "password"; 

void go_shell() { 
    char *shell = "/bin/sh"; 
    char *cmd[] = { "/bin/sh", 0 }; 
    setreuid(0); 
    execve(shell,cmd,0); 
} 

int authorize() { 
    char password[64]; 
    printf("Enter Password: "); 
    gets(password); 
    if (!strcmp(password,secret)) { 
     return 1; 
    } 
    else { 
     return 0; 
    } 
} 

int main() { 
    if (authorize()) { 
     printf("login successful\n"); 
     go_shell(); 
    } else { 
     printf("Incorrect password\n"); 
    } 
    return 0; 
} 

tôi biên dịch này với gcc và sau đó chạy nó trong gdb

tôi nhập khoảng 100 "A" s như mật khẩu và các chương trình bị treo.

Vấn đề là không đăng ký được ghi đè để 0x4141414141414141

Tôi googled này và bổ sung -fno-stack-protector cờ để gcc, cho phép RBP để được ghi đè để 0x4141414141414141 nhưng không có gì khác.

Tôi đã tự hỏi liệu có cách nào để biên dịch mã để RIP có thể được ghi đè hay không.

+0

Bạn đang sử dụng Linux? Bạn cũng cần đặt một số lá cờ ở đó, tôi nghĩ vậy. – nhahtdh

+0

Sử dụng Mac OSX. Bất kỳ ý tưởng lá cờ là gì? – carloabelli

+0

Tôi không biết về Mac OSX - có lẽ sẽ khác xa so với Ubuntu (xin lỗi, tôi thực sự đã làm điều này trên Ubuntu, chứ không phải Linux). – nhahtdh

Trả lời

3

Mã của bạn đã thực hiện những gì bạn muốn nếu bạn biên dịch với -fno-stack-protector. Lý do bạn không thấy RIP với giá trị 0x4141414141414141 trong GDB là lỗi bảo vệ chung được ném trước khi RIP được cập nhật. (Nếu xảy ra lỗi trang, trình xử lý GPF thường tải trang từ trao đổi và tiếp tục thực hiện bằng cách bắt đầu với hướng dẫn không thành công.)

+0

Thanks for the help, nhưng tôi đã tự hỏi nếu có một cách để tắt chức năng mà GPF nên RIP có thể được đặt cho '0x4141414141414141' bởi vì đó là những gì xảy ra trong hướng dẫn tôi đang sử dụng. – carloabelli

+0

@ cabellicar123 Bạn không thể tránh được những GPF trừ khi bạn tạo một trang thực thi tại địa chỉ đó. Chỉ cần tiếp tục với hướng dẫn của bạn. Có lẽ bước tiếp theo sẽ là cung cấp một mật khẩu được tạo đặc biệt để làm cho mã nhảy đến một địa chỉ hợp lệ. – nwellnhof

+0

Cảm ơn bạn rất nhiều vì đã giúp bạn! – carloabelli

1

Lý do bạn gặp sự cố EIP 0 × 41414141 trên x32 là vì chương trình hiện ra giá trị EIP đã lưu trước đó khỏi ngăn xếp và quay trở lại EIP CPU sau đó cố gắng thực hiện lệnh tại địa chỉ bộ nhớ 0 × 41414141 gây ra lỗi segfault. (nó phải tìm nạp trang trước khi thực hiện khóa học)

Bây giờ, trong khi thực thi x64 khi chương trình bật giá trị RIP đã lưu trước đó vào thanh ghi RIP, sau đó thử thực hiện lệnh tại địa chỉ bộ nhớ 0 × 4141414141414141. Thứ nhất, do định dạng địa chỉ chuẩn, các bit từ 48 đến 63 của bất kỳ địa chỉ ảo nào phải là bản sao của bit 47 (theo cách tương tự như phần mở rộng dấu), hoặc bộ xử lý sẽ tăng ngoại lệ. Nếu đó không phải là vấn đề - hạt nhân thực hiện kiểm tra bổ sung trước khi gọi trình xử lý lỗi trang vì địa chỉ không gian người dùng tối đa là 0x00007FFFFFFFFFF.

Để tóm tắt lại, trong kiến ​​trúc x32 địa chỉ được truyền mà không có bất kỳ "xác thực" nào cho trình xử lý lỗi trang cố gắng tải trang kích hoạt hạt nhân gửi segfault chương trình nhưng x64 không nhận được điều này.

Kiểm tra nó, ghi đè RIP bằng 0 × 0000414141414141 và bạn sẽ thấy giá trị mong đợi được đặt trong RIP vì số lần kiểm tra trước bằng thẻ nhân và sau đó trình xử lý lỗi trang được gọi như trường hợp x32 (tất nhiên, sau đó khiến chương trình bị lỗi).

Các vấn đề liên quan