Thông điệp ngắn
- RT @TelegraphNews Netflix lets its staff take as much holiday as they want, whenever they want – and it works http://bit.ly/ajRs6J
- Google Making Extraordinary Counteroffers To Stop Flow Of Employees To Facebook http://t.co/M2kCTgj via @techcrunch
- 'Power corrupts. PowerPoint corrupts absolutely." http://bit.ly/cWQUjP
- Lecture on lectures http://bit.ly/d6ODHd
- How panhandlers use free credit cards - thestar.com http://t.co/j3pSXMB
Phản hồi mới
- Administrator on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- Na K54 on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- Na K54 on VC
- xuanlong on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- Duy on VC
- xuanlong on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- Ngô Quang Hưng on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- Ngô Quang Hưng on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- XuanLong Nguyen on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
- XuanLong Nguyen on HM5 — Định lý Vapnik-Chervonenkis cho mô hình giả thuyết không nhất quán
-
Bài mới
Thư khố
Chuyên Mục
- Âm Nhạc (39)
- Ảnh hưởng của CNTT (3)
- Bảo mật và mật mã học (67)
- Blog cầu (5)
- Bơi (1)
- Các hệ thống máy tính (9)
- Các hội nghị KHMT (11)
- Công nghệ phần mềm (6)
- Chính trị trong ngành (29)
- Chưa phân loại (34)
- CNTT các nước và VN (47)
- Combinatorics (16)
- Cơ sở dữ liệu (2)
- Danh ngôn (12)
- Dành cho du học sinh (97)
- Games (2)
- Giáo dục (76)
- Giới thiệu sách (33)
- KHMT và Kinh Tế (1)
- KHMT và luật pháp (6)
- KHMT và sinh học (5)
- KHMT và triết học (3)
- Lập trình (3)
- Lịch sử Việt Nam (2)
- Lý thuyết mã hóa (2)
- Lý thuyết tính toán (53)
- Lý thuyết thông tin (15)
- Mạng máy tính (34)
- Mỹ quốc (12)
- Nghiên cứu nghiên kiếc (50)
- Nhân vật và sự kiện (127)
- Quả đất của ta (1)
- Thông báo (23)
- Thuật ngữ chuyên ngành (8)
- Thuật Toán (51)
- Tin tức đó đây (68)
- Toán Ứng Dụng (3)
- Toán tối ưu (5)
- Trang web hay (31)
- Trí tuệ nhân tạo (40)
- Vui – Giải Trí (216)
- Vượt định kiến (2)
- Xác suất & thống kê (49)
- Xuất bản (14)
Báo chí
Bảo mật
Blog Việt
Chưa phân loại
Giáo dục
Kỹ thuật
Khoa học khác
Kinh tế, luật pháp, xã hội
- A Tiny Revolution
- Andrew Sullivan.com
- Chicago’s Law Faculty
- Computing Chris
- Creative Capitalism
- Crooked Timber
- Daily Kos
- Freakonomics
- Free exchange
- Furdlog
- Instapundit
- Marginal Revolution
- Social Science Statistics
- Structured Procrastination
- The Becker-Posner Blog
- The Volokh Conspiracy
- Vietnam Quant. Society
- Đỗ Quốc Anh
Lý thuyết & thuật toán
Toán học
Vật Lý
Lỗi tràn bộ đệm (5): căn bản về shellcode
5. Căn bản về shellcode
Để tận dụng khả năng thay đổi điều khiển của một chương trình bằng cách thay đổi địa chỉ trả về của một hàm, ta cần biết cách làm thế nào để bỏ một đoạn mã vào stack và bắt chương trình chạy đoạn mã đó. Hãy xét ví dụ sau đây:
/* --------------------------------------------------------------------- * Example 3: "Hello, World!" using bytecode * --------------------------------------------------------------------- */ char bytecode[] = "\xeb\x1e\x59\xbb\x01\x00\x00\x00\xba\x0e\x00\x00\x00\xb8\x04\x00" "\x00\x00\xcd\x80\xbb\x00\x00\x00\x00\xb8\x01\x00\x00\x00\xcd\x80" "\xe8\xdd\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c" "\x64\x21\x0a"; int main() { int *ret; ret = (int *) &ret + 2; (*ret) = (int) bytecode; }Dịch và chạy cho kết quả sau:
Tuyệt đẹp! Ở đây ta thay địa chỉ trả về của hàm
main()cho nó trỏ vào đoạn mã bytecode – mã máy. Câu hỏi đầu tiên dĩ nhiên là: làm thế nào để viết mã máy? Chẳng ai có thể thuộc lòng tất cả các ánh xạ từ assembly sang mã máy cả, đó là chưa kể các ánh xạ này thay đổi tùy theo hệ điều hành và CPU.Muốn biết viết bytecode như thế nào, ta phải biết assembly. Hai assembler thông dụng nhất cho cấu hình IA-32 là gas và nasm, trong đó gas dùng ngữ pháp AT&T giống như gdb, còn nasm dùng ngữ pháp Intel. Ngữ pháp Intel dễ đọc hơn, nên tôi sẽ dùng nasm làm ví dụ.
Có rất nhiều cách để tìm mã máy của một đoạn lệnh mà ta muốn thực thi, bao gồm các cách sau:
Dùng cách lười thì mình không biết thật sự cái đoạn bytecode đó làm gì, có khi bị chơi khăm có virus trong đó thì tiêu tán thoòng.
Tôi minh họa cách dài trước. Chương trình in “Hello, World!” bằng C trên Linux có thể viết như sau:
int main() { write(1, "Hello, World!\n", 14); }Ở đây ta dùng system call của Unix để sau này minh họa cách viết shellcode (cần system call execve). Hãy xem tiếp (các chú thích sau các dấu “;” là tôi thêm vào để giải thích.)
Bạn nhớ dùng liên kết tĩnh (-static), nếu không thì mã của hàm write() sẽ không được viết vào mã xuất mà sẽ được liên kết lúc load chương trình, và như thế thì ta khó dùng gdb để xem write() làm gì.
Xem có vẻ phức tạp, nhưng ý chính rất đơn giản. Để gọi một system call như write(), ta bỏ mã số của write() vào thanh ghi %eax (write có mã số là 4). Sau đó lần lượt chép các tham số còn lại vào %ebx, %ecx, %edx, rồi chuyển sang kernel mode bằng lệnh int 0×80.
Mã số của các system calls có thể tìm được ở đây:
Dùng ý tưởng vừa học được này, ta có thể viết trực tiếp chương trình in “Hello, World!” bằng assembly như sau:
Dịch và chạy cho kết quả
Viết được “Hello, World!” bằng assembly rồi, nhưng có một vấn đề quan trọng ta phải giải quyết trước khi có thể chuyển nó thành bytecode thật sự. Trong bytecode thì ta không thể để chuỗi “Hello, World\n” vào data segment của chương trình đang chạy (vì data segment không ghi lên được). Ta phải tìm cách nào đó viết “Hello, World!” mà không dùng đến data segment.
Như vậy, chuỗi “Hello, World\n” phải được để ở chỗ nào đó trong text segment của chương trình. Nhưng ta lại cần địa chỉ trên bộ nhớ của chuỗi này để bỏ vào ecx trước khi gọi write(). Có vài cách để giải quyết vấn đề này, bao gồm hai cách sau đây. (Bạn có thể tự sáng tạo thêm cách khác.)
Trong các bài tới tôi sẽ minh họa cả hai cách.