Trao đổi với tôi

http://www.buidao.com

10/16/09

[Virus] Catch me if you can!

12/05/2008
Mục lục bài viết
Catch me if you can!
Trang 2
Click to see real sizeVới những ai quan tâm tới information security, việc hiểu được những người viết virus đã đạt tới những kỹ thuật nào là một điều quan trọng. Bài viết sau đây sẽ giới thiệu, và đi sâu vào phân tích kỹ thuật dưới góc độ của một người đã từng thử nghiệm virus sau nhiều năm để khái quát được một vấn đề và các khía cạnh quanh nó.

1. Giới thiệu:

Từ thuở sơ khai đến nay, các tác giả virus máy tính từ thế hệ này sang các thể hệ khác luôn luôn không ngừng cải tiến và phát triển kỹ thuật để khẳng định khả năng, và tạo ra một cuộc chơi, một sự thách thức so tài trong chính cộng đồng VXer (viruser – người viết virus) và với cộng đồng AVer (Antiviruser). Polymorphism là một trong những kỹ thuật đặc biệt được VXer phát triển trong cuộc chơi đó. Và hơn một thập kỷ trôi qua cùng các cải tiến kỹ thuật, polymorphism vẫn là sự thách thức tiềm ẩn đối với Aver. Thug nghĩ rằng, với những ai quan tâm tới information security, việc hiểu được những người viết virus đã đạt tới những kỹ thuật nào là một điều quan trọng. Bài viết sau đây sẽ giới thiệu, và đi sâu vào phân tích kỹ thuật dưới góc độ của một người đã từng thử nghiệm virus sau nhiều năm để khái quát được một vấn đề và các khía cạnh quanh nó mà có thể bạn chưa biết.
catch_me_8.jpg
2. Kỹ thuật phát hiện virus:

Để có thể hiểu polymorphism một cách dễ hiểu và bài bản nhất, Thug sẽ trình bày khái quát 3 kỹ thuật nói chung hiện nay được sử dụng để phát hiện virus. Điều này giúp bạn đọc hiểu được: polymorphism là gì? Polymorphism khắc chế antivirus product như thế nào?

2.1 Kỹ thuật phát hiện virus dựa trên mẫu byte:

Trước khi polymorphism xuất hiện, kỹ thuật để phát hiện virus được sử dụng là “string scan”. Đó là phương pháp sử dụng một chuỗi các byte theo thứ tự nhất định mà chương trình bình thường không có. Các chuỗi byte này được Aver tìm được khi nghiên cứu virus và lưu trữ thành database của chương trình antivirus. Chương trình diệt virus sẽ quét các file để tìm sự xuất hiện của các chuỗi byte virus trong file. Nếu chuỗi byte của virus xuất hiện, thì khả năng file đã bị nhiễm virus là rất cao. Ví dụ, mẫu byte sau được tìm thấy với virus DOS.Jerusalem-1767:

7F33 C0F2 AF8B D783 C202 B800 4B06 1F0E 07BB 3500 1E06 5053
Tuy nhiên, do một số loại virus có nhiều biến thể khác nhau nên đôi khi, các chuỗi byte có thể sai khác nhau một vài chỗ nên các chương trình AV có thể bỏ qua một số byte. Ví dụ, mẫu sau được lấy từ virus DOS.PCFluII, các dấu “?” là các byte sai khác giữa các biến thể: 50B? 2001 ???? B??? ???? ??B? 2008 ????
2.2 Heuristic analysis:
Với số lượng và chủng loại virus ngày càng nhiều, nếu Aver chỉ dựa trên byte-pattern để phát hiện virus thì đó là một thảm họa. Vì vậy, Aver sáng tạo ra kỹ thuật phân tích theo kinh nghiệm – Heuristic Analysis. Kỹ thuật này dựa trên những đặc tính chung hay gặp ở nhiều loại virus khi tác động vào file như: nhiều PE header, Virtual Size không đúng trong PE header, Entry Point của chương trình nằm ở section cuối … File được quét có một trong những đặc điểm đó sẽ bị nghi ngờ đã bị lây nhiễm. Nhược điểm lớn nhất của Heuristic analysis là thường hay bị false-pơsitive. Nhưng trong đa số trường hợp, nó thực sự hữu dụng.

2.3 Code emulation:

Nếu chỉ bao gồm byte-pattern scanning, heuristic analysis thì chương trình antivirus đó vẫn thực sự chưa hiệu quả. Và một kỹ thuật mới ra đời: code emulation. Đó là kỹ thuật mà trong đó, Aver tạo ra một máy ảo giả lập CPU và memory để bắt chước các mã lệnh mà chương trình được quét sẽ thi hành. Tất nhiên, đây chỉ là giả lập, và không có một mã lệnh thật nào được thi hành trên CPU thật. Chương trình antivirus với bộ giả lập này sẽ có khả năng đọc được các vùng nhớ được sủ dụng bởi chương trình/file được quét, và dễ dàng tìm trong bộ nhớ đó các dấu hiệu của virus như: các byte-pattern, các heuristic.. Trong thực tế, còn nhiều kỹ thuật phát hiện virus/malware khác song vì mục đích của bài viết này không nhằm giới thiệu các phương pháp nghiên cứu/phát hiện virus nên Thug sẽ không đi sâu vào thêm nữa. 3 kỹ thuật nói trên có thể được coi là xương sống của một chương trình antivirus.

3. Virus mã hóa:

3.1 Ý tưởng
Để chống lại kỹ thuật phát hiện theo chuỗi byte và giấu các tính năng, virus được bổ sung khả năng mã hóa (encryption). Một virus mã hóa sẽ bao gốm 2 phần: 1 bộ giải mã (decryptor) và phần virus đã bị mã hóa. Bộ giải mã sẽ giải mã phần virus bị mã hóa và chuyển quyền thi hành cho phần mã vừa mới được giải mã. Việc mã hóa bằng các khóa mã khác nhau với các file bị lây nhiễm khác nhau sẽ tạo ra phần code virus được mã hóa khác nhau. Do đó, sẽ không có một chuỗi byte nào cố định.

3.2 Quá trình lây nhiễm và mã hóa

Xét ví dụ như sau: - File thug4lif3.exe là file PE EXE đã bị nhiễm virus có tính năng mã hóa. - File kayoki.exe là file PE EXE sạch, chưa bị nhiễm virus. Một ví dụ đơn giản về quá trình lây nhiễm:

catch_me_1.jpg

3.3 Mã hóa vẫn chưa đủ - What is Polymorphism??
Thoạt nhìn, virus dường như đã không còn chuỗi byte cố định. Nhưng sự thật thì không phải như vậy. Phần code virus bị mã hóa theo các key khác nhau thì không cần bàn tới. Nhưng nếu bạn tinh ý một chút, thì bạn sẽ nhận ra: bộ giải mã không hề biến đổi. Rõ ràng là, một chuỗi byte cố định của virus sẽ được extract ra từ đây. Vậy làm sao để khắc phục điều này? Câu trả lời xuất hiện vào khoảng tháng 1 năm 1992, khi tác giả Dark Avenger (một vxer người Bulgaria nổi tiếng thời gian đó với những virus tiên phong về mặt kỹ thuật) đưa ra “MtE” – Mutation Engine. MtE không phải là 1 virus, mà thực chất là một module của virus nhằm tạo ra “bộ giải mã biến hình”. Yeah, bộ giải mã và bộ giải mã đó có khả năng biến hình. Đó chính là polymorphism.NOTE: Thực ra, MtE không phải là polymorphism engine đầu tiên, mà là virus 1260. Tuy nhiên, polymorphism sử dụng trong 1260 còn rất thô sơ so với MtE.
Việc tạo ra polymorphism dựa trên ý tưởng rất đơn giản: làm nhiều cách khác nhau để có kết quả cuối cùng giống nhau. Tạo ra nhiều bộ giải mã với các câu lệnh khác nhau, không cái nào giống cái nào, nhưng đều có khả năng giải mã virus. Nó giống như việc 1+2=3, 1+1+1=3, mà 1,5+1+0,5+0,5 cũng bằng 3 mà thôi (..nhưng..liệu có.. 1+1=3 không nhể ;;)?.. ). Giả sử, bạn cần EDX chứa giá trị key giải mã = 1234ABCDh. Có vô vàn cách để gán cho EDX giá trị này: -----[ Cách 1 ]------------------------ mov edx,1234ABCDh ; edx = 1234ABCDh -----[ Cách 2]------------------------ mov edx,1234ABCEh ; edx = 1234ABCEh dec edx ; edx = 1234ABCDh -----[ Cách 3 ]------------------------ mov dx,1234h ; dx = 1234h shl edx,10h ; edx = 12340000h add edx,ABCDh ; edx = 1234ABCDh -----[ Cách 4 ]------------------------ mov edx,9551E8ECh ; edx = 9551E8ECh xor edx,87654321h ; edx = 1234ABCDh -----[ Cách 5 ]------------------- mov eax,2469579Ah ; eax = 2469579Ah sub eax,1234ABCDh ; eax = 1234ABCDh mov edx,eax ; edx = eax -----[ Cách .. ]----------------------- Tóm lại, công việc của một polymorphic engine là tạo ra bộ giải mã với nhiều dạng instruction khác nhau, nhiều cấu trúc khác nhau nhưng vẫn đạt được tới một kết quả cuối cùng giống nhau.

