Thư viện bài tháng 08 năm 2005

Vạn lý trường … hỏa thành

Ngô Quang Hưng | 31 tháng 08, 2005 | Bản để in Bản để in

Tên tiếng Anh của “Vạn lý trường thành” là “The great wall of China”. Vì nhà nước Trung Quốc đặt tường lửa lọc traffic vào TQ rất chặt chẽ, người ta chơi chữ gọi các tường lửa này là “The great firewall of China“. Đặt tường lửa lọc traffic quá chặt chẽ có thể gây các hậu quả nghiêm trọng cho sự liên kết của Internet thế giới, đó là chưa nói đến các hậu quả chính trị liên quan:

  • Gần đây báo chí Mỹ bắt đầu chú ý nhiều đến việc các hackers từ Trung Quốc tìm cách hack vào các tổ chức lớn của Mỹ (bộ quốc phòng, CIA, bộ ngoại giao). Khoảng hai tuần trước có vài chương trình của CNN về vấn đề này. Tờ WasingtonPost có bài tương tự, tờ Time cũng có. Cho đến nay thì các hackers này chưa thành công, nhưng điểm đáng lo ngại là các hackers này làm việc với qui mô lớn, đến từ rất nhiều mạng khác nhau của TQ.
  • Tờ SecurityFocus cũng vừa có bài về đại hỏa thành và các hacks từ TQ. Một website ở Mỹ bị rất nhiều các requests linh tinh từ khắp nơi trên đất TQ. Khi admin của website tìm nguồn bằng WHOIS thì bị đại hỏa thành ngăn mất. Đại hỏa thành làm cho việc điều tra tội phạm mạng xuất phát từ TQ khó khăn hơn nhiều, trừ khi phải có nhà nước hợp tác. Nếu tình trạng này tiếp diễn thì website nọ sẽ phải ngăn toàn bộ các IPs từ Trung Quốc. Anh chặn tôi, tôi chặn anh!
  • Con worm Zotob vừa rồi, nếu không phải xuất phát từ Thổ Nhĩ Kỳ, mà từ TQ thì FBI đâu có dễ tìm ra thủ phạm và nghi phạm nhanh như thế (2 chàng, rồi 16 nghi phạm nữa).
  • Nếu các nước, tổ chức, websites trên thế giới tường lửa lẫn nhau chặt chẽ thì sẽ băm Internet ra thành nhiều mảnh, phá hỏng toàn bộ mục tiêu và toàn bộ lợi ích của Internet. Thử tưởng tượng Internet bị chia biên giới như biên giới quốc gia, đi đâu cũng phải xin visa, có passport, thì là lãng phí lớn bậc nhất trong lịch sử nhân loại.

Internet bùng nổ theo hàm mũ chỉ trong ba thập niên qua là nhờ nó không có quản lý chiều dọc, cho phép tất cả các người dùng sáng tạo và phát triển các ứng dụng mới, liên kết liên lạc với nhau thoải mái: học hỏi, trao đổi thông tin. Nếu quản lý chiều dọc thì đã không có P2P networks, cả WWW cũng phải chờ rất lâu, rồi Google, newsgroups, emails, Instance messengers, Internet phone, và nghìn vạn các ứng dụng mà ta đang dùng hàng ngày khác.

Ai làm chậm lại sự phát triển của cơ sở hạ tầng không biên giới đầu tiên của nhân loại thì thật là tội nhân thiên cổ, đáng bị vạn lý … lưu đày.

Chủ đề: CNTT các nước và VN & Nhân vật và sự kiện | Bình luận (2) »

Khoa học Việt Nam đang ở đâu?

Ngô Quang Hưng | 30 tháng 08, 2005 | Bản để in Bản để in

Trong hội thảo mùa hè ở Đà Nẵng cuối tháng 7 vừa qua về “tiếp tục đổi mới kinh tế, xã hội để phát triển” có nhiều bài về giáo dục và nghiên cứu khoa học ở VN. Bài của ông Phạm Duy Hiển với tựa đề “Khoa học Việt Nam đang ở đâu” có các số thống kê thú vị. Các bạn xem thử.

Chủ đề: CNTT các nước và VN & Nghiên cứu nghiên kiếc | Bình luận »

Bản đồ Internet

Ngô Quang Hưng | 29 tháng 08, 2005 | Bản để in Bản để in

Không ai trên thế giới có thể biết chính xác rằng có bao nhiêu máy nối mạng Internet (đếm địa chỉ IPs chẳng hạn), hay tổng số người dùng Internet. Hai lý do chính: (1) Internet về bản chất có tính phân bố cực cao, không một người hay tổ chức nào quản lý toàn bộ Internet; (2) Các con số trên thay đổi hàng phút hàng giây. Thậm chí, tổng số các routers (con số “tĩnh” hơn các số trên) cũng không ai biết được.

Vài nơi có ước lượng các số thống kê kiểu này, bao gồm World Fact Book của CIA, hay Computer Industry Almaniac (cũng viết tắt là CIA!). Theo thống kê của ISC thì đến tháng 7 năm 2005, Internet có khoảng hơn 350 triệu hosts. Tổng số người dùng thì đã hơn một tỉ.

Có khá nhiều dự án nhằm vẽ bản đồ Internet, bao gồm:

Tô màu bản đồ Internet cho các hình rất đẹp. Ví dụ, bản đồ dưới đây là của Opte Project:

[ Hình trên có kích thước 400 x 400; các độ phân giải khác: 1024x1024, 4000x4000 ]

MCI (hay MCI Worldcom/UUNET) hiện là ISP lớn nhất thế giới; mạng xương sống (backbone network) của họ đóng vai trò thiết yếu nối Internet toàn cầu. Xem bản đồ mạng xương sống của MCI ở đây.

