Skip to content

Commit 52aac94

Browse files
first commit
1 parent 9a33805 commit 52aac94

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1068
-0
lines changed

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/caches
5+
/.idea/libraries
6+
/.idea/modules.xml
7+
/.idea/workspace.xml
8+
/.idea/navEditor.xml
9+
/.idea/assetWizardSettings.xml
10+
.DS_Store
11+
/build
12+
/captures
13+
.externalNativeBuild
14+
.cxx
15+
local.properties

app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle.kts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import com.android.build.api.dsl.Packaging
2+
3+
plugins {
4+
alias(libs.plugins.android.application)
5+
}
6+
7+
android {
8+
namespace = "com.test.kerneltracedemo"
9+
compileSdk = 35
10+
11+
defaultConfig {
12+
applicationId = "com.test.kerneltracedemo"
13+
minSdk = 29
14+
targetSdk = 35
15+
versionCode = 1
16+
versionName = "1.0"
17+
18+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
19+
externalNativeBuild {
20+
cmake {
21+
cppFlags += ""
22+
targets += "kerneltracedemo"
23+
}
24+
}
25+
26+
ndk {
27+
abiFilters.add("arm64-v8a") // 只编译 arm64 架构
28+
}
29+
}
30+
31+
32+
33+
buildTypes {
34+
release {
35+
isMinifyEnabled = false
36+
proguardFiles(
37+
getDefaultProguardFile("proguard-android-optimize.txt"),
38+
"proguard-rules.pro"
39+
)
40+
}
41+
}
42+
43+
compileOptions {
44+
sourceCompatibility = JavaVersion.VERSION_11
45+
targetCompatibility = JavaVersion.VERSION_11
46+
}
47+
externalNativeBuild {
48+
cmake {
49+
path = file("src/main/cpp/CMakeLists.txt")
50+
version = "3.22.1"
51+
}
52+
}
53+
}
54+
55+
dependencies {
56+
57+
implementation(libs.appcompat)
58+
implementation(libs.material)
59+
implementation(libs.activity)
60+
implementation(libs.constraintlayout)
61+
testImplementation(libs.junit)
62+
androidTestImplementation(libs.ext.junit)
63+
androidTestImplementation(libs.espresso.core)
64+
}

app/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.test.kerneltracedemo;
2+
3+
import android.content.Context;
4+
5+
import androidx.test.platform.app.InstrumentationRegistry;
6+
import androidx.test.ext.junit.runners.AndroidJUnit4;
7+
8+
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
11+
import static org.junit.Assert.*;
12+
13+
/**
14+
* Instrumented test, which will execute on an Android device.
15+
*
16+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
17+
*/
18+
@RunWith(AndroidJUnit4.class)
19+
public class ExampleInstrumentedTest {
20+
@Test
21+
public void useAppContext() {
22+
// Context of the app under test.
23+
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24+
assertEquals("com.test.kerneltracedemo", appContext.getPackageName());
25+
}
26+
}

app/src/main/AndroidManifest.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
4+
5+
<application
6+
android:extractNativeLibs="true"
7+
android:allowBackup="true"
8+
android:dataExtractionRules="@xml/data_extraction_rules"
9+
android:fullBackupContent="@xml/backup_rules"
10+
android:icon="@mipmap/ic_launcher"
11+
android:label="@string/app_name"
12+
android:roundIcon="@mipmap/ic_launcher_round"
13+
android:supportsRtl="true"
14+
android:theme="@style/Theme.KernelTraceDemo"
15+
tools:targetApi="31">
16+
<activity
17+
android:name=".MainActivity"
18+
android:exported="true">
19+
<intent-filter>
20+
<action android:name="android.intent.action.MAIN" />
21+
22+
<category android:name="android.intent.category.LAUNCHER" />
23+
</intent-filter>
24+
</activity>
25+
</application>
26+
27+
</manifest>

app/src/main/cpp/CMakeLists.txt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
# For more information about using CMake with Android Studio, read the
3+
# documentation: https://d.android.com/studio/projects/add-native-code.html.
4+
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.
5+
6+
# Sets the minimum CMake version required for this project.
7+
cmake_minimum_required(VERSION 3.22.1)
8+
9+
# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
10+
# Since this is the top level CMakeLists.txt, the project name is also accessible
11+
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
12+
# build script scope).
13+
project("kerneltracedemo")
14+
15+
# Creates and names a library, sets it as either STATIC
16+
# or SHARED, and provides the relative paths to its source code.
17+
# You can define multiple libraries, and CMake builds them for you.
18+
# Gradle automatically packages shared libraries with your APK.
19+
#
20+
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
21+
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
22+
# is preferred for the same purpose.
23+
#
24+
# In order to load a library into your app from Java/Kotlin, you must call
25+
# System.loadLibrary() and pass the name of the library defined here;
26+
# for GameActivity/NativeActivity derived applications, the same library name must be
27+
# used in the AndroidManifest.xml file.
28+
add_library(${CMAKE_PROJECT_NAME} SHARED
29+
# List C/C++ source files with relative paths to this CMakeLists.txt.
30+
kerneltracedemo.cpp)
31+
32+
# Specifies libraries CMake should link to your target library. You
33+
# can link libraries from various origins, such as libraries defined in this
34+
# build script, prebuilt third-party libraries, or Android system libraries.
35+
target_link_libraries(${CMAKE_PROJECT_NAME}
36+
# List libraries link to the target library
37+
android
38+
log)
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#include <jni.h>
2+
#include <thread>
3+
#include <linux/unistd.h>
4+
#include <string>
5+
#include "log.h"
6+
#include "uprobe_trace_user.h"
7+
8+
#define MAX_VMA_NUM 10
9+
10+
char module_path[PATH_MAX];
11+
static uint64_t module_base = 0;
12+
unsigned long start_addrs[MAX_VMA_NUM];
13+
unsigned long end_addrs[MAX_VMA_NUM];
14+
unsigned long vma_base[MAX_VMA_NUM];
15+
int vma_num=0;
16+
17+
18+
19+
//用于解析进程自身maps文件获取module_base,module_path以及相关可执行段地址信息的函数
20+
//这个示例里so是没有加密代码段,并且so在maps文件中出现的第一段内存区域的起始地址就是其加载的基址
21+
//在很多其他情况下并非如此,这个要看情况改变获取的方法
22+
bool init_vma(){
23+
FILE *f;
24+
char buf[256];
25+
f = fopen("/proc/self/maps","r");
26+
bool flag = false;
27+
if(!f){
28+
return false;
29+
}
30+
while (fgets(buf,256,f)!=NULL){
31+
unsigned long tstart,tend,tbase;
32+
char permissions[5];
33+
int major,minor;
34+
unsigned long inode;
35+
char path[256];
36+
37+
int fields = sscanf(buf,"%lx-%lx %4s %lx %x:%x %lu %s",&tstart,&tend,permissions,&tbase,&major,&minor,&inode,path);
38+
if(fields==8){
39+
if(strstr(path,"libkerneltracedemo.so")){
40+
// LOGD("start:%lx,end:%lx,permissions:%s,tbase:%lx\n",tstart,tend,permissions,tbase);
41+
if(!flag){
42+
strcpy(module_path,path);
43+
module_base = tstart;
44+
flag = true;
45+
}
46+
if(permissions[2]=='x'){
47+
start_addrs[vma_num] = tstart;
48+
end_addrs[vma_num] = tend;
49+
vma_base[vma_num] = tbase;
50+
vma_num++;
51+
}
52+
}
53+
}
54+
55+
}
56+
fclose(f);
57+
if(vma_num==0){
58+
return false;
59+
}
60+
return true;
61+
}
62+
63+
64+
__attribute__((noinline)) void test_kernel_trace(){
65+
LOGD("test_kernel_trace fun calling");
66+
}
67+
68+
void test(){
69+
while (true){
70+
test_kernel_trace();
71+
sleep(1);
72+
}
73+
}
74+
75+
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
76+
if(!init_vma()){
77+
LOGE("can not parse maps files");
78+
return JNI_VERSION_1_6;
79+
}
80+
LOGD("success parse maps files");
81+
82+
//为KernelTrace提供必要的初始信息
83+
set_target_uid(getuid());
84+
set_module_base(module_base);
85+
set_target_file(module_path);
86+
87+
LOGD("module_base:%llx,module_path:%s",module_base,module_path);
88+
89+
//hook前进行的一些准备
90+
unsigned long test_fun_addr = (unsigned long)test_kernel_trace;
91+
unsigned long test_fun_offset = test_fun_addr - module_base;
92+
unsigned long uprobe_offset = 0;
93+
for (int i=0;i<vma_num;i++){
94+
if(test_fun_addr>start_addrs[i] && test_fun_addr<end_addrs[i]){
95+
uprobe_offset = test_fun_addr-start_addrs[i]+vma_base[i];//获取uprobe offset要进行的运算
96+
}
97+
}
98+
99+
char oins[4];
100+
memcpy(oins,(void *)test_kernel_trace,4);//获取被hook函数的第一条汇编指令
101+
LOGD("test_fun_offset:%lx,uprobe_offset:%lx",test_fun_offset,uprobe_offset);
102+
//如果so的相应汇编指令不是在so加载后才动态解密可直接设置fix_insn参数为NULL
103+
//set_fun_info(uprobe_offset,test_fun_offset,"test_kernel_trace",NULL);
104+
105+
//不过最好还是直接读取汇编指令并传入
106+
set_fun_info(uprobe_offset,test_fun_offset,"test_kernel_trace",oins);//发送hook请求
107+
108+
//启动测试线程开始测试
109+
std::thread test_thread(test);
110+
test_thread.detach();
111+
return JNI_VERSION_1_6;
112+
}

