原理:
我们进行动态调试的时候,其中有一个步骤是进行jdb连接操作:jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8600,当接连成功之后,isDebuggerConnected() 这个方法就会为ture。
然后我们把三项勾选取消,再点击运行就成功了。


代码 :
这个函数实在Java层的,所以不需要用到.so文件,直接在Mainactivity.java中就可以实现了。
package com.example.myapplicationisdubug;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Debug;
import android.util.Log;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Thread debuggerCheckThread; //创建线程也是为了循环检测
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startDebuggerCheckThread();
}
private void startDebuggerCheckThread() {
debuggerCheckThread = new Thread(() -> {
while (!Thread.interrupted()) {
// 检查是否有调试器连接
if (Debug.isDebuggerConnected()) {
// 如果有调试器连接,终止进程
Log.e("DEBUG", "debugging"); //为了方便得到检测效果
android.os.Process.killProcess(android.os.Process.myPid()); //kill进程
}else{
Log.e("DEBUG", "no debug");
}
// 每隔1秒检查一次 try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 线程被中断,退出循环
break;
}
}
});
debuggerCheckThread.start();
}
protected void onDestroy() {
super.onDestroy();
// 确保线程在Activity销毁时被中断
if (debuggerCheckThread != null) {
debuggerCheckThread.interrupt();
}
}
}
logcat
adb logcat查看效果,成功!

IDA这边也成功了

反反调试(待补充):
可以直接修改smali代码或者hook,以后补充
ptrace检测
这是进行的最顺利的一个了。
一个进程同时刻只能被一个进程跟踪,我们可以使用ptrace让进程自己跟踪自己,这样android_server就不能够调试。
代码原型:
#include <sys/ptrace.h>
long ptrace(enum _ptrace_request request,pid_t pid,void* addr,void* data)
效果如下:
当IDA进行附加时,会附加不上,提示这个就表示成功了

同时可以看看这个进程的Tracerpid值,就是zygote的值
使用命令:
ps -ef | grep ptrace
得到该进程的pid值为1662
然后cat /proc/1662/status得到TracerPid的值为128

再 使用命令ps -ef | grep 128发现就是zygote

反调试代码如下:
MainActivity.java:
package com.example.myapplicationptrace;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.myapplicationptrace.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
// Used to load the 'my_ptrace' library on application startup.
static {
System.loadLibrary("my_ptrace");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
tv.setText(stringFromJNI());
}
/**
* A native method that is implemented by the 'myapplicationptrace' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
native-lib.cpp:
#include <jni.h>
#include <string>
#include <linux/ptrace.h>
#include <sys/ptrace.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void ptrace_me(){
int ch = ptrace(PTRACE_TRACEME,0,NULL,NULL); //返回-1表示已经被调试
if (ch == -1){
int pid = getpid(); //ptrace附加自身,会导致此进程TracerPid变为父进程(zygote)的TracerPid
kill(pid,SIGKILL);
}
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
ptrace_me(); //通过JNI_OnLoad方法调用ptrace_me()
return JNI_VERSION_1_6; // 返回 JNI 版本号
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplicationptrace_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
CMakeLists.txt:
反反调试:
最简单的也是修改JNI_Onload()的相关方法
就是call这一行

我之前看其他师傅们写的文章,统一是说把相关代码nop掉,但是如果我这里nop掉之后,我返回看IDA的流程图,JNI_Onload()就变得不连续了,所以我其实有怀疑可以是这个原因导致的重新打包签名的apk闪退。

所以我今天没有nop掉代码,而是把call这一行的代码,改成和下面一行mov eax, 10006h一样,这样也不会影响函数逻辑。

然后再重新打包签名,发现成功了,程序也没有闪退!

注意,重新打包签名之前,需要把META-INF这个文件删了,这个是之前的签名文件
1463

被折叠的 条评论
为什么被折叠?



