Linux threads are standard process

As per Wikipedia, a computing thread is defined as “the smallest sequence of programmed instructions that can be managed independently by a scheduler”. And further goes on to say, the implementation of threads and processes differs between operating systems, but in most cases a thread is a component of a process. A process can have multiple threads within a shared memory address space of the process.  In this article, I won’t be going into the nitty-gritty of threads. There are many good resources available on the Internet discussing various details of threads. Rather I would like to focus on an important aspect of threads specifically in Linux kernel.

While discussing Linux internals with a senior developer, he mentioned that in case of Linux kernel, there is no difference between a process and a thread. Intrigued by the fact, I started looking into kernel’s source, aided by the excellent book on Linux kernel, Linux Kernel Development, by Robert Love.

Coming on to the topic, in Linux, there is no separate data structure defining a thread. A thread and a process have the same data structure. Also, a thread is created exactly in the same way as a normal process is created, i.e by calling fork or vfork() (which eventually calls clone() system call). Although, in case of a thread, while making clone() system call some extra flags are passed. These extra flags specify the resources which are to be shared. A typical call looks like:
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

So the address space, filesystem resources, file descriptors, and signal handlers are shared.

For the readers who want to delve more into the internal working, struct task_struct contains information about a process, defined in <linux/sched.h>. The field unsigned int flags stores all the flag related information. These flags, help specify the behaviour of the new process and detail what resources the parent and child will share. List of other clone flags can also be found in linux/sched.h.

For completeness, in case of Microsoft Windows, kernel have explicit support for kernels and also referred as lighweight process. For Windows, a thread is an abstraction which provides  a lighter, quicker execution than the heavy process. The pros and cons of the two approaches required more deep understanding of the two, and would require a much bigger post than this one.

Android Root Detection Techniques

I am trying to create a exhaustive list of various techniques which can be used to detect whether an Android device is rooted or not. These techniques have been taken from various sources, listed in the references section at the end of this post. If you are aware of techniques apart from one mentioned in the post, please add them in the comment.

  • Check Installed Packages:
    1. SuperSU app
    2. Rooting apps: Apps that exploit privilege-escalation vulnerabilities to root the device (e.g One Click Root, iRoot)
    3. Root Apps: Apps that require root privileges for their functions. E.g busybox, SetCPU, Titanium Backup.
    4. Root Cloakers: Apps that hide whether the device is rooted or not. e.g Root Cloaker, Root Cloaker Plus.
    5. API hooking frameworks: Libraries that provide API hooking functions. E.g Cydia Substrate, Xpose Framework.
  • Check Installed Files:
    1. Static Paths:
      1. /system/xbin/su, /system/bin/su or /system/xbin/../xbin/su (path manipulated)
      2. /system/xbin/busybox and all symbolic links of commands created by BusyBox.
      3. /data/app/<APK name> or /system/app/<APK name> of popular apps packages that are installed during or after rooting.
    2. Dynamic Paths: Parse the PATH variable, appending “/su” to each entry; open each in a loop
  • Check the BUILD tag: stock android images from Google are built with “release-keys” tag. If “test-keys” are presented, this can probably mean the Android image is developer build or an unofficial build. This value is basically from “ro.build.tags”.
  • Check Directory Permissions:
    1. Rooting makes certain root folders readable, like /data, or writable, like /etc, /system/xbin, /system, /proc, /vendor/bin etc. Run the mount command and check if any device is mounted with “rw” flag, or try to create a file under “/system” or “/data” folder.
    2. Attempt to mount “/system” partition with command “mount -o remount, rw /system“, and check the return code.
  • Check Processes/Services/Tasks:
    1. ActivityManager.getRunningAppProcesses method returns a list of currently running application processes. This API can be used to determine if any app which requires root privileges is running.
    2. getRunningServices or getRunningTasks: Get currently running services or tasks.
  • Check Rooting Traits Using Shell Commands: Using Runtime.exec, ProcessBuilder or execve()
    1. su
    2. which su
    3. ps | grep <target> : lists currently running processes.
    4. ls – <target>: check existence of a file in the file system
    5. pm list packages
    6. pm path <package>: Output the full path of the targeted package
    7. cat /system/build.prop or grep ro.build.tags: Check whether =release-keys. This test can be used only as an indicator, as there are many contrary observations in the wild.
    8. Build Version: “ro.modversion” can be used to identify certain custom Android ROMs (e.g CyanogenMod)
  • Check System Properties:
    1. ro.secure=0, means adb shell will be running as root, instead of shell user.
    2. ro.debuggable =1 or service.adb.root=1, then adb will run as root as well.

Needless to say, these techniques can be bypassed by function hooking or custom build Android ROMs etc.

REFERENCES:

[1] http://lersse-dl.ece.ubc.ca/record/310
[2] https://www.blackhat.com/docs/eu-15/materials/eu-15-Benameur-All-Your-Root-Checks-Are-Belong-To-Us-The-Sad-State-Of-Root-Detection.pdf