Cavity search engine of 29A
Author: Benina REA
Bài viết này chỉ đơn giản là nghiên cứu thuật tóan tìm một “hẫm code” (cavity code) (một lõm code trống) của một file.
Mục đích tìm hẫm code là để inject code tầm bậy tầm bạ vào file.
Bài này tôi dựa vào thuật tóan của Benny and Darkman of 29A.
Đầu tiên chúng ta tham khảo một cấu trúc định nghĩa trước hay dùng của các coder viruz:
Khi đầu một thủ tục hay một hàm, chúng ta bảo lưu các thanh ghi để sau này phục hồi, ta hay dùng lệnh pushad.
Vậy khi pushad thì các thanh ghi push vào stack theo thứ tự như thế nào. Đây là cấu trúc đó:
Pushad_struc struc
Pushad_edi dd ? ;esp+00h
Pushad_esi dd ? ;esp+04h
Pushad_ebp dd ? ;esp+08h
Pushad_esp dd ? ;esp+0ch
Pushad_ebx dd ? ;esp+10h
Pushad_edx dd ? ;esp+14h
Pushad_ecx dd ? ;esp+18h
Pushad_eax dd ? ;esp+1ah
Pushad_struc ends
Mục đích chính dùng cấu trúc này là khi trả về “giá trị trả về” của một thủ tục vào một thanh ghi nào đó mà chúng ta muốn.
Đây là thủ tục chính tìm cavity code :
;-----------------------------------------------------------------------------
; Cavity search engine Benny and Darkman of 29A
;
; Calling parameters:
; ECX = size of search area
; ESI = pointer to search area
; EDI = required size
;
; Return parameters:
; ESI = pointer to cave
;
; Changed registers:
; EAX, EBX, ECX, EDX, ESI, EDI
CSE: pushad
lodsb ; AL = byte within search area
reset_cavity_loop:
xchg eax,ebx ; BL = " " " "
xor edx,edx ; Zero EDX
dec ecx ; Decrease counter
jecxz no_cave_found ; Zero ECX? Jump to no_cave_found
find_cave_loop:
lodsb ; AL = byte within search area
cmp al,bl ; Current byte equal to previous byte?
jne reset_cavity_loop ; Not equal? Jump to reset_cavity_loop
inc edx ; Increase number of bytes found in
; cave
cmp edx,edi ; Found a cave large enough?
jne find_cave_loop ; Not equal? Jump to find_cave_loop
sub esi,edi ; ESI = pointer to cave
mov [esp+04h],esi
no_cave_found:
popad
ret
Chú giải:
-Tham số truyền vào hàm:
ecx : là size của vùng nhớ mà ta muốn search.
esi : Là con trỏ trỏ đến vùng nhớ để search.
edi : là size vùng cave yêu cầu
-Thuật tóan :
Lệnh lodsb là load một byte từ vùng nhớ trỏ đến bởi esi vào eax và esi sẽ tự động tăng lên
Biến ebx chứa tạm byte trước đó loaded để so sánh với byte load sau trong eax.
Chú ý lệnh xchg để hóan đổi byte loaded trong eax qua ebx
Nếu bằng nhau thì có nghĩa là có lõm code.
edx là biến đếm số bytes của lõm code.
Nếu có lõm code tức là al=bl thì so sánh với size yêu cầu (edi).
Nếu tìm thấy thì giá trị trả về trong thanh gi esi.
-Kết quả trả về.
Nếu không tìm thấy thì esi ko đổi
Nếu tìm thấy cave thì addr chứa trong esi
Sau đây là thủ tục trong masm :
peCaveSearchEngine proc
;-----------------------------------------------------------------------------
; Cavity search engine Benny and Darkman of 29A
;
; Calling parameters:
; ECX = size of search area
; ESI = pointer to search area
; EDI = required size
;
; Return parameters:
; ESI = pointer to cave
;
; Changed registers:
; EAX, EBX, ECX, EDX, ESI, EDI
;------------------------------------------------------------------------------
CSE: pushad
;mov al,byte ptr [esi]
;inc esi
lodsb ; AL = byte within search area
reset_cavity_loop:
xchg eax,ebx ; BL = " " " "
xor edx,edx ; Zero EDX
dec ecx ; Decrease counter
jecxz no_cave_found ; Zero ECX? Jump to no_cave_found
find_cave_loop:
;mov al,byte ptr [esi]
;inc esi
lodsb ; AL = byte within search area
cmp al,bl ; Current byte equal to previous byte?
jne reset_cavity_loop ; Not equal? Jump to reset_cavity_loop
inc edx ; Increase number of bytes found in
; cave
cmp edx,edi ; Found a cave large enough?
jne find_cave_loop ; Not equal? Jump to find_cave_loop
sub esi,edi ; ESI = pointer to cave
;assume esp : ptr Pushad_struc
mov [esp+04h],esi
;assume esp: nothing
no_cave_found:
popad
ret
peCaveSearchEngine endp