/-----------------------------\ | Xine - issue #4 - Phile 100 | \-----------------------------/ A tour over the PE infection How things are ? (okay, I know this part is b0ring) The Portable Executable was introduced with Windows NT. In order of building a TRUE 32 bit windows executable format, Microsoft programmer take the base of the New Executable format and improved it a bit. Since, things had a bit changed and some stuff are now obsolete. But for first from NE change you are in a long 32 bit segment and you don't call in other segs, this segment have reserved area in a paged memory. The Executable is launched in a segment fixed at ring 3 (The upper level of security). As Exe, PE have header that contain the same stuff plus import and export. Import/Export were designed for cooperation between PEs. In fact, PE are designed as win32 executable that theorically works on 100% of windows 32 bit platforms. The complete true is that win32 PE are executable that call libraries who calls the low system level in order of performing system operation. Libraries cover 100% of operations plus all user level operation. This sheme let windows NT control what you are doing depending the user right. Breaking the ring level mean hacking the NT station. Microsoft understood it and NT is a shit for changing segment protection (at least, a lot more than win9x) For the beginners... The PE header have a small image on how the system will have to manage memory for running it. In fact, some physical part of the PE header will be put in memory dependings on system informations. All required memory is divided by sections, some sections are loaded from the disk(physical), some are just allocating memory(virtual) and other aren't used at all(discardable) and just help windows on how to load, sections have flags like code, read, write, etc, etc... In order of infection you have to insert your code somewhere into the memory and change this image and take residency in a way or an other... Okay, this image will be loaded at an address called the Base Address. In this Base Address will be added each segment RVA (Relative Virtual Address). Plus as microsoft seems to have decided so, in the base address will be loaded the MZ header and the PE header. Other segment are loaded after this base address and the 1st segment is quasi allways loaded at 1000h+Base Address. Okay, we are ready to proceed to infection, the standard method is to change the physical and virtual size of the last section and then change the size of the physical datas and then change entrypoint. Okay, all right... Allright ? No, this is suspicious for some reasons, in many PE, the last section equal the ressource or the relocation section, theses section doesn't contain code at all. They just have datas need by windows/process. The entrypoint can't point in a nocode section eh , understood ? This is really annoying. Then some solution were adopted. The 1st solution was a small change introduced by Murkry, using the fact that windows load the header, the header is in image and on disk (the most often) 1000h byte, the pe header is really smaller, then murky virus drop the code over there. The 2nd solution introduced by 29A is based on the com technology, you put in the original entrypoint a jump to your virus and then the virus restore the entrypoint. When restoring the entrypoint, you are overwriting on the code segment, even emulated, this is never done by any kind of code. So when emulating, the avers will just have to detect writing on this segment and leave flags. An other problem is that solution is in some case easy to disinfect even with a really hard polymorphic because many PE start with the same entrypoint that check kernel version and such... The 3th solution was taken by b0z0, he look after the entrypoint and then hook calls. This operation is may be more difficult to do but also more difficult to disinfect because in fact, you have to make a good emulation and detect the good call. But the problem is that you make a call otherwhere than in code segment. The Padania solution was to drop the virus over reloc because they are never used (will explain later). So if the emulation is strong enough, it can detect a jump out of code section limit :( The 5th solution was changing the complete PE header and that in two ways, you can overwrite the PE and save the original information to the end, then when running, you disinfect it and run the original host. This is heurisitcally okay but you have like 1 mega of unused information, appears anyway strange :( The second way was changing the PE header into a new one placed at the end of the program. This is also heuristically free but the PE start at a large offset, things strange because it's the most often at 80h or 100h (except in some borland programs) The 6th solution is performing a mid infection. As does the SK virus, you have to hook some branch of the virus and point it to the virus, this is really hard to detect because avers can't emulate branch, just the entry point and some branch are called in given condition. So the virus is hidden for avers, when you code a mid infector, you see all best anti virus programs fooled. this make really enjoying. But hooking branch is not the only solution, all you have to do is to modify the main host somewhere you are sure that you will hook the entrypoint. But avers detect call out of section, and this is annoying so I had an other solution, some part of the code aren't used at all as exemple a series of int 3, why not drop a part of the poly routine there ? In that way you hide completely the virus entrypoint. Okay, now you saw how to hide us from such problems. Now, the other problem where placing the virus because avers allways think that a virus drop himself at the end of the program. Murky was the 1st to solve this problem by dropping in the header, damn, this guy is allways everywhere before everyone... 29A had an other reponse, if you look at PE, at the end of section you have usuned space, this is because the section alibgment add this space but doesn't use it, This is okay for putting the virus. The virus have to merge himself into it. I mean that maybe the alignement isn't big enough but you will have to put some part of it there and there, you are Padania virus had again a solution, instead of dropping the virus to the last section, he overwritte the reloc section, this is possible because windows doesn't use the reloc section. The reloc section was designed to patch the code section in order to work on other memory range, but this is not anymore used in the win9x system since it use allways the paging system. For win9x, all to do is to set to zero the relocs, for windows NT, it's an other history... This doesn't solve the problem, we call out of the section, how to do otherwise ? Jacky Qwerty had I think a part of the solution , you can compress the Code section (code often compress with 70% to 100% but on megabytes, it count!). The good idea is to compress it and then overwrite it over there. I'm currently working on that idea but forcing a good code compression is hard to do... Back to the 16 bit coding... Dos was totally dead ? In fact, not, you can infect PE from dos of course, you can you infect from win32 PE, 1st dos executable are still loaded from windows, auf course, cause it's runned by the Explorer that call the shell32.dll (I checked , with some undocumented api unfortunately, but dunno with last version of windows), this shell32.dll open the registry, check extension and then launch the PE with the attached program, but you attach a dos program to these programs, there's nothing against that =). This suck I know and you will say how to get residency this 16 bit infected programs, you can launch a 32 bit program that change the memory... How to take easily residency on a win32 system from 16 bit code, the reponse was given when I was debugging a f***** good polymorphic win16 virus. In fact, taking residency from a 16 bit program will let you stay in the global memory and stay activity when you want. But I saw that there was some 16 bit control from DrWatson in win98... Read Kernel Panic's tutorial about this. You can also use NT dos drivers, in windows NT, the dos is simulated, in fact, when you type dir, it call the interrupt that call the Ntoskernl that dispatch to the associated driver. This slow down dos a lot but it make compatible the bit 16 programs and don't stop a true 32 bit os by changing into real mode. Many poeple had problem with 16/32 bit codecs, I know, this is really boring but you can change the code32 status and mute into a code16 status by changing all the configuration of the segment Conclusion Make as you feel guys, you don't have to take care on what to do, and allways try to improve, it's important!