[Vietnamese] Làm thế nào để viết phần mềm diệt vi-rút – B.2 Cơ chế bảo vệ realtime, chức năng bảo vệ 24/7 cho máy tính

Bài trước chúng ta đã nói về cách quét và kiểm tra xem file có phải là vi-rút hay không bằng mã hash. Ở bài này chúng ta sẽ tìm hiểu về cơ chế bảo vệ realtime trong av ra sao. Ở bài này tui sẽ chỉ nói về cơ chế bảo vệ thời gian thực liên quan đến việc truy xuất file.

Chúng ta thường thấy cụm từ bảo vệ thời gian thực (realtime protection) trong các phần mềm av và cũng mường tưởng ra đôi chút về tính năng của nó giờ chúng ta sẽ cùng tìm hiểu cơ chế và cách viết tính năng realtime cho av.

Cơ chế bảo vệ realtime là gì tại sao nên bật nó? Thông thường sao các lần quét vi-rút toàn bộ hệ thống thì các av đã đảm bảo máy tính cho an toàn một phần rồi nhưng do quá trình sử dụng chúng ta thường hay download file, copy file từ ổ usb, cd/dvd hoặc thẻ nhớ, truy cập các thư mục chia sẻ trong công ty/trường học, cài đặt các phần mềm,… cho đến hiện tại đó là tác nhân gây lây nhiễm vi-rút lớn nhất cho máy tính. Dựa trên cơ chế lây nhiễm mà realtime được sinh ra để đảm bảo mỗi khi có file được truy cập (download, copy, thực thi,… ) sẽ luôn được kiểm tra xem có bị nhiễm vi-rút hay không và thông qua đó bảo vệ an toàn cho máy tính.

Vậy cách đơn giản nhất để làm cơ chế bảo vệ realtime như thế nào? Trước khi trả lời câu hỏi thì chúng ta thống nhất đặt tên cho tính năng bảo vệ realtime là realtime engine (và giả sử nó chạy trên hệ điều hành Windows). Để tạo ra realtime engine thì đơn giản chúng ta chỉ cần dùng cơ chế hook để hook các hàm liên quan đến truy cập file như createfile, openfile, writefile, createprocess, movefile… là chúng ta có thông tin được truy cập và dùng tính năng quét bằng hash trong bài trước để kiểm tra xem file được truy cập có bị nhiễm vi-rút hay không. Việc hook các hàm này diễn ra ở user-mode nên sẽ có nhiều hạn chế nên thường chúng ta chỉ dùng với mục đích cá nhân và học hỏi là chính.

Cơ chế hook có nhiều hạn chế vậy nếu muốn bảo vệ tốt hơn thì làm thế nào? Để có thể chặn và kiểm tra được mọi truy cập đến file thì chúng ta phải dùng các driver chạy ở tầng kernel-mode. Một trong các kiểu driver chúng ta có thể dùng là filter driver. Việc viết driver là tương đối khó, đòi hỏi chúng ta có hiểu biết nhất định về kiến trúc hệ điều hành Windows. Nếu bạn không muốn tốn quá nhiều công sức vào việc viết driver thì may mắn cho bạn là có các hãng thứ ba cung cấp driver dạng này và chúng ta chỉ cần dùng API ở tầng User-mode để làm việc với driver.

Realtime engine đơn giản thế thì tại sao lại khó mà không phải hãng nào cũng làm tốt? Việc chặn truy cập file và quét kiểm tra đơn giản là làm gia tăng độ trễ của việc load file của hệ thống và các ứng dụng (với rất nhiều phần mềm av bạn sẽ thấy máy tính chạy nhanh một cách đáng kể khi bạn tắt realtime đi) Và thường thì một ứng dụng được chạy (load lên memory) thì kéo theo việc load tầm vài chục đến cả trăm thư viện khác. Giả sử mỗi file bạn chặn để quét và kiểm tra mất 5-50ms thì với con số file được load như đã nêu thì bạn có thể ước lượng được nó chậm ra sao. Với một số ứng dụng, ứng dụng dạng dịch vụ, COM,… thì việc load chậm sẽ làm cho lỗi và có thể treo ứng dụng và hệ thống. Và việc xử lý không tốt trong engine mà gây lỗi có thể khiến máy tính treo hoặc BSOD (lỗi màn hình xanh). Dó đó việc làm realtime engine đòi hỏi phải tính toán và test cẩn thận trước khi đưa ra.

