| Editor Login | Register | ||
| > World > Security |
|
|
| Fighting EPO Viruses Part 2 | ||||
The EPO technique used in Win32.CTX.PhageThe Phage virus doesn"t modify the entry-point of an infected file, instead it scans all over the host code section and searches for API calls generated by Borland or the Microsoft linker. When such code is found, the virus checks that the destination address points somewhere inside the IMPORT section. If the call is really an import call, Phage gets a random number which tells the virus to patch the current processed instruction or to find next one. Figures 1, 2, 3, and 4 below show a few example schemas.
![]() Figure 1. Original application (ENTRYPOINT: 0x1000 – LINKER: BORLAND). ![]() Figure 2. Infected application (ENTRYPOINT: 0x1000 – LINKER: BORLAND). ![]() Figure 3. Original application (ENTRYPOINT: 0x1039 – LINKER: MICROSOFT). ![]() Figure 4. Infected application (ENTRYPOINT: 0x1039 – LINKER: MICROSOFT). The above schemas show how the CTX.Phage EPO virus works. As mentioned before, the virus injects the call instruction by overwriting it with a randomly found call. As the application size grows (and also the injected call range from the entry-point), it becomes increasingly difficult to find the injection of the virus. On the other hand, while using this EPO technique reduces the risk of virus execution, there are also some cases when the "call-to-virus" will not be executed at all. At this point, let"s find a way to detect such injections such that it does not cause false alarms. Finding the virus injectionHow difficult is it to find CTX.Phage injections? First of all, the virus inserts a call instruction as follows:
Where: Before we go any further, let"s summarize all the information we know about the current EPO: The injection is always done somewhere behind the entry-point. The injected call executes the virus code which is stored always in last section (this bit of information is really helpful).As the reader probably knows, we could simply search for 0xE8 bytes (call opcodes) but there is large possibility that we might find some "suspicious" call that thands in non-call instruction, for example:
As you can see, this is the push instruction, but the scanner finds the E8 byte and could consider it as a call. Unless we don"t want to build up our disassembler engine (which is very long and hard work) we need to find another way. Yes, you guessed it: we need to add a condition for the E8 byte scanning routine, remembering that the call always executes code that resides in last section! Now that everything is clear, here are the conditions we require: temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5; if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + pSH- >Misc.VirtualSize) BAD_CALL = 1;Where: A sample temp_loc calculation might look as follows: Scanned instruction: 00401025 \. E8 58270000 CALL Calculation: temp_loc = 1025 (virtual address) + 00002758 (call destination) + 5 (size of call instruction)If the temp_loc address resides somewhere between last section"s virtual address (start) and the last section"s virtual address + its virtual size, the call is marked as suspicious. Here is the short snippet from the author"s scanner: (searches for call and jump instructions and checks theirs destinations): // --- snip of scanner code ------------------------------------------------ ...(snip)... printf("[+] Starting from offset: 0x%.08x\n",pPE->OptionalHeader.ImageBase + pSHC->VirtualAddress); for (i = 0; (i != pSHC->SizeOfRawData); i++) { loc = (DWORD)((DWORD)mymap + pSHC->PointerToRawData) + i; if ((*(BYTE*)loc) == O_CALL || (*(BYTE*)loc) == O_JMP ) { loc++; temp_loc = (DWORD)((DWORD)pSHC->VirtualAddress + i + (*(DWORD*)loc)) + 5; if (temp_loc >= pSH->VirtualAddress && temp_loc <= pSH->VirtualAddress + \ pSH->Misc.VirtualSize) { printf("[!] Alert: Detected request to %s(0x%.08x) section at: 0x%.08x\n", pSH->Name,pPE->OptionalHeader.ImageBase + temp_loc, \ pSHC->VirtualAddress + pPE->OptionalHeader.ImageBase + i); if (where_ctx == NULL) { where_ctx = (DWORD)(pPE->OptionalHeader.ImageBase + temp_loc); caller = (DWORD)(pSHC->VirtualAddress + \ pPE->OptionalHeader.ImageBase + i); upa = (DWORD)(pSH->VirtualAddress + pPE->OptionalHeader.ImageBase); sv = loc - 1; } count++; } loc--; } } printf("[+] Scan finished, %d suspected instruction(s) found.\n",count); ...(snip)... // --- snip of scanner code ------------------------------------------------While scanning files with this code, I haven"t seen any false alarms, so it is probably one of the best solutions or techniques one can use to find such virus injections. the-r00t | Security Experts TIM |
|
| Bağlantılar: bilgininefendisi.net |
| Open Source Document Project | AUP&TOS |