本期内容是关于某app模拟登录的,涉及的知识点比较多,有unidbg补环境及辅助还原算法,ida中的md5以及白盒aes,fart脱壳,frida反调试
文章老是莫名被某sdn删掉,然后还审核不通过,后面估计发自己博客了
本章所有样本及资料均上传到了123云盘
网盘发不出来,审核过不了
目录
本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请联系作者立即删除!
首先抓包

看login请求,表单和响应都是大长串,猜测是对称加密算法或者是非对称,对称常见的有des和aes,非对称常见的有rsa.
fart脱壳
正常流程下应该是拖到jadx中反编译一下,但是目标app使用了梆梆企业加固

我换了一部由fart脱壳机定制的pixel 4后成功脱壳,后续我会把脱壳的dex放到网盘里,所以对脱壳不了解的可以略过脱壳这个步骤
寒冰的fart脱壳机
把脱下来的dex文件pull到电脑上

对比下脱壳前后的反编译结果

加密位置定位
接下来是定位加密位置了
尝试搜索"sd"

框中的可能性比较大,其他几个类名都是android aliyun google tencent这种系统文件或者第三方厂商的,框中的包含类名以及retrofit框架
这个是目标字段的可能性很大,点进去看看,然后查找用例

右下角框中的有一个decrypt函数,应该是响应的解密逻辑,那上面的应该是加密函数了

点进去然后复制frida片段
function call(){
Java.perform(function (){
let CheckCodeUtils = Java.use("com.cloudy.linglingbang.model.request.retrofit2.CheckCodeUtils");
CheckCodeUtils["encrypt"].implementation = function (str, i) {
console.log(`CheckCodeUtils.encrypt is called: str=${str}, i=${i}`);
let result = this["encrypt"](str, i);
console.log(`CheckCodeUtils.encrypt result=${result}`);
return result;
};
})
}
frida反调试
frida注入 frida -UF -l hook.js
以attach方式启动frida后报错无法附加进程,这里我们使用spwan方式启动即可

换成spwan方式后还是报错了,应该还有检测frida-server

换成葫芦娃形式的试试


成功了,接下来就是发个包看看有没有结果

对比下发现结果差不多就是hook的结果把+改成空格就是sd的值了

接着分析jadx中的函数,checkcode点进去

可以看到目标函数返回null,和hook的结果不一样,并且jadx给出了警告,不知道是脱壳脱的不全还是jadx的问题,后续可以用jeb试试,jeb的反编译能力比jadx强
同时可以看到下面有两个native函数,checkcode,和decheckcode,尝试hook checkcode函数

同样有结果
这两个native函数加载自libencrypt.so

这里我选择32位的so,拖到ida32中搜索java,发现是静态注册(如果是动态注册还可以hook libart.so来找导出函数)

unidbg搭架子
接下来是unidbg模拟执行
搭架子
package com;
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.AbstractJni;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.memory.Memory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class demo2 extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
private final Memory memory;
demo2(){
// 创建模拟器实例,进程名建议依照实际进程名填写,可以规避针对进程名的校验
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.cloudy.linglingbang").build();
// 获取模拟器的内存操作接口
memory = emulator.getMemory();
// 设置系统类库解析
memory.setLibraryResolver(new AndroidResolver(23));
// 创建Android虚拟机,传入APK,Unidbg可以替我们做部分签名校验的工作
vm = emulator.createDalvikVM(new File("unidbg-android/apks/llb/llb.apk"));
// 设置JNI
vm.setJni(this);
// 打印日志
vm.setVerbose(true);
// 加载目标SO
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/apks/llb/libencrypt.so"), true);
//获取本SO模块的句柄,后续需要用它
module = dm.getModule();
// 调用JNI OnLoad
dm.callJNI_OnLoad(emulator);
};
public String callByAddress(){
// args list
List<Object> list = new ArrayList<>(5);
// jnienv
list.add(vm.getJNIEnv());
// jclazz
list.add(0);
// str1
list.add(vm.addLocalObject(new StringObject(vm, "mobile=13535535353&password=fjfjfjffk&client_id=2019041810222516127&client_secret=c5ad2a4290faa3df39683865c2e10310&state=eu4acofTmb&response_type=token")));
// int
list.add(2);
// str2
list.add(vm.addLocalObject(new StringObject(vm, "1709100421650")));
Number number = module.callFunction(emulator, 0x13A19, list.toArray());
String result = vm.getObject(number.intValue()).getValue().toString();
System.out.println("======encrypt:"+result);
return result;
};
public static void main(String[] args) {
demo2 llb = new demo2();
// llb.callByAddress();
}
}
补环境
运行报错,currentActivityThread 通常用于一些需要获取全局上下文或执行一些与应用程序状态相关的操作的场景

补上,这里没什么好说的,孰能生巧
@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
switch (signature){
case "android/app/ActivityThread->currentActivityThread()Landroid/app/ActivityThread;":{
return vm.resolveClass("android/app/ActivityThread").newObject(null);
}
}
return super.callStaticObjectMethod(vm, dvmClass, signature, varArg);
}
接着运行,SystemProperties中的get像是在获取系统的某个属性

case "android/os/SystemProperties->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":{
String arg = varArg.getObjectArg(0).getValue().toString();
System.out.println("SystemProperties get arg:"+arg);
}
![]()
获取手机序列号的

adb shell getprop ro.serialno

最低0.47元/天 解锁文章
938

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



