车联网通信协议,车载通讯协议

  车联网通信协议,车载通讯协议

  一、目标之前我们已经用unidbg跑通了libencrypt.so,那么如何判断跑出来的结果是对是错?再如何纠正unidbg跑错误的流程,是我们今天的目标。

  6.1.0版

  二、步骤找到明显的接口来判断校验码是加密,加密的结果确实不好判断是否正确。不过我们可以试试解密,能解密就是对的,简单粗暴。这里解密函数是解码。

  公共void callB() {

  string strA= flk 6 xivmcwpse 3 sk 6 b 71m 9 wbwd/gztlajqgxhjmwezzir 51 rvwsedwui 4 un 9 rnocgblnmqi 80 fiog 4 SW==;

  String方法名称= de校验码(Ljava/lang/String;)Ljava/lang/String;;

  DvmObject ret=dvm类。callstaticjnimethodobject(仿真器,methodName,strA);

  String strOut=(String)ret。getvalue();

  系统。出去。println( call de check code: strOut );跑一下,这个结果明显不对,死心了

  调用decheckcode:分析问题结果不对,肯定是过程不对。

  那么解决方案就是分析对比unidbg运行的流程和应用运行的流程有哪里有不同?

  对比运行流程有三个粒度,函数、代码块和代码。 (在艾达山里按空格,出现的流程图中的每个块就是代码块)

  我们今天主要要对比去校验码函数,所以先从代码块的粒度来做追踪。

  跟踪块unidbg提供一个木块钩,每运行到一个代码块就触发这钩子,我们就利用他来做跟踪块

  //保存需要用弗里达胡克的街区的地址

  公共静态映射Integer,Integer subTraceMap=new HashMap Integer,Integer();

  //保存命中的街区地址的次数,命中次数太多的就忽略掉。

  公共静态映射Integer,Integer calc Map=new HashMap Integer,Integer();

  //入参是因此基地址,需要微量代码的开始地址和结束地址

  私有空跟踪块(最终长基址地址,最终长星地址,最终长{

  emulator.getBackend()。hook_add_new(new BlockHook() {

  @覆盖

  公共空钩座(后端后端,长地址,int {

  //代码块需要大于20个字节,块太小影响弗里达的钩

  如果(20码){

  指令[]insns=仿真器。拆卸(地址,4,0);

  int iSize=insns[0].getSize();

  int iUseAddr=0;

  if (iSize==4) {

  //手臂模式四字节

  iuse addr=(int)(地址基addr);

  }否则{

  //拇指模式2字节,挂钩的时候1 ,

  iuse addr=(int)(地址基addr)1;

  }

  如果(计算映射。包含密钥(iUseAddr)){

  //保存命中次数

  int iValue=计算映射。get(iUseAddr);

  calcMap.put(iUseAddr,iValue 1);

  //4次以上的调用就不显示了,也不用弗里达迹线了

  if (iValue 3) {

  子轨迹图。remove(iUseAddr);

  }否则{

  系统。出去。println( sub _ 整数。tohexstring((int)(address-base addr))“);

  }

  }否则{

  calcMap.put(iUseAddr,1);

  subTraceMap.put(iUseAddr,1);

  系统。出去。println( sub _ 整数。tohexstring((int)(address-base addr))“);

  }

  }

  }

  @覆盖

  公共void onAttach(UnHook unHook) {

  }

  @覆盖

  公共空的分离(){

  }

  },starAddr,endAddr,0);

  }跟踪块结束之后,把命中的代码块地址都打印出来,用于在弗里达中去钩

  public void printucksubinfo(){

  系统。出去。println( subTrace len= subtracemap。size());

  string strOut=

  对于(图Entry Integer,Integer entry:subtracemap。条目集()){

  int iShow=entry。getkey();

  //为了和unidbg显示一致这里处理下

  如果(正在显示% 2!=0){

  iShow=iShow-1;

  }

  strOut=strOut ,[ sub _ 整数。tohexstring(iShow)“”,整数“0x”。tohexstring((int)entry。getkey())“]”;

  }

  系统。出去。println(strOut);

  }有了这两个函数就可以干活了

  公共void callB(){

  traceBlock(模块.基础,模块.基础,模块.基础模块。大小);

  .

  String方法名称= de校验码(Ljava/lang/String;)Ljava/lang/String;;

  DvmObject ret=dvm类。callstaticjnimethodobject(emulator,methodName,strA);

  .

  打印挂钩subinfo();

  }在执行去校验码之前去做痕迹,执行之后去打印所有命中的街区地址。

  提示:这个样本没那么复杂,所以就直接微量所有代码范围,讲究人是需要缩小范围,只微量自己感兴趣的部分。

  查找本机函数Java _ com _ bangcle _ comapi protect _ CheckCodeUtil _ decheckcode=RX @0x 4002 B1 BC[lib encrypt。所以]公元前0x 2 B1

  sub_2b1bc

  sub_2b20c

  sub_2b238

  sub_2b254

  sub_2b270

  sub_2b28c

  sub_2b2a8

  sub_2b2c4

  sub_2b2e0

  sub_2b2fc

  sub_2b318

  sub_2b334

  .

  subTrace len=127

  ,[sub_21400 ,0x21400],[sub_21c00 ,0x21c00],[sub_22200 ,0x22200],[sub_2b604 ,0x2b604]Trace的结果出来了,命中的地址列表也打印出来了,一共命中了127个地址块。

  弗里达胡克对比把命中的地址列表导入到弗里达里面去钩子,然后就可以对比出来unidbg跑的流程和应用跑的流程的差别了。

  函数钩子_可疑_函数(目标函数){

  常量函数=[

  [sub_21400 ,0x21400],[sub_21c00 ,0x21c00],[sub_.

  ];

  对于(函数中的变量I){

  设相对ptr=funcs[I][1];

  设func ptr=targetso。add(相对ptr);

  let describe=funcs[I][0];

  let handler=(function() {

  返回函数(参数){

  //控制台。日志( \ n );

  console.log(标签描述);

  };

  })();

  Interceptor.attach(funcPtr,{ onEnter:handler });

  }

  }

  函数traceNative() {

  var targetSo=module。findbaseaddress( libencrypt。所以’);

  console.log(标签Trace # # # # # # # # # # # # lib encrypt。所以:‘targetSo’);

  钩子_疑似_函数(targetSo);

  }

  //然后在钩子去校验码的时候打印微量结果

  截击机。附加(targetso。添加(0x 2 B1 BC),{

  onEnter:函数(参数){

  跟踪native();

  var strCls=Java。使用( Java。郎。string’);

  var strA=Java。投(这个。语境。x2,str cls);

  控制台。log(TAG -de校验码a= strA);

  },

  onLeave: function(retval){

  var strCls=Java。使用( Java。郎。string’);

  var strRc=Java.cast(retval,strCls);

  控制台。日志(标签-de校验码RC=对比结果对比的方法比较低,先把unidbg跟踪块的结果复制到文本文件1,然后把弗里达胡克打印的结果复制到文本文件2。最后开启无与伦比来对比

  1:化学机械抛光

  过程虽然很低,但是结果可一点都不低,从对比的结果看,大家之前都是好朋友,不过sub_18650之后就开始分道扬镳了。

  这时候就需要问问艾达山了。

  1:fopen

  这里打开文件了一个文件,文件名是做了base64。

  base64谁不会呢,随便写两行代码就可以解出来了/proc/%d/cmdline

  这又在考我们的机器人编程知识了,问了下谷哥,哥说了,这是在读进程名,对于应用来说,进程名就是他的包名。

  回想在unidbg中有个不起眼的报错

  INFO[com。github。unidbg。Linux。arm 64 syscallhandler](arm 64 syscallhandler:1309)-在dirfd=-100处打开,路径名=/proc/2256/cmdline,oflags=0x0,模式=0这也是在提醒我们,读取进程名失败了。

  重定向iounidbg是支持这种情况的,先让CaranywhereDemo多继承一个IOResolver来做超正析象管重定向

  公共类CaranywhereDemo扩展抽象Jni实现IOResolver AndroidFileIO {

  .

  公共carany where(字符串apkFilePath)引发DecoderException,IOException {

  .

  emulator.getSyscallHandler().addIOResolver(this);

  .

  }

  FileResult AndroidFileIO f1

  公共文件结果AndroidFileIO get f1(String pathname,int) {

  if (f1==null) {

  f1=文件结果AndroidFileIO success(new ByteArrayFileIO(of lags,pathname, com.xxx.aeri.caranywhere ).getBytes()));

  }

  系统。出去。println( new f1==路径名=== VM。获取包名());

  返回f1;

  }

  @覆盖

  公共文件结果Android fileio resolve(Emulator Android fileio Emulator,String pathname,int) {

  System.out.println(路径名);

  if (/proc/self/cmdline ).等于(路径名) (/proc/模拟器。getpid()/cmdline ).等于(路径名)){

  返回getF1(路径名滞后);

  }

  返回空

  }

  }好的了,这几步又和应用跑的一样了,大家又是好朋友了。

  不过问题还是没有解决,跑出来的结果还是不对,木有解密成功。而且貌似这个应用还有坑,挂钩点一多就摆烂,直接崩溃。

  我们必须找到一种新的武器来对付它。期待下一章的大结局。

  第三,总结如何解决烦恼,只留痕迹。

  能破断点调试的App肯定是逃不掉的。所以现在App的重点是抵抗调试和断点。

  如果结果是错误的,将过程与正确的结果进行比较。你跑起来和你一模一样。有什么问题吗?

  1:ffshow

  难说的在于知道说了什么,说了就能说出来。

  版权归作者所有:来自博主fenfei331的原创作品,转载请联系作者授权,否则将追究法律责任。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: