Library intended to hook Binder interface and manipulate events
This library helps to hook binder communication between your App process and system services of Android.
Just include the maven repository
- In your root build.gradle:
allprojects {
repositories {
[..]
jcenter()
maven { url "https://jitpack.io" }
}
}
- In your library/build.gradle add:
dependencies {
implementation 'com.github.ChickenHook:BinderHook:3.0'
implementation 'com.github.ChickenHook:RestrictionBypass:2.2'
}
This chapter showcases how to use this hooking library. Also please have a look at MainActivity.kt, MainActivityTest.kt and ServiceHooksTest.java
Please check AIDL Implementation in order to learn parcel encode / decode instructions
ServiceHooks.hookPackageManager(packageManager, object :
OnBinderListener() {
val DESCRIPTOR = "android.content.pm.IPackageManager"
override fun transact(
originalBinder: IBinder,
code: Int,
data: Parcel,
reply: Parcel?,
flags: Int
): Boolean {
if (code == 193) { // setHarmfulAppWarning
log("Manipulate setHarmfulAppWarning")
data.setDataPosition(0)
val _data = Parcel.obtain()
_data.writeInterfaceToken(DESCRIPTOR)
data.writeInterfaceToken(DESCRIPTOR)
val packageName = data.readString()
_data.writeString(packageName)
var message: CharSequence?
if (data.readInt() != 0) {
message = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data)
_data.writeInt(1)
TextUtils.writeToParcel(message, _data, 0)
} else {
_data.writeInt(0)
message = null
}
val _flags = data.readInt()
_data.writeInt(1)
return originalBinder.transact(code, _data, reply, Binder.FLAG_ONEWAY)
}
if (code == 56) { // get installed packages
// try to manipulate this call
val _data = Parcel.obtain()
_data.writeInterfaceToken(DESCRIPTOR)
_data.writeInt(0)
_data.writeInt(0) // simulate system user?
return originalBinder.transact(code, _data, reply, flags)
}
return originalBinder.transact(code, data, reply, flags)
}
})
Please check AIDL Implementation in order to learn parcel encode / decode instructions
ServiceHooks.hookActivityManager(object :
OnBinderListener() {
val DESCRIPTOR = "android.app.IActivityManager"
override fun transact(
originalBinder: IBinder,
code: Int,
data: Parcel,
reply: Parcel?,
flags: Int
): Boolean {
if (code == 6) {// start activity
return startActivityHook(
originalBinder,
code,
data,
reply,
flags,
DESCRIPTOR
)
}
return originalBinder.transact(code, data, reply, flags)
}
})
Please check AIDL Implementation in order to learn parcel encode / decode instructions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
ServiceHooks.hookActivityTaskManager(object :
OnBinderListener() {
val DESCRIPTOR = "android.app.IActivityTaskManager"
override fun transact(
originalBinder: IBinder,
code: Int,
data: Parcel,
reply: Parcel?,
flags: Int
): Boolean {
if (code == 1) { // start activity
return startActivityHook(
originalBinder,
code,
data,
reply,
flags,
DESCRIPTOR
)
}
return originalBinder.transact(code, data, reply, flags)
}
})
Please check AIDL Implementation in order to learn parcel encode / decode instructions
ServiceHooks.hookWindowManager(object :
OnBinderListener() {
override fun transact(
originalBinder: IBinder,
code: Int,
data: Parcel,
reply: Parcel?,
flags: Int
): Boolean {
return originalBinder.transact(code, data, reply, flags)
}
})
A lot of other service hooks are also present. However some are missing and will come in future releases.
Service Name | ImplementationStatus |
---|---|
ContentResolver | OK |
NotificationManager | OK |
ActivityManager | OK |
AppOpsManager | OK |
PackageManager | OK |
WindowManager | OK |
ActivityTaskManager | OK |
AlarmManager | WIP |
WallpaperManager | WIP |
RoleService | WIP |
CameraService | WIP |
PrintService | WIP |
TrustService | WIP |
UsageStatsService | WIP |
... | Feel free to submit feature requests if you need more services |
If you just wanna change some args and not manipulate Parcel directly you can use ProxyListener:
ServiceHooks.hookActivityManager(new ProxyListener() {
@Override
public Object invoke(Object orig, Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("startActivity") && args.length == 10) {
args[args.length - 3] = ((int) args[args.length - 3]) |
START_FLAG_DEBUG |
START_FLAG_TRACK_ALLOCATION |
START_FLAG_NATIVE_DEBUGGING;
}
return method.invoke(orig, args);
}
});
By adding these lines of code you can enable the verbose mode
ProxyHook.VERBOSE = true
This will create output like:
2020-05-03 22:03:40.309 25785-25785/org.chickenhook.chickenbinder I/BinderHook: ProxyHook [+] trace [+]
java.lang.Exception: Trace
at org.chickenhook.binderhooks.ProxyHook.doStackTrace(ProxyHook.java:128)
at org.chickenhook.binderhooks.ProxyHook$FakeBinder.transact(ProxyHook.java:111)
at android.content.pm.IPackageManager$Stub$Proxy.setHarmfulAppWarning(IPackageManager.java:8654)
at android.app.ApplicationPackageManager.setHarmfulAppWarning(ApplicationPackageManager.java:3234)
at java.lang.reflect.Method.invoke(Native Method)
at org.chickenhook.chickenbinder.MainActivity$onCreate$$inlined$apply$lambda$1.onClick(MainActivity.kt:40)
at android.view.View.performClick(View.java:7356)
at android.view.View.performClickInternal(View.java:7333)
at android.view.View.access$3600(View.java:807)
at android.view.View$PerformClick.run(View.java:28200)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7476)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:939)
and
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/chickenbinder: dump parcel <0x7444767700>
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/chickenbinder: ---------------------------------------------------------------------------------------------------------------------------------------------
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/parcel: HEX (76 bytes):
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/parcel: 04:00:00:C2:FF:FF:FF:FF:1C:00:00:00:61:00:6E:00:64:00:72:00:6F:00:69:00:64:00:2E:00:61:00:70:00:70:00:2E:00:49:00:41:00:63:00:74:00:69:00:76:00:69:00
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/parcel: 74:00:79:00:4D:00:61:00:6E:00:61:00:67:00:65:00:72:00:00:00:00:00:61:13:00:00
2020-05-07 10:44:55.603 4911-4911/org.chickenhook.chickenbinder D/chickenbinder: ---------------------------------------------------------------------------------------------------------------------------------------------
for any transaction that went through your installed binder hook.
In order to work with existing parcels and be able to modify also restricted content like flattened Binder objects (aka writeStrongBinder, readStrongBinder) we added some low level edit functions.
This function dumps the content of the parcel as hexdump to logcat
ParcelEditor.dump(parcel);
Write a bunch of bites at the given offset
byte[] bytes = new byte[]{
1, 2, 3
};
ParcelEditor.write(parcel, 0, bytes);
Read a bunch of bytes from the given offset
byte[] content = ParcelEditor.read(parcel, 0, parcel.dataSize());
Please create a bug report if you find any issues. This chapter will be updated then.
Project | Description |
---|---|
ChickenHook | A linux / android / MacOS hooking framework |
BinderHook | Library intended to hook Binder interface and manipulate events |
RestrictionBypass | Android API restriction bypass for all Android Versions |
AndroidManifestBypass | Android API restriction bypass for all Android Versions |
.. |
If you're happy with my library please order me a cup of coffee ;) Thanks.