Monday, July 04, 2005

Rắc rối hóa chương trình (1)


Trong bài về các chương trình đẹp xấu, vân vân, tôi có nhắc đến các chương trình C được rắc rối hóa (obfuscated C code) và cả một cuộc thi quốc tế hàng năm cho các chương trình này. Sau đây là một ví dụ:
#include 
int O,o,i;char*I="";main(l){O&=l&1?*I:~*I,*I++||(l=2*getchar(),i+=O>8
?o:O?0:o+1,o=O>9,O=-1,I="t8B~pq`",l>0)?main(l/2):printf("%d\n",--i);}
Bạn thử bỏ vài phút nghĩ xem chương trình trên làm gì? Tôi chọn ví dụ này vì nó ngắn. Các ví dụ khác trông "ghê gớm" hơn nhiều: ví dụ 1, ví dụ 2, ví dụ 3.

Thế các chương trình loại này chỉ dùng để đố nhau cho vui, hay có ứng dụng gì khác?

Thử tưởng tượng ta tìm được một phương thức nào đó để viết một chương trình O làm công việc như sau: cho một chương trình P bất kỳ, O sẽ biến P thành chương trình O(P) với chức năng hệt như P, chỉ khác ở chỗ là đọc O(P) ta không thể hiểu được logic của nó, và vì thế ta không biết P thật sự chạy như thế nào. [Kể cả là đọc bằng máy tính hay đọc bằng mắt thường!]

Một chương trình O như vậy có rất nhiều ứng dụng trong mật mã hóa, đánh dấu mờ (watermark) phần mềm, bảo vệ phần mềm (software protection), vân vân.

Ví dụ tôi có một giải thuật tân kỳ nào đó và tôi muốn bán cho người khác để họ dùng giải thuật này trong một chương trình lớn. Tôi viết giải thuật này thành một đoạn mã gọi là P, sau đó tôi gửi O(P) cho người mua và họ có thể dùng O(P) trực tiếp mà tôi không bị tiết lộ giải thuật này. Nói chung, O có thể dùng để chống reverse-engineering. Đây là ứng dụng bảo vệ phần mềm của O.