4. Polymorphic decryptor:

4.1 Thuật toán mã hóa:
Trong thực tế, virus có thể áp dụng nhiều kiểu thuật toán mã hóa khác nhau để làm tăng thêm độ phức tạp, gây khó khăn cho antivirus software như: + Mã hóa/giải mã theo nhiều hướng khác nhau + Dùng nhiều khóa mã để mã hóa

+ Mã hóa/giải mã theo nhiều lớp

+ Tăng độ khó thuật toán mã hóa/giải mã. catch_me_2.jpg

Tính phức tạp còn được nâng cao hơn khi:

· Có thể không sử dụng key mã hóa mà sử dụng thuật toán mã hóa không tuyến tính dùng bảng thay thế như W32.Efish

· Có thể không chứa key trong virus. Mỗi lần cần tự giải mã, virus sử dụng brute-force để tìm key.

· Sử dụng thuật toán mã hóa mạnh, sử dụng cách mã hóa theo cặp secret/public key như W32.Crypto

· Sử dụng một khóa mã đặc biệt: sử dụng chính checksum hoặc một đoạn mã của virus làm khóa mã. Nếu Aver đặt break-point hoặc thay bất cứ thứ gì trong thân của virus thì khóa mã sẽ thay đổi, dẫn đến việc trục trặc và virus sẽ không được giải mã. Cách này đã được những lập trình viên chính thống áp dụng vào việc tạo các packer/protector cho software nổi tiếng như Armadillo hoặc Asprotect.

Tuy nhiên, trong bài viết này, Thug sẽ sử dụng cách mã hóa đơn giản dựa trên mã hóa tuyến tính byte-by-byte để bạn đọc dễ hiểu và dễ theo dõi bài viết. Thuật toán dùng để mã hóa là mã hóa XOR/ADD/SUB/ROL/ROR.


12/05/2008
Mục lục bài viết
Catch me if you can!
Trang 2

4.2 Ví dụ về một bộ giải mã/mã hóa:

Đối với XOR, ta có tính chất đặc biệt:

· A XOR B = C -> C XOR B = A Tính chất này được áp dụng để mã hóa virus khá rộng rãi do tính đơn giản và gọn nhẹ

· Khi mã hóa, A sẽ là byte/word/dword cần mã hóa và B sẽ là khóa mã. Dữ liệu đã được mà hóa là C.

· Khi giải mã, C XOR B sẽ trả lại giá trị nguyên vẹn ban đầu.

Để mã hóa bằng phép toán XOR, ta có một ví dụ về bộ khung mã hóa/giải mã (encrypt/decrypt):

catch_me_3.jpg

Bộ giải mã nói trên ứng với hình vẽ A. Phần virus được mã hóa nằm trong khoảng từ E_start đến E_end (“E_” là viết tắt cho Encrypt). Khóa mã là E_val.

Trước khi giải mã:

catch_me_4.jpg

Sau khi giải mã:

catch_me_5.jpg

Đối với ADD/SUB, ROL/ROR là 2 cặp phép toán đối ngẫu, ta có thể sử dụng như sau:

· Nếu ADD là phép toán để mã hóa, thì SUB sẽ là phép toán giải mã và ngược lại.
· D: khi mã hóa: add [edi],khóa_mã
· khi giãi mã: sub [edi],khóa_mã
· Với EDI là con trỏ trỏ tới nơi chứa code cần mã hóa/giải mã
· Với ROL/ROR: tương tự như trên.

4.3 Cấu trúc chung của một bộ giải mã/mã hóa 1 phép toán:

