Frida动静态结合分析Base64签名校验的四个变种

VSole2021-12-12 16:50:22

目标app为algorithmbase_10.apk。

点击CHECK会有加密后的字符串,看样子是Base64编码:

 

用jadx查看源码中关键代码:

 

输出的值由MainActivity类的静态方法encodeFromJni_10生成,该方法需要传入一个16个字符的随机字符串。

encodeFromJni_10是一个native方法:

其实现应该在libnative-lib.so中:

在ida中打开so文件,查看encodeFromJni_10方法的具体实现。

用findcrypt脚本定位到base64编码表:

 

既然能被识别,那应该是个标准的编码表,先从logcat中得到一批参数密文对:

分别放入CyberChef中直接尝试下:

 

 

看起来就是单纯的Base64编码。

为了方便对更多输入值进行确认,写了个frida脚本,将encodeFromJni_10执行后的值和调用Base64.encodeToString后的值进行比较,查看是否相等。

多次测试后发现确实都相等,确定就是标准的Base64编码。

目标app为algorithmbase_11.apk.

打开测试后,和之前的algorithmbase_10.apk结果十分相似,也像是用Base64编码:

直接定位其so中的encodeFromJni_111方法实现.

用findcrypt没有找到可用信息:

但离返回值最近的方法(后面做内存回收的不算)调用中可以发现类似base64编码表的内容:

双击查看完整内容:

 

猜测应该是非标准的base64编码,使用了自定义的编码表,将编码表复制到CyberChef中(还要加上等号):

从logcat中取两个测试案例,验证没有问题。

目标app为algorithmbase_12.apk。

点击测试后发现比之前两个app结果更加杂乱:

 

还是直接查看so文件中对应native方法encodeFromJni_112的实现。发现与之前的111极为相似。而加密的关键函数内部的实现,除了使用的编码表外一模一样。

 

按理说就是使用了另一种自定义编码表的base64编码才对。但是提取出其编码表并放入CyberChef中测试,发现密文结果并不一致。

CyberChef的结果为:

Logcat获取到的实际结果为:

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

会不会是base64编码完后还有什么步骤?还是说传入的参数在base64编码之前有被修改呢?为了确定这点,用frida hook了做base64操作的函数,输出其执行前后参数的内容。 

发现传入的第二个参数就是原始生成的随机字符串,而函数执行完后第一个参数中存放的内容就是最后打印出来的密文。

看来没有什么额外加密步骤。那唯一的变数就是编码表的内容了。会不会是运行的时候编码表被改了呢。直接用一段脚本打印运行时内存中的编码表内容。

发现果不其然和静态看的不一样。

将这段编码表内容放入CyberChef中,就可以得到正确的结果了:

那么编码表是何时被修改的呢?在ida中查找下编码表的引用:

发现有一处指向了另外一个之前没关注到的函数内部。很明显编码表就是在这里做了修改。

 这个方法也是在encodeFromJni_112方法比较前期的地方就被调用。

 

其他应该就没什么问题了。

目标app为algorithmbase_13.apk.

看结果又是变种base64编码的样子:

直接去观察so中native方法encodeFromJni_113用到的编码表:

和12用到的一样,不过测试发现用这个表得到的结果和打印出来的值不一致。猜测又是运行时被修改了。

先用之前的脚本确定没有其他加密过程:

再查看下运行时内存中的编码表内容:

将这部分内容作为编码表,到CyberChef上测试,发现提示编码表长度不对。

检查后发现CyberChef中的base64编码表对‘-’的位置有要求,如果单纯的放在两个字母或者数字中间会被判定为表示区间的字符。可以用’\’进行转义:

但是转完后生成的结果和目标结果不一致:

之前已经用frida hook脚本确定了所有加密只可能在函数sub_8b04中完成,那问题肯定还在这个函数中。

在ida中对照12和13两个apk的sub_8b04函数,发现13的sub_8b04函数中有两行代码与12不一致,多了一步异或操作。这里异或的变量v4值等于传入的第三个参数的值,也就是待编码内容的长度。

看来是base64编码的另一种魔改方式,这在CyberChef上应该是模拟不了了,需要自己实现一段代码。

只需要在标准的base64编码实现上,修改对应的地方即可。

再次运行就可以得到正确的内容了:

base64静态方法
本作品采用《CC 协议》,转载必须注明作者和本文链接
多次测试后发现确实都相等,确定就是标准的Base64编码。发现与之前的111极为相似。
冰蝎流量免杀初探
2022-12-20 09:11:06
本文仅针对冰蝎流量改造进行初步探讨,熟悉一下整个流程,真的要绕流量设备,估计还需要其他的技巧。
企业隔离网络环境中的DNS存在常见错误配置,可能导致气隙网络及其保护的高价值资产面临外部攻击风险。安全验证厂商Pentera的研究人员日前发布文章称,在使用接入DNS服务器的气隙网络时,组织可能会无意间将资产暴露给恶意黑客,并导致严重的数据泄露。而UDP并不具备内置安全机制,因此攻击者才能恶意利用DNS。DNS对所接收的字符类型有所限制,所以攻击一方不可能随意发送字符。
webshell免杀之传参方式及特征绕过传参方式 在这里解释一下为什么,需要讲述传参方式,由于在很多情况下,以请求头作为参数传递并非waf和人工排查的重中之重且非常误导和隐藏
为解决实验室,编辑会话cookie中的序列化对象以利用此漏洞并获得管理权限。然后,删除 Carlos 的帐户。您可以使用以下凭据登录自己的帐户:wiener:peter解决方案此实验与权限提升有关,我们使用bp抓包,重点关注cookie1.登录,查看我的账户页面,bp发现cookie内容是序列化的。在Repeater中替换cookie,已经有了admin权限。
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。 在进行fastjson的漏洞复现学习之前需要了解几个概念,如下:
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
unserialize()函数能够重新把字符串变回php原来的值。为了能够unserialize()一个对象,这个对象的类必须已经定义过。如果序列化类A的一个对象,将会返回一个跟类A相关,而且包含了对象所有变量值的字符串。将对象格式化成有序的字符串。序列化的目的是方便数据的传输和存储,在PHP中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。
2022年5月份Darkreading曾报道,Nozomi Networks公司的研究人员发现,在企业环境中实施域名系统 (DNS)的常见错误配置可能会使气隙网络及其旨在保护的高价值资产面临外部攻击者的风险。
VSole
网络安全专家