Using Adobe SWF Investigator on Blackhole

Blackhole

This post I am going to look at the relationship between a malicious SWF and its calling JavaScript. Earlier in the week, I was playing around with Cool Exploit Kit.  I didn’t go down the rabbit hole of looking into the SWF file.   I’m a novice when it comes to Adobe Action Script, but the structure can be figured out with patience. Yesterday, I was playing with the latest Blackhole exploit.  It’s JavaScript is almost verbatim in the exploit, though the SWF file does differ.

When reviewing malicious SWF, most example output I have seen is using SWF Tools (http://www.swftools.org).  Recently, I have been trying out Adobe’s SWF Investigator (http://labs.adobe.com/technologies/swfinvestigator/). My reasoning is that if Adobe can keep up improving this investigation and debugging tool, there will be a long term solution for providing forensics on SWF files, and I really do not like learning too many tools.

SWF Investigator

SWF Investigator

 

As stated in the previous post, The use of allowScriptAccess=’always’ means that the flash file will be able to see JavaScript functions of the page via an External Interface call.  This has two impacts.  First, it allows the SWF to be benign of the exploit payload (it still contains the exploit).  Second, it allows the attacker to configure the attack via the JavaScript eliminating the need to create new SWF files on the fly.

If we look at the landing page for a Blackhole using the SWF heap spray (I believe this exploit is implementing CVE- 2011-0611), we can see the external functions of getCN, getBlockSize, getAllocSize, getFillBytes, and getShellCode being defined.

JavaScript Functions that are to be used by SWF

JavaScript Functions that are to be used by SWF

Then there is the familiar creation of the object on the web page.  The function x() in the code is a function created for the formatting of data back to the server.

We can do this by hand, but a JavaScript shell makes it easy.  We drop the function x() in the shell.  Next we enter the url variable. This variable uses x() to encode elements of the call.  Finally, we enter the object write code and then inspect the javascript object.  This gives us the relative position of the address, which we use to curl the SWF file.

Getting the Link

Getting the Link using a JS Shell

We can now bring up SWF Investigator and load the malicious SWF.  We are out of scope for the shellcode, so we are fairly safe with the play button on the investigator.  There are a number of ways the view the internal code, and I have not decided which one I like better.  I started using the SWF Disassembler, but using the AS3 Navigator or Tag Viewer will provide the same information with a little more control.  The “SWF Disassembler” has an export button, but this does not work correctly, as it has a frustrating bug that does not actually output all the data.  You are better off just cutting & pasting for now.

SWF Inspector

SWF Inspector

In this case of the Blackhole SWF, when we open up the SWF we can see the references back to the JavaScript fairly simple.  We just need to search for the “External Interface” calls.  The referencing is build similar to function calls in assembly.  We give the instruction (external interface), then the agreements are pushed onto the stack.  The call property function does the work (Adobe Reference: The number of arguments specified byarg_count are popped off the stack and saved.)  The functions are then saved in the nameIndex and can be referred later by get local.
       136  getlex             ExternalInterface //nameIndex = 11
       138  pushstring         "getFillBytes"
       140  callproperty       call (1) //nameIndex = 12
       143  callproperty       u (1) //nameIndex = 16
       146  pushstring         "utf-16"
       148  callpropvoid       writeMultiByte (2) //nameIndex = 17
       151  getlocal           11
       153  findpropstrict     u //nameIndex = 16
       155  getlex             ExternalInterface //nameIndex = 11
       157  pushstring         "getFillBytes"
       159  callproperty       call (1) //nameIndex = 12
       162  callproperty       u (1) //nameIndex = 16
       165  pushstring         "utf-16"
       167  callpropvoid       writeMultiByte (2) //nameIndex = 17
       170  getlocal           12
       172  findpropstrict     u //nameIndex = 16
       174  getlex             ExternalInterface //nameIndex = 11
       176  pushstring         "get"
       178  getlex             sc //nameIndex = 18
       180  add               
       181  callproperty       call (1) //nameIndex = 12
       184  callproperty       u (1) //nameIndex = 16
       187  pushstring         "utf-16"

What we do not see is getShellCode.  That is because the string “ShellCode” has been assigned the variable sc (var sc:String = “ShellCode”).  The flow of this assignment is not so obvious, as it occurs after the function using it.  But if you go back to lines 176 and 178, you can see the pushing of “get” and then the variable sc with the value “ShellCode”.

 
static var allocs:Array     /* slot_id 1 */
static var u:Object     /* slot_id 2 */
static var sc:String = "ShellCode"     /* slot_id 3 */

static function Spray$cinit():*     /* disp_id=0 method_id=0 nameIndex = 0 */
     {
       // local_count=1 max_scope=1 max_stack=2 code_len=15
       // method position=819 code position=871
       0    getlocal0         
       1    pushscope         
       2    findproperty       u //nameIndex = 5
       4    getlex             unescape //nameIndex = 9
       6    setproperty        u //nameIndex = 5
       8    findproperty       sc //nameIndex = 7
       10   pushstring         "ShellCode"
       12   setproperty        sc //nameIndex = 7
       14   returnvoid        
     }
   }
So, what of that shellcode.  We go through the normal process of using the JavaScript shell to simply the unicode.
Getting the Unicode from the script

Getting the Unicode from the script

Then run a ruby script to change it to binary.  We look at the last hex to see the key (0x28 again).  We use that key in the ruby xor function and then “strings” the result.  This will give us the binary that we download.
vi rol.uuruby u2b.rb rol.uu > rol.binstrings rol.bin
AAAAf
((((pxBh@
(((x
@GF((@]ZDE|
,)((
,
ZMO[
l
,^Z
l5(_XJ\
l5!(q
l5,iyB(B({
]>B({
~,B(
X@\\X
I[MFAICZGD
NGZ]E
DAFC[
KGD]EF
$ ruby xorKey.rb rol.bin > rol.b2
$ strings rol.b2
iiiiN
}
3t
XPj@h
hurlmT
$regs
vr32
-s Sh
wpbt
.dll
/phxxp://aseniakrol.ru:8080/forum/links/column.php?if=32:30:2w:1o:31&ee=2v:1k:1m:32:33:1k:1k:31:1j:1o&r=1k&zz=r&af=p
Knowing the SWF file has little impact in determining where the executable is.  Looking at it via the SWF is good however, for there are times that you may need to know what is in the SWF.  In the past, I have seen exploit writers hardcode the string in the SWF and JAR files.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: