XX客户端APP签名分析之bp插件打造篇

VSole2021-08-02 19:09:58

前言

本篇主要思路及方法来自于bit4woo和CC11001100两位巨佬的成果。


学习链接https://github.com/bit4woo/burp-api-drops


根据大佬的建议,本次插件使用java进行编写。而且bp插件的编写对于类名也有严格的限制。


主要的调用逻辑如下所示



根据该图,对于插件编写的流程其实也很清楚了,我们只需要先调用这些之前写好的类,然后只需要编写BurpExtender这一个类就好了。


01 热编写流程


首先因为不同网站对应的Key不同,先创建个字典进行存放。


public BurpExtender() {  this.signMap = new ConcurrentHashMap<>();    signMap.put("class.mosaic.cn", "ac6190d7dfaa77df726f0a82244d3eda68675ccd4e95de802f5042e91d15edc7bae3026d8f0fb2a8287446bb289563970264");  signMap.put("bbsapi.mosaic.cn", "Wj8BI3VUZ6BuojAkqzBM3HWHNHv08xdZEtaksbRg6snnuLsvivwa8IvR6PvQ76H0IQQsqkIsa5OKJtg6QcBMfCblMMywgZaA8co");    }


然后是IBurpExtender必须实现的方法registerExtenderCallbacks


@Overridepublic void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {        this.callbacks = callbacks;        callbacks.setExtensionName("xxsign重放辅助渗透");        helpers = callbacks.getHelpers();        stdout = new PrintWriter(callbacks.getStdout(), true);        callbacks.registerHttpListener(this);//如果不注册,processHttpMessage方法不会生效。    }


接下来就是processHttpMessage方法,首先要确定toolFlag,不同的toolFlag代表不同的burp组件,此处我们只处理repeater发出的消息。


if (toolFlag != burp.IBurpExtenderCallbacks.TOOL_REPEATER) {            return;        }        // 只处理请求,响应则忽略        if (!messageIsRequest) {            return;        }        byte[] request = messageInfo.getRequest();        if (request == null || request.length == 0) {            return;        }
        // 只有特定的两个域名才会生效        final IHttpService httpService = messageInfo.getHttpService();        final String host = httpService.getHost();        if (!signMap.containsKey(host)) {            return;        }


接下来是获取参数,由于上一节中已经分析出了参数组成,key是固定值,noncestr是随机生成。timestamp是当前时间戳,因此实际上参数的获取所产生交互是比较少的。只需要生成这些参数的拼接格式,以及SHA1算法。


long now = System.currentTimeMillis();


private static String randomNoncestr() {        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 8; i++) {            char c = (char) (ThreadLocalRandom.current().nextInt(10) + 48);            sb.append(c);        }        return sb.toString();    }


final String sign = DigestUtils.sha1Hex(sb.toString());

最后每次重放就替换掉参数即可。

final IParameter newTimestampParam = helpers.buildParameter("timestamp", now + "", IParameter.PARAM_URL);        final IParameter newSignParam = helpers.buildParameter("sign", sign, IParameter.PARAM_URL);        final IParameter newNoncestrParam = helpers.buildParameter("noncestr", noncestr, IParameter.PARAM_URL);        request = helpers.updateParameter(request, newTimestampParam);        request = helpers.updateParameter(request, newSignParam);        request = helpers.updateParameter(request, newNoncestrParam);        messageInfo.setRequest(request);        stdout.println("更新了sign: " + sign);        stdout.println("更新了timestamp: " + now);        stdout.println("更新了noncestr: " + noncestr);        stdout.println("本次处理完毕");

所有的关键操作就这样完成了。

02 总结

最终BurpExtender类代码