Gọi: catch_me_6.jpg

Thì ta có các bước sau:
catch_me_5.jpg

Các bước thực hiện trên có một số bước có thể hoán đổi cho nhau. VD: bước 2,3,5 có thể hoán vị cho nhau -> ra 4! trường hợp. Bước 7,8 có thể đổi chỗ cho nhau. Bước 1 có thể đổi chỗ cho 2,3 tuy nhiên luôn luôn phải đứng trứoc bước 5... Mỗi bước được thực hiện bằng một tập các câu lệnh khác nhau và được polymorphism engine tạo ra. Mỗi lần tạo ra một bộ giải mã, polymorphism engine sẽ tự chọn lựa sinh ra các tập câu lệnh này một cách ngẫu nhiên. Để tăng tính rắc rối cho bộ decryptor này, giữa các instructions, ta chèn các instructions “rác”, với điều kiện là các instruction “rác” này không ảnh hưởng đến quá trình giải mã. Các polymorphism engine tốt là các engine có thể sinh ra nhiều loại rác, nhiều loại câu lệnh vô nghĩa để giấu các instruction thật. Sự kết hợp giữa tính phức tạp của cấu trúc và sự hỗn loạn của opcode rác tạo nên một bộ giải mã biến hình khó có khả năng bị phát hiện bởi antivirus software dựa trên byte-pattern database. Để đánh lừa hoàn toàn byte-pattern scanner, bạn cần đặt virus của mình trong nhiều lớp mã hóa (hình C). Ngay sau khi polymorhic decryptor lớp thứ nhất xong, là đến công việc của polymorphic decryptor thứ hai, and so on. Nên nhớ rằng, decryptor càng dài bao nhiêu, độ ngốn bộ nhớ cho byte-pattern scanner và thời gian quét càng lớn bấy nhiêu.

4.4 Anti heuristic analyzer – Anti code emulation:

Tất cả chúng ta đều biết rằng, xây dựng nên một thứ gì đó thì khó hơn rất nhiều so với việc phá vỡ nó (thử thì biết, thử cầm con di động mới kính cong ném vào tường thử độ bền rồi cố mà sửa xem hehe) và ngăn chặn bao giờ cũng dễ hơn là sửa chữa (đừng ném điện thoại vào tường nữa thì sẽ ổn thôi ;))...). Trong cuộc chiến không cân sức (hàng trăm người viết virus và một vài người viết antivirus :P) họ cần những công cụ mạnh như heuristic analyzer và code emulator. Chống heuristic và code emulator như thế nào?

Anti heuristic analyzer chính là anti code emulation:

Heuristic “là một đống các điều luật, các rules mà chương được áp dụng với một vấn đề với hy vọng sẽ tìm được một kết quả biết trước” –BlackBaron. Heuristic analyzer làm việc thế nào? Yep, khi bạn có một virus mới, không ai biết virus của bạn có byte-pattern signature như thế nào. Nhưng, AV software vẫn tìm thấy bạn. Đơn giản là virus của bạn có những đặc điểm được nhận dạng là virus được định nghĩa trong “một đống các điều luật, các rules mà chương được áp dụng với một vấn đề”. Heuristic analyzer dùng code emulator, chạy từng instruction, so sánh các thanh ghi, cờ, bộ nhớ ... kiểu như:”Yep, chương trình này đọc file này, ghi file khác, ghi dữ liệu vào ô nhớ này ô nhớ kia, và nó sẽ ghi vào ô nhớ tại địa chỉ 0 thì phải. Có vẻ không giống virus lắm” Vậy, câu hỏi “làm thế nào để diệt heuristic analyzer bằng polymorphism engine” tương đương với “làm thế nào để diệt code emulator bằng polymorphism engine”