Vậy làm sao để tối ưu realtime engine khi nó làm máy tính chạy quá chậm? Ngoài các kỹ thuật tối ưu như đã nêu ở bài trước thì các bạn cần phải có thêm một phần mới gọi là cache. Đối với file sạch (không bị nhiễm vi-rút) sau mỗi lần quét ta có thể lưu lại và coi như một local DB chứa các file sạch, trước khi quét ta cần kiểm tra xem file cần quét có nằm trong DB sạch không nếu không thì ta mới tiến hành quét còn có thì ta có thể tiến hành bỏ qua. Việc cache này nếu có đủ thông tin về file sẽ có thể giúp chúng ta dễ dàng giảm độ trễ xuống <1ms cho mỗi file (cho một cấu hình máy tính bình thường dùng ổ HDD).

Vậy cách cache thông tin file ra sao? Trường hợp này sẽ ưu tiên cho tốc độ nên ta thường không lưu hash được cho cả file. Đơn giản chúng ta có thể tính hash đường dẫn + phần đầu + phần cuối file + file size + date modified để làm thông tin so sánh. Mã hash ở đây để có dùng là CRC32/64. Bạn có thể dùng binary search tree để quản lý tìm kiếm trên DB Cache. Các file trên hệ thống thường không cố định (có thể bị xóa hoặc để sang thư mục khác)  nên bạn sẽ phải có timeout cho cache của từng file tránh làm rác DB cache dẫn đến tốn memory và giảm hiệu xuất tìm kiếm.

Vậy khi cập nhật mẫu mới mà trùng với file sạch trong DB cache thì sao? Để giải quyết vấn đề này ta có thể lưu thêm hash của file sạch để lọc ra khỏi DB cache sau mỗi lần cập nhật mẫu.

Kết luận: Vậy là ta có thể hình dung ra cách làm một realtime engine đơn giản cho av ra sao.

Bài tiếp: Làm thế nào để quét và kiểm tra các dòng lây file?

>VVM.

 

 

Advertisements

[Vietnamese] Làm thế nào để viết phần mềm diệt vi-rút – B.1 Quét file bằng mã hash

Giới thiệu: Tui (VVM) làm phần mềm diệt vi-rút (hay còn gọi là anti-virus software – gọi tắt là av) trong khoảng độ 6 năm cho bên CMC InfoSec. Hiện tại tui không còn làm về av nhưng khi nói chuyện và trao đổi với các bạn trong ngành IT thì phần lớn các bạn không hình dung ra cách làm av và nghĩ là làm av rất khó vì vậy tôi viết loạt bài về “Làm thế nào để xây dựng phần mềm diệt vi-rút” để các bạn có thể hình dung ra cách xây dựng một av (mức đơn giản) như thế nào.

AV ngay từ thời cổ xưa của nó vốn khởi chỉ là quét file và kiểm tra xem file đó có phải là vi-rút hay không. Và đến ngày nay tính năng quét file vẫn là tính năng chính và cơ bản nhất của một av. Tui cùng các bạn chúng ta bắt đầu với những câu hỏi.
Vậy làm sao ta biết một file có phải là vi-rút hay không? Có nhiều cách nhưng tui xin chỉ ra một cách cơ bản nhất và phổ biến nhất để nhận biết 1 file có phải là vi-rút hay không, đó là so sánh mã hash (vd: MD5, SHA1, SHA2,…) của file ta cần kiểm tra và tập mẫu vi-rút ta có, nếu 2 mã hash đó trùng nhau thì ta có thể khẳng định đó là file chứa vi-rút và nếu là file không can thiệp sâu vào hệ thống thì đơn giản ta chỉ cần xóa các file chứa vi-rút đi là coi như đã an toàn.

  *hash: Là dạng mã độc nhất được sinh ra từ nội dung nhất định. Tức là mỗi nội dụng khác nhau ta sẽ có một mã hash khác nhau (theo lý thuyết vẫn có tỷ lệ trùng lặp nhất định nhưng rất nhỏ nên ta có thể bỏ qua).
Câu hỏi đặt ra là làm sao ta có mẫu vi-rút? Các nguồn cung cấp mẫu phổ biến là từ diễn đàn chuyên ngành, từ các tổ chức chuyên ngành, từ các dịch vụ như virustotal.com, từ chương trình trao đổi mẫu giữa các hãng phần mềm diệt vi-rút, và từ quá trình thu nhập mẫu từ phía người dùng.

Giả sử bạn có tầm vài trăm đến tầm vài nghìn mẫu vi-rút rồi thì làm thế nào tìm kiếm trong tập mẫu đó? Cách đơn giản nhất là bạn đem so mã hash của file với từng mã hash của các mẫu vi-rút bạn có, nhưng tốt hơn là bạn nên áp dụng các thuật toán sắp xếp đơn giản (vd: Quick Sort, Bubble Sort, Merge Sort,…) và dùng thuật toán binary search để tìm kiếm.

