unidbg入门级案例-某航空app_hnairSign分析

news2024/11/16 7:44:04

今天要分析的是某航空app,版本号是8.19.0,分析的样本在文章底部会提供,这次我们要借用unidbg 来辅助进行算法还原。

有关unidbg的介绍笔者就不做过多的描述,大家可自行百度查询。
该样本的so比较简单,但重点是记录分析的思路和过程。这里万分感谢鹏佬的指定。

老规矩,上来先抓个包。

1.抓包

在这里插入图片描述
经分析该app没有壳,里面有一个hnairSign参数加密,hnairSign 就是本次样本研究的重点,我们不在意如何拿到数据,而是研究如何构造加密的。

2.jadx静态分析

把样本app 拖到jadx里面,直接搜索关键词 "hnairSign",可以看到只有一条搜索结果,跟进去看看。

在这里插入图片描述

然后来到了这个,可以看到i6.b("hnairSign", signRequest);,其中hnairSign 是该String signRequest = signRequest(aVar);方法返回来的。

在这里插入图片描述
紧接着跟进 signRequest(aVar) 函数看一看,来到这里

在这里插入图片描述
可以看到 signRequest 函数的入参是v.a aVar ,返回值是String,并且是由该(String) i.p(HNASignature.getHNASignature(headersForSign, queryForSign, requestBodyForSign, str, a9), new String[]{">>"}).get(0); 返回来的。

在这里我们看到了HNASignature.getHNASignature(),根据函数命名规范,大胆的猜测下,这里就是最核心的加密代码。
getHNASignature()函数的入参是headersForSign, queryForSign, requestBodyForSign, str, a9 几个连续的String,具体是什么,目前不知道,不过先放置在这里。

继续跟进去,来到这里。

在这里插入图片描述

package com.rytong.hnair;

public class HNASignature {
    public static native String getHNASignature(String str, String str2, String str3, String str4, String str5);
}

关键字native,看来本次样本不是在java层那么简单了,本着学习的态度,进入so层看看代码是如何写的。

通常情况下,会有如下的代码:

System.loadLibrary("xxxxx")

会告诉我们,样本加密在那个so文件,但是这里并没有。

不过我们也可以用yang神的frida脚本 hook_RegisterNatives( https://github.com/lasting-yang/frida_hook_libart) 来打印注册的native函数和so文件。

那它的脚本到底是如何做到的尼,点进去源码看看。

在这里插入图片描述

java层的静态分析到此就差不多结束了,接着要用frida动态分析下。

3. frida动态调试

打开frida服务,运行命令:

frida -U com.rytong.hnair -l hair_hook.js

hair_hook代码:


Java.perform(function () {
    var HNASignature = Java.use("com.rytong.hnair.HNASignature");
    HNASignature.getHNASignature.implementation = function (str1, str2, str3, str4, str5) {
        console.log("---------------------------");
        console.log('getHNASignature is called');
        console.log("str1:" + str1);
        console.log("str2:" + str2);
        console.log("str3:" + str3);
        console.log("str4:" + str4);
        console.log("str5:" + str5);
        var ret = this.getHNASignature(str, str2, str3, str4, str5);
        console.log('getHNASignature加密值:' + ret);
        return ret;
    };
})

frida hook结果:

在这里插入图片描述

getHNASignature is called
str1:{}
str2:{}
str3:{"akey":"184C5F04D8BE43DCBD2EE3ABC928F616","aname":"com.rytong.hnair","atarget":"standard","aver":"8.19.0","did":"9908e1587f76bbd6","dname":"OnePlus_ONEPLUS A5010","gtcid":"0629cf96a1a94543d3b1db7625b97e44","mchannel":"official","schannel":"AD","slang":"zh-CN","sname":"OnePlus\/OnePlus5T\/OnePlus5T:8.1.0\/OPM1.171019.011\/1812111113:user\/release-keys","stime":"1671674896594","sver":"8.1.0","system":"AD","szone":"+0800","abuild":"63403","hver":"8.19.0.30995.c079e3182.standard","cms":[{"name":"cdnConfig"}],"h5Version":"8.19.0.30995.c079e3182.standard"}
str4:21047C596EAD45209346AE29F0350491
str5:F6B15ABD66F91951036C955CB25B069F
getHNASignature加密值:F3DCBDD8A2350604A7487FF97E3A709B331F3E51>>63403184C5F04D8BE43DCBD2EE3ABC928F616com.rytong.hnairstandard8.19.09908e1587f76bbd6OnePlus_ONEPLUS A50100629cf96a1a94543d3b1db7625b97e448.19.0.30995.c079e3182.standard8.19.0.30995.c079e3182.standardofficialADzh-CNOnePlus/OnePlus5T/OnePlus5T:8.1.0/OPM1.171019.011/1812111113:user/release-keys16716748965948.1.0AD+0800>>F6B15ABD66F91951036C955CB25B069F

连续hook多次发现,参数 str1 和 str2 固定为{},参数str3是一个json字符串,参数str4为固定值21047C596EAD45209346AE29F0350491,参数str5为固定值F6B15ABD66F91951036C955CB25B069F,可以把它暂且理解为盐值吧!

4.so层分析

把样本app后缀修改成zip结尾,然后解压缩,在lib下的armeabi-v7a 32位目录下找到加密样本libsignature.so

把该so样本直接拖到ida里,全程选择默认,一路点击ok。

在这里插入图片描述

然后又是熟悉的页面,熟悉的晦涩难懂。。。硬着头皮上。。。。。

进入到这里,我们首先要确定两件事,第一加密的native函数到底是静态注册还是动态注册的。第二样本so用的是Thumb 指令 还是Arm指定。

那么有问题的小明同学就想问一句,你说的到底是个啥,能简单的介绍下吗?

一般在Exports导出表能搜索到以"java_"开头的函数就是静态注册,反之则为动态注册。

示例如图:

在这里插入图片描述

那如何判断 Thumb 和 Arm 指令集尼?
ida里依次找到Options ----> General
在这里插入图片描述

然后 Number of opcode bytes(non-graph) 设置为4 ,点击ok.

在这里插入图片描述

然后在IDA View中查看opcode 的长度, 如果出现 2 个字节和 4 个字节的, 说明为 thumb 指令集。

如果都是 4 个字节的, 说明是 arm 指令集。

在 Thumb 指令集下, inline hook 的需要进行偏移地址 +1 操作;

示例如图:

在这里插入图片描述

继续之前的,刚才我们找到了"java_" 开头的函数 Java_com_rytong_hnair_HNASignature_getHNASignature ,点进去。

在这里插入图片描述

使用空格键 可以实现 文字图 和 竖形流程图 的切换(ps:这里可能表述不准确)。

在这里插入图片描述

然后再按 Fn5健 就能看到 加密的 c/c++代码了。

在这里插入图片描述

这里就能看到加密的c函数HNASignature(&v19, &v25, &v24, &v23, &v22, &v21)
几个入参应该分别对应着java层的入参(形参)。

public static native String getHNASignature(String str, String str2, String str3, String str4, String str5);
}

同时我们在导出函数窗口还看到了CHMAC_SHA1::HMAC_SHA1()

在这里插入图片描述

根据经验,大胆的猜测下这里用的是hmac_sha1算法。

好了,so层的分析到一段落。

5.unidbg分析

unidbg 最重要的就是补环境

环境搭建 可参考文章:https://blog.csdn.net/qq_41179280/article/details/121771586

第一步,先搭建基本框架

package com.rytong.hnair;

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 java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class HNASignatureTest extends AbstractJni {
    private final AndroidEmulator emulator;
    private final Module module;
    private final VM vm;

    public HNASignatureTest() {
        // 创建模拟器实例,进程名依照实际进程名填写,要模拟32位或者64位,在这里区分
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.rytong.hnair").build();
        // 模拟器的内存操作接口
        final Memory memory = emulator.getMemory();
        // 设置系统类库解析,有19和23 两个版本选择
        memory.setLibraryResolver(new AndroidResolver(23));
        // 创建Android虚拟机,传入APK,Unidbg可以替我们做部分签名校验的工作
        vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/hair/hair_8.19.0.apk"));
        // 设置是否打印Jni调用细节
        vm.setVerbose(false);
        // 加载目标SO
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/hair/armeabi_v7a/libsignature.so"), false);
        //获取SO模块的句柄
        module = dm.getModule();
        System.out.println("baseAddr:"+  module.base);
        // 设置JNI
        vm.setJni(this);
        // 调用JNI OnLoad
        dm.callJNI_OnLoad(emulator);
    }

初始化的大致逻辑就是先创建个模拟器对象emulator,然后去内存申请接口,再传入apk和so文件,最后再执行JNI OnLoad。

unidbg 是模拟执行so 的,因为是模拟而并不是真正的,所以有很多东西没有实现,所以会报各种各种的错误。

接下来,我们逐行的详细解释下,代码中的注释已经很清楚。

new AndroidResolver() 指定系统类库解析,那为什么只有2个版本可供选择尼?

点进源码,我们发现unidbg作者只实现了 19和23 两个版本。

在这里插入图片描述

emulator.createDalvikVM()是创建Android虚拟机,为什么要传入apk文件尼?

点进源码看看

在这里插入图片描述

可以看到这里 Apk接口会自动获取版本号,版本名称,ManifestXml,签名,包名等(建议写上,会帮我们做部分签名校验的工作)

vm.setJni(this); 是设置jni,那什么是jni?

带着疑问,百度下?

在这里插入图片描述

详细可参考文章:https://blog.csdn.net/yaojingqingcheng/article/details/123497697

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多标签分类怎么做?(Python)

一、基本介绍 首先简单介绍下,多标签分类与多分类、多任务学习的关系: 多分类学习(Multi-class):分类器去划分的类别是多个的,但对于每一个样本只能有一个类别,类别间是互斥的。例如&#xff1…

electron:获取MAC地址

一、背景 当我们需要用户“使用指定设备”访问程序的时候,我们需要获取用户设备的固定的id,设备id用户id实现业务需求,这个所谓的id就是MAC地址。 对于其他方法: uuid:uuid是一个唯一的字符串,可以存放到…

深度融合钉钉PaaS,授客学堂助力企业实现培训数字化

方案简介 授客学堂将企业培训领域的经验与钉钉开放能力深度融合,通过集成钉钉人事一体、酷应用、IM底座、待办等多种开放能力,实现学员培训数据实时互通,为客户提供更新更酷的能力,高效解决企业培训的数字化服务。 方案场景 在…

tensorflow feature_columns

总结来说: feature_column定义了一种数据预处理的方式,可以看作是一种格式,指定了key,用于后续读取输入流中对应列的数据feature_column不是tensor,所以如果在下一步应用到模型中是需要tensor,还需要通过f…

非互联网人士如何转行互联网?

结论是,具备互联网式的做事思维积累互联网项目经验。我靠着这个方法从一名传统销售顺利转行,(之前没有任何互联网工作经验)入职了一家互联网公司做用户运营,半年前跳槽成为一个4人运营小团队的leader。 在分享我自身的…

我国丁辛醇行业现状:上游丙烯供给充足 下游需求下滑 市场出现高差价现象

根据观研报告网发布的《中国丁辛醇行业发展深度分析与投资前景研究报告(2022-2029年)》显示,丁辛醇是一种丁醇和辛醇合成的有机物,无色透明、易燃的油状液体,具有特殊的气味,能与水及多种化合物形成共沸物&…

服务器IPMI(BMC)装机

将网线连接服务器的控制口与PC,服务器的控制口默认IP为192.168.100.100,网关默认为192.168.100.1,将PC的IP修改为与服务器控制口相同网段。打开浏览器,输入https://19168.100.100,进入IPMI登录界面。账号密码需要找运维…

Apache Airflow Hive Provider <5.0.0 存在操作系统命令注入漏洞

漏洞描述 Apache Airflow 是一个用于以编程方式创作、安排和监控工作流平台。Apache Airflow Hive Provider 是一个使用 SQL 读取、写入和管理分布式存储中的大型数据集的工具包。 Apache Airflow Hive Provider 在 5.0.0 之前的版本中由于对airflow/providers/apache/hive/h…

Stm32标准库函数6——f103 PWM 电调(50Hz)

#include "stm32f10x.h" #include "delay.h" TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; u16 Ppm; /************************************************* 函数: void RCC_Configuration(void) 功能: 配…

D. Friends and Subsequences Codeforces Round #361 (Div. 2)RMQ+二分 单调队列

题目传送门 题意为 给定两个长度为n的数组,设为a数组和b数组,需要找到所有可能的区间中,a数组的最大值等于b数组的最小值的个数。 1:RMQ 二分 RMQ 能找到一个数组在任意区间的最大值或者最小值,只需要在O(n)的时间…

【Java基础知识复盘】HashMap篇——持续更新中

本人知识复盘系列的博客并非全部原创,大部分摘自网络,只是为了记录在自己的博客方便查阅,往后也会陆续在本篇博客更新本人查阅到的新的知识点,望悉知! HashMap 概述 HashMap 是一个散列表,它存储的内容是…

hashMap相关

文章目录HashMapHashMap介绍HashMap在 JDK1.7和 JDK1.8中的区别JDK1.7中HashMap头插法死循环的原因HashMap的底层原理HashMap的扩容机制解决Hash冲突的方法为什么在解决hash冲突的时候选择先用链表,再转红黑树?HashMap为什么线程不安全一般用什么作为HashMap的key?…

程序员需要达到什么水平才能顺利拿到 20k 无压力?

很有趣的是,在程序员身上,我看到了最明显,也最有趣的贫富差距。 根据2022最新版大厂新入职员工职级对应表,大厂技术线的员工轻而易举地拿到了20w的水平,而只要往上够一够,30w也不是什么难事。 然而&#xf…

玩转云服务器:怎样用云服务器架设大型3D魔幻手游【魔域】服务器,实现联机多人同玩,带你一起搞机,了解游戏搭建过程,详细教程

准备工作: 你首先要准备一台云服务器! 服务器配置:2核4G以上配置! 服务器系统:win2012 开始搭建: 下载游戏服务端(有些多人叫源码,这里我就不解释了,喜欢怎么叫就怎…

SpringCloud Alibaba | 网关(三) : SpringCloudGateway 过滤器获取application/json中body数据

SpringCloudGateway 过滤器获取application/json中body数据一、前言二、通过cachedRequestBodyObject缓存获取三、ServerHttpRequest getBody方法获取四、(* ̄︶ ̄)一、前言 项目接口需要加解密,就在网关层进行解密操作。那么问题来了怎么在gateway 的filt…

基于松鼠算法改进的DELM预测-附代码

松鼠算法改进的深度极限学习机DELM的回归预测 文章目录松鼠算法改进的深度极限学习机DELM的回归预测1.ELM原理2.深度极限学习机(DELM)原理3.松鼠算法4.松鼠算法改进DELM5.实验结果6.参考文献7.Matlab代码1.ELM原理 ELM基础原理请参考:https:…

线程池相关

文章目录为什么需要线程池?池化思想常用方法execute()方法submit()方法shutdownisShutdownisTerminatedawaitTerminationshutdownNow创建线程池 七个参数流程JAVA线程池有哪几种类型?线程池常用的阻塞队列有哪些?源码中线程池是怎么复用线程的?如何合理配置线程池…

EMQX Cloud 自定义函数实现多种 IoT 数据形式的灵活转化

物联网场景中,各类设备终端的种类繁杂,所使用的通信协议各异,从而使得应用层的数据格式也各不相同。为了帮助用户实现统一数据格式,EMQX Cloud 最近推出了自定义函数功能:根据用户自定义的脚本对设备上报的数据进行预处…

上美股份在港交所上市:预计全年利润下滑,一叶子收入持续走低

12月22日,上海上美化妆品股份有限公司(HK:02145,下称“上美股份”)在港交所上市。本次上市,上美股份的发行价格为25.20港元/股,为此前发行区间的最低值。据此计算,上美股份的募资总额约为9.31亿…

CDH6.3.2集成Apache Atlas2.1.0

1 环境准备 1.1 CDH6.3.2 环境搭建 参考文档如下 Cloudera Manager安装CDH6教程-(一)虚拟环境安装配置 Cloudera Manager安装CDH6教程-(二)搭建Cloudera和CDH6 CM和CDH在安装的时候遇到的问题 CDH6.3.2 各组件版本 1.2 apa…