Các hình ảnh mạng xương sống của các ISP lớn khác có thể xem ở CAIDA. Họ cũng có cả đồ thị nối kết của các Autonomous Systems cho IPv4 và cho IPv6.

Bạn có biết bản đồ các ISP của Việt Nam thì lấy ở đâu không? Hiện nay có bao nhiêu ISP, kích thước ra sao, ai làm chủ, …?

Chủ đề: Mạng máy tính & Trang web hay | Bình luận (1) »

Bài giảng nhân giải Turing của Cerf và Kahn

Ngô Quang Hưng | 26 tháng 08, 2005 | Bản để in Bản để in

Theo truyền thống, sau khi nhận giải Turing thì (những) người đoạt giải sẽ có một bài giảng ở một hội nghị đầu ngành, gọi là Turing Award Lecture. Thứ hai vừa qua (22 tháng 8), các tiến sĩ Vinton Cerf và Robert Kahn có bài giảng ở hội nghị SIGCOMM 2005 tại Philadelphia.

Các bạn có thể nghe bài giảng ở đây (cần Real Player). Bài giảng mang tên: “đánh giá Internet: các bài học, chiến lược tiến triển, và các khả năng trong tương lai“.

Chủ đề: Mạng máy tính & Nhân vật và sự kiện | Bình luận »

Các bài báo kinh điển của KHMT (6)

Ngô Quang Hưng | 25 tháng 08, 2005 | Bản để in Bản để in

Bài báo hôm nay là của các tiến sĩ Vinton CerfRobert Kahn, hai người cùng lãnh giải Turing năm 2004 (công bố tháng 2 năm 2005):

V. Cerf and R. Kahn, A Protocol for Packet Network Interconnection. IEEE Transactions on Communications COM-22, pp. 637-641 , 1974.

Đầu những năm 1960, các ý tưởng khởi điểm về mạng chuyển gói (packet switched networks) dẫn đến mạng ARPANET do DARPA tài trợ. Các nodes trên ARPANET chạy NCP (Network Control Protocol), bắt đầu năm 1970. Cùng năm này packet radio network đầu tiên - ALOHA Net - bắt đầu làm việc. Cùng với sự ra đời của ứng dụng phổ biến nhất trên Internet - email - cuối 71, đầu 72, và phác thảo ý tưởng về Ethernet, Robert Kahn nhận rõ sự cần thiết của việc nối các mạng khác nhau với nhau để chia sẻ tài nguyên và thông tin. Kahn phác thảo ý tưởng về một cấu hình mạng mở (open networking architecture) trong đó các mạng với kiến trúc, cấu hình máy, hệ điều hành … khác nhau có thể nối kết với nhau. Cái mạng của các mạng này được gọi là Internet.

NCP không đủ mạnh để làm việc này. Kahn phát triển giao thức TCP (Transmission Control Protocol), với các thành phần chính như sau:

  • Các mạng con, sau khi nối kết, không phải thay đổi gì (protocol, hệ điều hành, …)
  • Truyền thông sẽ theo kiểu cố hết sức (best effort), nghĩa là bên gửi và bên nhận chịu trách nhiệm truyền lại nếu dữ liệu bị mất hoặc hư hỏng, Internet không chịu trách nhiệm làm việc này.
  • Các gateways sẽ liên kết các mạng con lại với nhau, chịu trách nhiệm chuyển dạng tín hiệu, dạng dữ liệu từ mạng này sang mạng khác.
  • Mạng Internet mang tính phân bố (distributed) cực cao.

(Chú ý rằng ngày nay cấu trúc của Internet y nguyên như thế.)

Còn khá nhiều vấn đề kỹ thuật cụ thể phải giải quyết: xử lý mất packets, packets đến sai thứ tự, cung cấp dịch vụ đáng tin cậy, cách đánh địa chỉ các máy và các tiến trình trong các máy, flow control, giao tiếp với các hệ điều hành khác nhau, vân vân và vân vân.

Đầu năm 1973, Kahn mời thêm Cerf, người rất quen thuộc và góp phần thiết kế và phát triển NCP, để cùng phát triển TCP. Đến tháng 9 năm 1973, Cerf và Kahn báo cáo về công trình của họ ở một hội nghị tại đại học Sussex, Anh quốc. Bài báo trên chứa nội dung chi tiết của các ý tưởng của họ.

Thật ra TCP đầu tiên là viết tắt của Transmission Control Program. Họ muốn nói đến một chương trình sẽ làm công việc truyền dữ liệu giữa các tiến trình của một máy này và các tiến trình của một máy khác trên Internet. Lúc đầu thì IP (Internet Protocol) là một phần của TCP, nhưng đến năm 1978 thì tách ra thành hai protocols riêng biệt ở hai mức khác nhau của thiết kế. Từ đó trở đi, họ protocols này được gọi là họ TCP/IP. Đa phần các máy tính ta đang dùng đều chạy TCP/IP để giao tiếp trên mạng.

Dù có phát triển và thích nghi, các ý tưởng căn bản của TCP/IP đứng vững trước bao nhiêu kỹ thuật mạng mới, bao nhiêu trăm triệu máy mới nối mạng, nghìn vạn các ứng dụng mới của Internet mà dù Cerf và Kahn có mơ cũng không thể thấy hết. Đây là bằng chứng hùng hồn cho một ý tưởng vĩ đại.

Chủ đề: Mạng máy tính | Bình luận »

Tin tặc, hackers, và hồ sơ biệt ngữ

Ngô Quang Hưng | 24 tháng 08, 2005 | Bản để in Bản để in

Luôn dịch hacker thành tin tặc hoặc các từ mang nghĩa xấu khác là sai nghiêm trọng.

Chữ hack trong tiếng Anh có nhiều nghĩa. Dò tự điển Webster thì các nghĩa phổ thông “to manage successfully”, hoặc “to clear or make by or as if by cutting away vegetation” là gần nghĩa kỹ thuật nhất. Hai nghĩa gần đúng và thông dụng là “to write computer program for enjoyment” và “to gain access to computers illegally”. Hack có thể được dịch là “chọc ngoáy”, “mày mò”. Khi ngồi nghịch mã nguồn các device drivers của Linux, ta có thể nói: “I am hacking around with Linux drivers”.

Thế dân kỹ thuật nói gì về hack? Hack/hacker là các biệt ngữ của dân máy tính. Muốn hiểu thật kỹ thì ta phải đọc hồ sơ biệt ngữ hay còn gọi là The Jargon File. Dân máy tính và … hackers nói riêng phải biết các biệt ngữ này.

Giáo sư Raphael Finkel (lúc đó là sinh viên ở Stanford) viết phiên bản đầu tiên của hồ sơ biệt ngữ năm 1975. Đây là bộ sưu tập các biệt ngữ của văn hóa kỹ thuật ở các trường đại học, phòng nghiên cứu nối với nhau ở thời kỳ sơ khai của Internet (mạng ARPANET).

Ý nghĩa chính của hack là “áp dụng sự khéo léo một cách thích đáng”. Kết quả có thể là một đoạn mã chương trình thông minh, hay cả một hệ điều hành. Một nghĩa phụ của hack là trò đùa thực tế (practical joke). Bạn tham khảo phần bàn về định nghĩa hack của hồ sơ biệt ngữ để biết thêm các ví dụ về hack.

Một trong những hacker nổi tiếng nhất thế giới là tiến sĩ Richard M. Stallman, người khởi xướng GNU. Ông viết về ý nghĩa của hacking, rất đáng đọc.

Một trong những ví dụ tếu về hack mà tôi thích là vụ hiện thực hóa RFC 1149. Các RFC (request for comments) là các tài liệu đề cử các chuẩn mới cho Internet. Ví dụ: RFC 793 cho TCP, RFC 791 cho IP. TCP và IP là các protocols thông dụng nhất của Internet.

Ngày cá tháng tư nămg 1990, RFC 1149 đề nghị chuyển dữ liệu qua … lưng chim. Tựa đề của RFC này là “một chuẩn cho việc truyền các gói IP qua vận tải không gian”. Dĩ nhiên đây là một trò đùa cá tháng tư. Thế nhưng đến 28 tháng 4 năm 2001, nhóm người dùng Linux Bergen đã thực hiện thành công vụ chuyển dữ liệu qua lưng chim này. Họ in dữ liệu của các gói IP theo dạng Hex ra giấy, bắt bồ câu kẹp giấy bay qua một hòn núi nhỏ ở Bergen, Na Uy, sau đó dùng một phần mềm nhận dạng chữ in (ORC) để quét dữ liệu từ giấy vào máy bên kia, thiết lập lại gói IP.

Chủ đề: Bảo mật và mật mã học & Thuật ngữ chuyên ngành | Bình luận »

Phần mềm lậu: Việt Nam đứng đầu

Ngô Quang Hưng | 20 tháng 08, 2005 | Bản để in Bản để in

Một press release gần đây của Business Software Alliance báo cáo rằng Việt Nam đứng đầu danh sách các nước dùng phần mềm lậu: 92% các phần mềm được dùng là phần mềm lậu. Vài nước kế tiếp trong danh sách là Ukraine (91%), Trung Quốc (90%), và Indonesia (87%). Mỹ có tỉ lệ dùng phần mềm lậu thấp nhất, ở mức 21%.

Các con số này và cái tên Việt Nam lại vừa được nêu trong số mới nhất của tờ Communications of the ACM. Con số này cũng là một vấn đề quan trọng được thảo luận giữa thủ tướng Phan Văn Khải và Bill Gates trong chuyến thăm Mỹ vừa qua của thủ tướng.

Dân học/làm nghề máy tính mà dùng phần mềm lậu thì chẳng khác gì tự bắn vào chân mình. Ngược lại, có những thứ liên quan thiết yếu đến nghề nghiệp như Visual Studio, sinh viên Việt Nam chẳng đủ tiền mua, thì phải có cách nào đó để nhảy vào cái vòng lặp tai quái này. Không dùng phần mềm lậu thì khó mà học được.

Vấn đề tổng quát hơn: sở hữu trí tuệ - cũng ở tình trạng tương tự. Hơn 90% sách tiếng nước ngoài được in hoặc dịch lậu. Các bản photocopies tràn lan. Đây là báo cáo đặc biệt của International Intellectual Property Alliance. Phim ảnh và nhạc thì không cần phải nói.

Dùng nhiều phần mềm, sách, phim ảnh, nhạc lậu rất dễ biến thành thói quen xấu. Đến khi có đủ khả năng mua ta vẫn không mua. Tự điển Lạc Việt là một ví dụ. Lần vừa rồi về Việt Nam tôi thấy nhiều bạn dùng các sách photo tiếng Việt. Sách tiếng Việt và phần mềm Việt không phải là quá tầm tay của nhiều người. Đây còn là vấn đề tâm lý thú vị: nếu ta chôm vài trăm USD của người khác thì chắc chắn không làm, nhưng ra tiệm chép Windows XP dùng thì chẳng thấy tội lỗi gì.

Vấn đề phức tạp này cần một giải pháp vĩ mô hiệu quả.

Chủ đề: CNTT các nước và VN | Bình luận »

Mười bài học ước gì tôi đã được dạy

Ngô Quang Hưng | 19 tháng 08, 2005 | Bản để in Bản để in

Cố giáo sư Gian-Carlo Rota là người đã mang enumerative combinatorics vào Toán học chính thống. Một trong những học trò của ông, giáo sư Richard Stanley hiện là một trong những cây đại thụ của ngành Combinatorics thế giới.

Năm 1996, Rota có một bài nói chuyện nhan đề mười bài học ước gì tôi đã được dạy. Một trong những bài học mà tôi hay kể cho sinh viên nghe, và bản thân tôi đã ứng dụng thành công (trong một bài báo viết từ năm 1999) là cái mẹo Feynman.

Nhà vật lý lừng danh Richard Feynman rất thích nói về cái mẹo sau đây: muốn trở thành thiên tài, bạn hãy giữ trong đầu khoảng một tá các vấn đề chưa ai giải được. Mỗi khi bạn đọc một bài báo mới, học một kỹ thuật mới, bạn thử áp dụng nó vào một tá bài toán mở đó. Đến lúc nào đó sẽ có một kỹ thuật dùng được cho một trong 12 bài toán, và người ta sẽ thốt lên ngạc nhiên: “tay này quả là thiên tài!”

Trong bài báo năm 1999, một buổi tối tôi đang ngồi thử tìm cách xây dựng một cấu trúc thử nhóm chịu được lỗi, thì nảy ra ý tưởng dùng một khái niệm mới học được từ cấu hình tổ hợp của các đa thức vuông góc. Thế là mày mò ra được một cách xây dựng mới. Chẳng thành được thiên tài như Feynman đã dạy, nhưng có một bài báo mới cũng tốt chán :-). Sau đó vài tác giả khác đã phát triển thêm ý tưởng này.

Hiển nhiên đây là lối nói có phần ẩn dụ. Áp dụng bừa bãi thì chỉ có mất thời gian. Trên thực tế ta phải hiểu rất rõ các bài toán mở đó và kỹ thuật mới học được, sau đó để trực quan hướng đến kết luận là kỹ thuật này dùng được cho một trong những bài đó. Ngược lại, việc áp dụng thành công một kỹ thuật nằm ngoài mong đợi vào một bài toán cổ điển thường cho các kết quả rất tốt.

Các bài học khác của Rota cũng rất thú vị. Các bạn xem thử. Tôi cũng thích quyển indiscrete thoughts của ông.

Chủ đề: Giáo dục & Nhân vật và sự kiện | Bình luận »

Lỗi tràn bộ đệm (4)

Ngô Quang Hưng | 18 tháng 08, 2005 | Bản để in Bản để in

4. Buffer overflow trong cấu hình SPARC 32 bit

Để biết chi tiết hơn về cấu hình SPARC của hãng Sun Microsystem, bạn có thể tham khảo phiên bản 9 của SPARC Architecture Manual.

Thường thì trong cấu hình SPARC mỗi CPU có từ 40 đến khoảng 512 thanh ghi. Trong đó chỉ có 32 thanh ghi hiện hành dành cho một chương trình đang chạy ở bất kỳ thời điểm nào. Mỗi thanh ghi chứa 32 bits. Có 4 nhóm thanh ghi, mỗi nhóm chứa 8 thanh:

  1. Nhóm toàn cục (global): %g0 đến %g7
  2. Nhóm cục bộ (local): %l0 đến %l7
  3. Nhóm nhập (in): %i0 đến %i7

    %i6 chứa FP giống như %ebp trong cấu hình Intel IA-32. Biến %fp cũng trỏ đến %i6 cho tiện.

    %i7 chứa return address của hàm hiện hành. Cấu hình SPARC không PUSH return address vào stack như cấu hình Intel. Tuy vậy, ta vẫn có thể dùng buffer overflow để thay đổi return address với cách làm hơi khác trường hợp của Intel một chút.

  4. Nhóm xuất (out): %o0 đến %o7

    %o6 chứa SP chỉ đến đỉnh của stack frame hiện hành.

    %o7 được dùng để lưu return address cho hàm được gọi (callee) biết trả điều khiển về đâu.

Trong cấu hình SPARC, các tham số hàm, return address, … được truyền cho hàm được gọi dùng các thanh ghi này, thay vì được PUSH vào stack như trong cấu hình Intel.

Khi hàm foo() gọi hàm bar(), ngay trước khi bar() hoạt động thì nội dung các thanh ghi từ %i0 đến %i7, rồi %l0 đến %l7 của foo() được bỏ vào stack trước (tổng cộng 64 bytes), sau đó nội dung của tất cả các thanh ghi %o* được chuyển vào %i*. Như vậy, các thanh ghi xuất của hàm foo() “biến thành” các thanh ghi nhập của hàm bar(). Hàm bar() sau đó sẽ dùng nội dung của %i6 và %i7 để thiết lập lại trạng thái chương trình như cũ khi bar() kết thúc. Các thanh ghi %i0 đến %i5 được dùng để truyền tham số cho bar(). Nếu có nhiều tham số hơn nữa thì phải dùng stack.

Đến đây, ta đã có 64 bytes trên stack frame mới cho bar(). Kế tiếp có 4 bytes trỏ đến một struct nếu bar() trả về một struct. Kế đến có 24 bytes dành cho tham số (trong trường hợp %i0 đến %i5 không đủ dùng). Cuối cùng trên stack là các biến cục bộ của bar().

Để thay đổi dòng hoạt động của chương trình, ta có thể overflow lên nội dung thanh ghi %i7 được lưu trong stack của hàm foo(). Nội dung này là return address sau khi foo() chạy xong. Sau đây là một ví dụ trong cấu hình SPARC:

/* ---------------------------------------------------------------------
 * Vi' du. 3:
 * ---------------------------------------------------------------------
 */
void bar() {
  int buffer[24]; int i;
  (*(buffer+239)) += 8;
}

void bar8() { bar(); }
void bar7() { bar8(); }
void bar6() { bar7(); }
void bar4() { bar6(); }
void bar3() { bar4(); }
void bar2() { bar3(); }
void bar1() { bar2(); }
void foo() { bar1(); }

int main() {
  int x=0; foo(); x=10;
  printf("x = %d\n", x);
  return 0;
}

Lý do mà ta dùng nhiều hàm bar() là để buộc hệ điều hành phải dùng giá trị thanh ghi lưu trong stack thay vì dùng giá trị có sẵn trong thanh ghi. Trong các chương trình thực tế, hệ điều hành sẽ thường phải dùng các thanh ghi làm nhiều việc tính toán khác; và vì thế ta không nhất thiết phải có độ gọi hàm sâu như vậy để hiện thực hóa lỗi tràn bộ đệm.

Chủ đề: Bảo mật và mật mã học | Bình luận (2) »

Lỗi tràn bộ đệm (3)

Ngô Quang Hưng | 17 tháng 08, 2005 | Bản để in Bản để in

3. Tràn bộ đệm trong cấu hình Intel 32-bit

Bạn có thể tham khảo thêm về quá trình gọi hàm và tổ chức stack trong các manuals của Intel cho cấu hình IA-32, đặc biệt là chương 6 của Volume 1: Basic Architecture. Ở đây tôi chỉ tóm tắt các chi tiết chính.

Trong cấu hình i686 như tôi (và đa số các bạn xài PC) đang dùng thì stack phình xuống dưới vùng địa chỉ thấp, heap phình lên trên địa chỉ cao.

Hình dưới đây minh họa vùng nhớ của một process trong Linux.

Hình dưới đây minh họa vùng nhớ của một process trong Windows.

Windows Process Memory Map

Trong miền bộ nhớ của một process, đáy stack bắt đầu từ một vị trí nhất định trong bộ nhớ, đỉnh stack thay đổi theo thời gian và được trỏ tới bởi stack pointer (SP). Giá trị của biến SP nằm trong một thanh ghi (ESP) để truy cập nhanh. Stack chứa vài stack frames. Khi một hàm được gọi, stack frame tương ứng sẽ được PUSH(ed) vào stack. Stack frame của hàm được gọi chứa các tham số, biến cục bộ, và dữ liệu dùng để quay về hàm gọi.

Vì nhiều lý do, các bộ vi xử lý của Intel (IA-32, IA-34), Motorola, SPARC, và MIPS lưu giữ thêm một biến nữa gọi là frame pointer (FP, còn gọi là frame base pointer) trỏ về đáy của frame hiện tại trong stack. Trong cấu hình Intel, thanh ghi chứa base pointer là EBP. Thông thường thì hàm được gọi sẽ chép nội dung của ESP vào EBP trước khi PUSH các biến cục bộ lên stack. Các biến cục bộ, tham số, … thường được truy cập theo địa chỉ tương đối từ FP.

Để nhìn rõ hơn các khái niệm này, ta dịch ví dụ 1 ra Linux assembly dùng gcc. Trình dịch gcc dùng ngữ pháp AT&T cho assembly file.

hqn@hanoi (~/BO/Examples) % gcc -S -o e1.s e1.c

Xem file “e1.c”, vài dòng đầu tiên của hàm foo là:

foo:
     pushl   %ebp
     movl    %esp, %ebp
     subl    $56, %esp

Biến trong thanh ghi (register) %ebp chính là FP cũ (trước khi gọi hàm foo), thanh ghi %esp chứa SP. Khi gọi một hàm mới, ta

  1. Ghi lại %ebp cũ bằng cách PUSH nó vào stack:
            pushl   %ebp

  2. Chép %esp vào %ebp để có FP mới (cho hàm sắp gọi):
            movl    %esp, %ebp

  3. Rồi chuyển SP “lên” đỉnh stack
    
    

(Lưu ý: thông thường thì là thế, nhưng các trình dịch không nhất thiết phải đi theo các bước này, nhất là khi ta chọn cho trình dịch tốt ưu hóa chương trình.)

Như vậy là cái stack frame mới cho foo có kích thước 56 bytes. Tại sao 56 bytes trong khi ta chỉ cần 20 bytes cho biến buffer, 8 bytes cho các biến “i” và “c”, và 8 bytes nữa cho FP cũ và return address (tổng cộng 36 bytes)?

Để hiểu rõ hơn ta phải tham khảo các tài liệu về gcc và các yêu cầu về memory alignment của họ i686. Trình dịch gcc của GNU có một thuật toán allocate memory riêng cho từng cấu hình. Chi tiết này không quan trọng trong thảo luận của chúng ta. (Trong cấu hình i386 và i686, bạn có thể dùng chọn lựa

-mpreferred-stack-boundary

của gcc để ép trình dịch align memory theo số bytes nhất định. Các bộ vi xử lý khác cũng có chọn lựa tương tự.)

/* ---------------------------------------------------------------------
 * Vi' du. 2:
 * ---------------------------------------------------------------------
 */
#include <stdio .h>

void foo(int a, int b) {
  unsigned char buffer[20] = "Hello World";
  unsigned long int i=5;
  unsigned long int c=6;
  (*((int *) (buffer+44))) += 13;
}

int main() {
  int x=1; foo(2, 3); x=4;
  printf("x = %d\n", x);
  return 0;
}

Hừm …, x=1 chứ không phải 4 ? Cái dòng lệnh

  (*((int *) (buffer+44))) += 13;

