app 公众号文章列表 so 加解密算法分析还原 | 简单分析

android 逆向 12 / 38

仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。

const 龙哥 = Function() {}

const a = 全能的傻宝,每天都会换一种姿势来分享各种操作,最近 10 月在分享密码学;
const b = 点击加入星球;
return "无敌的龙哥";

前言

最近在学习 so 加解密逆向分析,算法还原,就拿星主分析过的一个样本来练手,那个星主?
当然是 call 龙哥 ();

样本

某狗搜索 app 版本 7.9.6.6 主要分析 wx 公众号文章请求参数的加解密

以上是抓包截图,请求跟响应都是加密串,主要是分析这些

jadx 分析

jadx-gui 打开之后,开始搜索,这里因为请求没啥关键字,搜索 url 即可,出来一个结果点进去看看

这里调用了两个函数 encrypt dencrypt 应该就是加解密了,跳转到声明函数的地方

进来发现全部是 navite 函数,这里加载了一个 so 文件,navite 的实现应该就在这里
使用 ida 打开看一下

ida 分析

打开 ida -> exports 窗口,搜索 java 发现这里是静态注册的函数,刚好对应 java 层的四个函数
先分析到这里,下篇文章在分析 so 具体的算法实现,下面使用 frida hook 验证一下

frida hook

function hook() {
    var ScEncryptWall = Java.use('com.sogou.scoretools.ScEncryptWall');

    ScEncryptWall.decrypt.implementation = function (a) {
        console.log('decrypt.a: ', a);

        var res = this.decrypt(a);
        console.log('decrypt.res: ', res);
        console.log('decrypt.res: ', Java.use('java.lang.String').$new(res));

        return res;
    }

    ScEncryptWall.encrypt.implementation = function (a, b, c) {
        console.log('encrypt.a: ', a);
        console.log('encrypt.b: ', b);
        console.log('encrypt.c: ', c);

        var res = this.encrypt(a, b, c);
        console.log('encrypt.res: ', res);

        return res;
    }
}

function main() {
    Java.perform(function () {
        hook();
    })
}

setImmediate(main);

结果全部 hook 出来了,跟抓包结果对比是一样的,在使用 unidbg 跑起来

unidbg

package com.xiayu.sougou;

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
import com.github.unidbg.debugger.Debugger;
import com.github.unidbg.hook.hookzz.HookZz;
import com.github.unidbg.hook.hookzz.IHookZz;
import com.github.unidbg.hook.xhook.IxHook;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.XHookImpl;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.memory.Memory;
import com.sun.jna.Pointer;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

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

    public String apkPath = "/Users/admin/Desktop/android/file/sougou-7.9.6.6.apk";
    public String soPath = "unidbg-android/src/test/resources/test_so/sougou/libSCoreTools-7.9.6.6.so";

    private static LibraryResolver createLibraryResolver() {
        return new AndroidResolver(23);
    }

    private static AndroidEmulator createARMEmulator() {
        return AndroidEmulatorBuilder
                .for32Bit()
//                .setProcessName("com.sogou.activity.src")
//                .setRootDir(new File("appFile/sougou-7966"))
                .build();
    }

    public SouGou() {
        emulator = createARMEmulator();
        final Memory memory = emulator.getMemory();
        memory.setLibraryResolver(createLibraryResolver());

        vm = emulator.createDalvikVM(new File(apkPath));
        vm.setVerbose(true);
        DalvikModule dm = vm.loadLibrary(new File(soPath), false);
        vm.setJni(this);

        dm.callJNI_OnLoad(emulator);
        module = dm.getModule();
    }

    public void encrypt() {
        List<Object> list = new ArrayList<>(10);
        list.add(vm.getJNIEnv());
        list.add(0);

        list.add(vm.addLocalObject(new StringObject(vm, "http://app.weixin.sogou.com/api/searchapp1")));
        list.add(vm.addLocalObject(new StringObject(vm, "type=2&ie=utf8&page=2&query=python&select_count=0&usip=1")));
        list.add(vm.addLocalObject(new StringObject(vm, "")));
        Number number = module.callFunction(emulator, 0x9CA0 + 1, list.toArray())[0];

        System.out.println("encrypt: " + vm.getObject(number.intValue()).getValue().toString());
    }

    public static void main(String[] args) throws IOException {
        SouGou sougou = new SouGou();
        sougou.encrypt();
        sougou.destroy();
    }

    private void destroy() throws IOException {
        emulator.close();
    }
}

以上就全部代码跑起来

代码跑起来但是结果为空,应该是哪里有问题
回去看下 so 发现有个 init 函数,应该就是初始化,先调用 init

public void init() {
    DvmClass Context = vm.resolveClass("android/content/Context");

    List<Object> list = new ArrayList<>(10);
    list.add(vm.getJNIEnv());
    list.add(0);
    list.add(vm.addLocalObject(Context.newObject(null)));
    Number number = module.callFunction(emulator, 0x9564 + 1, list.toArray())[0];

    System.out.println("init: " + number.intValue());
}

在运行结果就正常出来了

4 条评论
本文作者:
本文链接: https://www.qinless.com/?p=483
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 qinless 的博客!
100

4 条评论

tencent

大哥,能分享一下算法吗

回复

会爬山的小脑虎

@tencent 联系博主 wx:2027762055

回复

pyj

这个返回的是什么数据呢

回复

会爬山的小脑虎

@pyj 这是分析 so 加密参数的逻辑哦

回复

发表评论

返回顶部