混淆技术
动态加载方案,将需保护的代码单独编译成一个二进制文件,将其进行加密后保存在一个外部的二进制文件中。在外部程序运行的过程中,再将保护的二进制文件进行解密,并使用ClassLoader类加载器动态加载和运行被保护的代码。
将核心代码使用NDK套件编写,使用C++语言编写成为so文件,Java代码只是充当了一个二进制文件装载器的角色。
动态分析中,要将调试器附加进程或者通过注入将指令代码和数据注入目标进程中,要做到这一点,最基本的方法就是调用ptrace()函数对进程进行附加,而对抗的手段主要分为两种:运行时检测和事先阻止(双进程保护)。
APP加固(加壳)
主动调用方案FUPK3/FART
LLVM是一套开源的编译器,OLLVM是一个专门为混淆而生的LLVM
xx暂时略过,用到直接百度Smali语法
安卓程序的代码:
public class MainActivity extends AppCompatActivity {
//private static String TAG = "r0ysue666";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//locate the send request button
Button btn = findViewById(R.id.mybtn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String requestUrl = "https://www.baidu.com/";
example myexample = new example();
try{
myexample.run(requestUrl);
}catch (IOException e){
e.printStackTrace();
}
}
});
}
}
public class example {
//TAG is the label for log print
private static final String TAG = "r0ysue666";
//Create a new okhttpClient
OkHttpClient client = new OkHttpClient();
void run(String url) throws IOException{
Request request = new Request.Builder().url(url).header("toke", "r0ysue").build();
// initiate asynchronous request
client.newCall(request).enqueue(
new Callback() {
@Override
public void onFailure(Call call, IOException e) {
call.cancel();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.body().string());
}
}
);
}
}
下面使用objection进行hookobjection -g 26328 explore
使用android hooking list classes
,列出类列表,但我这里不知道为啥不行。
接下来hookokhttpClient.newCall()
函数,使用命令:android hooking watch class_method okhttp3.OkHttpClient.newCall --dump -args --dump-backtrace--dump-return
下面使用JS脚本注入
Java.perform(function(){
var OkHttpClient = Java.use("okhttp3.OkHttpClient")
OkHttpClient.newCall.implementation = function(request){
var result = this.newCall(request)
console.log(request.toString())
return result
}
});
到了这里我们其实发现,hook到的函数可能多了,因为有可能部分函数存在“Call”之后并没有发出实际请求。newCall函数的实现中调用了我们只有hook了execute()和enqueue(new Callback())才能保证每个从okhttp出去的请求都能被hook到。
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
拦截器是okhttp中的一个重要概念,每个网络请求都必须经过拦截器Interceptor,因此Interceptor是一个绝佳的hook点,可以同时打印输出请求和响应。