
                       . .: .:.. :.. .. .:.::. :. ..:
                     <<-=======<
                      .::  : .  .:.
                      . .:...:..
                       ...:: .::.
                      >===== =->>
                     .: .:.. ..:. .: ..:.::. ::.. :.:.


                             I-Worm.Serotonin
                                    by
                                 Benny/29A





 Ladies and gentlemen,
 I am maximaly proud to present you my newest creation, the most complex
 worm project I have ever done. I've been working on this code for almost
 one year. Much time had been spent not only by coding and debugging, but
 also researching in unknown field. I hope you will like the result.

 This worm is the final mix of many new and progresive ideas and
 technologies. Some ideas in this stuff are a bit old and described in some
 articles of mine about some thoughts that I would like to realise; and finaly
 now became the time to change them to working code. And something is A VERY
 HOT NEW stuff, born in my brain sometimes. The worm is pretty huge for assembler
 code - first generation binary size is 32kB and the number may increase in next
 generations. Nevertheless for such a big amount of functions integrated together
 it is not much. Well, this seems to be the top stuff I've ever made in my eyes.

 It is not easy job to describe the whole behavior of the worm in a few lines,
 so the description is divided to sub-articles:

 (1)	Principles of genetic programming (GP)
 (2)	Interneting
 (3)	Microsoft .NET (MSIL PE) EXE file infection
 (4)	E-mail spreading
 (5)	AntiVirus and firewall programs killing

 So, let's start.





 Principles of genetic programming (GP)
 

 There are tons of websitez that deeply describes what the GP is (just visit
 google.com and search), so I will be short. GP is style of programming that
 is inspired from natural biologic evolution - yeah, that thing that created
 so complex biocomputers like you are. By Darwin's theory only the best
 organisms can survive in the wild; they pass their genetic material on then.
 Evolution is done by genetic material pairing and its slow mutation. Pairing
 allows to create not only the good stuff, but also to improve it. Mutation
 increases the probability of abnormal genetic material creation, which is
 done by light random changes in genetic code. [Mutation sometimes causes that
 retarded organism is created, but sometimes the miracle happens and better
 organism got born.] Then it's a matter of time when the suffient variant
 become generated. And which genetic material is good and which not? The one that
 will give the organism chance to survive.

 I decided to took the concept from GP and implement it in Serotonin. Whole code
 is divided to two parts - common code and genotype code. Common code remains same
 for all possible versions of worm. It's the base code which handles all crucial
 operations. Genotype code is that part which may differ in each version. And even
 it is still needed by worm, each part is replaceable, updateable and independent
 from hosting environment (can be used anytime, anywhere). There can be also more
 than one code routine - worm can choose by itself which exact code it will use.
 Such code is very effectively manageable, importable, exportedable and eraseable.
 You can imagine genotype like set of independent procedures of special type
 (so called gens), where each type of gen is used when needed, but which concrete
 gen of needed type will be selected is up to worm.

 Yeah, worm has very flexible modular structure which allows to implement GP. Two
 different copies of worms with different genotypes can exchange them, compile all
 existing gens into one genotype (pairing process) and replace old genotype with the
 new one - in simple words, this gives the worm an ability to update some parts of
 itself and change the behavior of itself at runtime. This can be also called as
 functional morphing.



 Pairing (A+B=C) and mutation (C->Z):


   A       B       C           Z
                 _               _
  (1)     (1)     (1)         (1)
  (2)  +  (2)  = A(2)         (2)A
  (3)     (3)    _(3)_   ->  _(3)_
                  (1)        B(3)
                  (2)B       -
                  (3)_
 
 
 
 That's not all. The worm also supports light mutation (note that this kind of
 mutation is something different from polymorphism/metamorphism), so the amount of
 possible variants ain't equal to number of possible genotype pairs. Each time the
 worm pairs two genotype it also passes the genotype structure and randomly removes
 some gens - but the code garants that there will stay at least one gen of each type,
 so the code still remain functional. And each time the worm executes it randomly
 changes some important variables that specify a behavior of worm (see below). This
 gives the worm pretty good potential to adapt itself to current environment.

 Here is a little example: There is one colony of worms, say at university no.1,
 where most users use MS Outlook. And so the worms will use the gen that can extract
 e-mail addresses from MS Outlook. Mutations working with another gen won't work
 there and they will disappear (die, not survive). In case the worm will spread to
 another network, say at university no.2, where most users use MS Outlook Express,
 most of worms won't be able to work there. But some of them will be mutated so they
 will use another gen which can handle OE and will survive. The worm is adaptable and
 such organisms, by Darwin's theory, have better chances to survive in-the-wild. And
 where they will get that right new gen? See following "Interneting" sub-article.

 Now, the mutation variables. You won't understand them well now, so keep reading
 on and you will got it soon :-) Here comes the list of them:


 source code label	description

 mut_mailnum		number of infected e-mail addresses which will cause the server
			termination.

 mut_sleep_time		number of minutes the worm should spend in sleep mode

 mut_ipsnum		number of IP addresses stored in database which will cause the
			server termination.

 mut_clientnum		number of handled clients which will cause the server
			termination.

 mut_time		number of minutes the server may run. exceeding this limit
			causes the server termination.

 mut_nonstop_traffic	boolean value which says that the server will broadcast every
			recieved genotype on, to all worm in database. this may cause
			the nonstop network traffic among wormnet - worms will exchange
			genotypes without becoming idle. this may theoreticaly flood
			network if bigger count of worms have this option set ON.


 The main purpose of these variables is to reduce amount of running worms in case
 the worm "think" it's spreaded out enough or there's just a need to terminate itself.
 The last variable is present becoz of testing purposes. I'm not sure at all what it
 can cause (I had no large network for deep testing), so let's call it "payload" :-)



 Interneting
 

 Well, that was my primary idea - computer worm simulating how the real biological
 organisms work. Some principles only of course, I'm not God :P
 But if I wanted to simulate a real life in computer network, I had to give my worm
 some elementary social abilities. I had an idea that the worm should communicate
 via its own worm network (wormnet) (communication should be encrypted by some
 asymetric algorithm) by his own communication protocol. It should also be able to
 exchange its genetic information and so update itself and other worms in colony (this
 process should maximally act as a real fucking :). Wormnet MUST be decentralized,
 such like Gnutella P2P network. Here is a description of the model (from
 http://www.limewire.com/index.jsp/p2p):

 "Unlike a centralized server network, the Gnutella network does not use a central
 server to keep track of all user files. To share files using the Gnutella model, a
 user starts with a networked computer, which we'll call "A," equipped with a Gnutella
 " servent" (so called because the program acts as a combination of a "server" and a
 "client"). Computer "A" will connect to another Gnutella-networked computer, "B."
 A will then announce that it is "alive" to B, which will in turn announce to all the
 computers that it is connected to, "C," "D," "E," and "F," that A is alive. The
 computers C, D, E, and F will then announce to all computers to which they are
 connected that A is alive; those computers will continue the pattern and announce to
 the computers they are connected to that computer A is alive. Although the reach of
 this network is potentially infinite, in reality it is limited by "time-to-live"
 ( "TTL") constraints; that is, the number of layers of computers that the request
 will reach. Most Gnutella servents will reject any network messages which have TTL's
 that are excessively high."

 This is the way Serotonin works (for TTL stuff see mut_nonstop_traffic mentioned above).
 It can exchange public keys used for encrypted communication and genotypes, it can
 pair them into one and mutate the result and also it can exchange some strategic
 informations, which are significant for next actions. This means a finishing the
 question about next existence of worm. Worm can completely remove itself from
 infected computer. Immediately after execution it copies itself to address space
 of EXPLORER.EXE and deletes from disk and also removes its data stored in registry.
 While terminating it also removes itself from memory.



 Microsoft .NET (MSIL PE) EXE file infection
 

 I had an idea the worm should be able to infect MSIL-PE-EXE files. Unlike Donut,
 my first virus for .NET, it should be able to implant IL code the way normal file
 viruses infect normal EXE files. Firstly I thought I will have to figure out how
 metadata are stored and invent some algorithm to work with it. I found out .NET
 Framework provides complete, relatively well documented interface for compilers
 (ilasm.exe and csc.exe compilers use it too) that can be (ab)used. It has great
 advantage - worm does not need to understand details of metadata structures, it
 just calls proper functions over COM interface. I also thought that easiest way
 will be just add new section to PE file and inside metadata create reference to IL
 code stored there, but it could not work. Although the PE file was Ok, CLR
 environment wasn't able to execute it. MSIL-PE-EXE files have fixed structure
 and if you will change it a bit, the program won't work. Fortunately I found
 next interface for linkers which the EXE file generation process makes even more
 easier than the original idea could. Although the interface ain't documented
 much (there's almost NO documentation), methods are relatively easy to use and
 it hadn't taken much time to figure out how to make it working.

 The result of my reseach work is worm that can extract metadata from original
 program, implant there new methods (and other needed structures) and generate new
 EXE file with new metadata. After execution of infected program a worm IL code
 gets control, creates normal PE EXE file (worm dropper) and executes it. When
 finished it sets control back to host's IL code so user won't see anything
 suspicious. Even on disk there won't appear anything because the worm deletes its
 dropper file after execution (see above). Worm can recursively walk thru all
 sub-directories on C:\ path and search there for MSIL files. I still can't believe
 it, but it seems so - it works perfectly!

 The worm can infect only files that does NOT have strongname (hash), v-table
 fixups and CLR resource. It can also disable System File Protection under WinXP
 before modifying a victim file (thnx to Ratter/29A!).

 As a bonus I created an include file COR.INC which describes all important CLR
 structures and enables to use CLR functions from inside ASM files. I hope someone
 will find it useful.



 E-mail spreading
 

 Part of worm that handles a spreading is new and original too. At first there is
 a special way to get list of e-mail addresses - the worm have 3 gens for this
 stuff. 1st can extract them from MS Outlook address book, 2nd from MS Outlook
 Express and 3rd can parse all MS Internet Explorer cache and find addresses
 inside html documents. But the way of spreading is mostly impressing. Serotonin
 abuses a bug (or feature?) of MS Outlook Express - this mail client allows to
 include HTML tags, including <script> tag-pair, to plaintext message (!!!) via
 UTF-7 encoding.

 While opening an infected message (no need to click on anything) worm code is
 automaticaly activated. This code will decrypt worm body (Base128 -> binary)
 to the disk and modify registry so the worm will be activated after rebooting.
 This exploit is new stuff, not registered by MS yet.

 On this place I would like to thank Hamdi Ucar (hamdix@verisoft.com.tr). He found
 this bug and helped me with exploit programming. Thanx a lot!



 AntiVirus and firewall programs killing
 

 Worm can terminate many antivirus programs and firewalls via one easy trick - it
 retrieves a list of all active windows and parses their titles. In case some of
 windows contains some sub-string (firewall,dr.web,kasper,spider,virus,nod32,guard,
 anti,amon,avp,avg,avx and rav) the worm terminates owner process. This is a next
 gen routine.





 Well, that was a brief description. There are many interesting algorithms inside
 the code I had not mentioned. I believe an average asm coder will understand my
 source code (there are lot of comments, that's not very usual at me :-), so
 you can study this worm on your own. Before you will start, I have to explain
 some things. Such as structure and terminology of the worm code:



 Genotype is structure consisting of all accessible gens.
 Gen is one independent code routine that may be one of 8 types.
 Code recieves 3 arguments and returns 1 - 2 values.

 Address of GetModuleHandleA API in ESI,
 Address of GetProcAddress API in EDI,
 Additional argument depending on type of gen in EBX,
 1st output value in EAX,
 2nd output value in EBX.

 Type			Description

 GEN_INITWORM		Activated when initializing
 GEN_FINDVICTIMS	Activated when e-mail addresses have to be found.
 GEN_FINDWORM		Activated when valid IP address of worm server is needed.
 GEN_CREATEWORM	Activated when worm file have to be created.
 GEN_SPREADWORM	Activated when worm have to be spread.
 GEN_PAIRGENOTYPES	Activated when two genotypes have to be paired into one.
 GEN_MUTATEGENOTYPE	Activated when paired genotype have to be mutated.
 GEN_CUSTOM		Activated when installing server. This is not crucial gen.

 The worm body consists of
	Main code
	Global variables
	Manifest	(size is variable)

 Manifest structure consists of
	Genotype
	IP storage	(database of used IP addresses of worm)

 Source code consists of
	serotonin.asm	Main source code
	genotype.inc	Genotype structure
	serotonin.txt	This description file

	consts.inc	Used constants
	cor.inc		CLR support
	mz.inc		MZ DOS header support
	pe.inc		PE header support
	win32api.inc	Win32 API structures
	useful.inc	Misc stuff

	avs.inc		Anti-AV & firewall gen
	ie.inc		Find e-mail addresses in MSIE cache
	ol.inc		Find e-mail addresses in Outlook
	wab.inc		Find e-mail addresses in Outlook Express
	fwf.inc		Find IP address via FTP name cache
	fwi.inc		Find IP address brute-force
	cw.inc		Create worm file
	sw.inc		Spread worm file
	p1.inc		Pair two genotypes into one
	m1.inc		Mutate genotype
	dotnet.inc	Infect all MSIL-PE-EXE files on C:\





 And here comes the algorithm of whole worm which should help you understand
 the code. It is divided into more blocks to look more clear. Lines marked
 with *** sign means that a routine that (pseudo)randomly selects one gen
 of specified type is gonna activate.



 Main routine
 
 (1)	initialize
 (2)	check for active copy of worm in memory (named mutex test), JUMP TO (5)
	in such case
 (3)	mutate (randomly change) some code-behavior variables
 (4)	enumerate all running processes and inspect each process
 (5)	unitialize and quit



 Process inspection routine:
 

 (1)	open process
 (2)	check if the process is EXPLORER.EXE, return if not
 (3)	reserve 64MB of memory in EXPLORER.EXE, commit few pages for worm code
 (4)	copy worm code there
 (5)	execute worm code in EXPLORER.EXE address space and return



 Implanted (EXPLORER.EXE) (client) routine
 

 (1)	initialize
 (2)	create named mutex, wait 10 minutes, delete dropper (worm EXE file)
 (3)	erase \Run record from windows registry

 (4)	 *** RANDOM INITIALIZATION ROUTINE

 (5)	load WSOCK32.DLL, get CRYPT32.DLL api addresses
 (6)	generate new public/private key pair

 (7)	 *** RANDOM VICTIM-SEARCH ENGINE

 (8)	initialize WSOCK32.DLL

 (9)	 *** RANDOM WORMNET_IP-SEARCH ENGINE

 (10)	if no IP found
	 *** RANDOM CREATE-WORM ROUTINE
	 *** RANDOM SPREAD-WORM ROUTINE
	and JUMP TO (20)

 (11)	export public key and send it to found IP
 (12)	accept new public key and import it
 (13)	encrypt genotype and send it
 (14)	recieve manifest and decrypt it
 (15)	replace old manifest with the new one

 (16)	 *** RANDOM CREATE-WORM ROUTINE
 (17)	 *** RANDOM SPREAD-WORM ROUTINE

 (18)	encrypt and send report packet
 (19)	disconnect, unitialize WSOCK32.DLL and CRYPT32.DLL
 (20)	create server thread

 (21)	 *** RANDOM CUSTOM ROUTINE

 (22)	wait for server thread termination
 (23)	delete %sysdir%\win32ser.exe
 (24)	erase worm from memory and quit



 Server thread routine
 

 (1)	initialize
 (2)	initialize CRYPT32.DLL and WSOCK32.DLL
 (3)	bind to TCP port 194 and switch to listen mode
 (4)	accept incoming connection
 (5)	accept new public key and import it
 (6)	export public key and send it to client
 (7)	add IP address to database
 (8)	recieve encrypted genotype and decrypt it
 (9)	broadcast genotype to all IP from database

 (10)	 *** RANDOM PAIR-GENOTYPES ROUTINE
 (11)	 *** RANDOM MUTATE-GENOTYPE ROUTINE

 (12)	create manifest based on new genotype and IP database
 (13)	encrypt manifest and send it to client
 (14)	recieve encrypted report and decrypt it
 (15)	analyse report and status variables
	(a) ---> JUMP TO (4)
	(b) ---> terminate server and quit



 Broadcast routine
 

 (1)	send public key
 (2)	recieve new public key and import it
 (3)	encrypt genotype and send it
 (4)	disconnect and select next IP in a loop





 That was the algorithm of the main part of worm. Now algorithms of
 gens are following:



 AVS.INC
 

 (1)	initialize
 (2)	enumerate all windows
 (3)	search for sub-strings
 (4)	kill process if sub-string found



 IE.INC
 

 (1)	initialize
 (2)	get path to MSIE cache
 (2)	allocate one page in heap
 (3)	search in sub-directories for files
 	 (I)	check file
	 (II)	open file
	 (III)	wait some time
	 (IV)	search for mailto: string
	 (V)	append e-mail address to heap (allocate next page if it's needed)
 (4)	return pointer to heap



 OL.INC
 

 (1)	initialize
 (2)	allocate one page in heap
 (3)	connect to active MS Outlook, quit if not active
 (4)	retrieve e-mail addresses
 (5)	append them to heap (allocate next page if it's needed)
 (6)	return pointer to heap



 WAB.INC
 

 (1)	initialize
 (2)	get fullname of default Windows Address Book (WAB) file
 (3)	open WAB file
 (4)	allocate one page in heap
 (5)	search inside WAB for e-mail addresses
 (6)	append them to heap (allocate next page if it's needed)
 (7)	return pointer to heap



 FWF.INC
 

 (1)	initialize
 (2)	load and initialize WSOCK32.DLL
 (3)	enumerate all FTP accounts and try to connect to IP
 (4)	return IP address if found else 0



 FWI.INC
 

 (1)	initialize
 (2)	load and initialize WSOCK32.DLL
 (3)	connect to previously stored IP
 (4)	return IP if it's valid
 (5)	create new IP and try to connect again



 CW.INC
 

 (1)	initialize
 (2)	create file %sysdir%\win32ser.exe
 (3)	correct PE header
 (4)	write PE header
 (5)	write worm code
 (6)	write worm manifest
 (7)	write padding and quit



 SW.INC
 

 (1)	initialize
 (2)	load and initialize WSOCK32.DLL
 (3)	open %sysdir%\win32ser.exe, read to memory
 (4)	change Time for mail message
 (5)	allocate memory for whole message
 (6)	write mail header
 (7)	write UTF-7 encoded HTML code (1st part)
 (8)	encode file to Base128 and write it
 (9)	write UTF-7 encoded HTML code (2nd part)
 (10)	send e-mail to all e-mail addresses
 (11)	release memory and return number of sent e-mails



 P1.INC
 

 (1)	initialize
 (2)	allocate one page of memory
 (3)	copy genotype1 to memory (allocate next page if it's needed)
 (4)	append genotype2 to memory (allocate next page if it's needed)
 (5)	return pointer to new genotype



 M1.INC
 

 (1)	initialize
 (2)	allocate one page of memory
 (3)	for EDX=GEN_INITWORM to EDX=GEN_COUNTOFGENS
	 (I)	get count of genz of this type
	 (II)	check if the gen is only one (copy it in this case)
	 (III)	copy gen in 1:2 probability (allocate next page if it's needed)
	 (IV)	get next gen and JUMP TO (I)
 (4)	return pointer to new genotype and its size



 DOTNET.INC
 

 (1)	initialize
 (2)	load and initialize OLE32.DLL
 (3)	search for files at C:\
 (4)	check and open file, quit if not correct
 (5)	wait some time
 (6)	delete temporary file
 (7)	disable SFP under WinXP for this file
 (8)	create COM objects in memory
 (9)	get properties of entrypoint method
 (10)	check if it's already infected (quit if so)
 (11)	define new entrypoint method - Serotonin()
 (12)	define members for type conversion and others
 (13)	define references
 (14)	open %sysdir%\win32ser.exe
 (15)	allocate memory for IL code
 (16)	allocate memory for file and read content to there
 (17)	copy worm IL code to memory
 (18)	copy dropper to memory for IL code and deallocate memory for file
 (19)	load and initialize MSCORPE.DLL
 (20)	set output filename to s3r0t0nln.3x3
 (21)	set RVA of Serotonin()
 (22)	set RVA for field
 (23)	enumerate all methods
	 (I)	get method RVA
	 (II)	append method IL code to memory
	 (III)	set new RVA of method
 (24)	copy IL code memory to PE
 (25)	set new entrypoint token
 (26)	write metadata
 (27)	re-link and generate output file
 (28)	unitialize and unload MSCORPE.DLL
 (29)	close file and overwrite host file with s3r0t0nln.3x3
 (30)	try to find next file and JUMP TO (4)
 (31)	unitialize COM and quit





 I wanted to implement more gens, but becoz I wanted to publish Serotonin
 in 29A#7 I had to hurry. I had not too much time to finish it all to release
 date. Well, I think 1 year coding one worm is enough so I won't work anymore
 on this worm and new gens. But if you want, you can do it by yourself :-)
 Here is the stuff that hasn't been finished yet (but meant to be):

	GEN_INITWORM
		(-)	anti-debugger stuff

	GEN_FINDVICTIM
		(-)	retrieving e-mail addresses from MSN
		(-)	retrieving e-mail addresses from ICQ

	GEN_CREATEWORM
		(-)	encrypt worm code and create worm file

	GEN_SPREADWORM
		(-)	RAR archive infection routine

	GEN_CUSTOM
		(-)	graphical payload (using OpenGl)





 Yeah, I should not forget to greet Eugen Kaspersky. Once I met him at one AV
 conference and here I would like to say him something:

 *
 your ideas about a future of Internet are crazy. those cyber-IDs, monitoring
 and controling everybody, all that communistic shit looks like well known KGB
 practices to me. if there is someone dangerous to our society, then it is you,
 not me.
 *



 I had debugged whole code many times and I think the code is very stable.
 However, it is possible that there is some bug - I had no large network for
 deep testing. But I don't care, I didn't wanna create perfect worm with maximal
 spreading capabilities, but only to present new ideas and technologies.


 And that's all. If you have any [serious] comments you can e-mail me...





						................................
						.
						.  Jan 25 2003	Benny/29A
						.		benny@post.cz
						.
						... searching for perfection ...