写在最前面
上篇是通过frdia hook 分析目标app的sign参数,这篇文章通过unidbg补环境,来获取到目标参数。同时记录下unidbg补环境的过程。
补环境
- 搭建好模版
public class JingDongSign extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
private Memory memory;
public JingDongSign() {
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.jingdong.app.mall").build();
// 获取模拟器的内存操作接口
memory = emulator.getMemory();
// 设置系统类库解析
memory.setLibraryResolver(new AndroidResolver(23));
// 创建Android虚拟机,传入APK,Unidbg可以替我们做部分签名校验的工作
vm = emulator.createDalvikVM(new File("path/目标.apk"));
//
//vm = emulator.createDalvikVM(null);
// 加载目标SO
DalvikModule dm = vm.loadLibrary(new File("/path/libjdbitmapkit.so"), true); // 加载so到虚拟内存
//获取本SO模块的句柄,后续需要用它
module = dm.getModule();
vm.setJni(this); // 设置JNI
// vm.setVerbose(true); // 打印日志
dm.callJNI_OnLoad(emulator); // 调用JNI OnLoad
}
public void getSignFromJni() {
ArrayList<Object> args = new ArrayList<>(10);
args.add(vm.getJNIEnv());
args.add(0);
// 前两个参数固定写法
args.add(vm.addLocalObject(vm.resolveClass("android/content/Context").newObject(null)));
args.add(vm.addLocalObject(new StringObject(vm, "searchBoxWord")));
args.add(vm.addLocalObject(new StringObject(vm, " {\"geo\":\"VNfO2wQHmvP4y5nMzG57aoZ6JeMTGp8qU0MXssp7SNC338Ds0C1MbASr47trp0dd7idK5Yw57BgeHWK3CGvjZQ%3D%3D\",\"geoLast\":\"VNfO2wQHmvP4y5nMzG57aoZ6JeMTGp8qU0MXssp7SNC338Ds0C1MbASr47trp0dd7idK5Yw57BgeHWK3CGvjZQ%3D%3D\"}")));
args.add(vm.addLocalObject(new StringObject(vm, "259fb80b2a74f7a3")));
args.add(vm.addLocalObject(new StringObject(vm, "android")));
args.add(vm.addLocalObject(new StringObject(vm, "10.2.0")));
Number number = module.callFunction(emulator, 0x28b5, args.toArray()); // 调用so层方法
System.out.println(vm.getObject(number.intValue()).getValue().toString());
}
public static void main(String[] args) {
JingDongSign jd = new JingDongSign();
jd.getSignFromJni();
}
}
- 运行,根据报错信息来补环境
-
one
根据保存信息 补com/jingdong/common/utils/BitmapkitUtils->a:Landroid/app/Application;
-
@Override
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
if("com/jingdong/common/utils/BitmapkitUtils->a:Landroid/app/Application;".equals(signature)){
return vm.resolveClass("android/app/Activity").newObject(signature);
}
throw new UnsupportedOperationException(signature);
}
- two
取ApplicationInfo也就是apk的存放位置 可以在RE文件管理器/data/app中找到对应的位置
if ("android/content/pm/ApplicationInfo->sourceDir:Ljava/lang/String;".equals(signature)) {
return new StringObject(vm, "/data/app/com.jingdong.app.mall-cd4VeJ0b5yxrR0Zb-io_MA=/base.apk");
}
-
three
先查看传入的参数是
根据参数打开APK中中的META-INF搜索RSA结尾的文件
根据这个文件名补即可
-
if ("com/jingdong/common/utils/BitmapkitZip->unZip(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)[B".equals(signature)) {
System.out.println("arg0-- "+varArg.getObjectArg(0).getValue());
System.out.println("arg1-- "+varArg.getObjectArg(1).getValue());
System.out.println("arg2-- "+varArg.getObjectArg(2).getValue());
return new ByteArray(vm, vm.unzip("META-INF/JINGDONG.RSA"));
}
-
four
-
if("sun/security/pkcs/PKCS7-><init>([B)V".equals(signature)){
PKCS7 pkcs7= null;
try {
pkcs7 = new PKCS7((byte[]) varArg.getObjectArg(0).getValue());
} catch (ParsingException e) {
e.printStackTrace();
}
return vm.resolveClass("sun/security/pkcs/PKCS7").newObject(pkcs7);
}
-
five
-
if("sun/security/pkcs/PKCS7->getCertificates()[Ljava/security/cert/X509Certificate;".equals(signature)){
PKCS7 pkcs7 = (PKCS7) dvmObject.getValue();
X509Certificate[] x509Certificates = pkcs7.getCertificates();
return ProxyDvmObject.createObject(vm, x509Certificates);
}
-
six
补BitmapkitZip类下的objectToBytes方法
打开jdax搜这个方法
将此代码复制出来,写我们程序中
-
private static byte[] objectToBytes(Object obj) {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(obj);
objectOutputStream.flush();
byte[] byteArray = byteArrayOutputStream.toByteArray();
objectOutputStream.close();
byteArrayOutputStream.close();
return byteArray;
} catch (IOException e) {
return null;
}
}
继续补环境
if("com/jingdong/common/utils/BitmapkitZip->objectToBytes(Ljava/lang/Object;)[B".equals(signature)){
return new ByteArray(vm, JingDongSign.objectToBytes(varArg.getObjectArg(0).getValue()));
}
-
seven
-
if("java/lang/StringBuffer-><init>()V".equals(signature)){
StringBuffer stringBuffer = new StringBuffer();
return vm.resolveClass("java/lang/StringBuffer").newObject(stringBuffer);
}
-
eight
-
if("java/lang/StringBuffer->append(Ljava/lang/String;)Ljava/lang/StringBuffer;".equals(signature)){
StringBuffer stringBuffer = (StringBuffer) dvmObject.getValue();
return vm.resolveClass("java/lang/StringBuffer").newObject(stringBuffer.append(vaList.getObjectArg(0).getValue()));
}
-
nine
-
if("java/lang/Integer->toString()Ljava/lang/String;".equals(signature)){
Integer integer = (Integer) dvmObject.getValue();
return new StringObject(vm, integer.toString());
}
-
ten
-
if("java/lang/StringBuffer->toString()Ljava/lang/String;".equals(signature)){
StringBuffer stringBuffer = (StringBuffer) dvmObject.getValue();
return new StringObject(vm, stringBuffer.toString());
}
-
end
运行成功,至此补环境完毕。之后就可以黑盒调试,不想调试也可以用spring boot搭建个服务,远程调用即可
-