app/src/main/cpp/log.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include <android/log.h>
2+
3+
#define LOG_TAG "Test-Log"
4+
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
5+
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
6+
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
7+
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <sys/syscall.h>
2+
#include <unistd.h>
3+
4+
5+
#define TRACE_FLAG 511
6+
#define MAX_HOOK_NUM 1000
7+
#define SET_TRACE_SUCCESS 1000
8+
#define SET_TRACE_ERROR 1001
9+
10+
enum trace_info {
11+
SET_TARGET_FILE,
12+
SET_MODULE_BASE,
13+
SET_FUN_INFO,
14+
FIX_ORI_INS,
15+
SET_TARGET_UPROBE,
16+
SET_TARGET_UID,
17+
CLEAR_UPROBE,
18+
};
19+
20+
// unsigned long start, size_t len, unsigned char *vec
21+
22+
int set_module_base(unsigned long module_base){
23+
int ret = syscall(__NR_mincore,module_base,TRACE_FLAG+SET_MODULE_BASE,"");
24+
return ret;
25+
}
26+
27+
int set_target_uid(uid_t uid){
28+
int ret = syscall(__NR_mincore,uid,TRACE_FLAG+SET_TARGET_UID,"");
29+
return ret;
30+
}
31+
32+
int set_target_file(char* file_name){
33+
int ret = syscall(__NR_mincore,0,TRACE_FLAG+SET_TARGET_FILE,file_name);
34+
return ret;
35+
}
36+
37+
int set_fun_info(unsigned long uprobe_offset,unsigned long fun_offset,char *fun_name,char *fix_insn){
38+
int insert_key_ret = syscall(__NR_mincore,fun_offset,TRACE_FLAG+SET_FUN_INFO,fun_name);
39+
if(insert_key_ret==SET_TRACE_SUCCESS){
40+
if(fix_insn){
41+
int fix_insn_ret = syscall(__NR_mincore,uprobe_offset,TRACE_FLAG+FIX_ORI_INS,fix_insn);
42+
if(fix_insn_ret == SET_TRACE_ERROR){
43+
return SET_TRACE_ERROR;
44+
}
45+
}
46+
int ret = syscall(__NR_mincore,uprobe_offset,TRACE_FLAG+SET_TARGET_UPROBE,"");
47+
return ret;
48+
}
49+
return SET_TRACE_ERROR;
50+
}
51+
52+
int clear_all_uprobes(){
53+
int ret = syscall(__NR_mincore,0,TRACE_FLAG+CLEAR_UPROBE,"");
54+
return ret;
55+
}

0 commit comments

Comments
 (0)