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@xxxxxxx> 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.
Attachment:
impurity-1.0.tgz
Description: GNU Zip compressed data
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.1 (GNU/Linux) iD8DBQA/fl0zP2KVJkEIREsRAsX2AJ9Y41C1YISESNwljA/AoJATxfPKGgCfdMeX RpOgRZvyoRaHuPIFKnpWsik= =WzvC -----END PGP SIGNATURE-----
Attachment:
pgpQaGEi0HozP.pgp
Description: PGP signature