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:
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
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
simple, but effective system independent anti-debug trick based on well-documented APIs and does not involve assembly inline (means: it could be implemented in pure C). also it works as anti-dump sensor.
caution: I would recommend do _not_ use this thick in production code, because it’s based on the bug (two bugs actually: one in Windows, another in OllyDbg), which could be fixed at any moment. however, noting terrible happens if the bug would be fixed - the application just could not detect debugger/dumper.
in passing: I found this bug working on the project for a spectrography cherry group, well, not a cherry actually, but I prefer to keep the real name if it under the mat, anyway it’s all about Ciscar Fon - my first love, a gothic type, very kinky and yet creative.
in a nutshell: the whole idea based on PAGE_GUARD attribute. SDK says: "any attempt to access a guard page causes the system to raise a STATUS_GUARD_PAGE (80000001h) exception and turn off the guard page status… if a guard page exception occurs during a system service, the service typically returns a failure status indicator". wow! how I like these words: "typically”, "usually”, "normally”… they say nothing, but at the same time they say everything!!! just read between the lines…
ReadProcessMemory: normally, /* I mean _normally_ */ ReadProcessMemory() returns error if it meet a page with PAGE_GUARD attribute. does it make sense? of course! but, _normally_ does not mean "every time”. Windows has a bug (I tested W2K SP4, XP SP3, Vista SP0 and Vista 64bit SP1 - they are all affected).
the bug: if PAGE_GUARD page is created by VirtualAlloc() call, ReadProcessMemory() turns off the guard page status without any exception and returns a failure status indicator. however, the second ReadProcessMemory() call returns a positive status (because PAGE_GUARD was turned off), so when the application will try to access to that page - there will be no exception (as it’s supposed to be), because there is no guard anymore.
the sensor: it’s easy to create a sensor to detect dumpers. allocate a page with PAGE_GUARD attribute and check it from time to time: just install SEH handler and read the content. no exception means we’re fucked, oh, sorry, dumped. I tested PE-TOOLS and other popular dumpers and they all were detected.
demo: to demonstrate the bug, I wrote two simple applications. one - "protected-like” application, another - dumper-like application. please download the sources and binaries.
"protected” application (PAGE_GUARD_BUG.c) is very simple, basically it just callsVirtualAlloc(,,,PAGE_READWRITE | PAGE_GUARD), displays the address/PID, waits for pressing ENTER and attempts to read the content of the allocated block. there is no SEH handler, so if an exception happens you will see the standard Windows message box.
and the "dumper” (turnoff.c ) just calls ReadProcessMemory() and displays the result:
h = OpenProcess(PROCESS_ALL_ACCESS, 0, atol(arg_id)); x = ReadProcessMemory(h, (void*)atol(arg_addr), &buf, 0×1, &n);
oh, here we go. follow me, please!
1) run the protected app (”$start PAGE_GUARD_BUG.exe"); 2) it displays ID/addr, like: id:1216 addr:4325376; 3) press right now; 4) ops! exception! this means: PAGE_GUARD works!!! 5) run the protected app again (”$start PAGE_GUARD_BUG.exe"); 6) it displays ID/addr, like: id:1212 addr:4325376; 7) run the dumper, passing ID and addr (”$turnoff.exe 1212 4325376"); 8) it says: "satus:0, bytes read: 0″ (means: ReadProcMem failed); 9) but! if you switch to PAGE_GUARD_BUG.exe and press ENTER you will see no exception (means: PAGE_GUARD was turned off); 10) if you run the dumper twice (of course without pressing ENTER) it will displays: "satus:1, bytes read: 1″ (means: there is no PAGE_GUARD anymore);
nice trick, it’s it? but actually it was just a little warming-up. the real tricks are coming.
NOTE: if PAGE_GUARD attribute is assigned by VirtualProtect(), Windows respects the attribute and ReadProcessMemory() fails, leaving PAGE_GUARD turned on.
debuggers: what happens if a debugger meet PAGE_GUARD page? the answer is: there will be no exception, the debugger just turns PAGE_GUARD off, processes the content and forgets to return PAGE_GUARD back.
demonstration: to demonstrate this nasty behavior I wrote a simple program PAGE_GUARD_DBG.c,download it, please. and follow me. the source code is easy to understand:
execute it step-by-step, make step over the VirtualAlloc() call and display the content of the allocated memory block (for example, in IDA-Pro press , eax, ENTER and to go back). continue tracing, and… ops! where is our exception?! there is no one!!!
OllyDbg is even worse. it automatically resolves memory references displaying the content in the right column, so we don’t need to go to the dump window nor pressing CTRL-G… just trace it and the debugger will be detected, since there will be no exception!!!
IDA-Pro: well, what about if we just run the program under debugger? just run, no trace! IDA-Pro triggers an exception: "401035: A page of memory that marks the end of a data structure such as a stack or an array has been accessed (exc. code 80000001, TID 1312)” and offers to pass the exception to the application. in this case the debugger will be _not_ detected.
OllyDbg: the standard de-facto debugger stops when the application accesses PAGE_GUARD, giving the message "Break-on-access when reading” in the status bar, but Olly does not offer us to pass the exception to the application. even we go to options->exceptions and add 0×80000001 (STATUS_GUARD_PAGE) exception to the list, Olly will ignore it! guess, PAGE_GUARD is just a part of "memory-breakpoint” engine, so no way to pass PAGE_GUARD exception to the application, so it’s easy to detect the debugger. (I testedOllyDbg 1.10).
Soft-Ice: it does not display the content of PAGE_GUARDED pages, so it could not be detected by this way. in other hand, keeping the impotent content under PAGE_GUARD makes debugging much harder. we can’t perform full memory search, we can’t find cross references… we’re blind.
the love triangle: PAGE_GUARD, Windows and OllyDbg: Windows has a bug, Olly has a bug, so... how we're supposed to debug?!
dial it now or never!
was invited toXcon 2009Security Conference (Beijing, China, 18th-19th August 2009) where I’m going to talk about a new generation of passive non-resident win32/Linux root-kits. the brief introduction is followed bellow:.
In the dark… …I heard your voice: "hey, you on the other side! In this dark and rainy night, we come out of the shadows just to finish what we began a thousand years ago. my gun is pumping, you’re down on your knees. a closer step to death. I think I’m coming, are you ready to receive? I spray you full with my killer disease! now life is death and light is dark!”
there is a full-scale subterranean war been raged for every shred of information, there are things that go bump in the night, everybody knows about it and nobody says anything about it. they don’t intend to upset the balance of the war. I will. I wlll open a portal… and awaken the Ogdru Jahad. behind this door, a dark entity. evil, ancient and hungry.
The Seven Gods of Chaos turn out to be a new kind of root-kits. non-resident passive Ring-3 Root-Kits affect Windows and Linux. sounds boring, doesn’t it? but hold a candle to the sun and listen. they’re coming inside to break you down, they hide exe/dll modules, using only well-documented win32 APIs, working _everywhere_ from 9x to Vista, they don’t request administrator rights and every known AV fails to find the hidden modules as well as to detect the root-kits, because there is nothing to detect — thanks to the passive non-resident nature of them! your favorite tool — the manual detection (”hands-n-brain”) fails to detect them as well! soft-ice, syser, and root-kit finders show us nothing! what the hell is this — science or black magic?! I don’t know, I just hear how your PC box is crying: what’s happening to me? everything is so cold! everything is so dark! what is this pain I feel, why does it hurt? please no, let me die… let me die… let me die… hey! don’t you know it is supposed to work? you always get what you deserve! there is no cure. there is no solution. in death and dark we are all alone.
facts: This is not something absolutely new. this is what the hacker community started to talk about a year ago. it was a part of my Reverse Engineering Course lectured to Sec++ Group (Israel) Sense Post company(South Africa) and many others. at that moment we considered it as a win32 bug, allowing us to infect running EXEs and loaded DLLs. Discussing this stuff with the Apple Panda and Soft Forum guys (Seoul, South Korea) suddenly we realized — this is much more than just infection, the same trick might be used for hiding and there is no way to find the coffined modules. it was supposed to be a part of my speech on CodeGate-2009 conference, but for some reasons this topic was removed and suspended for a while. There were some (just a few) internal reports that I sent to my company (McAfee, Avert Labs), but the wide public had no idea about what was going on till now, and from now till doomsday you will know for sure what this is all about. this is a new threat, spotlighting maladjustment of three major Windows engines - file system, virtual memory manager and object manager. Linux boxes are not affected. well, in fact, they’re affected, but for them there is a solution — a cure. but not for Windows! we’re all waiting for an official patch, fixing the problem.
/* snippets from New Rose Hotel, Queen Of The Damned, Hell-boy, BlutEngel, Pain were used */
updated on: Jul-09, grammar fix (thanks to Ben Layer, McAfee)
Xcon - one of the most authoritative and famous information security conference in China
Posted in anti-dbg, win32 on 07/05/2009 01:36 pm by kpnc
intraarterial injection: fixing old bugs in Vista ms-guys inevitably add new ones. don’t ask me for proofs unless you want to hurt your face-painting wretched system. do you know the system I’m talking about? good! the following code has no impact on NT, W2K, XP, but… it freezes malformed Vista. it just hangs the system up! (I tested Vista SP0). download the binary or compile the file by yourself.
get off the subject: remember a simple anti-dbg trick with closing a non-existing handler? something likeCloseHandle(0xBADC0DE) or CloseHandle(0xBADC0DE). if we’re under a debugger - OS generates C0000008h (INVALID HANDLE) exception. no debugger means no exception. the problem is: how to close an assuredly invalid handler? if you didn’t open it, any system DLL might opened it. of course, you can useGetHandleInformation() to check: if the handler has been opened, but… it’s too obvious (for hackers) and too trivial to be interested for us. there is another way — our way.
flowing well: has it never come in upon your mind how OS assigns handlers? a handler is DWORD, right? but it’s impossible to get all values busy. some values will be taken, but some of them should be free, because it’s impossible to open all of 4,294,967,296 possible handlers. it’s out of the limit! so, lets perform a fast research of system internals. what we’re going to do is: to consume all handlers until CreateFile() says: "no more handlers, I give up". well, time to call GetHandleInformation() and check: is there any predictable template? which handlers are taken and which are not?
dead marines: holly cow!!! just look at it!!! wow! this is the very template we looked for! handlers 0h .. 02h are taken, handler 07h is taken as well, but… the rest of them fits the following equation: (((h - 0×12) % 04). so, it’s easy to determine handlers that will be not taken whatever happens to them, thus these handlers will definitely raise an exception on the close attempt. the point is: closing a handler like 1Bh looks reasonable from hacker’ point of view, but it’s just a way to generate an exception under debugger.
HANDLE: 00h is invalid HANDLE: 01h is invalid HANDLE: 02h is invalid HANDLE: 03h is valid HANDLE: 04h is valid HANDLE: 05h is valid HANDLE: 06h is valid HANDLE: 07h is invalid HANDLE: 08h is valid HANDLE: 09h is valid HANDLE: 0Ah is valid HANDLE: 0Bh is valid HANDLE: 0Ch is valid HANDLE: 0Dh is valid HANDLE: 0Eh is valid HANDLE: 0Fh is valid HANDLE: 10h is valid HANDLE: 11h is valid HANDLE: 12h is valid HANDLE: 13h is invalid HANDLE: 14h is valid HANDLE: 15h is valid HANDLE: 16h is valid HANDLE: 17h is invalid HANDLE: 18h is valid HANDLE: 19h is valid HANDLE: 1Ah is valid HANDLE: 1Bh is invalid HANDLE: 1Ch is valid HANDLE: 1Dh is valid HANDLE: 1Eh is valid
Achilles’ spear: so, you got it! we have the magic formula allowing us to check any arbitrary value. take 0xBADC0DEh for example. download the sources of IsInvalid.c and call IsHandlerInvalid(0xBADC0DE) or simile run IsInvalid.exe. as you can see, 0xBADC0DE could not be taken, so it’s a good choice to cause an exception.
ok, another try — 0xDEADBEEF. just pass the value to our magic function and… ops! it says: "HANDLE: DEADBEEFh is possibly valid", so it’s potentially unsafe to use CloseHanlde(0xDEADBEEF). oh, come on! fat chance to close a file, opened by system or custom DLL, but… it’s still possible. btw, VMProtect uses CloseHanle(0xBADC0DE), which is safe. coincidence? or… anyway, Dermatolog (Иван Пермяков, Екатеринбург –the geek who created it) is a very wise guy and his protector is one of the best. it’s stuffed by anti-dbg tricks and it was a pleasure for me to dig them up. what’s about you?
handler consuming leads to consume kernel memory as well (handler_explorer.exe is running), sorry for the Russian screen-shoot, will appreciate your help, if somebody send me eng one (info # re - lab . org )