/***********************************************************************************/
/*                                                                                 */
/*  WMFA - ICQ Backdoor with include files and two example programs                */
/*  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                */
/*                                                                                 */
/* IMPORTANT NOTICE:                                                               */
/* ~~~~~~~~~~~~~~~~~                                                               */
/* Im NOT responsible for any damages or other abuse or illegal actions done       */
/* by/with this program. It is provided AS IS and it is your risk to use it.       */
/* You may freely distribute this program or parts of it as long as you don't      */
/* modify the "IMPORTANT NOTICE" section of this file.                             */
/*										   */
/* This program creates a "backdoor" using ICQ. It was tested on		   */
/* ICQ 2001b Version 5.18. 							   */
/* 										   */
/* This program is for educational purposes only. 				   */
/* Only YOU are responsible for 						   */
/* what you do with it and for what is done to you by this program. I've tried     */
/* to keep this program bug free, but I CANNOT guarantee that there aren't any     */
/* errors in it.								   */
/*										   */
/* If you do not agree, don't use WMFA or any parts of this software.		   */
/*                                                                                 */
/***********************************************************************************/


		PLEASE EXCUSE MY POOR ENGLISH, IT'S NOT MY MOTHER LANGUAGE



This paper is separated in 6 sections which will follow this order:

	- LIST OF DESCRIBED FILES
		
		List of all important files of WMFA

	- DESCRIPTIONS

		All important files are briefly described in that section

	- HOW WMFA WORKS

		The general concept of how WMFA works is described there

	- USAGE OF WMFAINS.DLL

		There is described how you can use WMFAINS.dll with WMFA.h and WMFA.cpp

	- WMFACONNC
		
		Description of the WMFACONNC.exe example

	- WMFACLIENT
		
		Description of the WMFA control program




Here is a list of all files in this package that are described below. In each directory
there also is an Info.txt file that tells you more about this part of WMFA.

After that section, another one follows that describes how all these files work together.


				LIST OF DESCRIBED FILES
				~~~~~~~~~~~~~~~~~~~~~~~

***************************************************************************************

	[WMFAINS_DLL]

		WMFAINS.dll

	[WMFAINS]

		WMFAINS.exe
		WMFAINSS.bin
		WMFAINSC.bin

	[WMFAINST]

		WMFAINST.exe

	[WMFAIN]

		WMFAIN.exe

	[WMFAUNST]

		WMFAUNST.exe

	WMFA.h
	WMFA.cpp

	[WMFACONNC]
	
		WMFACONNC.exe

	[WMFACLIENT]

		WMFACLIENT.exe
	
****************************************************************************************	
	
				    DESCRIPTIONS
				    ~~~~~~~~~~~~
		Now you will see partial descriptions of each file.


[WMFAINS_DLL]

	WMFAINS.dll
	~~~~~~~~~~~

		This is WMFA's Server DLL Module. It will be loaded into the ICQ Process
		by WMFA so it can provide useful remote control functions.

[WMFAINS]

	WMFAINS.exe
	~~~~~~~~~~~

		This is the program that modifys ICQ.exe's memory at runtime and inserts
		the code in WMFAINSS.bin and WMFAINSC.bin into ICQ's private address space.
		Then it changes the addresses of strlen() and _exit() in ICQ's import
		table to the addresses where the .bin code is located.
 
	WMFAINSS.bin
	~~~~~~~~~~~~

		This contains the code to start WMFAINS.dll.
		
	WMFAINSC.bin
	~~~~~~~~~~~~

		This contains the code to unload WMFAINS.dll.

[WMFAINST]

	WMFAINST.exe
	~~~~~~~~~~~~
		
		This Program will install WMFA on a computer.

[WMFAIN]

	WMFAIN.exe
	~~~~~~~~~~

		This Program is a self-extracting ZIP archive that extracts all WMFA
		files except WMFAUNST.exe to C:\Windows\Temp and then executes 
                C:\Windows\Temp\WMFAINST.exe

[WMFAUNST]

	WMFAUNST.exe
	~~~~~~~~~~~~

		This Program will uninstall WMFA.
WMFA.h
~~~~~~
	This is the header file for WMFA usage. See below.

WMFA.cpp
~~~~~~~~
	This is the cpp file with WMFA functions. See below.

[WMFACONNC]
	
	WMFACONNC.exe
	~~~~~~~~~~~~~

		This is an example program using WMFA. See below.

[WMFACLIENT]

	WMFACLIENT.exe
	~~~~~~~~~~~~~~

		This is a control program for WMFA. See below.

***************************************************************************************

				       HOW WMFA WORKS
				       ~~~~~~~~~~~~~~
			   This is a description of how WMFA works.

- Well, at first, WMFAIN.exe needs to be executed on the target computer. This file is
  a "silent" self-extracting ZIP archive that includes the following files:

	WMFAINS.dll
	WMFAINS.exe
	WMFAINSS.bin
	WMFAINSC.bin
	WMFAINST.exe

  All these files will be automatically extracted to C:\Windows\Temp.
 

- Then, C:\Windows\Temp\WMFAINST.exe will be executed, that does the following:

	- It copies WMFAINS.dll, WMFAINS.exe, WMFAINSS.bin and WMFAINSC.bin to the
	  Windows directory and deletes these files from C:\Windows\Temp.

	- Then, it creates the following registry value:
	  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\WMFAINS
	  After that, it sets its value to: %WINDIR%\WMFAINS.exe

	- At last, it starts %WINDIR%\WMFAINS.exe

- So now WMFAINS.exe is running and will be started whenever Windows reboots. This
  Program does the following:

	- This program waits in the background until ICQ.exe is started.

	- When it detects ICQ, it waits for ICQ to finish initializing.

	- Then, it reads the data in WMFAINSS.bin and copies it into ICQ.exe's private
	  memory at address 0x610000 (somewhere in stack space, I guess).

	- After that, WMFAINS.exe does the same with WMFAINSC.bin at address 0x611000.

	- Then WMFAINS.exe reads the jump table adress of the strlen() function that is
	  located at 0x532658 and copies the address (the value of *(0x532658)) to 0x6101F8.

	- After that, WMFAINS.exe changes the jump table address of the strlen() function
	  that ICQ.exe imports (= *(0x532658)) to 0x610000.

- So why does this make sense? Well, because the jump table address of strlen() has been 
  changed, the next time ICQ calls strlen() it will look up its address, but instead it
  finds 0x610000 and jumps to the code WMFAINS.exe has inserted at this location. So
  this little peace of machine code will do the following:

	- At first, it changes the jump table address of strlen() (= *(0x532658)) to its
	  original value that WMFAINS.exe has saved at 0x6101F8 as mentioned above. So
	  the next time strlen() is called ICQ will approach at the correct address.

	- Then the code loads WMFAINS.dll and saves its handle at 0x610200. 

	- Then, WMFAINSS.bin uses GetProcAddress() to recieve the address of the stdcall
	  function @DoStart$qqsul that WMFAINS.dll exports, Then it saves its address to
	  0x610204.

	- Then, it gets the address of the function @DoQuit$qqsv and saves the address at
  	  0x610208 for later use.

	- After that, 0x610204 (= address of @DoStart$qqsul) is called with the 
          parameter value of 15432. This is the port that WMFAINS.dll's server will be 
          listening on.

	- Then the jump table address of _exit() located at 0x5325C8 will be copied to
	  0x6101FC.

	- Then the address of _exit() (= *(0x5325C8)) is replaced by 0x611000, where 
          WMFAINSC.bin's  code has been loaded by WMFAINS.exe.

	- Finally, it WMFAINSS.bin's code jumps to *(0x532658) (= strlen()'s address)
	  to make the strlen() call continue. So ICQ.exe doesn't notice anything of 
	  what has happened and thinks it has just done a normal strlen() call.

- Now, WMFAINS.dll is loaded in ICQ.exe's address space and acts silently as a server.
  This is described in greater detail below. But now you'll see what happens with
  WMFAINSC.bin:

	- When ICQ.exe quits, it calls _exit(), but it's address has been changed to
          0x611000, so WMFAINSC.bin's code gets executed:

	- This codes calls FreeLibrary() with the libary handle stored at 0x610200 to
	  unload WMFAINS.dll.

	- Then it jumps to the address at *(0x6101FC), which is _exit()'s real address.
	  So ICQ.exe finishes unload and exits.

 

