汽车之家apisign unidbg实现
Java分析
抓包
image-20220109114223655 image-20220109114319108找到一个疑似的,进去看看
image-20220109114426827可惜的是,无法查看源码,不过addHeader
极有可能就是加密的地方,hook看看。
function printReq(req, tag) {
console.log("=========== ", tag, " ============");
console.log("url:", req.url.value);
var vmap = req.headers.value;
var it = vmap.keySet().iterator();
while (it.hasNext()) {
var key = it.next().toString();
console.log(key + ": " + vmap.get(key).toString());
}
}
function hook_util(){
var util = Java.use("com.autohome.mainlib.common.util.ApisignUtils");
util.addHeader.implementation = function(str, req) {
console.log(str);
printReq(req, "in");
util.addHeader(str, req);
printReq(req, "out");
}
}
function searchClassLoader(className) {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass(className)) {
Java.classFactory.loader = loader;
console.log("find", loader);
}
} catch (error) {
}
},
onComplete: function () {
console.log("finish search");
}
})
}
function main() {
Java.perform(function() {
searchClassLoader("com.autohome.mainlib.common.util.ApisignUtils");
hook_util();
})
}
image-20220109115555275
可以看到,apisign就是在这里被加上去的。
之后该怎么办,我的选择是hook一下NewStringUTF
,看看sign是不是在so
里面生成的。
function hook_libart() {
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrNewStringUTF = null;
var so_name = "lib";
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0 &&
symbol.name.indexOf("_ZN3art3JNI") >= 0
) {
if (symbol.name.indexOf("NewStringUTF") >= 0) {
addrNewStringUTF = symbol.address;
console.log("NewStringUTF is at ", symbol.address, symbol.name);
}
}
}
if (addrNewStringUTF != null) {
Interceptor.attach(addrNewStringUTF, {
onEnter: function (args) {
if (args[1] != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var string = Memory.readCString(args[1]);
if (string && string.length == 32) {
console.log("====================");
console.log("[NewStringUTF] bytes:" + string, DebugSymbol.fromAddress(this.returnAddress));
console.log(Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join("\n"));
var stack = Java.use('java.lang.Thread').$new().currentThread().getStackTrace();
console.log(stack.join("\n"));
}
}
}
},
onLeave: function (retval) { }
});
}
}
image-20220109144853574
可以清楚看到Java层最后调用的地方,也可以看到对应的so是libblackBox.so
。
看看com.autohome.mainlib.common.util.BlackBox.getInterfaceSign
hook一下
function hook_box() {
var box = Java.use("com.autohome.mainlib.common.util.BlackBox");
box.getInterfaceSign.overload('java.util.List').implementation = function(list) {
console.log("box-arg:", list);
console.log("list.size:", list.size());
for (var i=0; i<list.size(); i++) {
console.log("\t", i, "=> ", list.get(i));
}
var ret = this.getInterfaceSign(list);
console.log("ret:", ret);
return ret;
}
}
image-20220109152421930
unidbg实现
基础代码
package com.autohome;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class AutoHome extends AbstractJni{
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
public static String pkgName = "com.cubic.autohome";
public static String apkPath = "unidbg-android/src/test/java/com/autohome/autohome1197.apk";
public static String soPath = "unidbg-android/src/test/java/com/autohome/libblackBox.so";
public AutoHome() {
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File(apkPath));
vm.setJni(this);
vm.setVerbose(true);
DalvikModule dm = vm.loadLibrary(new File(soPath), false);
module = dm.getModule();
dm.callJNI_OnLoad(emulator);
}
public void call_sign() {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
list.add(0);
List<NameValuePair> pairs = new ArrayList<>(10);
pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
// 1C4E5C182F7FFF5C350E1BB1B4C2B50C
module.callFunction(emulator, 0x2d91d, list.toArray());
}
public static void main(String[] args) {
AutoHome test = new AutoHome();
test.call_sign();
}
}
又到了喜闻乐见的报错与补环境环节。
image-20220109154357531直接出结果,可惜是个空的。。
ida跳转到0x2d91d
看看。
似乎没有正确识别。按D
解析为数据
选取0x2d91c
到0x2d937
,按C
转换为代码。
选取0x2d91c
到0x2d937
,按P
转换为函数。
F5
查看伪代码
看看sub_2D8C0
可以看到a1, a2, a3
都有检查,我们的a2
只是传了个0进去,所以要改改,传入真的jobject
。
public void call_sign() {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
// list.add(0);
list.add(vm.addLocalObject(vm.resolveClass("com/autohome/mainlib/common/util/BlackBox").newObject(null)));
List<NameValuePair> pairs = new ArrayList<>(10);
pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
// 1C4E5C182F7FFF5C350E1BB1B4C2B50C
module.callFunction(emulator, 0x2d91d, list.toArray());
}
也可以通过另外一种方式来调用函数
public void call_sign2() {
DvmClass clz = vm.resolveClass("com/autohome/mainlib/common/util/BlackBox");
String method = "getInterfaceSign(Ljava/util/List;)Ljava/lang/String;";
List<NameValuePair> pairs = new ArrayList<>(10);
pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
// 1C4E5C182F7FFF5C350E1BB1B4C2B50C
clz.callStaticJniMethodObject(emulator, method, vm.resolveClass("java/util/List").newObject(pairs));
}
再次运行
image-20220109155819650好像需要读文件,然后报错了,我们还是先补函数。
@Override
public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "com/autohome/mainlib/common/util/BlackBox->reportNativeErrorCode(ILjava/lang/String;)V": {
}
}
}
image-20220109160003908
补了之后,好像继续执行下去了,这样看来好像不用补文件。看看现在的报错,看看AbstractJni.java:364
看来需要自己写代码把org.apache.http.message.BasicNameValuePair
转为com.github.unidbg.linux.android.dvm.DvmObject
。
@Override
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "java/util/List->get(I)Ljava/lang/Object;": {
List<?> list = (List<?>) dvmObject.getValue();
Object obj = list.get(vaList.getIntArg(0));
if (obj instanceof BasicNameValuePair) {
return vm.resolveClass("org/apache/http/message/BasicNameValuePair").newObject(obj);
}
}
}
return super.callObjectMethodV(vm, dvmObject, signature, vaList);
}
image-20220109160430819
case "org/apache/http/message/BasicNameValuePair->getName()Ljava/lang/String;": {
BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
return new StringObject(vm, pair.getName());
}
image-20220109160509515
case "org/apache/http/message/BasicNameValuePair->getValue()Ljava/lang/String;": {
BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
return new StringObject(vm, pair.getValue());
}
image-20220109160556803
出结果了。
完整代码
package com.autohome;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class AutoHome extends AbstractJni{
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
public static String pkgName = "com.cubic.autohome";
public static String apkPath = "unidbg-android/src/test/java/com/autohome/autohome1197.apk";
public static String soPath = "unidbg-android/src/test/java/com/autohome/libblackBox.so";
public AutoHome() {
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File(apkPath));
vm.setJni(this);
vm.setVerbose(true);
DalvikModule dm = vm.loadLibrary(new File(soPath), false);
module = dm.getModule();
dm.callJNI_OnLoad(emulator);
}
@Override
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "java/util/List->get(I)Ljava/lang/Object;": {
List<?> list = (List<?>) dvmObject.getValue();
Object obj = list.get(vaList.getIntArg(0));
if (obj instanceof BasicNameValuePair) {
return vm.resolveClass("org/apache/http/message/BasicNameValuePair").newObject(obj);
}
}
case "org/apache/http/message/BasicNameValuePair->getName()Ljava/lang/String;": {
BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
return new StringObject(vm, pair.getName());
}
case "org/apache/http/message/BasicNameValuePair->getValue()Ljava/lang/String;": {
BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
return new StringObject(vm, pair.getValue());
}
}
return super.callObjectMethodV(vm, dvmObject, signature, vaList);
}
@Override
public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "com/autohome/mainlib/common/util/BlackBox->reportNativeErrorCode(ILjava/lang/String;)V": {
}
}
}
public void call_sign() {
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv());
// list.add(0);
list.add(vm.addLocalObject(vm.resolveClass("com/autohome/mainlib/common/util/BlackBox").newObject(null)));
List<NameValuePair> pairs = new ArrayList<>(10);
pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
// 1C4E5C182F7FFF5C350E1BB1B4C2B50C
module.callFunction(emulator, 0x2d91d, list.toArray());
}
public void call_sign2() {
DvmClass clz = vm.resolveClass("com/autohome/mainlib/common/util/BlackBox");
String method = "getInterfaceSign(Ljava/util/List;)Ljava/lang/String;";
List<NameValuePair> pairs = new ArrayList<>(10);
pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
// 1C4E5C182F7FFF5C350E1BB1B4C2B50C
clz.callStaticJniMethodObject(emulator, method, vm.resolveClass("java/util/List").newObject(pairs));
}
public static void main(String[] args) {
AutoHome test = new AutoHome();
test.call_sign();
// test.call_sign2();
}
}
网友评论