public class BurpExtender implements IBurpExtender, IHttpListener {
    private IBurpExtenderCallbacks callbacks;    private IExtensionHelpers helpers;    private PrintWriter stdout;
    private ConcurrentHashMap signMap;
    public BurpExtender() {        this.signMap = new ConcurrentHashMap<>();        signMap.put("class.mosaic.cn", "ac6190d7dfaa77df726f0a82244d3eda68675ccd4e95de802f5042e91d15edc7bae3026d8f0fb2a8287446bb289563970264");        signMap.put("bbsapi.mosaic.cn", "Wj8BI3VUZ6BuojAkqzBM3HWHNHv08xdZEtaksbRg6snnuLsvivwa8IvR6PvQ76H0IQQsqkIsa5OKJtg6QcBMfCblMMywgZaA8co");    }
    @Override    public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {        this.callbacks = callbacks;        callbacks.setExtensionName("xx客户端sign重放辅助渗透");        helpers = callbacks.getHelpers();        stdout = new PrintWriter(callbacks.getStdout(), true);        callbacks.registerHttpListener(this);    }
    @Override    public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {        // 只处理repeater发出的消息        if (toolFlag != burp.IBurpExtenderCallbacks.TOOL_REPEATER) {            return;        }        // 只处理请求,响应则忽略        if (!messageIsRequest) {            return;        }        byte[] request = messageInfo.getRequest();        if (request == null || request.length == 0) {            return;        }
        // 只有特定的两个域名才会生效        final IHttpService httpService = messageInfo.getHttpService();        final String host = httpService.getHost();        if (!signMap.containsKey(host)) {            return;        }
        stdout.println("检测到,开始处理...");        final IRequestInfo requestInfo = helpers.analyzeRequest(request);        TreeMap signParamsMap = new TreeMap<>();        requestInfo.getParameters().forEach(x -> {            if (IParameter.PARAM_URL != x.getType()) {                return;            }            if ("timestamp".equals(x.getName()) || "sign".equals(x.getName()) || "noncestr".equals(x.getName())) {                return;            }            signParamsMap.put(URLDecoder.decode(x.getName(), UTF_8), URLDecoder.decode(x.getValue(), UTF_8));        });
        String appSignKey = signMap.get(host);        signParamsMap.put("appSignKey", appSignKey);
        long now = System.currentTimeMillis();//        long now = 1626237221383L;        signParamsMap.put("timestamp", now + "");
        String noncestr = randomNoncestr();//        String noncestr = "73699378";        signParamsMap.put("noncestr", noncestr);
        StringBuilder sb = new StringBuilder();        signParamsMap.forEach((key, value) -> {            sb.append(key).append("=").append(value).append("&");        });        if (sb.length() > 0) {            sb.deleteCharAt(sb.length() - 1);        }        stdout.println("用来SHA1加密的字符串: " + sb.toString());        final String sign = DigestUtils.sha1Hex(sb.toString());
        // 替换掉参数        final IParameter newTimestampParam = helpers.buildParameter("timestamp", now + "", IParameter.PARAM_URL);        final IParameter newSignParam = helpers.buildParameter("sign", sign, IParameter.PARAM_URL);        final IParameter newNoncestrParam = helpers.buildParameter("noncestr", noncestr, IParameter.PARAM_URL);        request = helpers.updateParameter(request, newTimestampParam);        request = helpers.updateParameter(request, newSignParam);        request = helpers.updateParameter(request, newNoncestrParam);        messageInfo.setRequest(request);        stdout.println("更新了sign: " + sign);        stdout.println("更新了timestamp: " + now);        stdout.println("更新了noncestr: " + noncestr);        stdout.println("本次处理完毕");



    }
    private static String randomNoncestr() {        StringBuilder sb = new StringBuilder();        for (int i = 0; i < 8; i++) {            char c = (char) (ThreadLocalRandom.current().nextInt(10) + 48);            sb.append(c);        }        return sb.toString();    }
    public static void main(String[] args) {        System.out.println(randomNoncestr());    }
}


stringsign
本作品采用《CC 协议》,转载必须注明作者和本文链接
得益于Unicorn的强大的指令trace能力,可以很容易实现对cpu执行的每一条汇编指令的跟踪,进而对ollvm保护的函数进行剪枝,去掉虚假块,大大提高逆向分析效率。
介绍实战中由于各种情况,可能会对反序列化Payload的长度有所限制,因此研究反序列化Payload缩小技术是有意义且必要的本文以CommonsBeanutils1链为示例,
本篇主要思路及方法来自于bit4woo和CC11001100两位巨佬的成果。学习链接https://github.com/bit4woo/burp-api-drops
JSP Webshell的检测工具
2021-12-13 12:04:53
在11月初,我做了一些JSP Webshell的免杀研究,主要参考了三梦师傅开源的代码。然后加入了一些代码混淆手段,编写了一个免杀马生成器JSPHorse,没想到在Github上已收获500+的Star
它们基于JSON格式,并包含一个令牌签名以确保令牌的完整性。本文主要讨论使用JSON Web令牌的安全隐患,以及攻击者如何利用它们绕过访问控制。有效载荷和签名。
frida复现某app算法
2023-01-11 10:44:51
获取数据某app的登录界面抓包,发现参数都加密了查验一下壳,未加壳,可以进行反编译使用jadx进行反编译,尝试搜索一下参数名”Encrypt”,发现两个JsonRequest类的方法存在运用frida及其下面的代码在java层进行hook,发现只调用了addRequestMap方法Java.perform(function (){. 跟进addRequestMap方法,了解其使用des加密,hook该方法可获取明文及加密结果hook代码Java.perform(function () {
首先使用jadx对apk进行逆向。?搜索关键字 QDSign,可以直接找到对应的类,可以看到参数经过加密得到。??进一步跟踪,发现了c类中有如下三个so方法,还有3个loadlibrary,分别进行了hook,发现c-lib动态注册了sign,sos动态注册了s,没有发现crypto有动态注册。
买车报价APP sign分析
2023-01-12 11:14:54
数字企业壳懂得都懂不可能全部脱下来的只能用哪些类就脱哪些了,略微麻烦点。想着通过url的地址去找对应的发请求的位置是不是可以,于是通过搜索url路径找到了一个类。这是具体的加密方法,没啥难度了。
在火线zone看到利用app历史版本来进行app的逆向分析,可以降低一下分析难度,比较老版本的安全防护做的不是很到位。正好最近有一个app,尝试利用一下老版本进行分析登录签名,没想到效果非常好。
FastJson结合二次反序列化绕过黑名单
VSole
网络安全专家