ChatGPT太强了,这里展示一个如何让它帮你生成JNI校验Android Signature的代码,几分钟搞定
Input
As Android developer, I want to protect my App from hacked during the App launch, so I need to do App signature check before the user start to use the App. The prefered way is hardcode the App’s signature in the JNI code, and run the JNI code when the App start, can you show the solution and code?
后面我还试了修正的版本
As Android developer, I want to do the check App signature check before the user start to use the App, so I know it’s not hacked. The prefered way is hardcode the App’s signature in the JNI code, and run the JNI code when the App start, The package name is me.pjq.android The JNI method name is `check_signature`, the return type is true or false. The App’s original signature should be hardcoded in the JNI code but not the plaintext and readable, the original signature should be masked. can you show the solution and code and full structure of the App?
Output
To perform an App signature check in JNI code, you can follow these steps:
- Get the App’s signature:
First, you need to get the App’s signature. You can use the PackageInfo class to retrieve the App’s signature.
Copy codePackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
- Convert the signature to a string:
Next, you need to convert the signature to a string. You can use the Signature.toCharsString() method to convert the signature to a string.
Copy codeString signatureString = signatures[0].toCharsString();
- Pass the signature string to the JNI code:
Then, you need to pass the signature string to the JNI code. You can use the JNI SetStringField() method to pass the signature string to the JNI code.
Copy codejstring signatureString = env->NewStringUTF(signatureString);
env->SetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "signature", "Ljava/lang/String;"), signatureString);
- Verify the signature in the JNI code:
In the JNI code, you can verify the signature by comparing the signature string with the hardcoded signature. If the signatures match, the App is considered to be authentic and can be launched. Otherwise, the App is considered to be hacked and should not be launched.
Copy codejstring signature = (jstring) env->GetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "signature", "Ljava/lang/String;"));
const char* signatureString = env->GetStringUTFChars(signature, 0);
if (strcmp(signatureString, "hardcoded_signature") == 0) {
// App is authentic, launch the App
} else {
// App is hacked, do not launch the App
}
env->ReleaseStringUTFChars(signature, signatureString);
Note: The hardcoded signature should be kept secret and not included in the App’s code to prevent it from being hacked.
Continue
After verifying the App’s signature in the JNI code, you can launch the App by calling the appropriate Android activity. For example, you can use the JNI StartActivity() method to launch the main activity of the App.
Copy codejclass activityClass = env->FindClass("android/app/Activity");
jmethodID startActivityMethod = env->GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V");
jclass intentClass = env->FindClass("android/content/Intent");
jmethodID intentConstructor = env->GetMethodID(intentClass, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)V");
jclass mainActivityClass = env->FindClass("com/example/app/MainActivity");
jobject intent = env->NewObject(intentClass, intentConstructor, obj, mainActivityClass);
env->CallVoidMethod(obj, startActivityMethod, intent);
Note: The main activity class name, “com/example/app/MainActivity” in the above code, should be replaced with the actual main activity class name of your App.
The complete JNI code for performing an App signature check and launching the App can be as follows:
Copy code#include <jni.h>
#include <string.h>
extern "C"
JNIEXPORT void JNICALL
Java_com_example_app_App_launch(JNIEnv *env, jobject obj) {
// Verify the App's signature
jstring signature = (jstring) env->GetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "signature", "Ljava/lang/String;"));
const char* signatureString = env->GetStringUTFChars(signature, 0);
if (strcmp(signatureString, "hardcoded_signature") == 0) {
// App is authentic, launch the App
jclass activityClass = env->FindClass("android/app/Activity");
jmethodID startActivityMethod = env->GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V");
jclass intentClass = env->FindClass("android/content/Intent");
jmethodID intentConstructor = env->GetMethodID(intentClass, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)V");
jclass mainActivityClass = env->FindClass("com/example/app/MainActivity");
jobject intent = env->NewObject(intentClass, intentConstructor, obj, mainActivityClass);
env->CallVoidMethod(obj, startActivityMethod, intent);
} else {
// App is hacked, do not launch the App
}
env->ReleaseStringUTFChars(signature, signatureString);
}
In the Java code, you can call the JNI launch() method to perform the App signature check and launch the App.
Copy codepublic class App {
public static native void launch();
static {
System.loadLibrary("app");
}
}
You can call the launch() method in the onCreate() method of the App’s main activity to perform the App signature check
Continue
and launch the App when the App is launched.
Copy codepublic class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Perform App signature check and launch the App
App.launch();
}
}
Note: The above code assumes that the JNI library “app” is already built and placed in the App’s libs directory.
This is the general solution for performing an App signature check in JNI code and launching the App. It is important to note that this solution is not foolproof and can be hacked if the attacker is determined and skilled enough. Therefore, it is recommended to use other security measures such as using a secure server to store the App’s signature and performing the signature check on the server.
Show me the make file
To build the JNI library, you need to create a makefile with the following content:
Copy codeLOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := app
LOCAL_SRC_FILES := app.cpp
include $(BUILD_SHARED_LIBRARY)
You can use the make command to build the JNI library.
Copy code$ make app
The JNI library will be built and placed in the libs directory. You can then include the JNI library in your Android project and use it as explained in the previous solution.
Show me the full structure of the App
Here is the general structure of the App that performs an App signature check in JNI code and launches the App.
Copy code- app/
- src/
- main/
- java/
- com/
- example/
- app/
- App.java
- MainActivity.java
- jni/
- app.cpp
- libs/
- armeabi/
- libapp.so
- Makefile
- Android.mk
The App.java file contains the JNI launch() method that performs the App signature check and launches the App.
Copy codepublic class App {
public static native void launch();
static {
System.loadLibrary("app");
}
}
The MainActivity.java file contains the onCreate() method that calls the JNI launch() method to perform the App signature check and launch the App.
Copy codepublic class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Perform App signature check and launch the App
App.launch();
}
}
The app.cpp file contains the JNI code that verifies the App’s signature and launches the App.
Copy code#include <jni.h>
#include <string.h>
extern "C"
JNIEXPORT void JNICALL
Java_com_example_app_App_launch(JNIEnv *env, jobject obj) {
// Verify the App's signature
jstring signature = (jstring) env->GetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "signature", "Ljava/lang/String;"));
const char* signatureString = env->GetStringUTFChars(signature, 0);
if (strcmp(signatureString, "hardcoded_signature") == 0) {
// App is authentic, launch the App
jclass activityClass = env->FindClass("android/app/Activity");
jmethodID startActivityMethod = env->GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V");
jclass intentClass = env->FindClass("android/content/Intent");
jmethodID intentConstructor = env->GetMethodID(intentClass, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)V");
jclass mainActivityClass = env->FindClass("com/example/app/MainActivity");
jobject intent = env->NewObject(intentClass, intentConstructor, obj, mainActivityClass);
env->CallVoidMethod(obj, startActivityMethod, intent);
} else {
// App is hacked, do not launch the App
}
env->ReleaseStringUTFChars(signature, signatureString);
}
The Makefile contains the instructions to build the JNI library.
Copy codeLOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := app
LOCAL
The package name is me.pjq.android
Here is the updated structure of the App that performs an App signature check in JNI code and launches the App.
Copy code- app/
- src/
- main/
- java/
- me/
- pjq/
- android/
- App.java
- MainActivity.java
- jni/
- app.cpp
- libs/
- armeabi/
- libapp.so
- Makefile
- Android.mk
The App.java file contains the JNI launch() method that performs the App signature check and launches the App.
Copy codepackage me.pjq.android;
public class App {
public static native void launch();
static {
System.loadLibrary("app");
}
}
The MainActivity.java file contains the onCreate() method that calls the JNI launch() method to perform the App signature check and launch the App.
Copy codepackage me.pjq.android;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Perform App signature check and launch the App
App.launch();
}
}
The app.cpp file contains the JNI code that verifies the App’s signature and launches the App.
Copy code#include <jni.h>
#include <string.h>
extern "C"
JNIEXPORT void JNICALL
Java_me_pjq_android_App_launch(JNIEnv *env, jobject obj) {
// Verify the App's signature
jstring signature = (jstring) env->GetObjectField(obj, env->GetFieldID(env->GetObjectClass(obj), "signature", "Ljava/lang/String;"));
const char* signatureString = env->GetStringUTFChars(signature, 0);
if (strcmp(signatureString, "hardcoded_signature") == 0) {
// App is authentic, launch the App
jclass activityClass = env->FindClass("android/app/Activity");
jmethodID startActivityMethod = env->GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V");
jclass intentClass = env->FindClass("android/content/Intent");
jmethodID intentConstructor = env->GetMethodID(intentClass, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)V");
jclass mainActivityClass = env->FindClass("me/pjq/android/MainActivity");
jobject intent = env->NewObject(intentClass, intentConstructor, obj, mainActivityClass);
env->CallVoidMethod(obj, startActivityMethod, intent);
} else {
// App is hacked, do not launch the App
}
env->ReleaseStringUTFChars(signature, signatureString);
}
The Makefile contains the instructions to build the JNI library.
Copy codeLOCAL_PATH := $(
continue
call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := app LOCAL_SRC_FILES := app.cpp
include $(BUILD_SHARED_LIBRARY)
Copy code
You can use the make command to build the JNI library.
$ make app
Copy code
The JNI library will be built and placed in the libs directory. You can then include the JNI library in your Android project and use it as explained in the previous solution.
Note: The package name, "me.pjq.android" in the above code, should be replaced with the actual package name of your App.