đã làm gì nhỉ? Số là ta đã truy cập đến địa chỉ trả về của hàm foo và tăng nó lên 13, bỏ qua dòng gán x=1. Tại sao ta biết nhảy lên 13 bytes? Hãy thử disassemble chương trình ex2 bằng gdb. Các chú thích sau các dấu “;” là tôi thêm vào cho rõ.

[hqn@hanoi]:~/BO$ gcc -g ex2.c -o ex2
[hqn@hanoi]:~/BO$ gdb ex2
GNU gdb 6.2-2mdk (Mandrakelinux)
Copyright 2004 Free Software Foundation, Inc.
…

(gdb) disas main
Dump of assembler code for function main:
                        ; main’s prologue
0×080483ae 
: push %ebp 0×080483af
: mov %esp,%ebp 0×080483b1
: sub $0×8,%esp 0×080483b4
: and $0xfffffff0,%esp 0×080483b7
: mov $0×0,%eax 0×080483bc
: add $0xf,%eax 0×080483bf
: add $0xf,%eax 0×080483c2
: shr $0×4,%eax 0×080483c5
: shl $0×4,%eax 0×080483c8
: sub %eax,%esp ; x = 1 0×080483ca
: movl $0×1,0xfffffffc(%ebp) ; preparing to call foo 0×080483d1
: push $0×3 0×080483d3
: push $0×2 ; foo is called, EIP pushed onto the stack 0×080483d5
: call 0×804836c ; returning to main (EIP = 0×080483da) 0×080483da
: add $0×8,%esp ; x = 4 0×080483dd
: movl $0×4,0xfffffffc(%ebp) 0×080483e4
: sub $0×8,%esp ; prepare for printf (13 bytes from the above EIP) 0×080483e7
: pushl 0xfffffffc(%ebp) 0×080483ea
: push $0×80484ec ; printf is called 0×080483ef
: call 0×80482b0 <_init +56> 0×080483f4
: add $0×10,%esp 0×080483f7
: mov $0×0,%eax ; main’s epilogue 0×080483fc
: leave 0×080483fd
: ret End of assembler dump. - oOo -

Ta thấy sau khi gọi foo thì đáng lẽ ta phải trở về lệnh ở địa chỉ 0×080483da (bằng <main+44>). Lệnh này chỉnh %esp lại cho đúng, và lệnh kế tiếp gán 4 vào x. Ta bỏ qua hai lệnh này, tăng địa chỉ trả về lền 13 bytes, vào đúng lệnh ở địa chỉ <main+57>.

Thế tại sao ta lại biết là buffer+44 sẽ là địa chỉ trả về? Dùng disassembler và xem trực tiếp các bytes, ta biết rất rõ cái stack frame cho hàm foo được cấu tạo như thế nào.

Trước hết, hãy xem cấu trúc của hàm foo.

(gdb) disas foo
Dump of assembler code for function foo:
                        ; foo's prologue
0x0804836c :     push   %ebp                   ; save main’s EBP
0×0804836d :     mov    %esp,%ebp              ; new EBP is old ESP
0×0804836f :     sub    $0×38,%esp             ; size of foo’s frame
0×08048372 :     mov    0×80484d8,%eax         ; buffer
0×08048377 :    mov    %eax,0xffffffd8(%ebp)
0×0804837a :    mov    0×80484dc,%eax         ; buffer = “Hello World”
0×0804837f :    mov    %eax,0xffffffdc(%ebp)
0×08048382 :    mov    0×80484e0,%eax
0×08048387 :    mov    %eax,0xffffffe0(%ebp)
0×0804838a :    movl   $0×0,0xffffffe4(%ebp)
0×08048391 :    movl   $0×0,0xffffffe8(%ebp)
0×08048398 :    movl   $0×5,0xffffffd4(%ebp)  ; i = 5
0×0804839f :    movl   $0×6,0xffffffd0(%ebp)  ; c = 6
0×080483a6 :    lea    0×4(%ebp),%eax
0×080483a9 :    addl   $0xd,(%eax)            ; += 13
                        ; foo’s epilogue
0×080483ac :    leave
0×080483ad :    ret
End of assembler dump.

Sau đó, ta dùng gdb để xem stack của foo trong lúc đang chạy:

(gdb) run
Starting program: /home/hungngo/BO/ex1 

Breakpoint 1, foo (a=2, b=3) at ex1.c:11
11        (*((int *) (buffer+44))) += 13;
(gdb) x/30x $esp
0xbffff508:     0x400156f0      0x00000000      0x00000006      0x00000005
0xbffff518:     0x6c6c6548      0x6f57206f      0x00646c72      0x00000000
0xbffff528:     0x00000000      0x40141940      0x00000000      0x080495e0
0xbffff538:     0xbffff548      0x0804828d      0xbffff568      0x080483da
0xbffff548:     0x00000002      0x00000003      0x40141940      0x00000000
0xbffff558:     0x080494f8      0x40141940      0x00000000      0x00000001
0xbffff568:     0xbffff598      0x4003c323      0x00000001      0xbffff5c4
0xbffff578:     0xbffff5cc      0x080482c0

Từ đó, ta hình dung ra chính xác cấu trúc stack của foo như sau

Chủ đề: Bảo mật và mật mã học | Bình luận »

Lại một con worm nữa

Ngô Quang Hưng | 16 tháng 08, 2005 | Bản để in Bản để in

đang lây lan các máy chạy Windows 2000 trên toàn nước Mỹ và vòng quanh thế giới (Đức, và Châu Á). Các chuyên gia tin rằng con worm này tận dụng một lỗ hổng trong dịch vụ plug-and-play của Win2K. Tuần trước Microsoft có một patch lấp lỗ này, nhưng nhiều người chưa kịp lấp.