4.4.1 Làm thế nào để vượt qua heuristic analyzer?
Đầu tiên, nguyên tắc để vượt qua heuristic analyzer là đừng vi phạm các luật mà AV thường đặt ra. Các rules này rất nhiều, song chủ yếu được extract từ các điểm chung của nhiều loại virus. Để tránh các rules này, hãy tự phát triển kỹ thuật lây nhiễm của chính mình :) Có thể list ra một số heuristic nổi bật: Entry Point của PE nằm ở section cuối cùng Sử dụng FindFirstFile/FindNextFile với tham số “*.exe” rối open bằng CreateFile, map file và ghi vào địa chỉ mapping. SizeOfImage không được làm tròn với alignment Import các API như FindFirstFile, FindNextFile, WriteFile, CreateFile, CreateFileMapping, MapViewOfFile WriteFile .. Sai lệch về kích thước của các section. Sai checksum (với hệ NT) And many more ... Thứ hai, để vượt được code-emulator, tâm niệm trong đầu là nó không phải một CPU hoàn chỉnh. Tìm cách để gây rối loạn cho nó. Một loạt các phương pháp sau được sử dụng: Sử dụng các undocument/MMX/SSE instruction. Rất nhiều instruction loại này không được giả lập. Sử dụng Structure Exception Handling Áp dụng multi-thread cho virus. Sử dụng FPU instruction (Floating Point Unit). Áp dụng metamorphism but it’s another story .. - Self-modifying code Hãy tạo một polymorphic decryptor thật phức tạp (thuật toán, nhiều lớp..) và dựa trên random numbers, áp dụng thật nhiều thread (kể cả fake thread), lồng ghép FPU instructions, SEH .. và cộng thêm kỹ thuật riêng do bạn tự phát triển thì càng tốt.
4.4.2 Vài suy nghĩ khác
Nhưng thử suy nghĩ theo hướng khác. Giả sử virus có mã hóa, nhưng không phải lúc nào cũng giải mã và chạy. Thử tưởng tượng virus đó 50% chạy, 50% không chạy mà chỉ chuyển quyền cho chương trình bị lây nhiễm. Nghĩa là xác suất emulator có thể giả lập quá trình giải mã và các hoạt động của virus cao nhất là 50%. Và 50% còn lại là virus không hoạt động, không giải mã, không lòng vòng qua polymorphic decryptor nữa mà nhảy thẳng vào chương trình chủ. Xác xuất này còn giảm hơn nữa khi virus tự giảm thiểu xác suất giải mã phần mã hóa và lây nhiễm. Suy nghĩ sâu hơn, Thug nhận thấy rằng không có gì thiệt thòi. Bạn muốn một virus tốc độ lây lan nhanh với khả năng bị phát hiện cao hơn hay một virus có tốc độ lây lan chậm hơn nhưng lại khó bị phát hiện hơn?Một virus nếu có các tính năng sau:
1. Anti heuristic mạnh
2. Anti debug mạnh
3. Anti emulator mạnh
4. Polymorphic decryptor mạnh
5. Metamorphic virus
6. Tự giảm thiểu xác suất giải mã và hoạt động thì xem chừng, khả năng phát hiện ra virus đó là rất NHỎ.

5. Thug4Lif3 Polymorphic Engine – TPE

