Archive for the ‘(un)packers’ Category

# faked Adobe PDF.SWF exploit on milw0rm

on July-23, milw0rm uploaded “Adobe Flash (Embedded in PDF) LIVE VIRUS/MALWARE Exploit” written by @hdmoore who states that it’s (I quote) “live exploit sample for the new Flash bug (embedded in PDF)“, which is far from the truth.

the truth is – it’s the old getIcon exploit having nothing to do with the new vulnerability in ActiveScript Virtual Machine. the real worms (described here ) uses PDF with two embedded SWF files, one – triggers the bug, another performs heap-spraying and generates the shell-code on the fly! yeah! it uses Active Script byte-code (which is not plain text like JavaScript, it’s more like Java byte-code) to generate the shell-code, so there is no unescape strings, so my shell-detector fails to find it (of course it fails, it does not support Active Script byte code, at least not yet).

I will write about the real SWF exploit tomorrow. today we’re going talk about that faked exploit. it’s pretty interested as well. the first thing we have to do is to decompress all streams. it’s easy. zlib support that format, we just should write PDF parser… should we?! oh, not really!!!

according to RFC-1950 a zlib stream has the following structure: CMF_FLG (more–>). so, we can just look for CMF_FLG header, trying to decompress every stream we meet – very useful universal decompressor, supporting now only PDF, but much more (HTTP streams for example).

FLG filed has 4 bits FCHECK checksum and the header itself is quite predicable, so it’s easy to find a potential ZLIB header inside a byte stream. how to defeat false positives? (2byte header is too short to be reliable enough). well, no problem guys! if we found something looks like CMF_FLG just try to unpack the first 512 bytes by zlib inflate() function. if it fails it means – false positive, otherwise we have to call it again to unpack the rest.

ok, all streams of hereEvil.pdf are decompressed. 15th stream is JavaScript with a large Array contains unescaped string. looks like a shell-code, but hell no! decode it with a simple deURI converter and… ops!!! another JavaScript!!! yes!!! exploit inside exploit, nested obfuscation. could you believe me?! I just improved my shell-code locator, adding recursive filtering support (zlib-decompror and unescape decoder – basically are external filters for the locator engine). I have not released the new version yet, just was testing in and… wow!!! I met the exploit that really uses the nested JavaScripts for better obfuscation! well, just in time, just in time…

NOTE: if you have no idea how to write deURI decoder, download ECMA-262.pdf (ECMAScript Language Specification) and go to section “B.2.2 unescape (string)“. there you will find unescape decoder, written in pseodo-code.

the second (underlined) layer is not interested. it’s just Array with uneascape string contains the real shell-code includes well-known ["doc"]["Collab"]["getIcon"]. do they look familiar?! of course they do!!! it’s the old getIcon exploit, just more obfuscated.

now, about the shell-code. it’s very simple, don’t even encrypted. this is what my shell-code locator said:

+KRNL32 BASE ADDR PEB FINDER @ 00000019h
XOR key: 00 00 00 00 (00000000h)
#GREEN

ok, open the file with HIEW, go to 19h offset and see:

00000019: mov eax,[eax][0C]
0000001C: mov esi,[eax][1C]
0000001F: lodsd
00000020: mov eax,[eax][08]
00000023: jmps 00000002E —

yep, a typical KERNEL32 base address finder. what’s else?! the most interesting thing is — the shell-code has text strings. just look at them:

URLMON.DLL, URLDownloadToFileA, update.exe, crash.php, http://viorfjoj-2.com/2/update.php?id=0

wow!!! the domain name!!! I checked it and found out that viorfjoj-2.com is down, so I went to who is who service and… ops! surprise!!!

WHOIS information for viorfjoj-2.com:
* Registration Service Provided By: DOMAIN NAMES REGISTRAR REG.RU LTD.
* Contact: +7.4955801111
* Domain Name: VIORFJOJ-2.COM

Registrant:
Private person
Dmitry Ostupin (conroetxwelc@gmail.com)
ul. Malaya Semenovskaya, d.5, kv. 28
g. Moskva
g. Moskva,107023
RU
Tel. +7.4952240537

Creation Date: 08-Jul-2009
Expiration Date: 08-Jul-2010

Russian guy! that’s a deal! I have no idea whether he is the author of the exploit or maybe his server was used by another person, but I wonder… I wonder… going to give him a call tomorrow just out of curiosity.

well, maybe I should not public his contact info here because of etiquette, but… why not?! the exploit was taken from the public source, the hard-coded domain name was found, so… everyone can use the whois service to get this contact info.

well, what we’re going to do on ISP side? if you meet a packet from/to viorfjoj-2.com it means the host is infected and the packet should be blocked. well, since the server is down – obviously all major ISPs had blocked it already.

faked exploit on milw0rm - it has nothing to do with the real SWF security hole

faked exploit on milw0rm - it has nothing to do with the real SWF security hole

 

# simple OllyScript for upx

suddenly, I felt the need of automatic upx OEP finder. it’ easy to do with my hands, but I wanted to analyze files in batch mode, so I open the folder with large collection of Olly Scripts. tried one. nothing. ok, the second. nothing. well, third. nobody wants to work. upx 3.01. um…

it took about a minute to write my own script. it’s work. tested on upx 0.76, 1.20, 1.24, 3.01, the code is follow. maybe somebody will find it useful.

var s

mov s, [eip]
and s, FF
cmp s, 60
jne not_upx

eob Break_1
mov s, esp
sub s, 04
bphws s, “r”
run

