android 逆向 33 / 38
- app OAuth api_sign 分析
- app sig 参数加密分析 unidbg 模拟黑盒调用
- app sign so 加密参数破解|unidbg
- sgmain x-sign 分析 - unidbg
- androidAsync fridaManager sgmain 70102 rpc 远程调用
- app edata 参数 so aes 加密分析破解|unidbg
- frida 加载 sekiro dex 文件 实现与服务端交互
- frida sekiro 实现 sgmain 70102 远程 rpc 调用
- xposed sekiro hook 获取 wx 万能 key
- unidbg console debugger 使用
- unidbg hook inline hook 使用
- app 公众号文章列表 so 加解密算法分析还原 | 简单分析
- app 公众号文章列表 so 加解密算法分析还原 | 加密 rsa base64 分析
- app 公众号文章列表 so 加解密算法分析还原 | 加密 zip aes 分析
- app 公众号文章列表 so 加解密算法分析还原 | response 内容解密分析
- app sign so 加密算法分析还原|简单分析
- app sign so 加密算法分析还原|so 算法分析
- app sign so 加密算法分析还原|so sub_126AC 函数算法还原
- app so signkeyV1 参数分析
- ida 动态调试 android so 文件|基础入门环境搭建
- app so newSign 参数分析破解
- app tzRgz52a 参数分析破解
- app sign-v2 签名算法 aes 加解密分析
- app so 加密参数分析|protocbuf 分析
- mxtakatak android app 加解密分析
- android app so 加密算法分析破解|mtgsig unidbg
- android app so 加密算法分析破解|siua unidbg
- android app nsign so 加密算法分析
- android app sig 参数 so 加密逻辑逆向分析
- android app so sig 加密参数 unidbg
- 狗狗音乐登陆协议加密参数逆向分析
- android sign so 加密参数分析|unidbg
- android app X-SS-QUERIES 参数分析
- unidbg android app xgorgon 加密参数 leviathan
- sgmain 6.4.x xsign 加密算法分析研究
- sgmain 6.4.x xminiwua 加密算法分析研究
- 某 app mas 算法分析还原 cms so
- 某东登陆协议 tlv 逻辑分析
前言
帮朋友看的一个样本,版本比较老,逻辑也不复杂,这里就简单分享下 so 算法的还原思路
样本下载: https://www.wandoujia.com/apps/35609/history_v7600
charles 抓包
就是这个参数
java 层分析
全局搜索 X-SS-QUERIES
关键词,定位到这里
加密结果是调用的 TTEncryptUtils.a
这个函数获取的
这里调用了 ttEncrypt native
函数,在 ttEncrypt.so
文件里。嗯 java
逻辑就是这么简单
frida hook
function getMapData(mapSet) {
try {
var result = {};
var key_set = mapSet.keySet();
var it = key_set.iterator();
while (it.hasNext()) {
var key_str = it.next().toString();
result[key_str] = mapSet.get(key_str).toString();
}
return result
} catch (error) {
return mapSet
}
}
function bytes2Hex(arrBytes) {
var str = "";
for (var i = 0; i < arrBytes.length; i++) {
var tmp;
var num = arrBytes[i];
if (num < 0) {
tmp = (255 + num + 1).toString(16);
} else {
tmp = num.toString(16);
}
if (tmp.length === 1) {
tmp = "0" + tmp;
}
if (i > 0) {
str += " " + tmp;
} else {
str += tmp;
}
}
return str.replace(' ', '');
}
function bytes2String(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length === 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
try {
str += String.fromCharCode(parseInt(store, 2));
} catch (error) {
str += parseInt(store, 2).toString();
console.log(error);
}
i += bytesLength - 1;
} else {
try {
str += String.fromCharCode(_arr[i]);
} catch (error) {
str += parseInt(store, 2).toString();
console.log(error);
}
}
}
return str;
}
function getProcessId() {
var androidProcess = Java.use('android.os.Process');
return 'processId: ' + androidProcess.myTid() + ' - ';
}
function printLog() {
var result = '';
for (var i = 0; i < arguments.length; i++) {
result += arguments[i] + ' ';
}
console.log(getProcessId(), result)
}
function hook() {
var TTEncryptUtils = Java.use('com.bytedance.frameworks.core.encrypt.TTEncryptUtils');
TTEncryptUtils.a.implementation = function (a, b) {
printLog('TTEncryptUtils.a.a: ', a);
printLog('TTEncryptUtils.a.a: ', bytes2Hex(a));
printLog('TTEncryptUtils.a.b: ', b);
var res = this.a(a, b);
printLog('TTEncryptUtils.a.res: ', res);
printLog('TTEncryptUtils.a.res: ', bytes2Hex(res));
return res;
}
}
function main() {
Java.perform(function () {
hook();
})
}
setImmediate(main);
输入输出都 hook
出来了
unidbg
package com.xiayu.jinritoutiao;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.arm.backend.CodeHook;
import com.github.unidbg.arm.backend.UnHook;
import com.github.unidbg.arm.context.Arm32RegisterContext;
import com.github.unidbg.debugger.Debugger;
import com.github.unidbg.debugger.DebuggerType;
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.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;
import com.xiayu.XiayuUtils;
import jdk.nashorn.internal.runtime.Debug;
import unicorn.ArmConst;
import java.io.File;
import java.io.IOException;
public class TTEncrypt extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
private final DvmClass TTEncryptUtils;
public String apkPath = "/Volumes/T7/android/android-file/jinritoutiao-7.0.6.apk";
TTEncrypt() {
emulator = AndroidEmulatorBuilder.for32Bit().build();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File(apkPath));
DalvikModule dm = vm.loadLibrary("ttEncrypt", true);
module = dm.getModule();
vm.setVerbose(true);
vm.setJni(this);
dm.callJNI_OnLoad(emulator);
TTEncryptUtils = vm.resolveClass("com/bytedance/frameworks/core/encrypt/TTEncryptUtils");
}
public void callFunction() {
String input = "";
ByteArray array = TTEncryptUtils.callStaticJniMethodObject(
emulator, "ttEncrypt([BI)[B",
new ByteArray(vm, input.getBytes()),
input.length()
);
System.out.println(XiayuUtils.bytesToHexString(input.getBytes()));
System.out.println(XiayuUtils.bytesToHexString(array.getValue()));
}
public static void main(String[] args) {
TTEncrypt ttEncrypt = new TTEncrypt();
ttEncrypt.callFunction();
ttEncrypt.destroy();
}
private void destroy() {
try {
emulator.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
unidbg
也是没啥需要补的环境,直接就能跑出结果出来
so 层分析
这里是静态注册的函数,主要关注这两个函数 initKey, ss_encrypt
initKey
函数,静态初始化一些数据
ss_encrypt
函数,逻辑也比较简单,但是有两个 S
盒
了解 AES
算法的小伙伴一眼就能看出来,这是 S 盒跟逆 S 盒
- 但是看代码逻辑,很明显不是
aes
就很奇怪也看不出来是啥,简化版的aes S-AES
的S
盒也不对,有了解的巨佬还望指点一下。这里因为代码逻辑也不是很复杂就直接参照着还原了
so 还原思路
- 我这个只用了一个
S
盒,先定义S, Key
- 这里的
v22 = a3 = key
跟S0
进行置换
- 这里是获取一些水,用于下面的计算
- 这里是明文跟
S0
进行置换
- 这里就是最后的计算逻辑了
最后
逻辑不是很复杂,最后也是成功还原了
我没有名字
2022-02-18你咋这么厉害呢
会爬山的小脑虎
2022-02-18@我没有名字 巨佬怎么说