Đây là một polymorphic engine Thug viết cũng đã lâu. Tuy nhiên, theo chủ quan của Thug thì đây là 1 polymorphic engine khá tốt. Bạn có thể tham khảo source code để hiểu công việc của polymorphic engine đã nêu trong bài. Những gì polymorphic engine này có thể làm:
· Tạo decryptor với XOR/ADD/SUB/ROL/ROR
· Decryptor với 10 khối lệnh. Mỗi khối lệnh trên dưới 6 cấu trúc với lựa chọn bất kỳ.
· Hoàn toàn ngẫu nhiên với tất cả: thanh ghi, cấu trúc và thứ tự Có thể tạo ra các opcode như sau:
-----------------------------------------------------------------------------------
1. <Lệnh call/jmp địa với chỉ tức thời
2. <Lệnh call/jmp với thanh ghi 32bit
3. Tất cả các lệnh nhảy có điều kiện:
ja/jna/jc/jnc/jb/jnb/jz/jnz/jae/jbe/jc/jnc /…
4. Lệnh bt/bts/btr/btc giữa các thanh ghi 32bit/16bit với nhau
5. Lệnh bt/bts/btr/btc giữa các thanh ghi 32bit/16bit với tham số 32bit/16bit
6. 16 lệnh set byte:seta/setae/setb/setbe/sete/setg/setge/setl/setle/setno/setne /setnp/setns/seto/setp/sets với tất cả các thanh ghi 8bit.
7. Lệnh bswap với tất cả các thanh ghi 32bit
8. Tất cả các lệnh 1 byte:
nop/clc/stc/std/cld/cmc/inceax/dec eax/cwde/sahf/lahf/db 0D6h/db 0F1h
9. Cấu trúc lệnh: push imm32/16/8 …. pop thanh ghi 32 /16/8bit
10. Cấu trúc lệnh: push thanh ghi 32/16/8bit …. pop thanh ghi 32/16/8bit
11. Các đoạn mã tạo thanh ghi 32bit có giá trị bằng 0 (11 cấu trúc khác nhau)
12. Tất cả các câu lệnh mov từ thanh ghi 32/16/8bit vào thanh ghi 32/16/8bit
13. Tất cả các câu lệnh mov tham số tức thời 32/16/8bit vào thanh ghi 32/16/8bit
14. Tất cả các lệnh rotate của thanh ghi 32/16/8bit với tham số 32/16/8bit: rol/ror/rcl/rcr/shl/shr/sar
15. Tất cả các lệnh rotate của thanh ghi 32/16/8bit với thanh ghi CL:rol/ror/rcl/rcr/shl/shr/sar
16. Tất cả các lệnh tính toán số học của thanh ghi32/16/8bit với tham số 32/16/8bit :add/adc/sub/sbb/and/xor/or/not
17. Tất cả các lệnh tính toán số học của thanh ghi 32/16/8bit với thanh ghi 32/16/8bit :add/adc/sub/sbb/and/xor/or/not
18. Lệnh xchg giữa các thanh ghi 32/16/8bit với các thanh ghi 32/16/8bit 19.
Lệnh cmpxchg giữa các thanh ghi 32/16/8bit với các thanh ghi 32/16/8bit
20. Lệnh xadd giữa các thanh ghi 32/16/8bit với các thanh ghi 32/16/8bit 21.
Lệnh movzx/movsx giữa các thanh ghi 32/16/8bit với các thanh ghi 32/16/8bit 22. Lệnh shld/shrd giữa các thanh ghi 32/16bit với cácthanh ghi 32/16bit 23.
Lệnh imul thanh ghi 32bit với thanh ghi 32bit với tham số 32bit 24.
Lệnh imul thanh ghi 16bit với thanh ghi 16bit với tham số 32bit 25.
Các cấu trúc lệnh thực hiện công việc chỉ 1 thanh ghi tới 1 địa chỉ ô nhớ (4 cấu trúc khác nhau) 26. Các lệnh lodsb/lodsw/lodsd 27. Các lệnh stosb/stosw/stosd 28. Các lệnh mov vào ô nhớ từ các thanh ghi 32/16/8bit (Kể cả ESP, SP)
29. Các lệnh tính toán số học giữa ô nhớ và thanh ghi 32/16/8bit :
add/adc/sub/sbb/and/xor/or/not 30. Các lệnh rotate ô nhớ với thanh ghi CL:rol/ror/rcr/rcl/shl/shr/sar 31. Các lệnh mov vào thanh ghi 32/16/8bit từ ô nhớ 32.
Lệnh shld/shrd giữa ô nhớ với thanh ghi 32bit 33. Các FPU opcode (43 opocde)

fabs/fadd/faddp/fchs/fnclex/fcom/fcomp/fcompp/fcos/fdecstp/fdiv/fdivp/fdivr/

fdivrp/ffree/fincstp/fld1/fldl2t/fldl2e/fldpi/fldln2/fldz/fmul/fmulp/fnclex/fnop/fpatan/

fprem/fprem1/fptan/frndint/fscale/fsin/fsincos/fsqrt/fst/fstp/fsub/fsubp/fsubr/

fsubrp/ftst/fucom/fucomp/fucompp/fxam/fxtract/fyl2x/fyl2xp1

-----------------------------------------------------------------------------------

+ Ví dụ về 2 bộ decryptor sinh ra bởi TPE: [Link trên conmaz]

+ TPE Source code: [Link trên conmaz]

6. Final words
Polymorphic viruses, metamorphic viruses are out there, in the wild. Thực sự, theo quan điểm của Thug, kể cả đã cài cắm BitDefender, NAV, NOD32 .. thì chưa hẳn bạn đã an toàn 100% với virus :P Emulator cannot guarantee anything. Byte-pattern scanners r useless. Nhớ một điều “Hãy biết sợ cảm giác an toàn”, vì có thể đâu đó trên chiếc máy tính thân yêu của bạn, polymorphic viruses vẫn đang âm thầm hoạt động ...
Nguồn: Connections Magazine.com
(Conmaz.com)