应用场景
对抗各种基于 libc.so 的 Hook.
方式一:静态链接 libc.a
把 libc 以静态库的方式内联到可执行文件或 so 库。从而不调用系统 libc.so 库的函数
代码
main.cpp
1 2 3 4 5 6
| #include <unistd.h>
int main(int argc, char *argv[]) { sleep(20); }
|
Android.bp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| cc_binary { name: "testLibc", srcs: ["*.cpp"],
cppflags: [ "-Wno-error", "-Wno-sign-conversion", "-Wno-unused-parameter", "-Wno-sign-conversion", ],
static_executable: true, static_libs: [ "libc", ],
}
|
编译
1 2 3 4
| source build/envsetup.sh lunch 2 cd external/testLibc mm
|
效果
将编译后的文件用 ida 打开,观察其导入函数.
发现是空的,说明 sleep 函数已经被内联.
丢到真机执行,
20 秒后退出,也没啥问题.
测试用例:
https://github.com/PShocker/PShocker.github.io/releases/download/testLibc/testLibc
方式二:汇编方式内联 SVC 指令
代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| #define SYSCALL(number_, nb_args, args...) \ ({ \ register word_t number asm("r7") = number_; \ register word_t result asm("r0"); \ PREPARE_ARGS_##nb_args(args) \ asm volatile ( \ "svc #0x00000000 \n\t" \ : "=r" (result) \ : "r" (number), \ OUTPUT_CONTRAINTS_##nb_args \ : "memory"); \ result; \ })
|
使用例:
1 2 3 4 5 6 7 8 9 10 11 12
| int main(){ fd = SYSCALL(__NR_openat, 4, AT_FDCWD, (word_t) & "/data/local/tmp/test.txt", O_RDWR, 0);
if (fd < 0){ printf("openat error\n"); return -1; } ...... }
|
参考:
https://github.com/SsageParuders/Android_SVC_Edu
编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| set abi=arm64-v8a SET ANDROID_SDK_HOME=C:\Users\Shocker\AppData\Local\Android\Sdk
if not exist %abi% md %abi% cd %abi%
%ANDROID_SDK_HOME%\cmake\3.23.1\bin\cmake ^ -DANDROID_ABI=%abi% ^ -DANDROID_NDK=%ANDROID_SDK_HOME%\ndk\23.1.7779620 ^ -DCMAKE_BUILD_TYPE=Release ^ -DCMAKE_TOOLCHAIN_FILE=%ANDROID_SDK_HOME%\ndk\23.1.7779620\build\cmake\android.toolchain.cmake ^ -DANDROID_NATIVE_API_LEVEL=21 ^ -DANDROID_TOOLCHAIN=clang -DCMAKE_GENERATOR="Ninja" ^ -DCMAKE_MAKE_PROGRAM=%ANDROID_SDK_HOME%\cmake\3.23.1\bin\ninja ^ ..
%ANDROID_SDK_HOME%\cmake\3.18.1\bin\ninja cd ..
|