- So quite difficult to understand, isn't it? Don't worry if you didn't understand this,
  just take your time and read this code over and over again and try to imagine what
  happens. If you'd like to disassemble WMFAINSS.bin and WMFAINSC.bin to see what I've 
  coded, I suggest you download the good disassembling utility called HIEW. Just search
  for it, using Google, for instance (http://www.google.com). You will surely find a place
  to download HIEW. 

***************************************************************************************

				USAGE OF WMFAINS.DLL
				~~~~~~~~~~~~~~~~~~~~
		This sections will describe how to use WMFAINS.dll's server

In the WMFA package, there also are two files named WMFA.h and WMFA.cpp. These files 
include several functions.

Please remember that one client can only call ONE function at the same time, so you have to 
wait for the function to  return before your client program can carry on.

   - RmtDoConnect(DWORD IP, WORD Port)

	This function must be called by all WMFAINS.dll clients before then can use it.
	WARNING: You can't establish more than one connection to WMFAINS.dll by the same
        host. Note that at a MAXIMUM 10 CLIENTS can connect to WMFAINS.dll simultaniously.
	You can change this by editing WMFAINS.dll's source code and recompiling it, but
        take care of that the exported functions MUST have the same names as before! (If
	there is a need to manage this that way, you can create a .DEF file (Refer to your 
        compiler's documentation)
	

	- IP 
		The target IP, in network byte order, of the computer running 
                WMFAINS.dll. for example, this can be inet_addr("127.0.0.1");
									^
							   IP as char*  |

	- Port

		The target port on which WMFAINS.dll's Server listens, usually 15432.
		This value must NOT be in network byte order.

   - RmtDoDisconnect()

	This function disconnects you from WMFAINS.dll



   - RmtAccept(...)
   - RmtBind(...)
   - RmtClosesocket(...)
   - RmtConnect(...)
   - RmtListen(...)
   - RmtRecv(...)
   - RmtRecvform(...)
   - RmtSelect(...SEE BELOW...)    SEE BELOW
   - RmtSend(...)
   - RmtSendto(...)
   - RmtSocket(...)  SEE BELOW
   - RmtGetpeername(...)
   - RmtGetsockname(...)
   - RmtIoctlsocket(...)
   - RmtShutdown(...)
   - RmtGetsockopt(...)
   - RmtSetsockopt(...)

	These are the most important socket funtions that work almost exactly like the
	real ones, except for three differences:

		- When pointers to memory locations are expected, you ALWAYS must pass a
		  valid memory address because all data is transferred over the net. So 
		  when you pass 0 or NULL and WMFA.cpp tries to read the value, it will 
		  crash. PLEASE REMEMBER THIS IMPORTANT FACT!

		- RmtSocket(...)

			This function doesnt return a real socket handle, but just one that
			is used by WMFAINS.dll. You can use it the same way as real handles,
			but you should keep that in mind for some reason. The first handle 
			you get from WMFAINS.dll will probably be 0 or 1, then the value
			increases with each new socket. So don't wonder when you have a 
			valid socket handle 0 or 1 or whatever....
			Note that at a MAXIMUM 10 SOCKETS one client can use simultaniously.
			You can change this by editing WMFAINS.dll's source code and 
    			recompiling it, but take care of that the exported functions MUST 
			have the same names as before! (If there is a need to manage this 
			that way, you can create a .DEF file (Refer to your compiler's 
			documentation).

		- RmtSelect(int nfds, SOCKET* readsocket, SOCKET* writesocket, 
                            SOCKET* exceptsocket, timeval* timeout);  

			This function doesn't expect an fd_set as the real one does, but
			can just take one socket as a parameter, so you can't test more
			sockets at one time. Please remember what I've said before:
			YOU MUST ALWAYS PASS VALID POINTERS. So even if you don't need the
			other sockets to be tested, you must pass socket handles whose 
			values you have set to INVALID_SOCKET to avoid problems.

			Please try to keep the timeout's values as small as pssible, at the
			best 1 or 0 milliseconds because you WMFAINS.dll calls a blocking
			operation, it cannot do anything else for you meanwhile as before.



   - ULONG RmtCodeResv(ULONG Size)
   - ULONG RmtCodeFree(ULONG CodeID)
   - ULONG RmtCodeRead(ULONG CodeID, char* buffer, ULONG BufferSize) 
   - ULONG RmtCodeWrite(ULONG CodeID, char* buffer, ULONG BufferSize)
   - ULONG RmtCodeGetAddress(ULONG CodeID)
   - ULONG RmtCodeExec(ULONG CodeID, ULONG Param)
   - ULONG RmtCodeFixGetAddress()
   - ULONG RmtCodeFixExec(char* buffer, ULONG BufferSize, ULONG Param)

	- These functions are used to remotely reserve, transfer and execute code to
	  ICQ.exe running WMFAINS.dll. This is quite complicated and you probably won't
	  need those functions anyway. An example of their usage can be seen below, where
	  WMFACLIENT.exe is described.

		- ULONG RmtCodeResv(ULONG Size)

			This function reserves code space for you and returnes it's handle.

			- Size

				Specifies the size of the code, in bytes.
				Note that you are limited to 20 code handles simultaniously
				to 5000 Bytes max. You can change this by editing 
				WMFAINS.dll's source code and recompiling it, but take care 
				of that the exported functions MUST have the same names as 
				before! (If there is a need to manage this that way, you can
				create a .DEF file (Refer to your compiler's documentation).		
	
   		- ULONG RmtCodeFree(ULONG CodeID)

			This function frees code that has been allocated before using
			RmtCodeResv().

			- CodeID

				The code handle obtained by RmtCodeResv().

   		- ULONG RmtCodeRead(ULONG CodeID, char* buffer, ULONG BufferSize)

			This functions reads the information that is stored inside
			your code area.

			- CodeID

				The code handle obtained by RmtCodeResv().	

			- buffer

				Pointer to an array of chars.

			- BufferSize

				Size, in bytes, of buffer. If this size is smaller than 
				specified in RmtCodeResv(), the code string will be recieved
				from position 0 up to (BufferSize - 1).
	 
   		- ULONG RmtCodeWrite(ULONG CodeID, char* buffer, ULONG BufferSize)

			This functions copies data in your code area.

			- CodeID

				The code handle obtained by RmtCodeResv().	

			- buffer

				Pointer to an array of chars.

			- BufferSize

				Size, in bytes, of buffer. If this size is smaller than
				specified in RmtCodeResv(), the code string will be set
				from position 0 up to (BufferSize - 1).
   		
		- ULONG RmtCodeGetAddress(ULONG CodeID)

			Returns the real address of your code string in WMFAINS.dll
			(= ICQ.exe's memory).

			- CodeID

				The code handle obtained by RmtCodeResv().	

   		- ULONG RmtCodeExec(ULONG CodeID, ULONG Param)

			Executes your code that you have set by RmtCodeWrite().
			Please note that no debugging is done. If you code contains
			a single error, for instance, when you forgot to save register
			values on the stack before changing, WMFAINS.dll (and therefore
			ICQ.exe) will crash. 
			Your code is called as if it was a __cdecl function like this:

				ULONG YourCode(ULONG Param);

			The return value will be returned by RmtCodeExec(). For coding,
			I suggest you get HIEW (search for it, for instance with
			http://www.google.com). DO NOT forget to use 32 Bit mode while
			coding! 

			You could start like this:

			push ebp			; save stack
			mov ebp,esp			; create "local" stack
			push ebx
			push ecx
			push edx
			push esi
			push edi
			.....	
			.....				; your code here
			.....
			pop edi
			pop esi
			pop edx
			pop ecx
			pop ebx
			pop ebp				 ; load "old" stack
			mov eax,1                        ; return value
			retn

			Note that there is no value after "retn", you don't have to do
			parameter clean-up because it's a __cdecl function.			

   		- ULONG RmtCodeFixGetAddress()

			This function returns the real address of the "fixed" code,
			that will always be the same, even after reloading ICQ.
			You can use "fixed" code as private, but prefer private
			code since it's more flexible. 

   		- ULONG RmtCodeFixExec(char* buffer, ULONG BufferSize, ULONG Param)

			This function does the same as RmtCodeWrite() and RmtCodeExec()
			together. At first, it copies buffer into the "fixed" code space, 
			and then executes it passing Param to the code. For more 
			information, see RmtCodeExec() and RmtCodeWrite().

			- buffer
			
				an array of chars that will be copied to the "fixed" code
				space.

			- BufferSize

				Size, in bytes, of buffer (max 5000 Bytes, see RmtCodeResv()
				for more information).

			- Param

				The parameter passed to your code that will be "called" like
				a __cdecl function like this:

				ULONG YourCode(ULONG Param);

			The return value of your code will be returned by RmtCodeFixExec().


***************************************************************************************

					WMFACONNC
					~~~~~~~~~
				Description of WMFACONNC.exe


WMFACONNC.exe is a small connection program using WMFA. You will be showed how to use it
by an example with a chat program, for instance mIRC (Download from http://www.mirc.com).

So do the following exercise:

1) Start mIRC.

2) Click on "File" | "Options..."

3) Select (= click on) "Connect" on the left side

4) Click on the "Add" button on the right side

5) Enter the following:

	Description: WMFATest
	IRC Server: 127.0.0.1
	Port(s): 6667
	Group: WMFATest

6) Click on "OK"

7) In the "IRC Servers" list, select WMFATest

8) Now start WMFACONNC.exe.

9) Enter the following data, notes in <> means fill in the fitting value yourself:

	Remote Server Port: <target port, usually 15432>
	Remote Server IP: <target IP, if you are testing on your own computer, enter
			   127.0.0.1>
	Client Port: 6667
	Real ServerPort: 6667
	Real Server IP: <a chat server, for instance nexgo.de.eu.dal.net>

10) Be sure that you target has running WMFAINS.dll with ICQ.exe and click on
   "Connect to IRC Server".

11) Now you should be connected to the DALnet chat network.

12) Also note that all data sent over WMFACONNC is logged to a file called ConncLog.txt.

***************************************************************************************

					WMFACLIENT
					~~~~~~~~~~

			   WMFACLIENT.exe command Description

WMFACLIENT.exe is a program which can be used to control WMFAINS.dll. It supports quite
a lot of commands, so they will be described here.

The commands will be explained during the following exercise:

1) Start WMFACLIENT.exe and enter the following data:

	Remote Server Port: <target port, usually 15432>
	Target Server IP: <target IP, use 127.0.0.1 for experiments on you own computer>
	Address to connect to: <e.g. a chat server, try nexgo.de.eu.dal.net>
	Port which the server is listening on: <In our case, 6667>

2) Now, you'll get notices like "Found your hostname". Now you must react FAST:

	- Press 'e' and type: 
		NICK WMFATest <Press Enter>

	- Press 'e' and type: 
		USER WMFA "WMFA.com" "127.0.0.1" :WMFA

	- after some seconds you should be logged on the DALnet network.

3) Now, after doing that exercise, I'll explain all available commands:	

	- 'd' : Disconnect (= Quit WMFACLIENT.exe)

	- 'r' : Send raw text (Doesn't postfix message with anything)

	- 's' : Send text, will be postfixed with 0x0A

	- 'e' : Send text, will be postfixed with 0x0D,0x0A

	- 'f' : Send data from file (must enter path name of file)

	- 'c' : Execute coe command, you have to enter a subcommand:

		- 'r': Reserve code space

			Offset: Must be between 0 and 9; this identifys the LOCAL
				offset where your code handle will be stored

			Size: Must be less or equal 5000

		- 'f': Free code

			Offset: Offset you typed when using 'r'

		- 'a': Get real address of your code in WMFAINS.dll

			Offset: Offset you typed when using 'r'

			Note: Address will be showed as HEXADECIMAL number

		- 'l': Load and display data of your code space

			Offset: Offset you typed when using 'r'

		- 'w': Write data in your code space

			Offset: Offset you typed when using 'r'

			
			Load from file: type 'j', and specify a file (File Name:) to load 
 					from, or type 'n', and enter data by hand

		- 'e': Execute code

			Offset: Offset you typed when using 'r'

			Parameter: Parameter value, as DECIMAL number
				   NOTE: You can also specify # as Parameter, if you
					 do so, the real code address which can also be
					 obtained by 'a' will be passed as parameter

		- 'k': Get code size

			Offset: Offset you typed when using 'r'

	
		- 'g': Get real address of "fixed" code in WMFAINS.dll

			Note: Address will be showed as HEXADECIMAL number

		- 's': Load and start fixed code


			Similar to 'w' and 'e', but you don't have to specify an offset;
			see 'w' and 'e' for more information
         

Remote code execution example:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An example code is in the TEST.bin file, which will be used for the following execise:

1) Start WMFACLIENT and connect to nexgo.de.eu.dal.net and log in as described above. 
   HINT: if WMFATest is already used as nickname, try NICK Blabla etc.

2) After you have logged in, press 'c' and press 'r'
   Enter the following: Offset: 0
			Size: 1000

3) Then, press 'c' and press 'w', then enter the following data:

		Offset: 0
		Load from file(j/n)?: j
		File name: TEST.bin

4) now press 'c' and press 'e' and enter:

		Offset: 0
		Parameter: #
		
		(Note: The #-Sign means "pass code address", as described above)

5) The target computer running WMFAINS.dll under ICQ.exe should receive a dialog                  
   box saying: "This is a test!"





	