Kể ra người ta kiên nhẫn với các lỗi phần mềm máy tính một cách khủng khiếp. Ta chẳng bao giờ mua một cái TV mà cứ dăm bữa nửa tháng lại phải cập nhật gì đó, nếu không nó trây ra không chạy, hoặc hở ra là tắt xuống bật lên (re-boot như Win2K bị worm).

WormBlog có thông tin mới nhất về các loại worm. Infosecdaily thu thập thông tin bảo mật. Security focus vừa phỏng vấn Jose Nazario, tác giả của hai websites này nhân vụ Win2K worm. Jose có viết một bài về tương lai của Internet worm năm 2001.

Vài bài báo gần đây về worms và worm simulators:

Gần đây tôi rất quan tâm đến vấn đề mô hình hóa worm propagation trong mạng. Khác với các bài báo trên, con worm mà tôi quan tâm sẽ càng lúc càng mạnh hơn khi lây được vào nhiều nốt mới. [Mạnh = có nhiều thông tin hơn để lây vào các hệ thống khó lây.] Đây là một đề tài nghiên cứu thú vị.

Chủ đề: Bảo mật và mật mã học | Bình luận »

Giới hạn H1B Visa đã đầy

Ngô Quang Hưng | 16 tháng 08, 2005 | Bản để in Bản để in

USCIS thông cáo hôm 12 tháng 8 vừa qua là họ đã đạt đến giới hạn 65000 H1B visas cho năm 2006. Điều này nói chung có nghĩa là không thể xin vào Mỹ làm việc trong năm nay và năm tới. (Giới hạn của 2005 đã đầy từ ngày 1 tháng 10 năm 2004).

Tuy nhiên, nếu bạn có bằng cấp sau đại học của Mỹ, thì vẫn còn khoảng 10 nghìn chỗ cho 2005 (hết hạn ngày 30 tháng 9) và 12 nghìn chỗ cho 2006. Nói cách khác, các tân thạc sĩ và tiến sĩ chưa phải lo lắm về vấn đề visa làm việc, nếu có nơi nhận bảo trợ visa H1B. Còn các chỗ thêm vào này là nhờ một dự luật mà quốc hội Mỹ thông qua cuối năm 2004, cho thêm 20 nghìn visa mỗi năm cho những người tốt nghiệp bằng cấp sau đại học ở Mỹ.

Nhiều công ty và dân trong ngành, từ Bill Gates đến các giáo sư, vẫn càm ràm liên tục về giới hạn H1B này. Ngược lại, cũng có người không đồng ý rằng giới hạn H1B làm tổn hại sự phát triển IT ở Mỹ, như Gerald Cohen, CEO của Information Builder Inc. Nếu bỏ giới hạn H1B này đi thì nước được lợi nhiều nhất là Ấn Độ, sau đó đến Trung Quốc.

Trong tình trạng hiện nay, các sinh viên VN học KHMT bậc đại học ở Mỹ sẽ khó xin việc, trừ khi thật sự giỏi. Đối với sinh viên VN ngành KHMT ở bậc thạc sĩ/tiến sĩ thì visa cap này chưa ảnh hưởng gì trong 2 năm tới. Viết bài tốt, đăng báo nhiều, và bạn sẽ có việc làm nếu muốn.

Quan trọng hơn hết, nếu bạn tốt nghiệp tiến sĩ và xin đi làm researcher ở một phòng lọai lab nhất định, hoặc làm assistant professor ở một trường đại học nào đó thì visa H1B của bạn không nằm trong phạm trù bị giới hạn 65 nghìn visa này. Trang hai của press release của USCIS có một dòng về vấn đề này:

USCIS also notes that petitions for new H-1B employment are not subject to the annual cap at all if the alien will be employed at an institution of higher education or a related or affiliated nonprofit entity, or at a nonprofit research organization or a governmental research organization.

Chủ đề: Dành cho du học sinh | Bình luận »

Lỗi tràn bộ đệm (2)

Ngô Quang Hưng | 15 tháng 08, 2005 | Bản để in Bản để in

Trong loạt bài này, tôi sẽ viết thêm (và học thêm) về các chi tiết kỹ thuật của sự tràn bộ đệm và các cách phòng chống. Một phần của loạt bài này tôi viết đã lâu, nhưng chưa bao giờ tìm ra thời gian viết tiếp. Nay nhân vụ Cisco chọi Michael Lynn, khi lỗi trong IOS của Cisco là lỗi tràn bộ đệm kinh điển, tôi nghĩ vẫn có nhu cầu cần phổ cập hóa kiến thức về cái bug này. (Xem thêm bài trình bày của Michael Lynn do một bạn đọc gửi.)

2. Căn bản về buffer overflow với ngôn ngữ C

Lỗi buffer overflow (hay overrun) khá phổ biến trong các chương trình viết bằng C, vì C không cung cấp cấu trúc dữ liệu mảng (array) kèm kích thước và sự kiểm tra kích thước mảng trước khi dùng. Đây là một trong những cái giá phải trả cho sự hiệu quả (efficiency) của C, ngôn ngữ thông dụng nhất cho lập trình hệ thống.

Với mục tiêu minh họa, C là ngôn ngữ lý tưởng cho các thao tác liên quan đến bộ nhớ, stack, heap, …

Hãy xét một chương trình C nho nhỏ và “vô tội” sau:

/* ---------------------------------------------------------------------
 * Vi' du. 1:
 * ---------------------------------------------------------------------
 */
#include 

void foo() {
  unsigned char buffer[20]; int i=0; int c;
  while ((c = getc(stdin)) != EOF) {
    buffer[i++] = (unsigned char) c;
  }
  buffer[i] = ‘\0′;
  printf("You entered %s\n", buffer);
}

int main() {
  foo();
  return 0;
}

Ta dĩ nhiên có thể dùng stdin làm input cho chương trình. Tuy vậy, để làm ví dụ ta tạo một file dữ liệu làm input cho chương trình này. Tạo một file tên là data với nội dung chỉ có một dòng:

01234567890123456789012345678901234567

Sau khi dịch, bạn thử chạy chương trình:

hqn@hanoi (~/BO/Examples) % e1 < data
You entered 01234567890123456789012345678901234567

Không có vấn đề gì hết. Chương trình làm cái nó được thiết kết để làm. Thử cái khác nhé. Làm cho data dài hơn một byte:

hqn@hanoi (~/BO/Examples) % more data
01234567890123456789012345678901234567*
hqn@hanoi (~/BO/Examples) % e1 < data
You entered 01234567890123456789012345678901234567*
Segmentation fault
hqn@hanoi (~/BO/Examples) %

Tôi chỉ thêm vào data một byte (dấu *) và chương trình đã bị lỗi phân đoạn (segmentation fault). Dễ thấy rằng segmentation fault là do ta đọc vào nhiều bytes hơn là ta đã dành cho buffer (20 bytes). Đây chính là nội dung cơ bản của sự tràn bộ đệm.

Segmentation fault thường xuất hiện khi ta truy cập phần bộ nhớ không thuộc về process hiện hành. Thế nhưng tại sao data file đầu tiên có đến 38 bytes thì vẫn chưa bị tràn mà 39 bytes thì lại bị, trong khi ta chỉ có 20 bytes cho buffer? Ta sẽ trả lời câu hỏi này sau.

Cũng cần chú ý rằng tôi đang dùng gcc phiên bản 3.2. Với gcc phiên bản khác và cấu hình máy khác thì con số 38, 39 có thể khác do stack alignment khác nhau (xem thêm về data alignment trên MSDN). Tuy vậy nguyên tắc overflow này không đổi. Nếu 38 không phải là con số của bạn thì bạn có thể thí nghiệm tăng từ từ kể tử 21 lên đến con số cần thiết cho overflow.

Có thể thấy từ một ví dụ đơn giản này rằng một chương trình nào đó của hệ thống (httpd chẳng hạn), nếu lập trình cẩu thả là đã có thể bị phá hoại dễ dàng. Trong trường hợp này, ít nhất ta có thể làm nó ngưng chạy bằng cách cung cấp nhiều dữ liệu hơn dự tính.

Bạn có thể nghĩ rằng đọc từng byte từng byte một có vẻ không thực tế lắm. Không hẳn thế! Nhiều network protocols dùng các ký tự đặc biệt như ‘\n’ hay ‘\r’ để đánh dấu kết thúc một field nào đó trong packet header. Các TCP sockets cũng chỉ là file descriptors, và ta thường phải kiểm tra từng byte cho đến khi thấy ký tự giới hạn.

Chủ đề: Bảo mật và mật mã học | Bình luận (8) »

Trở lại làm việc

Ngô Quang Hưng | 12 tháng 08, 2005 | Bản để in Bản để in

Sau một chuyến đi dài ngày, đồng bộ hóa lại thời gian và công việc tốn khá nhiều công sức. Một trong những thứ tôi phải bắt lại tốc độ cũ là blogging. Chưa chi đã phải dự vài buổi bảo vệ của sinh viên, chưa có thời gian viết gì về kỹ thuật (dù vẫn muốn viết chi tiết hơn về lỗi tràn bộ đệm sau vụ Cisco vừa qua), tôi muối mặt quảng cáo cho khoa mình vậy.

Robin Li, tốt nghiệp thạc sĩ từ khoa CSE - SUNY Buffalo, là đồng sáng lập viên và CEO của baidu.com, website được mệnh danh là google của Trung Quốc. Ngày 5 tháng 8 vừa qua, baidu “go public” (bắt đầu bán stock cho công chúng đầu tư; tiếng Việt gọi là gì?) và giá stock cuối ngày ở cỡ 122USD, hơn gấp 4 lần giá IPO.

Không biết giáo dục ở khoa giúp Li được bao nhiêu trong thành công này (chuyên ngành lúc Li tốt nghiệp là machine learning/pattern recognition, nên có liên quan mật thiết đến thiết kế search engines). Cái đó không quan trọng lắm. Khoa phải chộp ngay lấy các cựu sinh viên lọai này vì các lý do kinh tế, quảng bá, … Có lẽ không lâu Li sẽ được thưởng vài cái giải alumni xuất sắc - mấy cái giải thưởng mà người thưởng cần hơn người nhận :-).

Dù gì thì gì, mừng cho anh ta!

Chủ đề: Nghiên cứu nghiên kiếc | Bình luận (2) »

CRA khởi tạo một blog mới

Ngô Quang Hưng | 06 tháng 08, 2005 | Bản để in Bản để in

Blog này của CRA sẽ có nhiều thông tin bổ ích liên quan đến khoa học tính toán (computing science) như: tình trạng việc làm, lương bổng, các nhánh nghiên cứu, … của KHMT và các ngành có liên quan.

Một thống kê cho biết tiền tài trợ nghiên cứu KHMT cho các trường đại học ở Mỹ được khoảng 1.3 tỉ USD trong năm 2003, trong đó đa phần vẫn là tài trợ của liên bang (tiền nhà nước). Được nhiều tiền tài trợ nhất vẫn là các ngành y/sinh học.

Tôi thắc mắc con số tương ứng cho Việt Nam là bao nhiêu, so tương đối với tỉ lệ ngân sách quốc gia thì VN nay Mỹ cho các đại học nhiều tiền nghiên cứu hơn?

Chủ đề: Trang web hay | Bình luận (1) »