The joys of impurity (was: MOSDEF, InlineEgg)

From: Alexander E. Cuttergo (cuttergo_at_gmx.net)
Date: 10/06/03

  • Next message: Dave Korn: "I've found the Allchin bug."
    Date: Mon, 6 Oct 2003 14:05:20 -0700
    To: vuln-dev@securityfocus.com
    
    
    
    

    Hi,
    I enclose the impurity-1.0 release. The README follows. I would like to hear
    some comparisons with MOSDEF and InlineEgg; can you guys implement nmap in
    your shellcode ;) ?
    peace,
    algo

            Impurity-1.0
            by Alexander E. Cuttergo <cuttergo@gmx.net>
            
            Concept
            Impurity is a set of scripts which make it easy to produce a
    shellcode ("first stage") which is able to download over the net an
    executable ELF file ("second stage") and execute it without writing it to
    the disk first. The first stage shellcode itself is almost constant (except
    for one parameter, the executable length) and very short - 46 bytes. Using
    this approach, one does not waste hours composing and debugging a complex
    shellcode - just write a .c program, run impurity (which creates the second
    stage ELF binary) and you are all set.
            Impurity is mostly useful when exploiting a daemon which runs
    chrooted and with dropped privileges; in such case one cannot simply execute
    /bin/sh. Compare it with MOSDEF and InlineEgg.
            Currently impurity is implemented for Linux/i386 only; however,
    porting to other OS/architectures should be trivial, provided they use ELF
    standard.

            License
            GPL v2

            Theory of operation
            In order to be able to execute an ELF binary easily, we will have to
    compile it (more precisely, link it) in a special way.
    1) In order to not be troubled by shared libraries, we will link the binary
    statically.
    2) An usual executable text segment is mapped at 0x8048000. In our case,
    this area is occupied by the text segment of an overflown binary. We could
    unmap() it, but this would make our shellcode unnecessarily large. The
    solution - use a linker script which will place the text segment starting at
    different address. We will use 0xbfff1000 - it is within the stack, so all
    we need to allocate memory for our executable is to do
    "movl $0xbfff1000, %esp". This also means we will need an executable stack -
    this should not be a problem usually. Enhancing shellcode in a way which
    allocates memory for our ELF by mmap(...,PROT_EXEC,...) is left as an
    excercise for a reader.
    Moreover, in order to consequently simplify our first stage shellcode,
    command line arguments and environment are not set, dereferencing them will
    cause a SIGSEGV most likely. It is easily fixable in the second stage itself
    (see tracepath.c example).
    3) In a normal executable, the text and data segments are in disjoint memory
    areas, with different permissions. This again complicates the loading
    process. To avoid it, we will link our ELF executable as impure executable
    (ld -N).
    4) Binaries linked statically with recent glibc are large. This is usually
    not a problem - during the bruteforcing stage of an exploit, we do not need
    to send the binary at all to determine whether the correct offset has been
    found. Anyway, "diet libc" is recommended - small programs linked with diet
    libc are usually in 2k-30k size range. The provided shellcode (bootcode.S)
    uses an unsigned short to store the executable length, thus limiting the
    ELF binary to 64k (bla bla excercise for a reader bla).
    5) The first stage shellcode downloads the second stage ELF binary from file
    descriptor 0. It should not be difficult to add code which utilizes "find
    socket shellcode", or just creates appropriate socket itself. Excercise,
    reader, make bucks by selling this enhancement, bla.

    Having 1-5 in mind, executing an ELF is really simple - just read
    appropriate number of bytes from fd 0 into memory starting at 0xbfff1000,
    and then jump to 0xbfff1074, where the entry point should be. Execve()
    demystified ;)

            Provided code
    bootcode.S - first stage shellcode
    bootstrap.c - trivial stub which emits to stdout asm from bootcode.S,
            adjusting file length u16 in its body
    filesize.c - a helper which prints the file size to stdout
    script-ld-impure-into-stack - a proper ld script
    tracepath.c - a sample second stage. It is almost a verbatim copy of
            tracepath.c from iputils; the only changes are a few lines to
            prepare a command line and environment.
    shelix.c - a sample program, vulnerable to a buffer overflow. It does
    chroot(/var/empty) and setuid(12345), so we cannot break out of chroot nor
    execute /bin/sh; also we have no writeable directory to download any
    executable to. As an example, we use impurity to produce a second stage
    based on tracepath, hoping to learn the DMZ layout. Yes, we can use nmap (or
    linux_autorooter.0227) as the second stage easily.

            Running a sample code
    You have to install diet libc (http://www.fefe.de/dietlibc/) first.
    1) Run "make"
    2) Run "shelix" as root via [x]inetd or "nc -l -p shelix_port -e ./shelix"
    3) "make" produces "ovdata" file, which contains buffer overflow payload and
    the first stage shellcode, so:
    $ (cat ovdata ; sleep 1; cat tracepath; cat) | nc localhost shelix_port
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 2
    Shelix: got token length 46
    Second stage OK. Which ipaddr should I try ?
    c.d.40.1 <- entered from stdin
     1?: [LOCALHOST] pmtu 1500
     1: x.y.131.57 2.127ms
     2?: x.y.20.176
     3?: a.b.40.5
     4?: c.d.40.1
         Resume: pmtu 1500 hops 4 back 4

    Again, if you want to use a different second stage, all you need is to compile
    its sources instead of tracepath.c . If attacking a different vulnerable
    daemon, you will need to change the overflow payload creation ("ovdata"
    target in Makefile), but no need to touch any assembly.

    
    
    

    
    





  • Next message: Dave Korn: "I've found the Allchin bug."

    Relevant Pages

    • The joys of impurity (was: MOSDEF, InlineEgg)
      ... your shellcode;)? ... in such case one cannot simply execute ... It is easily fixable in the second stage itself ... Shelix: got token length 2 ...
      (Bugtraq)
    • Re: DEFCON 16 and Hacking OpenVMS
      ... It is possible to execute shellcode stored in logicals, ... Since the PC is controlled in the CLI bug we simply jump to the ...
      (comp.os.vms)
    • Re: DEFCON 16 and Hacking OpenVMS
      ... placing some shellcode after the overflow. ... It is possible to execute shellcode stored in logicals, ...
      (comp.os.vms)
    • Re: Doubts in shellcode !?
      ... |> I'm reading a tutorial about shellcode, ... Because it doesn't execute /bin/sh directly, ... It is assembler, not machine code. ... such things as offsets are filled in by the compiler. ...
      (comp.security.unix)