Tôi có một câu hỏi nhỏ. Tôi biết rằng mã định dạng% x có thể được sử dụng để đọc các giá trị từ ngăn xếp trong một cuộc tấn công chuỗi định dạng.
Tôi tìm thấy mã sau:
%08x%08x%08x%08x
08 có nghĩa là gì? Chính xác thì nó đang làm gì? Cảm ơn :)
Tôi có một câu hỏi nhỏ. Tôi biết rằng mã định dạng% x có thể được sử dụng để đọc các giá trị từ ngăn xếp trong một cuộc tấn công chuỗi định dạng.
Tôi tìm thấy mã sau:
%08x%08x%08x%08x
08 có nghĩa là gì? Chính xác thì nó đang làm gì? Cảm ơn :)
printf()
đang được sử dụng.
Câu trả lời:
Phá vỡ:
8
nói rằng bạn muốn hiển thị 8 chữ số0
mà bạn muốn đặt tiền tố bằng 0
's thay vì chỉ có khoảng trắngx
mà bạn muốn in trong hệ thập lục phân viết thường.Ví dụ nhanh (cảm ơn Grijesh Chauhan):
#include <stdio.h>
int main() {
int data = 29;
printf("%x\n", data); // just print data
printf("%0x\n", data); // just print data ('0' on its own has no effect)
printf("%8x\n", data); // print in 8 width and pad with blank spaces
printf("%08x\n", data); // print in 8 width and pad with 0's
return 0;
}
Đầu ra:
1d
1d
1d
0000001d
Cũng có thể xem http://www.cplusplus.com/reference/cstdio/printf/ để tham khảo.
%-8x
và vốn X
. và quan sát hiệu ứng
8
và 0
cả hai đều là số (và do đó các phần giống hệt nhau của ngữ pháp bằng tiếng Anh) nhưng chúng là các phần khác nhau của ngữ pháp định dạng printf. 0
là một "lá cờ" và 8
là một tham số để "width" (có thể <ε (no input)>
, <d (any number greater than 0)>
hoặc * (a literal asterisk)
). Chắc chắn đây là một API không trực quan! Nhưng bạn có thể nói gì ... đó là tất cả những thứ C kiểu cũ, nơi bộ nhớ là thứ cao cấp đến mức bạn muốn lưu càng nhiều ký tự trong một chương trình càng tốt - Tôi đồng ý với quyết định của họ vì những hạn chế mà họ phải đối mặt!
printf
cú pháp như thế nào? Tôi thích sử dụng %
làm ký tự thoát, nó rất độc đáo và thích hợp để định dạng chuỗi. Tôi nghĩ rằng các bổ ngữ nên được thêm vào thay vì thêm vào trước - theo cách đó bạn có thể đọc nó từ trái sang phải. Một cái gì đó như %<specifier>[%f<flags>][%-w<width>.<precision>]%
, thay vì %[flags][width][.precision][length]specifier
. Tôi chọn một %
giữa từng lĩnh vực, cũng như một đến gần (vì vậy bạn vẫn có thể làm %x%x
- `% x %% x%) và cho phép một specifier đa char
Điều đó chỉ định số lượng chữ số bạn muốn nó hiển thị.
giá trị số nguyên hoặc * chỉ định độ rộng trường tối thiểu. Kết quả được đệm bằng các ký tự khoảng trắng (theo mặc định), nếu được yêu cầu, ở bên trái khi căn phải hoặc ở bên phải nếu căn trái. Trong trường hợp khi * được sử dụng, chiều rộng được chỉ định bởi một đối số bổ sung kiểu int. Nếu giá trị của đối số là âm, nó dẫn đến - cờ được chỉ định và độ rộng trường dương.
Từ http://en.wikipedia.org/wiki/Printf_format_string
sử dụng 0 thay vì khoảng trắng để đệm một trường khi tùy chọn chiều rộng được chỉ định. Ví dụ: printf("%2d", 3)
kết quả là "3", trong khi printf("%02d", 3)
kết quả là "03".
Cuộc tấn công chuỗi định dạng trên printf mà bạn đã đề cập không dành riêng cho định dạng "% x" - trong bất kỳ trường hợp nào printf có nhiều tham số định dạng hơn các biến đã truyền, nó sẽ đọc các giá trị từ ngăn xếp không thuộc về nó. Bạn sẽ gặp vấn đề tương tự với% d chẳng hạn. % x hữu ích khi bạn muốn xem các giá trị đó dưới dạng hex.
Như đã giải thích trong các câu trả lời trước,% 08x sẽ tạo ra một số hex gồm 8 chữ số, được đệm bởi các số không đứng trước.
Sử dụng định dạng trong ví dụ mã của bạn trong printf, không có tham số bổ sung:
printf ("%08x %08x %08x %08x");
Sẽ tìm nạp 4 tham số từ ngăn xếp và hiển thị chúng dưới dạng số hex có đệm 8 chữ số.
000007ac
hoặc0005ceef
.