Câu hỏi dẫn thêm là làm thế nào để so sánh hiệu quả với tập mẫu tầm vài triệu mẫu trở lên (đôi khi là cả chục triệu mẫu)? Để trả lời câu hỏi này thì ta bắt đầu phải dùng đến bài toán tối ưu, nhưng trong trường hợp cơ bản nhất thì các bản có thể dùng binary search tree (cây nhị phân tìm kiếm) và rất nhiều phần mềm cũng tận dụng thuật toán này để xây dựng database (DB) cho riêng cho mình. Và nếu dùng binary search tree thì bạn nên dùng self-balancing binary search tree (red-black tree là một dạng đó) hoặc không nếu bạn chỉ làm để tìm hiểu hoặc cung ứng dạng dịch vụ online/cloud thì các bạn có thể dùng hẳn DB (RocksDB, Redis, Riak, MongoDB, PostgresSQL,…) để khỏi phải mất công viết và thử nghiệm DB.

Đó là với một file còn cả một thư mục hay ổ đĩa với cả trăm nghìn (đôi khi là triệu) file + kích thức file khác nhau thì làm thế nào? Thứ nhất về việc quét nhiều file thì các bạn có thể mở nhiều thread/process để duyệt và kiểm tra file (tối ưu hơn thì các bạn có thể phân luồng công việc (vd: thread thì quét file, thread thì tính hash, thread thì tìm kiếm và so sánh với DB,…), và tối ưu cho các thread/process dựa trên tài nguyên của hệ thống). Thứ hai với file lớn thì các bạn có thể phân làm 2 giai đoạn: giai đoạn một chỉ quét vài KByte đầu để kiểm tra xem dữ liệu có trong DB mẫu hay không và nếu có chuyển qua giai đoạn 2 là lấy thêm hash + file size hoặc là tính hash toàn file để chắc chắn là trùng mẫu trong DB (với cách này thì mẫu vi-rút dung lượng lớn các bạn cũng phải làm tương tự).

Vậy ta còn có thể tối ưu được nữa không? Vâng ta vẫn còn có thể tối ưu thêm được nữa . Nếu các bạn hiểu các CPU tính toán thì sẽ biết là CPU sẽ tính toán nhanh với các phép tính dạng số nguyên và nếu tính toán tốt để hạn chế sự trùng lặp thì các bạn có thể dùng CRC32/CRC64 kết hợp với file size để kiểm tra hash một cách nhanh chóng hơn MD5/SHA1/SHA2 tương đối. Ngoài ra cũng nên tận dụng các kỹ thuật tối ưu về cấp phát bộ nhớ (memory), các dạng thuật toán hỗ trợ lock-free/lockless, inline function để có tăng tốc độ tính toán. Và nếu sau này ta có gắn thêm Realtime Engine thì ta còn có thể tận dụng làm tăng tốc độ quét nhanh lên tương đới nữa (bằng cách lưu lịch sử trạng thái file,…).

Vậy còn DB mẫu vi-rút thì quản lý thế nào? Nếu là DB bạn tự xây dụng thì đây cũng là một bài toán cần cân nhắc và tính toán kỹ. DB mẫu có thể tổ chức dưới định dạng nhất định để av sau khi cập nhật về có thể load ngay lên mà không cần thêm công đoạn import,… . Việc thêm và loại bỏ mẫu vi-rút cũng là việc diễn ra thường xuyên, và để hạn chế việc download lại phần không cần nhiết nhiều thì các bạn có thể chia nhỏ DB mẫu thành nhiều tập con dưới dạng các file khác nhau (có thể phân loại dựa theo thời gian, mức độ nguy hiểm, nguồn mẫu,…). Và cũng nói thêm là DB mẫu thì thường rất nhẹ nên chỉ chứa thông tin về mã hash của vi-rút, tên virus (do cách bạn tự đặt hoặc mượn từ các nguồn khác), mức độ nguy hiểm và id để truy vấn thông tin thêm khi cần.

Kết luận: Vậy ta đã biết cách dùng hash để kiểm tra một file có phải là vi-rút hay không. Về quét vi-rút lây file hay còn gọi là vi-rút đa hình là trường hợp đặc biệt tui sẽ nói trong các bài sau.

Bài kế tiếp: Cơ chế bảo vệ realtime, chức năng bảo vệ 24/7 cho máy tính

>VVM.

Posted in AV