?? normalunpacker.asm
字號:
; Author: Brandon LaCombe
; Date: February 3, 2006
; License: Public Domain
.386
.model flat, stdcall
option casemap:none
include windows.inc
include LoaderStructs.inc
VIRTUALALLOC typedef proto lpAddress:dword, dwSize:dword, flAllocationType:dword, flProtect:dword
VIRTUALFREE typedef proto lpAddress:dword, dwSize:dword, dwFreeType:dword
UNPACK typedef proto pbDest:dword, pbSrc:dword, pbWorkMem:dword
.code
ExportNormalUnpacker proc pdwNormalUnpackerSize:dword
mov eax, pdwNormalUnpackerSize
.if eax
mov dword ptr[eax], normal_unpacker_end - normal_unpacker_start
.endif
mov eax, normal_unpacker_start
ret
ExportNormalUnpacker endp
ExportNormalDefilter proc pdwNormalDefilterSize:dword
mov eax, pdwNormalDefilterSize
.if eax
mov dword ptr[eax], normal_defilter_end - normal_defilter_start
.endif
mov eax, normal_defilter_start
ret
ExportNormalDefilter endp
; In normal packing mode, each section is compressed in place. To decompress
; the section we have to decompress to a buffer and then copy the uncompressed
; section back from that buffer.
normal_unpacker_start:
invoke VIRTUALALLOC ptr[(KERNEL_IAT ptr[ebp]).pVirtualAlloc], ecx, (LOADER_STRUCT ptr[ebx]).dwTotalMemSize, MEM_COMMIT, PAGE_READWRITE
mov esi, eax ; esi = decompression buffer
add eax, (LOADER_STRUCT ptr[ebx]).dwUnpackMemSize ; eax = work memory
mov edx, (LOADER_STRUCT ptr[ebx]).pSectionData ; edx = section data pointer
jmp normal_unpacker_loop_enter ; enter unpacking loop
@@: add edi, (LOADER_STRUCT ptr[ebx]).dwImageBase ; edi = compressed section pointer
pushad ; Unpack doesn't preserve regs
invoke UNPACK ptr[(LOADER_STRUCT ptr[ebx]).pUnpack], esi, edi, eax ; decompress section to unpack mem
shr eax, 2 ; convert decompressed size to size in dwords
mov [esp + 18h], eax ; ecx = uncompressed size (in dwords)
popad ; restore registers
push esi ; movs corrupts esi
rep movsd ; copy uncompressed section back
pop esi ; restore esi
add edx, 4 ; point to next compressed section rva
normal_unpacker_loop_enter:
mov edi, [edx] ; load compressed section rva
test edi, edi ; test for terminating entry
jnz @B ; process section if needed
invoke VIRTUALFREE ptr[(KERNEL_IAT ptr[ebp]).pVirtualFree], esi, edi, MEM_RELEASE
normal_unpacker_end:
normal_defilter_start:
invoke VIRTUALALLOC ptr[(KERNEL_IAT ptr[ebp]).pVirtualAlloc], ecx, (LOADER_STRUCT ptr[ebx]).dwTotalMemSize, MEM_COMMIT, PAGE_READWRITE
mov esi, eax ; esi = decompression buffer
add eax, (LOADER_STRUCT ptr[ebx]).dwUnpackMemSize ; eax = work memory
mov edx, (LOADER_STRUCT ptr[ebx]).pSectionData ; edx = section data pointer
jmp normal_defilter_loop_enter ; enter unpacking loop
@@: add edi, (LOADER_STRUCT ptr[ebx]).dwImageBase ; edi = compressed section pointer
pushad ; Unpack doesn't preserve regs
invoke UNPACK ptr[(LOADER_STRUCT ptr[ebx]).pUnpack], esi, edi, eax ; decompress section to unpack mem
mov [esp + 18h], eax ; ecx = uncompressed size (in dwords)
popad ; restore registers
; defilter code
pushad
sub edi, (LOADER_STRUCT ptr[ebx]).dwImageBase ; compute section rva
mov ebx, edi ; ebx = section rva
mov ebp, esi ; ebp = section pointer
lea edi, [ecx - 5] ; edi = section size - 5
xor esi, esi ; esi = index variable
push -4 ; push -4 to load it into edx
pop edx ; edx = last suspected call index
jmp defilter_loop_enter ; enter the defilter loop
defilter_loop_start:
mov al, [ebp+esi] ; al = current byte
and al, 0FEh ; and al so that E8 and E9 compute to E8
cmp al, 0E8h ; if al is E8 or E9
je defilter_suspected_call ; examine the suspected call
mov eax, [ebp+esi] ; ax = current word
and ah, 0F0h ; and out the low nibble of the first byte
cmp ax, 0800Fh ; is this a jxx instruction?
jne defilter_continue_loop ; if not, continue the defilter loop
inc esi ; jxx is a word sized opcode so point to the end of it
defilter_suspected_call:
mov eax, esi ; eax = index variable
sub eax, edx ; eax = current index - last index
xor al, 3 ; eax = (current index - last index) ^ 3
mov edx, esi ; last index = current index
mov cl, [ebp+esi+4] ; cl = highest byte of absolute call data
inc ecx ; manipulate cl so that only values
shr cl, 1 ; of 0xFF and 0x00 make cl zero
jnz defilter_continue_loop ; if cl is not 0xFF or 0x00, continue the defilter loop
push edi ; backup edi (which is the maximum index allowed)
inc esi ; skip past call opcode and point to absolute call data
mov edi, [ebp+esi] ; edi = relative call data
defilter_recode_loop:
sub edi, ebx ; edi = absolute call data - (section rva + index + 1)
sub edi, esi ; or in other words, convert absolute data to relative data
mov [ebp+esi], edi ; store relative call data
cmp eax, 3 ; only continue if the delta between the last
ja defilter_exit_recode_loop ; two suspected calls is less than or equal to 3
mov ecx, eax ; ecx = delta
shl ecx, 3 ; ecx = delta * 8
mov edi, 0FFh ; edi = 0xFF
shl edi, cl ; edi = 0xFF << (delta * 8)
xor edi, [ebp+esi] ; edi = relative call data ^ 0xFF << (delta * 8)
lea ecx, [esi + eax] ; ecx = address of conflicting byte
mov cl, byte ptr[ebp+ecx] ; cl = conflicting byte
inc ecx ; manipulate cl so that only values
shr cl, 1 ; of 0xFF and 0x00 make cl zero
jz defilter_recode_loop ; if the recode loop loops, it is because the
defilter_exit_recode_loop: ; conflicting byte was 0xFF or 0x00
add esi, 3 ; point to last byte of call data
mov cl, [ebp+esi] ; load in the highest byte of the call data
shr cl, 1 ; test the low bit of the highest byte
setnc ch ; if the low bit is set, then set cl to 0xFF
dec ch ; otherwise set cl to 0x00
mov byte ptr[ebp+esi], ch ; store the 0xFF or 0x00 high byte
pop edi ; restore edi (maximum index allowed)
defilter_continue_loop:
inc esi ; increase index by 1
defilter_loop_enter:
cmp esi, edi ; is index variable in range?
jl defilter_loop_start ; if so, process next byte
popad
push esi ; movs corrupts esi
shr ecx, 2 ; convert decompressed size to size in dwords
rep movsd ; copy uncompressed section back
pop esi ; restore esi
add edx, 4 ; point to next compressed section rva
normal_defilter_loop_enter:
mov edi, [edx] ; load compressed section rva
test edi, edi ; test for terminating entry
jnz @B ; process section if needed
invoke VIRTUALFREE ptr[(KERNEL_IAT ptr[ebp]).pVirtualFree], esi, edi, MEM_RELEASE
normal_defilter_end:
end
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -