Drop useless native part
This commit is contained in:
1 parent
657e1b1d0f
commit
7307c136ee
19 files changed
+3
-3462
No files matched your search
@@ -1,16 +1,10 @@
|
||||
project(ehviewer)
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -fno-stack-protector")
|
||||
|
||||
add_subdirectory(image)
|
||||
add_subdirectory(integrity)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED main.c)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC -fvisibility=hidden -fvisibility-inlines-hidden -fno-exceptions)
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC image/image)
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC image/image integrity)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} image genuine)
|
||||
target_link_libraries(${PROJECT_NAME} image)
|
||||
@@ -1,12 +0,0 @@
|
||||
project(genuine C)
|
||||
|
||||
add_library(genuine STATIC
|
||||
am-proxy.c
|
||||
apk-sign-v2.c
|
||||
common.c
|
||||
genuine.c
|
||||
inline.c
|
||||
openat.c
|
||||
path.c
|
||||
plt.c)
|
||||
target_include_directories(genuine PUBLIC integrity)
|
||||
@@ -1,824 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/15.
|
||||
//
|
||||
|
||||
#include "common.h"
|
||||
#include "am-proxy.h"
|
||||
|
||||
static inline void fill_android_app_ActivityManager(char v[]) {
|
||||
// android/app/ActivityManager
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 23;
|
||||
} else if (m == 29) {
|
||||
m = 31;
|
||||
}
|
||||
|
||||
v[0x0] = 'e';
|
||||
v[0x1] = 'k';
|
||||
v[0x2] = 'b';
|
||||
v[0x3] = 'u';
|
||||
v[0x4] = 'g';
|
||||
v[0x5] = '`';
|
||||
v[0x6] = 'n';
|
||||
v[0x7] = '$';
|
||||
v[0x8] = 'm';
|
||||
v[0x9] = '}';
|
||||
v[0xa] = '~';
|
||||
v[0xb] = ' ';
|
||||
v[0xc] = 'Q';
|
||||
v[0xd] = 'r';
|
||||
v[0xe] = 'f';
|
||||
v[0xf] = 'z';
|
||||
v[0x10] = 'b';
|
||||
v[0x11] = '|';
|
||||
v[0x12] = 'b';
|
||||
v[0x13] = 'y';
|
||||
v[0x14] = 'L';
|
||||
v[0x15] = 'c';
|
||||
v[0x16] = 'm';
|
||||
v[0x17] = 'e';
|
||||
v[0x18] = 'b';
|
||||
v[0x19] = 'c';
|
||||
v[0x1a] = 'u';
|
||||
for (unsigned int i = 0; i < 0x1b; ++i) {
|
||||
v[i] ^= ((i + 0x1b) % m);
|
||||
}
|
||||
v[0x1b] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getService(char v[]) {
|
||||
// getService
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 7;
|
||||
} else if (m == 11) {
|
||||
m = 13;
|
||||
}
|
||||
|
||||
v[0x0] = 'd';
|
||||
v[0x1] = 'a';
|
||||
v[0x2] = 'q';
|
||||
v[0x3] = 'U';
|
||||
v[0x4] = 'e';
|
||||
v[0x5] = 's';
|
||||
v[0x6] = 't';
|
||||
v[0x7] = 'j';
|
||||
v[0x8] = 'g';
|
||||
v[0x9] = '`';
|
||||
for (unsigned int i = 0; i < 0xa; ++i) {
|
||||
v[i] ^= ((i + 0xa) % m);
|
||||
}
|
||||
v[0xa] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getService_signature(char v[]) {
|
||||
// ()Landroid/app/IActivityManager;
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 31;
|
||||
} else if (m == 37) {
|
||||
m = 41;
|
||||
}
|
||||
|
||||
v[0x0] = ')';
|
||||
v[0x1] = '+';
|
||||
v[0x2] = 'O';
|
||||
v[0x3] = 'e';
|
||||
v[0x4] = 'k';
|
||||
v[0x5] = 'b';
|
||||
v[0x6] = 'u';
|
||||
v[0x7] = 'g';
|
||||
v[0x8] = '`';
|
||||
v[0x9] = 'n';
|
||||
v[0xa] = '$';
|
||||
v[0xb] = 'm';
|
||||
v[0xc] = '}';
|
||||
v[0xd] = '~';
|
||||
v[0xe] = ' ';
|
||||
v[0xf] = 'Y';
|
||||
v[0x10] = 'P';
|
||||
v[0x11] = 'q';
|
||||
v[0x12] = 'g';
|
||||
v[0x13] = '}';
|
||||
v[0x14] = 'c';
|
||||
v[0x15] = '\x7f';
|
||||
v[0x16] = 'c';
|
||||
v[0x17] = 'a';
|
||||
v[0x18] = 'T';
|
||||
v[0x19] = '{';
|
||||
v[0x1a] = 'u';
|
||||
v[0x1b] = '}';
|
||||
v[0x1c] = 'z';
|
||||
v[0x1d] = '{';
|
||||
v[0x1e] = 'r';
|
||||
v[0x1f] = ':';
|
||||
for (unsigned int i = 0; i < 0x20; ++i) {
|
||||
v[i] ^= ((i + 0x20) % m);
|
||||
}
|
||||
v[0x20] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_android_app_ActivityManagerNative(char v[]) {
|
||||
// android/app/ActivityManagerNative
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 31;
|
||||
} else if (m == 37) {
|
||||
m = 41;
|
||||
}
|
||||
|
||||
v[0x0] = 'c';
|
||||
v[0x1] = 'm';
|
||||
v[0x2] = '`';
|
||||
v[0x3] = 'w';
|
||||
v[0x4] = 'i';
|
||||
v[0x5] = 'n';
|
||||
v[0x6] = 'l';
|
||||
v[0x7] = '&';
|
||||
v[0x8] = 'k';
|
||||
v[0x9] = '{';
|
||||
v[0xa] = '|';
|
||||
v[0xb] = '"';
|
||||
v[0xc] = 'O';
|
||||
v[0xd] = 'l';
|
||||
v[0xe] = 'd';
|
||||
v[0xf] = 'x';
|
||||
v[0x10] = 'd';
|
||||
v[0x11] = 'z';
|
||||
v[0x12] = '`';
|
||||
v[0x13] = 'l';
|
||||
v[0x14] = '[';
|
||||
v[0x15] = 'v';
|
||||
v[0x16] = 'v';
|
||||
v[0x17] = 'x';
|
||||
v[0x18] = '}';
|
||||
v[0x19] = '~';
|
||||
v[0x1a] = 'n';
|
||||
v[0x1b] = 'S';
|
||||
v[0x1c] = '\x7f';
|
||||
v[0x1d] = 't';
|
||||
v[0x1e] = 'h';
|
||||
v[0x1f] = 't';
|
||||
v[0x20] = 'f';
|
||||
for (unsigned int i = 0; i < 0x21; ++i) {
|
||||
v[i] ^= ((i + 0x21) % m);
|
||||
}
|
||||
v[0x21] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getDefault(char v[]) {
|
||||
// getDefault
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 7;
|
||||
} else if (m == 11) {
|
||||
m = 13;
|
||||
}
|
||||
|
||||
v[0x0] = 'd';
|
||||
v[0x1] = 'a';
|
||||
v[0x2] = 'q';
|
||||
v[0x3] = 'B';
|
||||
v[0x4] = 'e';
|
||||
v[0x5] = 'g';
|
||||
v[0x6] = 'c';
|
||||
v[0x7] = 'v';
|
||||
v[0x8] = 'h';
|
||||
v[0x9] = 'q';
|
||||
for (unsigned int i = 0; i < 0xa; ++i) {
|
||||
v[i] ^= ((i + 0xa) % m);
|
||||
}
|
||||
v[0xa] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getDefault_signature(char v[]) {
|
||||
// ()Landroid/app/IActivityManager;
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 31;
|
||||
} else if (m == 37) {
|
||||
m = 41;
|
||||
}
|
||||
|
||||
v[0x0] = ')';
|
||||
v[0x1] = '+';
|
||||
v[0x2] = 'O';
|
||||
v[0x3] = 'e';
|
||||
v[0x4] = 'k';
|
||||
v[0x5] = 'b';
|
||||
v[0x6] = 'u';
|
||||
v[0x7] = 'g';
|
||||
v[0x8] = '`';
|
||||
v[0x9] = 'n';
|
||||
v[0xa] = '$';
|
||||
v[0xb] = 'm';
|
||||
v[0xc] = '}';
|
||||
v[0xd] = '~';
|
||||
v[0xe] = ' ';
|
||||
v[0xf] = 'Y';
|
||||
v[0x10] = 'P';
|
||||
v[0x11] = 'q';
|
||||
v[0x12] = 'g';
|
||||
v[0x13] = '}';
|
||||
v[0x14] = 'c';
|
||||
v[0x15] = '\x7f';
|
||||
v[0x16] = 'c';
|
||||
v[0x17] = 'a';
|
||||
v[0x18] = 'T';
|
||||
v[0x19] = '{';
|
||||
v[0x1a] = 'u';
|
||||
v[0x1b] = '}';
|
||||
v[0x1c] = 'z';
|
||||
v[0x1d] = '{';
|
||||
v[0x1e] = 'r';
|
||||
v[0x1f] = ':';
|
||||
for (unsigned int i = 0; i < 0x20; ++i) {
|
||||
v[i] ^= ((i + 0x20) % m);
|
||||
}
|
||||
v[0x20] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_android_os_BinderProxy(char v[]) {
|
||||
// android/os/BinderProxy
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 19;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
|
||||
v[0x0] = 'b';
|
||||
v[0x1] = 'j';
|
||||
v[0x2] = 'a';
|
||||
v[0x3] = 't';
|
||||
v[0x4] = 'h';
|
||||
v[0x5] = 'a';
|
||||
v[0x6] = 'm';
|
||||
v[0x7] = '%';
|
||||
v[0x8] = 'd';
|
||||
v[0x9] = '\x7f';
|
||||
v[0xa] = '"';
|
||||
v[0xb] = 'L';
|
||||
v[0xc] = 'f';
|
||||
v[0xd] = '~';
|
||||
v[0xe] = 'u';
|
||||
v[0xf] = 'w';
|
||||
v[0x10] = 'r';
|
||||
v[0x11] = 'Q';
|
||||
v[0x12] = 'p';
|
||||
v[0x13] = 'l';
|
||||
v[0x14] = '|';
|
||||
v[0x15] = '|';
|
||||
for (unsigned int i = 0; i < 0x16; ++i) {
|
||||
v[i] ^= ((i + 0x16) % m);
|
||||
}
|
||||
v[0x16] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_android_os_IInterface(char v[]) {
|
||||
// android/os/IInterface
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 19;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
|
||||
v[0x0] = 'c';
|
||||
v[0x1] = 'm';
|
||||
v[0x2] = '`';
|
||||
v[0x3] = 'w';
|
||||
v[0x4] = 'i';
|
||||
v[0x5] = 'n';
|
||||
v[0x6] = 'l';
|
||||
v[0x7] = '&';
|
||||
v[0x8] = 'e';
|
||||
v[0x9] = 'x';
|
||||
v[0xa] = '#';
|
||||
v[0xb] = 'D';
|
||||
v[0xc] = 'G';
|
||||
v[0xd] = 'a';
|
||||
v[0xe] = 'd';
|
||||
v[0xf] = 't';
|
||||
v[0x10] = '`';
|
||||
v[0x11] = 'f';
|
||||
v[0x12] = '`';
|
||||
v[0x13] = 'a';
|
||||
v[0x14] = 'f';
|
||||
for (unsigned int i = 0; i < 0x15; ++i) {
|
||||
v[i] ^= ((i + 0x15) % m);
|
||||
}
|
||||
v[0x15] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_asBinder(char v[]) {
|
||||
// asBinder
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 7;
|
||||
} else if (m == 11) {
|
||||
m = 13;
|
||||
}
|
||||
|
||||
v[0x0] = '`';
|
||||
v[0x1] = 'q';
|
||||
v[0x2] = 'A';
|
||||
v[0x3] = 'm';
|
||||
v[0x4] = 'k';
|
||||
v[0x5] = 'b';
|
||||
v[0x6] = 'e';
|
||||
v[0x7] = 's';
|
||||
for (unsigned int i = 0; i < 0x8; ++i) {
|
||||
v[i] ^= ((i + 0x8) % m);
|
||||
}
|
||||
v[0x8] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_asBinder_signature(char v[]) {
|
||||
// ()Landroid/os/IBinder;
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 19;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
|
||||
v[0x0] = '+';
|
||||
v[0x1] = '-';
|
||||
v[0x2] = 'I';
|
||||
v[0x3] = 'g';
|
||||
v[0x4] = 'i';
|
||||
v[0x5] = 'l';
|
||||
v[0x6] = '{';
|
||||
v[0x7] = 'e';
|
||||
v[0x8] = 'b';
|
||||
v[0x9] = 'h';
|
||||
v[0xa] = '"';
|
||||
v[0xb] = 'a';
|
||||
v[0xc] = '|';
|
||||
v[0xd] = '?';
|
||||
v[0xe] = 'X';
|
||||
v[0xf] = 'P';
|
||||
v[0x10] = 'i';
|
||||
v[0x11] = 'o';
|
||||
v[0x12] = 'f';
|
||||
v[0x13] = 'f';
|
||||
v[0x14] = 'v';
|
||||
v[0x15] = '>';
|
||||
for (unsigned int i = 0; i < 0x16; ++i) {
|
||||
v[i] ^= ((i + 0x16) % m);
|
||||
}
|
||||
v[0x16] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_android_os_ServiceManager(char v[]) {
|
||||
// android/os/ServiceManager
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 23;
|
||||
} else if (m == 29) {
|
||||
m = 31;
|
||||
}
|
||||
|
||||
v[0x0] = 'c';
|
||||
v[0x1] = 'm';
|
||||
v[0x2] = '`';
|
||||
v[0x3] = 'w';
|
||||
v[0x4] = 'i';
|
||||
v[0x5] = 'n';
|
||||
v[0x6] = 'l';
|
||||
v[0x7] = '&';
|
||||
v[0x8] = 'e';
|
||||
v[0x9] = 'x';
|
||||
v[0xa] = '#';
|
||||
v[0xb] = '^';
|
||||
v[0xc] = 'k';
|
||||
v[0xd] = '}';
|
||||
v[0xe] = 'f';
|
||||
v[0xf] = 'x';
|
||||
v[0x10] = 'q';
|
||||
v[0x11] = 'v';
|
||||
v[0x12] = 'Y';
|
||||
v[0x13] = 't';
|
||||
v[0x14] = 'x';
|
||||
v[0x15] = 'a';
|
||||
v[0x16] = 'f';
|
||||
v[0x17] = 'g';
|
||||
v[0x18] = 'q';
|
||||
for (unsigned int i = 0; i < 0x19; ++i) {
|
||||
v[i] ^= ((i + 0x19) % m);
|
||||
}
|
||||
v[0x19] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getService_signature_IBinder(char v[]) {
|
||||
// (Ljava/lang/String;)Landroid/os/IBinder;
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 37;
|
||||
} else if (m == 41) {
|
||||
m = 43;
|
||||
}
|
||||
|
||||
v[0x0] = '+';
|
||||
v[0x1] = 'H';
|
||||
v[0x2] = 'o';
|
||||
v[0x3] = 'g';
|
||||
v[0x4] = 'q';
|
||||
v[0x5] = 'i';
|
||||
v[0x6] = '&';
|
||||
v[0x7] = 'f';
|
||||
v[0x8] = 'j';
|
||||
v[0x9] = 'b';
|
||||
v[0xa] = 'j';
|
||||
v[0xb] = '!';
|
||||
v[0xc] = '\\';
|
||||
v[0xd] = 'd';
|
||||
v[0xe] = 'c';
|
||||
v[0xf] = '{';
|
||||
v[0x10] = '}';
|
||||
v[0x11] = 's';
|
||||
v[0x12] = '.';
|
||||
v[0x13] = '?';
|
||||
v[0x14] = '[';
|
||||
v[0x15] = 'y';
|
||||
v[0x16] = 'w';
|
||||
v[0x17] = '~';
|
||||
v[0x18] = 'i';
|
||||
v[0x19] = 's';
|
||||
v[0x1a] = 't';
|
||||
v[0x1b] = 'z';
|
||||
v[0x1c] = '0';
|
||||
v[0x1d] = 'O';
|
||||
v[0x1e] = 'R';
|
||||
v[0x1f] = '\r';
|
||||
v[0x20] = 'j';
|
||||
v[0x21] = 'f';
|
||||
v[0x22] = 'i';
|
||||
v[0x23] = 'o';
|
||||
v[0x24] = 'f';
|
||||
v[0x25] = 'f';
|
||||
v[0x26] = 'v';
|
||||
v[0x27] = '>';
|
||||
for (unsigned int i = 0; i < 0x28; ++i) {
|
||||
v[i] ^= ((i + 0x28) % m);
|
||||
}
|
||||
v[0x28] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_activity(char v[]) {
|
||||
// activity
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 7;
|
||||
} else if (m == 11) {
|
||||
m = 13;
|
||||
}
|
||||
|
||||
v[0x0] = '`';
|
||||
v[0x1] = 'a';
|
||||
v[0x2] = 'w';
|
||||
v[0x3] = 'm';
|
||||
v[0x4] = 's';
|
||||
v[0x5] = 'o';
|
||||
v[0x6] = 't';
|
||||
v[0x7] = 'x';
|
||||
for (unsigned int i = 0; i < 0x8; ++i) {
|
||||
v[i] ^= ((i + 0x8) % m);
|
||||
}
|
||||
v[0x8] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getName(char v[]) {
|
||||
// getName
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 5;
|
||||
} else if (m == 7) {
|
||||
m = 11;
|
||||
}
|
||||
|
||||
v[0x0] = 'e';
|
||||
v[0x1] = 'f';
|
||||
v[0x2] = 'p';
|
||||
v[0x3] = 'N';
|
||||
v[0x4] = '`';
|
||||
v[0x5] = 'o';
|
||||
v[0x6] = 'f';
|
||||
for (unsigned int i = 0; i < 0x7; ++i) {
|
||||
v[i] ^= ((i + 0x7) % m);
|
||||
}
|
||||
v[0x7] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_getName_signature(char v[]) {
|
||||
// ()Ljava/lang/String;
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 19;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
|
||||
v[0x0] = ')';
|
||||
v[0x1] = '+';
|
||||
v[0x2] = 'O';
|
||||
v[0x3] = 'n';
|
||||
v[0x4] = 'd';
|
||||
v[0x5] = 'p';
|
||||
v[0x6] = 'f';
|
||||
v[0x7] = '\'';
|
||||
v[0x8] = 'e';
|
||||
v[0x9] = 'k';
|
||||
v[0xa] = 'e';
|
||||
v[0xb] = 'k';
|
||||
v[0xc] = '"';
|
||||
v[0xd] = ']';
|
||||
v[0xe] = '{';
|
||||
v[0xf] = 'b';
|
||||
v[0x10] = 'x';
|
||||
v[0x11] = '|';
|
||||
v[0x12] = 'g';
|
||||
v[0x13] = ':';
|
||||
for (unsigned int i = 0; i < 0x14; ++i) {
|
||||
v[i] ^= ((i + 0x14) % m);
|
||||
}
|
||||
v[0x14] = '\0';
|
||||
}
|
||||
|
||||
static inline void fill_activity_manager_service_is_s(char v[]) {
|
||||
// activity manager service is %s
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 29;
|
||||
} else if (m == 31) {
|
||||
m = 37;
|
||||
}
|
||||
|
||||
v[0x0] = '`';
|
||||
v[0x1] = 'a';
|
||||
v[0x2] = 'w';
|
||||
v[0x3] = 'm';
|
||||
v[0x4] = 's';
|
||||
v[0x5] = 'o';
|
||||
v[0x6] = 's';
|
||||
v[0x7] = 'q';
|
||||
v[0x8] = ')';
|
||||
v[0x9] = 'g';
|
||||
v[0xa] = 'j';
|
||||
v[0xb] = 'b';
|
||||
v[0xc] = 'l';
|
||||
v[0xd] = 'i';
|
||||
v[0xe] = 'j';
|
||||
v[0xf] = 'b';
|
||||
v[0x10] = '1';
|
||||
v[0x11] = 'a';
|
||||
v[0x12] = 'v';
|
||||
v[0x13] = 'f';
|
||||
v[0x14] = 'c';
|
||||
v[0x15] = '\x7f';
|
||||
v[0x16] = 't';
|
||||
v[0x17] = '}';
|
||||
v[0x18] = '9';
|
||||
v[0x19] = 's';
|
||||
v[0x1a] = 'h';
|
||||
v[0x1b] = '<';
|
||||
v[0x1c] = '%';
|
||||
v[0x1d] = 'r';
|
||||
for (unsigned int i = 0; i < 0x1e; ++i) {
|
||||
v[i] ^= ((i + 0x1e) % m);
|
||||
}
|
||||
v[0x1e] = '\0';
|
||||
}
|
||||
|
||||
static inline void showError(JNIEnv *env, jclass object) {
|
||||
char v1[0x8], v2[0x1f];
|
||||
|
||||
if (object == NULL) {
|
||||
fill_activity_manager_service_is_s(v2); // 0x1f
|
||||
LOGE(v2, NULL);
|
||||
} else {
|
||||
fill_getName(v1); // 0x8
|
||||
fill_getName_signature(v2); // 0x15
|
||||
|
||||
jclass clazz = (*env)->GetObjectClass(env, object);
|
||||
jmethodID method = (*env)->GetMethodID(env, clazz, v1, v2);
|
||||
jstring string = (*env)->CallObjectMethod(env, object, method);
|
||||
|
||||
const char *name = (*env)->GetStringUTFChars(env, string, NULL);
|
||||
fill_activity_manager_service_is_s(v2); // 0x1f
|
||||
LOGE(v2, name);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, string, name);
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
(*env)->DeleteLocalRef(env, clazz);
|
||||
}
|
||||
}
|
||||
|
||||
bool isAmProxy(JNIEnv *env, int sdk) {
|
||||
char v1[0xb], v2[0x29];
|
||||
bool proxy = false;
|
||||
jmethodID method;
|
||||
jclass classActivityManager;
|
||||
|
||||
if (sdk >= 26) {
|
||||
fill_android_app_ActivityManager(v2); // 0x1b + 1
|
||||
classActivityManager = (*env)->FindClass(env, v2);
|
||||
debug(env, "ActivityManager: %s", classActivityManager);
|
||||
fill_getService(v1); // 0xa + 1
|
||||
fill_getService_signature(v2); // 0x20 + 1
|
||||
method = (*env)->GetStaticMethodID(env, classActivityManager, v1, v2);
|
||||
#ifdef DEBUG
|
||||
LOGI("ActivityManager.getService: %p", method);
|
||||
#endif
|
||||
if (method == NULL) {
|
||||
#ifdef DEBUG
|
||||
LOGW("cannot find ActivityManager.getService");
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
goto clean3;
|
||||
}
|
||||
} else {
|
||||
fill_android_app_ActivityManagerNative(v2); // 0x21 + 1
|
||||
classActivityManager = (*env)->FindClass(env, v2);
|
||||
debug(env, "ActivityManagerNative: %s", classActivityManager);
|
||||
fill_getDefault(v1); // 0xa + 1
|
||||
fill_getDefault_signature(v2); // 0x20 + 1
|
||||
method = (*env)->GetStaticMethodID(env, classActivityManager, v1, v2);
|
||||
#ifdef DEBUG
|
||||
LOGI("ActivityManagerNative.getDefault: %p", method);
|
||||
#endif
|
||||
}
|
||||
|
||||
jobject activityManager = (*env)->CallStaticObjectMethod(env, classActivityManager, method);
|
||||
if (activityManager == NULL) {
|
||||
#ifdef DEBUG
|
||||
LOGW("activity manager is null");
|
||||
#endif
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
#ifdef DEBUG
|
||||
(*env)->ExceptionDescribe(env);
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
goto clean3;
|
||||
}
|
||||
debug(env, "activity manager: %s", activityManager);
|
||||
|
||||
jclass binderClass = NULL;
|
||||
jobject binder = NULL;
|
||||
|
||||
fill_android_os_BinderProxy(v2); // 0x16 + 1
|
||||
jclass classBinderProxy = (*env)->FindClass(env, v2);
|
||||
if (classBinderProxy == NULL) {
|
||||
#ifdef DEBUG
|
||||
LOGW("cannot find BinderProxy");
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
} else {
|
||||
debug(env, "BinderProxy: %s", classBinderProxy);
|
||||
}
|
||||
|
||||
fill_android_os_IInterface(v2); // 0x15 + 1
|
||||
jclass classIInterface = (*env)->FindClass(env, v2);
|
||||
debug(env, "IInterface: %s", classIInterface);
|
||||
|
||||
if (!(*env)->IsInstanceOf(env, activityManager, classIInterface)) {
|
||||
#ifdef DEBUG
|
||||
LOGW("activity manager is not IInterface");
|
||||
#endif
|
||||
goto clean2;
|
||||
}
|
||||
|
||||
fill_asBinder(v1); // 0x8 + 1
|
||||
fill_asBinder_signature(v2); // 0x16 + 1
|
||||
method = (*env)->GetMethodID(env, classIInterface, v1, v2);
|
||||
#ifdef DEBUG
|
||||
LOGI("IInterface.asBinder: %p", method);
|
||||
#endif
|
||||
binder = (*env)->CallObjectMethod(env, activityManager, method);
|
||||
if (binder == NULL) {
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
#ifdef DEBUG
|
||||
(*env)->ExceptionDescribe(env);
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
showError(env, NULL);
|
||||
proxy = true;
|
||||
goto clean2;
|
||||
}
|
||||
debug(env, "binder: %s", binder);
|
||||
|
||||
binderClass = (*env)->GetObjectClass(env, binder);
|
||||
debug(env, "binder class: %s", binderClass);
|
||||
|
||||
if (classBinderProxy != NULL && !(*env)->IsSameObject(env, binderClass, classBinderProxy)) {
|
||||
showError(env, binderClass);
|
||||
proxy = true;
|
||||
goto clean2;
|
||||
}
|
||||
|
||||
fill_android_os_ServiceManager(v2); // 0x19 + 1
|
||||
jclass classServiceManager = (*env)->FindClass(env, v2);
|
||||
if (classServiceManager == NULL) {
|
||||
#ifdef DEBUG
|
||||
LOGW("cannot find ServiceManager");
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
goto clean2;
|
||||
}
|
||||
debug(env, "ServiceManager: %s", classServiceManager);
|
||||
|
||||
fill_getService(v1); // 0xa + 1
|
||||
fill_getService_signature_IBinder(v2); // 0x28 + 1
|
||||
method = (*env)->GetStaticMethodID(env, classServiceManager, v1, v2);
|
||||
|
||||
#ifdef DEBUG
|
||||
LOGI("ServiceManager.getService: %p", method);
|
||||
#endif
|
||||
if (method == NULL) {
|
||||
(*env)->ExceptionClear(env);
|
||||
goto clean1;
|
||||
}
|
||||
|
||||
fill_activity(v2); // 0x8 + 1
|
||||
jstring stringActivity = (*env)->NewStringUTF(env, v2);
|
||||
jobject service = (*env)->CallStaticObjectMethod(env, classServiceManager, method,
|
||||
stringActivity);
|
||||
jclass serviceClass = NULL;
|
||||
|
||||
if (service == NULL) {
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
#ifdef DEBUG
|
||||
(*env)->ExceptionDescribe(env);
|
||||
#endif
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
showError(env, NULL);
|
||||
proxy = true;
|
||||
goto clean;
|
||||
}
|
||||
debug(env, "service: %s", service);
|
||||
|
||||
serviceClass = (*env)->GetObjectClass(env, service);
|
||||
debug(env, "service class: %s", serviceClass);
|
||||
if (classBinderProxy != NULL && !(*env)->IsSameObject(env, serviceClass, classBinderProxy)) {
|
||||
showError(env, serviceClass);
|
||||
proxy = true;
|
||||
goto clean;
|
||||
}
|
||||
|
||||
bool equals = (*env)->IsSameObject(env, binder, service);
|
||||
#ifdef DEBUG
|
||||
LOGI("binder: %p, service: %p, equals: %d", binder, service, equals);
|
||||
#endif
|
||||
proxy = !equals;
|
||||
|
||||
clean:
|
||||
if (serviceClass != NULL) {
|
||||
(*env)->DeleteLocalRef(env, serviceClass);
|
||||
}
|
||||
if (service != NULL) {
|
||||
(*env)->DeleteLocalRef(env, service);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, stringActivity);
|
||||
|
||||
clean1:
|
||||
(*env)->DeleteLocalRef(env, classServiceManager);
|
||||
|
||||
clean2:
|
||||
if (binderClass != NULL) {
|
||||
(*env)->DeleteLocalRef(env, binderClass);
|
||||
}
|
||||
if (binder != NULL) {
|
||||
(*env)->DeleteLocalRef(env, binder);
|
||||
}
|
||||
if (classBinderProxy != NULL) {
|
||||
(*env)->DeleteLocalRef(env, classBinderProxy);
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, classIInterface);
|
||||
(*env)->DeleteLocalRef(env, activityManager);
|
||||
|
||||
clean3:
|
||||
(*env)->DeleteLocalRef(env, classActivityManager);
|
||||
|
||||
return proxy;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/15.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_AM_PROXY_H
|
||||
#define BREVENT_AM_PROXY_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool isAmProxy(JNIEnv *env, int sdk);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_AM_PROXY_H
|
||||
@@ -1,169 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/8.
|
||||
//
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef MAIN
|
||||
#include <stdio.h>
|
||||
#else
|
||||
|
||||
#include "common.h"
|
||||
#include "openat.h"
|
||||
|
||||
#endif
|
||||
|
||||
static bool isApkSigBlock42(const char *buffer) {
|
||||
// APK Sig Block 42
|
||||
return *buffer == 'A'
|
||||
&& *++buffer == 'P'
|
||||
&& *++buffer == 'K'
|
||||
&& *++buffer == ' '
|
||||
&& *++buffer == 'S'
|
||||
&& *++buffer == 'i'
|
||||
&& *++buffer == 'g'
|
||||
&& *++buffer == ' '
|
||||
&& *++buffer == 'B'
|
||||
&& *++buffer == 'l'
|
||||
&& *++buffer == 'o'
|
||||
&& *++buffer == 'c'
|
||||
&& *++buffer == 'k'
|
||||
&& *++buffer == ' '
|
||||
&& *++buffer == '4'
|
||||
&& *++buffer == '2';
|
||||
}
|
||||
|
||||
int checkSignature(const char *path) {
|
||||
unsigned char buffer[0x11] = {0};
|
||||
uint32_t size4;
|
||||
uint64_t size8, size_of_block;
|
||||
|
||||
#ifdef DEBUG
|
||||
LOGI("check signature for %s", path);
|
||||
#endif
|
||||
|
||||
int sign = -1;
|
||||
int fd = (int) openAt(AT_FDCWD, path, O_RDONLY);
|
||||
#ifdef DEBUG_OPENAT
|
||||
LOGI("openat %s returns %d", path, fd);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
return sign;
|
||||
}
|
||||
|
||||
sign = 1;
|
||||
// https://en.wikipedia.org/wiki/Zip_(file_format)#End_of_central_directory_record_(EOCD)
|
||||
for (int i = 0;; ++i) {
|
||||
unsigned short n;
|
||||
lseek(fd, -i - 2, SEEK_END);
|
||||
read(fd, &n, 2);
|
||||
if (n == i) {
|
||||
lseek(fd, -22, SEEK_CUR);
|
||||
read(fd, &size4, 4);
|
||||
if ((size4 ^ 0xcafebabeu) == 0xccfbf1eeu) {
|
||||
#ifdef MAIN
|
||||
if (i > 0) {
|
||||
printf("warning: comment length is %d\n", i);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 0xffff) {
|
||||
#ifdef MAIN
|
||||
printf("error: cannot find eocd\n");
|
||||
#endif
|
||||
goto clean;
|
||||
}
|
||||
}
|
||||
|
||||
lseek(fd, 12, SEEK_CUR);
|
||||
// offset
|
||||
read(fd, &size4, 0x4);
|
||||
lseek(fd, (off_t) (size4 - 0x18), SEEK_SET);
|
||||
|
||||
read(fd, &size8, 0x8);
|
||||
read(fd, buffer, 0x10);
|
||||
if (!isApkSigBlock42((char *) buffer)) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
lseek(fd, (off_t) (size4 - (size8 + 0x8)), SEEK_SET);
|
||||
read(fd, &size_of_block, 0x8);
|
||||
if (size_of_block != size8) {
|
||||
goto clean;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
uint32_t id;
|
||||
uint32_t offset;
|
||||
read(fd, &size8, 0x8); // sequence length
|
||||
if (size8 == size_of_block) {
|
||||
break;
|
||||
}
|
||||
read(fd, &id, 0x4); // id
|
||||
offset = 4;
|
||||
#ifdef MAIN
|
||||
printf("id: 0x%08x\n", id);
|
||||
#endif
|
||||
if ((id ^ 0xdeadbeefu) == 0xafa439f5u || (id ^ 0xdeadbeefu) == 0x2efed62f) {
|
||||
read(fd, &size4, 0x4); // signer-sequence length
|
||||
read(fd, &size4, 0x4); // signer length
|
||||
read(fd, &size4, 0x4); // signed data length
|
||||
offset += 0x4 * 3;
|
||||
|
||||
read(fd, &size4, 0x4); // digests-sequence length
|
||||
lseek(fd, (off_t) (size4), SEEK_CUR);// skip digests
|
||||
offset += 0x4 + size4;
|
||||
|
||||
read(fd, &size4, 0x4); // certificates length
|
||||
read(fd, &size4, 0x4); // certificate length
|
||||
offset += 0x4 * 2;
|
||||
#ifdef MAIN
|
||||
int hash = 1;
|
||||
signed char c;
|
||||
for (unsigned i = 0; i < size4; ++i) {
|
||||
read(fd, &c, 0x1);
|
||||
hash = 31 * hash + c;
|
||||
}
|
||||
offset += size4;
|
||||
printf(" size: 0x%04x, hash: 0x%08x\n", size4, ((unsigned) hash) ^ 0x14131211u);
|
||||
#else
|
||||
#if defined(GENUINE_SIZE) && defined(GENUINE_HASH)
|
||||
if (size4 == GENUINE_SIZE) {
|
||||
int hash = 1;
|
||||
signed char c;
|
||||
for (unsigned i = 0; i < size4; ++i) {
|
||||
read(fd, &c, 0x1);
|
||||
hash = 31 * hash + c;
|
||||
}
|
||||
offset += size4;
|
||||
if ((((unsigned) hash) ^ 0x14131211u) == GENUINE_HASH) {
|
||||
sign = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
sign = 0;
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
lseek(fd, (off_t) (size8 - offset), SEEK_CUR);
|
||||
}
|
||||
|
||||
clean:
|
||||
close(fd);
|
||||
|
||||
return sign;
|
||||
}
|
||||
|
||||
#ifdef MAIN
|
||||
int main(int argc, char **argv) {
|
||||
if (argc > 1) {
|
||||
checkSignature(argv[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/8.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_APK_SIGN_V2_H
|
||||
#define BREVENT_APK_SIGN_V2_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int checkSignature(const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_APK_SIGN_V2_H
|
||||
@@ -1,233 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/20.
|
||||
//
|
||||
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/system_properties.h>
|
||||
#include "common.h"
|
||||
#include "plt.h"
|
||||
|
||||
static volatile int mGenuine;
|
||||
|
||||
static bool onCheckTrue(JNIEnv *env __unused) {
|
||||
#ifdef DEBUG_NATIVE
|
||||
has_native_libs();
|
||||
#endif
|
||||
#ifdef DEBUG_GENUINE_MOCK
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckFalse(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_FALSE_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_FALSE_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckFake(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_FAKE_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_FAKE_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckOverlay(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_OVERLAY_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_OVERLAY_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckOdex(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_ODEX_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_ODEX_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckDex(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_DEX_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_DEX_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckProxy(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_PROXY_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_PROXY_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckError(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_ERROR_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_ERROR_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckFatal(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_FATAL_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_FATAL_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool onCheckNoapk(JNIEnv *env __unused) {
|
||||
#if defined(GENUINE_NOAPK_CRASH)
|
||||
return false;
|
||||
#elif defined(GENUINE_NOAPK_NATIVE)
|
||||
start_native_activity_async(env);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setGenuine(JNIEnv *env, int genuine) {
|
||||
mGenuine = genuine;
|
||||
switch (genuine) {
|
||||
case CHECK_TRUE:
|
||||
return onCheckTrue(env);
|
||||
case CHECK_FALSE:
|
||||
return onCheckFalse(env);
|
||||
case CHECK_FAKE:
|
||||
return onCheckFake(env);
|
||||
case CHECK_OVERLAY:
|
||||
return onCheckOverlay(env);
|
||||
case CHECK_ODEX:
|
||||
return onCheckOdex(env);
|
||||
case CHECK_DEX:
|
||||
return onCheckDex(env);
|
||||
case CHECK_PROXY:
|
||||
return onCheckProxy(env);
|
||||
case CHECK_ERROR:
|
||||
return onCheckError(env);
|
||||
case CHECK_FATAL:
|
||||
return onCheckFatal(env);
|
||||
case CHECK_NOAPK:
|
||||
return onCheckNoapk(env);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int getGenuine() {
|
||||
return mGenuine;
|
||||
}
|
||||
|
||||
char *getGenuinePackageName() {
|
||||
#ifdef GET_GENUINE_PACKAGE_NAME
|
||||
return GET_GENUINE_PACKAGE_NAME();
|
||||
#elif defined(GENUINE_NAME)
|
||||
static unsigned int m = 0;
|
||||
if (m == 0) {
|
||||
m = 20;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
char name[] = GENUINE_NAME;
|
||||
unsigned int length = sizeof(name) - 1;
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
name[i] ^= ((i + length) % m);
|
||||
}
|
||||
name[length] = '\0';
|
||||
return strdup(name);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((__format__ (__printf__, 2, 0)))
|
||||
void genuine_log_print(int prio, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
__android_log_vprint(prio, TAG, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static inline void fill_ro_build_version_sdk(char v[]) {
|
||||
// ro.build.version.sdk
|
||||
static unsigned int m = 0;
|
||||
|
||||
if (m == 0) {
|
||||
m = 19;
|
||||
} else if (m == 23) {
|
||||
m = 29;
|
||||
}
|
||||
|
||||
v[0x0] = 's';
|
||||
v[0x1] = 'm';
|
||||
v[0x2] = '-';
|
||||
v[0x3] = 'f';
|
||||
v[0x4] = 'p';
|
||||
v[0x5] = 'o';
|
||||
v[0x6] = 'k';
|
||||
v[0x7] = 'l';
|
||||
v[0x8] = '\'';
|
||||
v[0x9] = '|';
|
||||
v[0xa] = 'n';
|
||||
v[0xb] = '~';
|
||||
v[0xc] = '~';
|
||||
v[0xd] = 'g';
|
||||
v[0xe] = '`';
|
||||
v[0xf] = '~';
|
||||
v[0x10] = '?';
|
||||
v[0x11] = 'a';
|
||||
v[0x12] = 'd';
|
||||
v[0x13] = 'j';
|
||||
for (unsigned int i = 0; i < 0x14; ++i) {
|
||||
v[i] ^= ((i + 0x14) % m);
|
||||
}
|
||||
v[0x14] = '\0';
|
||||
}
|
||||
|
||||
int getSdk() {
|
||||
static int sdk = 0;
|
||||
if (sdk == 0) {
|
||||
char v1[0x20];
|
||||
char prop[PROP_VALUE_MAX] = {0};
|
||||
fill_ro_build_version_sdk(v1);
|
||||
__system_property_get(v1, prop);
|
||||
sdk = (int) strtol(prop, NULL, 10);
|
||||
}
|
||||
return sdk;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void debug(JNIEnv *env, const char *format, jobject object) {
|
||||
if (object == NULL) {
|
||||
LOGI(format, NULL);
|
||||
} else {
|
||||
jclass objectClass = (*env)->FindClass(env, "java/lang/Object");
|
||||
jmethodID toString = (*env)->GetMethodID(env, objectClass, "toString",
|
||||
"()Ljava/lang/String;");
|
||||
jstring string = (jstring) (*env)->CallObjectMethod(env, object, toString);
|
||||
const char *value = (*env)->GetStringUTFChars(env, string, NULL);
|
||||
LOGI(format, value);
|
||||
(*env)->ReleaseStringUTFChars(env, string, value);
|
||||
(*env)->DeleteLocalRef(env, string);
|
||||
(*env)->DeleteLocalRef(env, objectClass);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,73 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/20.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_COMMON_H
|
||||
#define BREVENT_COMMON_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdbool.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#if __has_include("genuine.h")
|
||||
#include "genuine.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
CHECK_TRUE,
|
||||
CHECK_FALSE,
|
||||
CHECK_FAKE,
|
||||
CHECK_OVERLAY,
|
||||
CHECK_ODEX,
|
||||
CHECK_DEX,
|
||||
CHECK_PROXY,
|
||||
CHECK_ERROR,
|
||||
CHECK_FATAL,
|
||||
CHECK_NOAPK,
|
||||
};
|
||||
|
||||
#ifndef TAG
|
||||
#define TAG "Genuine"
|
||||
#endif
|
||||
|
||||
#ifndef LOGI
|
||||
#define LOGI(...) (genuine_log_print(ANDROID_LOG_INFO, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef LOGW
|
||||
#define LOGW(...) (genuine_log_print(ANDROID_LOG_WARN, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
#ifndef LOGE
|
||||
#define LOGE(...) (genuine_log_print(ANDROID_LOG_ERROR, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
void genuine_log_print(int prio, const char *fmt, ...);
|
||||
|
||||
char *getGenuinePackageName();
|
||||
|
||||
bool setGenuine(JNIEnv *env, int genuine);
|
||||
|
||||
int getGenuine();
|
||||
|
||||
int getSdk();
|
||||
|
||||
bool has_native_libs();
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void debug(JNIEnv *env, const char *format, jobject object);
|
||||
|
||||
#else
|
||||
#define debug(...) do {} while(0);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_COMMON_H
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,43 +0,0 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GENUINE_NAME {0x62, 0x63, 0x23, 0x69, 0x66, 0x64, 0x79, 0x67, 0x71, 0x2e, 0x6f, 0x67, 0x68, 0x6b, 0x6c, 0x68, 0x71, 0x6d, 0x7b, 0x7e, 0x6e, 0x7e, 0x23, 0x6b, 0x67, 0x66, 0x78, 0x77, 0x64, 0x65, 0x73, 0x0}
|
||||
#define GENUINE_SIZE 0x02d1
|
||||
#define GENUINE_HASH 0x9a99ba0c
|
||||
|
||||
/* genuine false handler */
|
||||
#define GENUINE_FALSE_CRASH
|
||||
// #define GENUINE_FALSE_NATIVE
|
||||
|
||||
/* genuine fake handler */
|
||||
#define GENUINE_FAKE_CRASH
|
||||
// #define GENUINE_FAKE_NATIVE
|
||||
|
||||
/* genuine overlay handler */
|
||||
// #define GENUINE_OVERLAY_CRASH
|
||||
// #define GENUINE_OVERLAY_NATIVE
|
||||
|
||||
/* genuine odex handler */
|
||||
// #define GENUINE_ODEX_CRASH
|
||||
// #define GENUINE_ODEX_NATIVE
|
||||
|
||||
/* genuine dex handler */
|
||||
#define GENUINE_DEX_CRASH
|
||||
// #define GENUINE_DEX_NATIVE
|
||||
|
||||
/* genuine proxy handler */
|
||||
#define GENUINE_PROXY_CRASH
|
||||
// #define GENUINE_PROXY_NATIVE
|
||||
|
||||
/* genuine error handler */
|
||||
#define GENUINE_ERROR_CRASH
|
||||
// #define GENUINE_ERROR_NATIVE
|
||||
|
||||
/* genuine fatal handler */
|
||||
#define GENUINE_FATAL_CRASH
|
||||
// #define GENUINE_FATAL_NATIVE
|
||||
|
||||
/* genuine noapk handler */
|
||||
#define GENUINE_NOAPK_CRASH
|
||||
// #define GENUINE_NOAPK_NATIVE
|
||||
|
||||
bool checkGenuine(JNIEnv *env);
|
||||
@@ -1,333 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/18.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "inline.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifdef DEBUG_HOOK_SELF
|
||||
|
||||
#include <syscall.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "whale/whale.h"
|
||||
|
||||
static long faccessat_replace(int dirfd, const char *pathname, int mode, int flags) {
|
||||
return syscall(__NR_faccessat, dirfd, pathname, mode, flags);
|
||||
}
|
||||
|
||||
static long fchownat_replace(int dirfd, const char *pathname, uid_t owner, gid_t group, int flags) {
|
||||
return syscall(__NR_fchownat, dirfd, pathname, owner, group, flags);
|
||||
}
|
||||
|
||||
static int futimens_replace(int fd, const struct timespec times[2]) {
|
||||
return utimensat(fd, NULL, times, 0);
|
||||
}
|
||||
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
|
||||
void check_inline_hook_hookzz() {
|
||||
void *backup;
|
||||
zz_disable_arm_arm64_b_branch();
|
||||
|
||||
ZzReplace(&fchownat, &fchownat_replace, &backup);
|
||||
LOGI("hookzz fchownat: %p, replace: %p, hooked: %d", &fchownat, &fchownat_replace,
|
||||
isInlineHooked(&fchownat));
|
||||
|
||||
ZzReplace(&faccessat, &faccessat_replace, &backup);
|
||||
LOGI("hookzz faccessat: %p, repalce: %p, hooked: %d", &faccessat, &faccessat_replace,
|
||||
isInlineHooked(&faccessat));
|
||||
|
||||
ZzReplace(&futimens, &futimens_replace, &backup);
|
||||
LOGI("hookzz futimens: %p, replace: %p, hooked: %d", &futimens, &futimens_replace,
|
||||
isInlineHooked(&futimens));
|
||||
}
|
||||
|
||||
void check_inline_hook_hookzz_b() {
|
||||
void *backup;
|
||||
zz_enable_arm_arm64_b_branch();
|
||||
|
||||
ZzReplace(&fchownat, &fchownat_replace, &backup);
|
||||
LOGI("hookzz-b fchownat: %p, replace: %p, hooked: %d", &fchownat, &fchownat_replace,
|
||||
isInlineHooked(&fchownat));
|
||||
|
||||
ZzReplace(&faccessat, &faccessat_replace, &backup);
|
||||
LOGI("hookzz-b faccessat: %p, repalce: %p, hooked: %d", &faccessat, &faccessat_replace,
|
||||
isInlineHooked(&faccessat));
|
||||
|
||||
ZzReplace(&futimens, &futimens_replace, &backup);
|
||||
LOGI("hookzz-b futimens: %p, replace: %p, hooked: %d", &futimens, &futimens_replace,
|
||||
isInlineHooked(&futimens));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void check_inline_hook_whale() {
|
||||
WInlineHookFunction(&fchownat, &fchownat_replace, NULL);
|
||||
LOGI("whale fchownat: %p, replace: %p, hooked: %d", &fchownat, &fchownat_replace,
|
||||
isInlineHooked(&fchownat));
|
||||
|
||||
WInlineHookFunction(&faccessat, &faccessat_replace, NULL);
|
||||
LOGI("whale faccessat: %p, repalce: %p, hooked: %d", &faccessat, &faccessat_replace,
|
||||
isInlineHooked(&faccessat));
|
||||
|
||||
WInlineHookFunction(&futimens, &futimens_replace, NULL);
|
||||
LOGI("whale futimens: %p, replace: %p, hooked: %d", &futimens, &futimens_replace,
|
||||
isInlineHooked(&futimens));
|
||||
}
|
||||
|
||||
#if defined(__arm__) || defined(DEBUG_HOOK_IDE)
|
||||
|
||||
#include "substrate/CydiaSubstrate.h"
|
||||
|
||||
void check_inline_hook_substrate() {
|
||||
MSHookFunction(&fchownat, &fchownat_replace, NULL);
|
||||
LOGI("substrate fchownat: %p, replace: %p, hooked: %d", &fchownat, &fchownat_replace,
|
||||
isInlineHooked(&fchownat));
|
||||
|
||||
MSHookFunction(&faccessat, &faccessat_replace, NULL);
|
||||
LOGI("substrate faccessat: %p, repalce: %p, hooked: %d", &faccessat, &faccessat_replace,
|
||||
isInlineHooked(&faccessat));
|
||||
|
||||
MSHookFunction(&futimens, &futimens_replace, NULL);
|
||||
LOGI("substrate futimens: %p, replace: %p, hooked: %d", &futimens, &futimens_replace,
|
||||
isInlineHooked(&futimens));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
bool isInlineHooked(void *symbol) {
|
||||
if (symbol == NULL) {
|
||||
return false;
|
||||
}
|
||||
#if defined(__arm__) || defined(DEBUG_HOOK_IDE)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0597/b/base-instructions-alphabetic-order/ldr-literal-load-register-literal
|
||||
// A1, !(P == 0 && W == 1), we don't check P and W
|
||||
// cond 010P U0W1 1111 _Rt_ xxxx xxxx xxxx
|
||||
#define IS_LDR_PC_A1(x) (((x) & 0xfe5ff000u) == 0xe41ff000u)
|
||||
// T2
|
||||
// 1111 1000 U101 1111 | _Rt_ xxxx xxxx xxxx
|
||||
#define IS_LDR_PC_T2(x) (((x) & 0xf000ff7fu) == 0xf000f85fu)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0597/b/base-instructions-alphabetic-order/b-branch
|
||||
// A1
|
||||
// cond 100 xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
#define IS_B_A1(x) (((x) & 0xff000000u) == 0xea000000u)
|
||||
// T2
|
||||
// 1110 0xxx xxxx xxxx
|
||||
#define IS_B_T2(x) (((x) & 0xf800u) == 0xe000u)
|
||||
// T4
|
||||
// 1111 0Sxx xxxx xxxx | 10J1 Jxxx xxxx xxxx
|
||||
// -- imm10 --- | --- imm11 ---
|
||||
#define IS_B_T4(x) (((x) & 0xd000f800u) == 0x9000f000u)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0597/b/base-instructions-alphabetic-order/nop-no-operation
|
||||
// T1, hint should be 0000, we don't check
|
||||
// 1011 1111 hint 0000
|
||||
#define IS_NOP_T1(x) (((x) & 0xff0fu) == 0xbf00u)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0597/b/base-instructions-alphabetic-order/mov-movs-register-move-register
|
||||
// cydia use `mov r8, r8` for Nop
|
||||
// T1, Mmmm is Rm, Dddd is Rd
|
||||
// 0100 0110 DMmm mddd
|
||||
#define _IS_MOV_T1(x) (((x) & 0xff00u) == 0x4600u)
|
||||
#define _RM_MOV_T1(x) ((((x) & 0x78u) >> 3u))
|
||||
#define _RD_MOV_T1(x) ((((x) & 0x80u) >> 4u) | ((x) & 7u))
|
||||
#define IS_MOV_T1_RR(x) (_IS_MOV_T1(x) && _RM_MOV_T1(x) == _RD_MOV_T1(x))
|
||||
|
||||
// https://developer.arm.com/docs/ddi0597/b/base-instructions-alphabetic-order/bx-branch-and-exchange
|
||||
// cydia use `bx`
|
||||
// T1
|
||||
// 0100 0111 0Rmm m000
|
||||
#define IS_BX_T1(x) (((x) & 0xff87u) == 0x4700u)
|
||||
#define RM_BX_T1(x) (((x) & 0x0078u) >> 3u)
|
||||
#define IS_BX_PC_T1(x) ((x) == 0x4778u)
|
||||
|
||||
uintptr_t address = (uintptr_t) symbol;
|
||||
if ((address & 1U) == 0) {
|
||||
uint32_t *value32 = (uint32_t *) address;
|
||||
if (IS_LDR_PC_A1(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(arm ldr pc) symbol: %p, value: %08x", symbol, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_B_A1(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(arm b) symbol: %p, value: %08x", symbol, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
LOGI("(arm) symbol: %p, value: %08x", symbol, *value32);
|
||||
#endif
|
||||
} else {
|
||||
address = address & ~1U;
|
||||
uint16_t *value16 = (uint16_t *) address;
|
||||
uint32_t *value32 = (uint32_t *) address;
|
||||
if (IS_LDR_PC_T2(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb ldr pc) symbol: %p, address: %p, value: %08x",
|
||||
symbol, address, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_B_T4(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb b) symbol: %p, address: %p, value: %08x",
|
||||
symbol, address, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_B_T2(*value16)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb b) symbol: %p, address: %p, value: %04x",
|
||||
symbol, address, *value16);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_NOP_T1(*value16) || IS_MOV_T1_RR(*value16)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb nop) symbol: %p, address: %p, value: %04x",
|
||||
symbol, address, *value16);
|
||||
#endif
|
||||
address += 2;
|
||||
value16 = (uint16_t *) address;
|
||||
value32 = (uint32_t *) address;
|
||||
}
|
||||
if (IS_LDR_PC_T2(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb ldr pc) symbol: %p, address: %p, value: %08x",
|
||||
symbol, address, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_BX_PC_T1(*value16) && IS_LDR_PC_A1(*(value32 + 1))) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(thumb bx + arm ldr pc) symbol: %p, address: %p, value: %08x %08x",
|
||||
symbol, address, *value32, *(value32 + 1));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
LOGI("(thumb) symbol: %p, address: %p, value: %08x %08x",
|
||||
symbol, address, *value32, *(value32 + 1));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(__aarch64__) || defined(DEBUG_HOOK_IDE)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch
|
||||
// 0001 01xx xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
// ------------ imm26 -------------
|
||||
#define IS_B(x) (((x) & 0xfc000000u) == 0x14000000u)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/ldr-literal-load-register-literal
|
||||
// 0101 1000 xxxx xxxx xxxx xxxx xxxR tttt
|
||||
// -------- imm19 --------
|
||||
#define IS_LDR_X(x) (((x) & 0xff000000u) == 0x58000000u)
|
||||
#define X_LDR(x) ((x) & 0x1fu)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/adrp-form-pc-relative-address-to-4kb-page
|
||||
// 1xx1 0000 xxxx xxxx xxxx xxxx xxxR dddd
|
||||
// lo -------- immhi --------
|
||||
#define IS_ADRP_X(x) (((x) & 0x9f000000u) == 0x90000000u)
|
||||
#define X_ADRP(x) ((x) & 0x1fu)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/br-branch-to-register
|
||||
// 1101 0110 0001 1111 0000 00Rn nnn0 0000
|
||||
#define IS_BR_X(x) (((x) & 0xfffffc0f) == 0xd61f0000u)
|
||||
#define X_BR(x) (((x) & 0x3e0u) >> 0x5u)
|
||||
|
||||
// https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/movz-move-wide-with-zero
|
||||
// 1op1 0010 1hwx xxxx xxxx xxxx xxxR dddd
|
||||
// ------ imm16 -------
|
||||
// for op, 00 -> MOVN, 10 -> MOVZ, 11 -> MOVK
|
||||
#define IS_MOV_X(x) (((x) & 0x9f800000u) == 0x92800000u)
|
||||
#define X_MOV(x) ((x) & 0x1fu)
|
||||
|
||||
uint32_t *value32 = symbol;
|
||||
if (IS_B(*value32)) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(arm64 b) symbol: %p, value: %08x", symbol, *value32);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (IS_LDR_X(*value32) && IS_BR_X(*(value32 + 1))) {
|
||||
uint32_t x = X_LDR(*value32);
|
||||
if (x == X_BR(*(value32 + 1))) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(arm64 ldr+br x%d) symbol: %p, value: %08x %08x",
|
||||
x, symbol, *value32, *(value32 + 1));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (IS_ADRP_X(*value32) && IS_BR_X(*(value32 + 1))) {
|
||||
uint32_t x = X_ADRP(*value32);
|
||||
if (x == X_BR(*(value32 + 1))) {
|
||||
#ifdef DEBUG_HOOK
|
||||
LOGW("(arm64 adrp+br x%d) symbol: %p, value: %08x %08x",
|
||||
x, symbol, *value32, *(value32 + 1));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (IS_MOV_X(*value32)) {
|
||||
uint32_t x = X_MOV(*value32);
|
||||
for (int i = 1; i <= 4; ++i) {
|
||||
if (IS_BR_X(*(value32 + i))) {
|
||||
if (x != X_BR(*(value32 + i))) {
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_HOOK
|
||||
for (int k = 0; k < i; ++k) {
|
||||
LOGW("(arm64 mov x%d) symbol: %p, value: %08x",
|
||||
x, symbol + sizeof(uint32_t) * k, *(value32 + k));
|
||||
}
|
||||
LOGW("(arm64 br x%d) symbol: %p, value: %08x",
|
||||
x, symbol + sizeof(uint32_t) * i, *(value32 + i));
|
||||
#endif
|
||||
return true;
|
||||
} else if (IS_MOV_X(*(value32 + i))) {
|
||||
if (x != X_MOV(*(value32 + i))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
LOGI("(arm64) symbol: %p, value: %08x %08x", symbol, *value32, *(value32 + 1));
|
||||
#endif
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_HOOK_IO
|
||||
bool setRead(void *symbol) {
|
||||
uintptr_t address = (uintptr_t) symbol;
|
||||
uintptr_t page_size = (uintptr_t) getpagesize();
|
||||
uintptr_t base = address & ~(page_size - 1);
|
||||
// inline check read at most 20 bytes
|
||||
uintptr_t end = (address + 20 + page_size - 1) & -page_size;
|
||||
#ifdef DEBUG
|
||||
LOGI("set r+x from %p to %p", base, end);
|
||||
#endif
|
||||
if (mprotect((void *) base, end - base, PROT_READ | PROT_EXEC)) {
|
||||
#ifdef DEBUG
|
||||
LOGW("cannot mprotect: %s", strerror(errno));
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/18.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_INLINE_H
|
||||
#define BREVENT_INLINE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_HOOK_IO
|
||||
bool setRead(void *symbol);
|
||||
#endif
|
||||
|
||||
bool isInlineHooked(void *symbol);
|
||||
|
||||
#ifdef DEBUG_HOOK_SELF
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
|
||||
#include "hookzz/hookzz.h"
|
||||
|
||||
void check_inline_hook_hookzz();
|
||||
|
||||
void check_inline_hook_hookzz_b();
|
||||
|
||||
#endif
|
||||
|
||||
void check_inline_hook_whale();
|
||||
|
||||
#if defined(__arm__)
|
||||
|
||||
void check_inline_hook_substrate();
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_INLINE_H
|
||||
@@ -1,56 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/30.
|
||||
//
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#include "openat.h"
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
intptr_t openAt(intptr_t fd, const char *path, intptr_t flag) {
|
||||
#if defined(__arm__)
|
||||
intptr_t r;
|
||||
__asm__ volatile(
|
||||
#ifndef OPTIMIZE_ASM
|
||||
"mov r0, %1\n\t"
|
||||
"mov r1, %2\n\t"
|
||||
"mov r2, %3\n\t"
|
||||
#endif
|
||||
|
||||
"mov ip, r7\n\t"
|
||||
".cfi_register r7, ip\n\t"
|
||||
"ldr r7, =" STR(__NR_openat) "\n\t"
|
||||
"svc #0\n\t"
|
||||
"mov r7, ip\n\t"
|
||||
".cfi_restore r7\n\t"
|
||||
|
||||
#ifndef OPTIMIZE_ASM
|
||||
"mov %0, r0\n\t"
|
||||
#endif
|
||||
: "=r" (r)
|
||||
: "r" (fd), "r" (path), "r" (flag));
|
||||
return r;
|
||||
#elif defined(__aarch64__)
|
||||
intptr_t r;
|
||||
__asm__ volatile(
|
||||
#ifndef OPTIMIZE_ASM
|
||||
"mov x0, %1\n\t"
|
||||
"mov x1, %2\n\t"
|
||||
"mov x2, %3\n\t"
|
||||
#endif
|
||||
|
||||
"mov x8, " STR(__NR_openat) "\n\t"
|
||||
"svc #0\n\t"
|
||||
|
||||
#ifndef OPTIMIZE_ASM
|
||||
"mov %0, x0\n\t"
|
||||
#endif
|
||||
: "=r" (r)
|
||||
: "r" (fd), "r" (path), "r" (flag));
|
||||
return r;
|
||||
#else
|
||||
return (intptr_t) syscall(__NR_openat, fd, path, flag);
|
||||
#endif
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/3/30.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_OPENAT_H
|
||||
#define BREVENT_OPENAT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include "common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
||||
intptr_t openAt(intptr_t fd, const char *path, intptr_t flag);
|
||||
|
||||
#else
|
||||
#define openAt openat
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_OPENAT_H
|
||||
@@ -1,95 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019-05-03.
|
||||
//
|
||||
|
||||
#include "path.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static inline bool isSystem(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 's'
|
||||
&& *++str == 'y'
|
||||
&& *++str == 's'
|
||||
&& *++str == 't'
|
||||
&& *++str == 'e'
|
||||
&& *++str == 'm'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
static inline bool isVendor(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 'v'
|
||||
&& *++str == 'e'
|
||||
&& *++str == 'n'
|
||||
&& *++str == 'd'
|
||||
&& *++str == 'o'
|
||||
&& *++str == 'r'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
static inline bool isOem(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 'o'
|
||||
&& *++str == 'e'
|
||||
&& *++str == 'm'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
bool isThirdParty(const char *str) {
|
||||
if (isSystem(str) || isVendor(str) || isOem(str)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isDataApp(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 'd'
|
||||
&& *++str == 'a'
|
||||
&& *++str == 't'
|
||||
&& *++str == 'a'
|
||||
&& *++str == '/'
|
||||
&& *++str == 'a'
|
||||
&& *++str == 'p'
|
||||
&& *++str == 'p'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
bool isAsecApp(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 'm'
|
||||
&& *++str == 'n'
|
||||
&& *++str == 't'
|
||||
&& *++str == '/'
|
||||
&& *++str == 'a'
|
||||
&& *++str == 's'
|
||||
&& *++str == 'e'
|
||||
&& *++str == 'c'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
bool isExpandApp(const char *str) {
|
||||
return str != NULL
|
||||
&& *str == '/'
|
||||
&& *++str == 'm'
|
||||
&& *++str == 'n'
|
||||
&& *++str == 't'
|
||||
&& *++str == '/'
|
||||
&& *++str == 'e'
|
||||
&& *++str == 'x'
|
||||
&& *++str == 'p'
|
||||
&& *++str == 'a'
|
||||
&& *++str == 'n'
|
||||
&& *++str == 'd'
|
||||
&& *++str == '/';
|
||||
}
|
||||
|
||||
bool isExternalSdApp(const char *str) {
|
||||
return isAsecApp(str) || isExpandApp(str);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019-05-03.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_PATH_H
|
||||
#define BREVENT_PATH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool isThirdParty(const char *str);
|
||||
|
||||
bool isDataApp(const char *str);
|
||||
|
||||
bool isExternalSdApp(const char *str);
|
||||
|
||||
#endif //BREVENT_PATH_H
|
||||
@@ -1,355 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/2/16.
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include "plt.h"
|
||||
#include "common.h"
|
||||
#include "path.h"
|
||||
|
||||
/*
|
||||
* reference: https://android.googlesource.com/platform/bionic/+/master/linker/linker_soinfo.cpp
|
||||
*/
|
||||
static uint32_t gnu_hash(const uint8_t *name) {
|
||||
uint32_t h = 5381;
|
||||
|
||||
while (*name) {
|
||||
h += (h << 5) + *name++;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32_t elf_hash(const uint8_t *name) {
|
||||
uint32_t h = 0, g;
|
||||
|
||||
while (*name) {
|
||||
h = (h << 4) + *name++;
|
||||
g = h & 0xf0000000;
|
||||
h ^= g;
|
||||
h ^= g >> 24;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static ElfW(Dyn) *find_dyn_by_tag(ElfW(Dyn) *dyn, ElfW(Sxword) tag) {
|
||||
while (dyn->d_tag != DT_NULL) {
|
||||
if (dyn->d_tag == tag) {
|
||||
return dyn;
|
||||
}
|
||||
++dyn;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool is_global(ElfW(Sym) *sym) {
|
||||
unsigned char stb = ELF_ST_BIND(sym->st_info);
|
||||
if (stb == STB_GLOBAL || stb == STB_WEAK) {
|
||||
return sym->st_shndx != SHN_UNDEF;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static ElfW(Addr) *
|
||||
find_symbol(struct dl_phdr_info *info, ElfW(Dyn) *base_addr, const char *symbol) {
|
||||
ElfW(Dyn) *dyn;
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_SYMTAB);
|
||||
ElfW(Sym) *dynsym = (ElfW(Sym) *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_STRTAB);
|
||||
char *dynstr = (char *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_GNU_HASH);
|
||||
if (dyn != NULL) {
|
||||
ElfW(Word) *dt_gnu_hash = (ElfW(Word) *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
size_t gnu_nbucket_ = dt_gnu_hash[0];
|
||||
uint32_t gnu_maskwords_ = dt_gnu_hash[2];
|
||||
uint32_t gnu_shift2_ = dt_gnu_hash[3];
|
||||
ElfW(Addr) *gnu_bloom_filter_ = (ElfW(Addr) *) (dt_gnu_hash + 4);
|
||||
uint32_t *gnu_bucket_ = (uint32_t *) (gnu_bloom_filter_ + gnu_maskwords_);
|
||||
uint32_t *gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - dt_gnu_hash[1];
|
||||
|
||||
--gnu_maskwords_;
|
||||
|
||||
uint32_t hash = gnu_hash((uint8_t *) symbol);
|
||||
uint32_t h2 = hash >> gnu_shift2_;
|
||||
|
||||
uint32_t bloom_mask_bits = sizeof(ElfW(Addr)) * 8;
|
||||
uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_;
|
||||
ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num];
|
||||
|
||||
if ((1 & (bloom_word >> (hash % bloom_mask_bits)) &
|
||||
(bloom_word >> (h2 % bloom_mask_bits))) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t n = gnu_bucket_[hash % gnu_nbucket_];
|
||||
|
||||
if (n == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
ElfW(Sym) *sym = dynsym + n;
|
||||
if (((gnu_chain_[n] ^ hash) >> 1) == 0
|
||||
&& is_global(sym)
|
||||
&& strcmp(dynstr + sym->st_name, symbol) == 0) {
|
||||
ElfW(Addr) *symbol_sym = (ElfW(Addr) *) (info->dlpi_addr + sym->st_value);
|
||||
#ifdef DEBUG_PLT
|
||||
LOGI("found %s(gnu+%u) in %s, %p", symbol, n, info->dlpi_name, symbol_sym);
|
||||
#endif
|
||||
return symbol_sym;
|
||||
}
|
||||
} while ((gnu_chain_[n++] & 1) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_HASH);
|
||||
if (dyn != NULL) {
|
||||
ElfW(Word) *dt_hash = (ElfW(Word) *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
size_t nbucket_ = dt_hash[0];
|
||||
uint32_t *bucket_ = dt_hash + 2;
|
||||
uint32_t *chain_ = bucket_ + nbucket_;
|
||||
|
||||
uint32_t hash = elf_hash((uint8_t *) (symbol));
|
||||
for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) {
|
||||
ElfW(Sym) *sym = dynsym + n;
|
||||
if (is_global(sym) &&
|
||||
strcmp(dynstr + sym->st_name, symbol) == 0) {
|
||||
ElfW(Addr) *symbol_sym = (ElfW(Addr) *) (info->dlpi_addr + sym->st_value);
|
||||
#ifdef DEBUG_PLT
|
||||
LOGI("found %s(elf+%u) in %s, %p", symbol, n, info->dlpi_name, symbol_sym);
|
||||
#endif
|
||||
return symbol_sym;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define Elf_Rela ElfW(Rela)
|
||||
#define ELF_R_SYM ELF64_R_SYM
|
||||
#else
|
||||
#define Elf_Rela ElfW(Rel)
|
||||
#define ELF_R_SYM ELF32_R_SYM
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_PLT
|
||||
#if defined(__x86_64__)
|
||||
#define R_JUMP_SLOT R_X86_64_JUMP_SLOT
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#elif defined(__i386__)
|
||||
#define R_JUMP_SLOT R_386_JMP_SLOT
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#elif defined(__arm__)
|
||||
#define R_JUMP_SLOT R_ARM_JUMP_SLOT
|
||||
#define ELF_R_TYPE ELF32_R_TYPE
|
||||
#elif defined(__aarch64__)
|
||||
#define R_JUMP_SLOT R_AARCH64_JUMP_SLOT
|
||||
#define ELF_R_TYPE ELF64_R_TYPE
|
||||
#else
|
||||
#error unsupported OS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static ElfW(Addr) *find_plt(struct dl_phdr_info *info, ElfW(Dyn) *base_addr, const char *symbol) {
|
||||
ElfW(Dyn) *dyn = find_dyn_by_tag(base_addr, DT_JMPREL);
|
||||
if (dyn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
Elf_Rela *dynplt = (Elf_Rela *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_SYMTAB);
|
||||
ElfW(Sym) *dynsym = (ElfW(Sym) *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_STRTAB);
|
||||
char *dynstr = (char *) (info->dlpi_addr + dyn->d_un.d_ptr);
|
||||
|
||||
dyn = find_dyn_by_tag(base_addr, DT_PLTRELSZ);
|
||||
if (dyn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
size_t count = dyn->d_un.d_val / sizeof(Elf_Rela);
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
Elf_Rela *plt = dynplt + i;
|
||||
#ifdef DEBUG_PLT
|
||||
if (ELF_R_TYPE(plt->r_info) != R_JUMP_SLOT) {
|
||||
LOGW("invalid type for plt+%zu in %s", i, info->dlpi_name);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
size_t idx = ELF_R_SYM(plt->r_info);
|
||||
idx = dynsym[idx].st_name;
|
||||
if (strcmp(dynstr + idx, symbol) == 0) {
|
||||
ElfW(Addr) *symbol_plt = (ElfW(Addr) *) (info->dlpi_addr + plt->r_offset);
|
||||
#ifdef DEBUG_PLT
|
||||
ElfW(Addr) *symbol_plt_value = (ElfW(Addr) *) *symbol_plt;
|
||||
LOGI("found %s(plt+%zu) in %s, %p -> %p", symbol, i, info->dlpi_name, symbol_plt,
|
||||
symbol_plt_value);
|
||||
#endif
|
||||
return symbol_plt;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool isso(const char *str) {
|
||||
if (str == NULL) {
|
||||
return false;
|
||||
}
|
||||
const char *dot = strrchr(str, '.');
|
||||
return dot != NULL
|
||||
&& *++dot == 's'
|
||||
&& *++dot == 'o'
|
||||
&& (*++dot == '\0' || *dot == '\r' || *dot == '\n');
|
||||
}
|
||||
|
||||
static inline bool should_check_plt(Symbol *symbol, struct dl_phdr_info *info) {
|
||||
const char *path = info->dlpi_name;
|
||||
if (symbol->check & PLT_CHECK_PLT_ALL) {
|
||||
return true;
|
||||
} else if (symbol->check & PLT_CHECK_PLT_APP) {
|
||||
return *path != '/' || isThirdParty(path);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int callback(struct dl_phdr_info *info, __unused size_t size, void *data) {
|
||||
if (!isso(info->dlpi_name)) {
|
||||
#ifdef DEBUG_PLT
|
||||
LOGW("ignore non-so: %s", info->dlpi_name);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
Symbol *symbol = (Symbol *) data;
|
||||
#if 0
|
||||
LOGI("Name: \"%s\" (%d segments)", info->dlpi_name, info->dlpi_phnum);
|
||||
#endif
|
||||
++symbol->total;
|
||||
for (ElfW(Half) phdr_idx = 0; phdr_idx < info->dlpi_phnum; ++phdr_idx) {
|
||||
ElfW(Phdr) phdr = info->dlpi_phdr[phdr_idx];
|
||||
if (phdr.p_type != PT_DYNAMIC) {
|
||||
continue;
|
||||
}
|
||||
ElfW(Dyn) *base_addr = (ElfW(Dyn) *) (info->dlpi_addr + phdr.p_vaddr);
|
||||
ElfW(Addr) *addr;
|
||||
addr = should_check_plt(symbol, info) ? find_plt(info, base_addr, symbol->symbol_name) : NULL;
|
||||
if (addr != NULL) {
|
||||
if (symbol->symbol_plt != NULL) {
|
||||
ElfW(Addr) *addr_value = (ElfW(Addr) *) *addr;
|
||||
ElfW(Addr) *symbol_plt_value = (ElfW(Addr) *) *symbol->symbol_plt;
|
||||
if (addr_value != symbol_plt_value) {
|
||||
#ifdef DEBUG_PLT
|
||||
LOGW("%s, plt %p -> %p != %p", symbol->symbol_name, addr, addr_value,
|
||||
symbol_plt_value);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
symbol->symbol_plt = addr;
|
||||
if (symbol->check & PLT_CHECK_NAME) {
|
||||
if (symbol->size == 0) {
|
||||
symbol->size = 1;
|
||||
symbol->names = calloc(1, sizeof(char *));
|
||||
} else {
|
||||
++symbol->size;
|
||||
symbol->names = realloc(symbol->names, symbol->size * sizeof(char *));
|
||||
}
|
||||
#ifdef DEBUG_PLT
|
||||
LOGI("[%d]: %s", symbol->size - 1, info->dlpi_name);
|
||||
#endif
|
||||
symbol->names[symbol->size - 1] = strdup(info->dlpi_name);
|
||||
}
|
||||
}
|
||||
addr = find_symbol(info, base_addr, symbol->symbol_name);
|
||||
if (addr != NULL) {
|
||||
symbol->symbol_sym = addr;
|
||||
if (symbol->check == PLT_CHECK_SYM_ONE) {
|
||||
return PLT_CHECK_SYM_ONE;
|
||||
}
|
||||
}
|
||||
if (symbol->symbol_plt != NULL && symbol->symbol_sym != NULL) {
|
||||
ElfW(Addr) *symbol_plt_value = (ElfW(Addr) *) *symbol->symbol_plt;
|
||||
// stop if unmatch
|
||||
if (symbol_plt_value != symbol->symbol_sym) {
|
||||
#ifdef DEBUG_PLT
|
||||
LOGW("%s, plt: %p -> %p != %p", symbol->symbol_name, symbol->symbol_plt,
|
||||
symbol_plt_value, symbol->symbol_sym);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *plt_dlsym(const char *name, size_t *total) {
|
||||
Symbol symbol;
|
||||
memset(&symbol, 0, sizeof(Symbol));
|
||||
if (total == NULL) {
|
||||
symbol.check = PLT_CHECK_SYM_ONE;
|
||||
}
|
||||
symbol.symbol_name = name;
|
||||
dl_iterate_phdr_symbol(&symbol);
|
||||
if (total != NULL) {
|
||||
*total = symbol.total;
|
||||
}
|
||||
return symbol.symbol_sym;
|
||||
}
|
||||
|
||||
bool isPltHooked(const char *name, bool all) {
|
||||
Symbol symbol;
|
||||
memset(&symbol, 0, sizeof(Symbol));
|
||||
symbol.check = all ? PLT_CHECK_PLT_ALL : PLT_CHECK_PLT_APP;
|
||||
symbol.symbol_name = name;
|
||||
return dl_iterate_phdr_symbol(&symbol) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* symbol->check PLT_CHECK_PLT | PLT_CHECK_NAME
|
||||
* @param symbol
|
||||
* @return
|
||||
*/
|
||||
int dl_iterate_phdr_symbol(Symbol *symbol) {
|
||||
int result;
|
||||
#ifdef DEBUG_PLT
|
||||
LOGI("start dl_iterate_phdr: %s", symbol->symbol_name);
|
||||
#endif
|
||||
#if __ANDROID_API__ >= 21 || !defined(__arm__)
|
||||
result = dl_iterate_phdr(callback, symbol);
|
||||
#else
|
||||
int (*dl_iterate_phdr)(int (*)(struct dl_phdr_info *, size_t, void *), void *);
|
||||
dl_iterate_phdr = dlsym(RTLD_NEXT, "dl_iterate_phdr");
|
||||
if (dl_iterate_phdr != NULL) {
|
||||
result = dl_iterate_phdr(callback, symbol);
|
||||
} else {
|
||||
result = 0;
|
||||
void *handle = dlopen("libdl.so", RTLD_NOW);
|
||||
dl_iterate_phdr = dlsym(handle, "dl_iterate_phdr");
|
||||
if (dl_iterate_phdr != NULL) {
|
||||
result = dl_iterate_phdr(callback, symbol);
|
||||
} else {
|
||||
LOGW("cannot dlsym dl_iterate_phdr");
|
||||
}
|
||||
dlclose(handle);
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUG_PLT
|
||||
LOGI("complete dl_iterate_phdr: %s", symbol->symbol_name);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
//
|
||||
// Created by Thom on 2019/2/16.
|
||||
//
|
||||
|
||||
#ifndef BREVENT_PLT_H
|
||||
#define BREVENT_PLT_H
|
||||
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
#include <android/log.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PLT_CHECK_PLT_APP ((unsigned short) 0x1u)
|
||||
#define PLT_CHECK_PLT_ALL ((unsigned short) 0x2u)
|
||||
#define PLT_CHECK_NAME ((unsigned short) 0x4u)
|
||||
#define PLT_CHECK_SYM_ONE ((unsigned short) 0x8u)
|
||||
|
||||
typedef struct Symbol {
|
||||
unsigned short check;
|
||||
unsigned short size;
|
||||
size_t total;
|
||||
ElfW(Addr) *symbol_plt;
|
||||
ElfW(Addr) *symbol_sym;
|
||||
const char *symbol_name;
|
||||
char **names;
|
||||
} Symbol;
|
||||
|
||||
int dl_iterate_phdr_symbol(Symbol *symbol);
|
||||
|
||||
void *plt_dlsym(const char *name, size_t *total);
|
||||
|
||||
bool isPltHooked(const char *name, bool all);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //BREVENT_PLT_H
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <jni.h>
|
||||
|
||||
#include "genuine.h"
|
||||
#include "java_wrapper.h"
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JNIEnv* env;
|
||||
|
||||
if ((*vm)->GetEnv(vm, (void**) (&env), JNI_VERSION_1_6) != JNI_OK) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user