Break_1:
BPHWC s
eob Break_2
mov s, eip
sub s, 1
findop s, #E9#
cmp eip, $RESULT
JAE last_jmp

bphws $RESULT, “x”
run

Break_2:
BPHWC $RESULT
last_jmp:
sti
ret

not_upx:
MSG “not upx?!”
ret

 

# FreeLibrary bug becomes a PE packers bug

there is a way to find out if a program was packed or not. XP/S2K3 has a bug that has to be taken into account unless a packer wants to crash a packed program.

FreeLibrary() does not unload statically linked libraries, but frees dynamically linked ones. consider the following code. it should work. at least it works on XP/S2K3 (W2K is a bug free):

// get USER32 module handle
HANDLE h; h = GetModuleHandle(“USER32.DLL”);

// free the library (3 times just to guarantee the reference count is zero)
FreeLibrary(h); FreeLibrary(h); FreeLibrary(h);

// time to unload
Sleep(3000);

// call any function from statically linked USER32
MessageBox(0,”:-)”,”[x]“,0);

ok, now remove USER32 from the import table and load it on the fly.

// load USER32 and get the module handle
HANDLE h; h = LoadLibrary(“USER32.DLL”);

// free the library (3 times just to guarantee the reference count is zero)
FreeLibrary(h); FreeLibrary(h);FreeLibrary(h);

// time to unload
Sleep(3000);

// call any function from dynamically linked USER32
(int (WINAPI *)(int, char*, char*, int)) GetProcAddress(h,”MessageBoxA”)(0, “:-)”, “[x]“, 0);

wow! the program crashes!!! interesting… but… it has nothing to do with packers! um, actually it has. some packers (and especially protectors) leaves only KERNEL32.DLL there and loads the rest on the fly.

guess, we have a file with statically linked libraries. guess, the program frees one or more libraries doing it deliberately or maybe there is a bug. this bug does not appear, coz FreeLibrary not unloads statically linked DLLs. imagine what happens if we pack the file by packer removes all DLL from the import table? the answer: the program will crash!!!

download the POC (original exe and file packed by RLPack) and test your packer/protector collection.

 

# MS VC – challenge for PE packers

blackd0t () started working on his own PE packer and reached the moment where everything is fine, but MSVC++ 2005 floating point files refuse to work and end up with the runtime error: “R6002: floating point not loaded error” . it’s a common problem. many commercial packers meet the same bug.

well, let’s find out what’s this bug all about! first of all I wrote a simple floating-point program and translated it with Microsoft Visual C++ 2008 (Express). the source code is followed (if don’t have MS VC under your hands, just download the archive):

int a; double x = 1.2f;
for (a = 0; a < 10; a++) x += sin(x); cout << x; return 0;

ok. run it and get 3.14159. the program runs fine! now, we’re going to make “.rdata” writable. why? blackd0t mentioned what he already found out: if “.rdata” is writable, we get the error. the question is why?! maybe there is a bug: if .rdata section is writable – floating point library damages critical data, maybe not, who knows?

open exe with HIEW, press ENTER to go to hex-mode, F8 to call PE-header, F6 for ObjTable, move cursor to “.rdata”, F3 to edit, find “Attributes” there, F3 to edit, change the highest bit from 0 to 1 and press F9 twice to save changes. ESC (twice) to exit.

ops! now we see:

$R6002bug-demo.exe
runtime error R6002
- floating point support not loaded

ok. run HIEW and restore the attributes back. everything works fine as before. load exe into OllyDbg, View -> Memory, find “.rdata” and set memory breakpoint on write. run the program. the program runs fine, nobody tries to write something to “.rdata” section. hm… strange…

ok, ask HIEW to make “.rdata” writable again, reload the file into OllyDbg and run it (with memory breakpoint). the program does not work (the same error), but our breakpoint has been not triggered. what’s a helll?!

make “.rdata” non-writable, reload the file into OllyDbg, View -> Memory and change access of “.rdata” section to RW. run the file. no error! the program works fine.

ok. we got it!!! the floating point library checks not access attributes themselves, but verifies PE-header. go to dump windows (in Olly). press CTRL-G and type the address of the header (400000h in this case). find “.rdata” there and move cursor to 40 00 00 40 (the last DWORD before “.data”). set hardware breakpoint on access and press F9 to run the program, the breakpoint is triggered!!!
how do you like this:

.text:0040E780 __IsNonwritableInCurrentImage proc near
.text:0040E780
.text:0040E782 push ebp
.text:0040E783 mov ebp, esp

.text:0040E7C1 call __ValidateImageBase

.text:0040E7D6 push 400000h
.text:0040E7DB call __FindPESection
.text:0040E7E0 add esp, 8
.text:0040E7E3 test eax, eax
.text:0040E7E5 jz short loc_40E822
.text:0040E7E7 mov eax, [eax+24h] ; !!! breakpoint is triggered here !!!
.text:0040E7EA shr eax, 1Fh

_IsNonwritableInCurrentImage() reads PE-header in order to checks – if its argument belongs to non-writable section.

so, packers are obligated to keep original PE sections layout (or restore only PE header in memory) unless they want to crash floating point applications translated with MS VC and maybe other compilers.

thanks blackd0t for the interesting question!

I wonder: how may packers/protectors will be unable to process this file? going to find out. plz, test all packers/protectors you only have under your hands and leave comments. time to send bug reports :-)

first of all it’s bug of MS RTL – bitch should check real page attributes, not just PE-header!

second of all: numerous packers/protectors do not restore PE-header or damage it to prevent dumping or… disables all PE-header pages (PAGE_NO ACCESS)