T
tmnt53
Guest
Giới thiệu lỗi format string
T
- tmnt53
- 9.418 Lượt xem
Giới thiệu: lỗi format string là một lỗi nguy hiểm không thua gì lỗi tràn bộ đệm. Khi một chương trình có lỗi này, hacker có thể leak dữ liệu, làm crash chương trình, và thậm chí là khai thác chạy mã độc. Trong khuôn khổ bài viết này, mình xin giới thiệu sơ qua về lỗi format string.
Đối tượng: bài viết phù hợp với các bạn đã lập trình C, và tốt hơn là đã có kinh nghiệm debug assembly với gdb.
Format string là string dùng để format trong các hàm: printf, fprintf, sprintf, snprintf, vsprintf, vsnprintf vfprintf, vprintf,...
Vd: printf(arg1, arg2, arg3,…) thì arg1 là format string
Kiểu định dạng
Một số kiểu format đáng chú ý:
Cùng tìm hiểu qua ví dụ.
Bình thường ta hay dùng hàm printf như sau:
printf("Hello %s
", name);
Nhưng nếu dùng như dưới đây:
printf("Hello "); printf(name); printf("
");
Là đã mắc lỗi format string. Ta sẽ cùng tìm hiểu cụ thể hơn qua một study case: echo server.
Mã nguồn + chương trình:
Chương trình có chức năng in ra mọi thứ mà ta nhập vào, cho đến khi ta nhập exit. Ví dụ:
Nếu nhập xâu vào ở dạng format string, ta có:
Xâu %p%p%p đã biến thành 0x100 0xf7722c20 (nil). Nguyên nhân là do các dword nằm trong stack đã bị in ra. Để giải thích rõ hơn, dùng gdb debug (có peda), đặt breakpoint tại lời gọi printf, ta có:
Tại lời gọi hàm printf, ta có tham số là 0xffffd43c – địa chỉ của xâu “My name is %p %p %p” (xem trong hình vẽ). Đó là dword đầu tiên trong stack. Phía dưới nó, tại offset thứ 4, 8, 12 của stack, ta có các dword 0x100, 0xf7fb8c20, 0x0. Và ta nhận thấy, %p %p %p đã in ra các giá trị này (%p thứ 3 cho ra nil, tương ứng với 0x0).
%p thứ 2 cho ra 0xf7fbb8c20, là một địa chỉ hợp lệ trong bộ nhớ mà ta có thể truy cập (là một địa chỉ trong libc). Nếu ta thay %p này bằng %s:
Thì ta leak được ra nội dung tại địa chỉ này. Như vậy, nếu trong stack có địa chỉ của một dữ liệu quan trọng, chẳng hạn mật khẩu, private-key của một mã hóa gì đó, thì dữ liệu sẽ hoàn toàn bị mất.
Còn việc làm crash chương trình thì sao. Đơn giản, %p thứ nhất tương ứng với 0x100, là một địa chỉ không hợp lệ. Nếu như ta thay bằng %s thì chương trình sẽ bị crash:
Qua đây, mình đã giới thiệu tới các bạn một số kiến thức về lỗi format string. Kiến thức này cũng sẽ hữu ích đối với các bạn lập trình trên C/C++, cần phải lưu ý không được phạm phải lỗi này. Còn một phần mình chưa demo, đó là cách khai thác lỗi format string để chiếm quyền điều khiển chương trình như thế nào. Mình sẽ giới thiệu trong bài tiếp theo, ở đó yêu cầu các bạn một số kiến thức, kỹ năng về khai thác mới có thể nắm được.
Đối tượng: bài viết phù hợp với các bạn đã lập trình C, và tốt hơn là đã có kinh nghiệm debug assembly với gdb.
Format string là string dùng để format trong các hàm: printf, fprintf, sprintf, snprintf, vsprintf, vsnprintf vfprintf, vprintf,...
Vd: printf(arg1, arg2, arg3,…) thì arg1 là format string
Kiểu định dạng
Thông số | Đầu ra | |
%p | Trỏ tới địa chỉ chứa giá trị của biến | |
%d | Số thập phân | |
%c | Đầu ra là một kí tự hoặc 1 số | |
%u | Số thập phân không dấu | |
%x | Dạng số hexa 0-F | |
%s | Đầu ra là một chuỗi kí tự | |
%n | Đếm độ dài của chuỗi nhập vào |
Một số kiểu format đáng chú ý:
- %s: In ra xâu được trỏ bởi tham số.
- %x: In ra tham số ở dạng hexa.
- %p: In ra tham số ở dạng con trỏ.
Cùng tìm hiểu qua ví dụ.
Bình thường ta hay dùng hàm printf như sau:
printf("Hello %s
", name);
Nhưng nếu dùng như dưới đây:
printf("Hello "); printf(name); printf("
");
Là đã mắc lỗi format string. Ta sẽ cùng tìm hiểu cụ thể hơn qua một study case: echo server.
Mã nguồn + chương trình:
Chương trình có chức năng in ra mọi thứ mà ta nhập vào, cho đến khi ta nhập exit. Ví dụ:
Nếu nhập xâu vào ở dạng format string, ta có:
Xâu %p%p%p đã biến thành 0x100 0xf7722c20 (nil). Nguyên nhân là do các dword nằm trong stack đã bị in ra. Để giải thích rõ hơn, dùng gdb debug (có peda), đặt breakpoint tại lời gọi printf, ta có:
Tại lời gọi hàm printf, ta có tham số là 0xffffd43c – địa chỉ của xâu “My name is %p %p %p” (xem trong hình vẽ). Đó là dword đầu tiên trong stack. Phía dưới nó, tại offset thứ 4, 8, 12 của stack, ta có các dword 0x100, 0xf7fb8c20, 0x0. Và ta nhận thấy, %p %p %p đã in ra các giá trị này (%p thứ 3 cho ra nil, tương ứng với 0x0).
%p thứ 2 cho ra 0xf7fbb8c20, là một địa chỉ hợp lệ trong bộ nhớ mà ta có thể truy cập (là một địa chỉ trong libc). Nếu ta thay %p này bằng %s:
Thì ta leak được ra nội dung tại địa chỉ này. Như vậy, nếu trong stack có địa chỉ của một dữ liệu quan trọng, chẳng hạn mật khẩu, private-key của một mã hóa gì đó, thì dữ liệu sẽ hoàn toàn bị mất.
Còn việc làm crash chương trình thì sao. Đơn giản, %p thứ nhất tương ứng với 0x100, là một địa chỉ không hợp lệ. Nếu như ta thay bằng %s thì chương trình sẽ bị crash:
Qua đây, mình đã giới thiệu tới các bạn một số kiến thức về lỗi format string. Kiến thức này cũng sẽ hữu ích đối với các bạn lập trình trên C/C++, cần phải lưu ý không được phạm phải lỗi này. Còn một phần mình chưa demo, đó là cách khai thác lỗi format string để chiếm quyền điều khiển chương trình như thế nào. Mình sẽ giới thiệu trong bài tiếp theo, ở đó yêu cầu các bạn một số kiến thức, kỹ năng về khai thác mới có thể nắm được.
Chỉnh sửa lần cuối bởi người điều hành: