app 逆向 平头哥实战(某农产品app )
本文由 简悦
SimpRead 转码, 原文地址 mp.weixin.qq.com
转发说明:
本文章对
对平头哥感兴趣的同学,可以添加微信:virjar1,备注平头哥,拉入微信交流群
以下为黑同学对平头哥使用的文章全文:
使用渣总的平头哥对这个
平头哥项目地址:https://github.com/virjarRatel
克隆如下图的项目模板地址:https://github.com/virjarRatel/ratel-module-template
克隆下来之后用
我们通过以下命令来快速创建平头哥项目,因为我是
template.bat -a C:\Users\LEGION\Desktop\ptg2.0\com.nst.android_7.5.5_408308_ratel.apk -m create_nst
命令:template.bat -a 【指定你的
就会生成一个后缀名字为
打开创建好的项目会发现有一些代码逻辑,我们可以给他删除掉编写自己的代码逻辑
样本
平头哥脱壳代码 如图所示 因为脱下来的壳会
public class Unpack {
public static final String tag = "TR_HOOK";
public static void entry(RC_LoadPackage.LoadPackageParam lpparam) {
// TODO 抽取壳要把这个选项打开
// UnPackerToolKit.autoEnable(true);
UnPackerToolKit.unpack(new UnPackerToolKit.UnpackEvent() {
@Override
public void onFinish(File file) {
try {
FileUtils.copyFile(file, new File("/sdcard/nst-unpack.apk"));
} catch (IOException e) {
Log.e(tag, "unpacked error", e);
e.printStackTrace();
}
}
});
}
}
注意:这个
下面安装插件进行脱壳 点击这个按钮等待安装
安装成功之后在会在
下面运行我们写好的插件开始进行脱壳
进入
就会看到脱壳日志
/data/user/0/com.nst.android/files/ratel_unpack/unpacked.apk
可以看到这个有很多
因为我们脱壳代码写的是把脱壳
发现是有这个
如果设置一机多号功能是有一个默认用户(default_0)需要在下面路径下寻找的
也可以直接导出
现在我们开始抓包,为了方便我就先用
下面用平头哥进行抓包和堆栈打印 非常简单建议去看渣总的平头哥的文档
SocketMonitor.setPacketEventObserver(new FileLogEventObserver(new File(RatelToolKit.whiteSdcardDirPath, "socketMonitor")));
默认抓包文件是在
我们对比
因为平头哥下面打印出调用栈了,又是
经过查找果不其然是这个发包函数在下面我们正好看到了有关签名的信息
之前抓包的时候对比过有一个 “x” 的签名我们根据平头哥的调用栈追溯到
具体的签名逻辑就是这个 我们只关心
x:的签名逻辑发现是调用的这个类下的这个方法
再往下追溯就到到了加密实现的类标准的
我们开始
其实到这里我们已经分析的差不多了,现在要做的就是知道她的明文是什么就可以了,我们开始
因为是带壳的
可以看到使用平头哥的插件
最后的明文加密数据就是就是
str:就是时间戳
str2:也是固定值
最后献上平头哥
package ratel.com.nst.android;
import android.util.Log;
import com.virjar.ratel.api.RatelToolKit;
import com.virjar.ratel.api.extension.FileLogger;
import com.virjar.ratel.api.inspect.ClassLoadMonitor;
import com.virjar.ratel.api.rposed.IRposedHookLoadPackage;
import com.virjar.ratel.api.rposed.RC_MethodHook;
import com.virjar.ratel.api.rposed.RposedHelpers;
import com.virjar.ratel.api.rposed.callbacks.RC_LoadPackage;
public class HookNst implements IRposedHookLoadPackage {
private static final String tag = "NST_HOOK";
@Override
public void handleLoadPackage(RC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
Log.i(tag, "start");
ClassLoadMonitor.addClassLoadMonitor("com.nst.android.utils.aes.AESUtils", new ClassLoadMonitor.OnClassLoader() {
@Override
public void onClassLoad(Class<?> clazz) {
Log.i(tag, "find class: " + clazz.getName());
RposedHelpers.findAndHookMethod(clazz, "encrypt",
String.class,
String.class,
new RC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
String arg1 = (String) param.args[0];
String arg2 = (String) param.args[1];
Log.i(tag, "加密前的参数1:" + arg1);
Log.i(tag, "加密前的参数2:" + arg2);
Log.i(tag, "-------------------------");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
String agr3 = (String) param.getResult();
Log.i(tag, "加密后的结果:" + agr3);
}
});
}
});
Log.i(tag, "end");
}
}
最后线上
import base64
from Crypto.Cipher import AES
def AES_Encrypt(key, data):
vi = '0312032293271340'
pad = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16)
data = pad(data)
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
encryptedbytes = cipher.encrypt(data.encode('utf8'))
# 加密后得到的是bytes类型的数据
encodestrs = base64.b64encode(encryptedbytes)
# 使用Base64进行编码,返回byte字符串
enctext = encodestrs.decode('utf8')
# 对byte字符串按utf-8进行解码
return enctext
def AES_Decrypt(key, data):
vi = '0102030405060708'
data = data.encode('utf8')
encodebytes = base64.decodebytes(data)
# 将加密数据转换位bytes类型数据
cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8'))
text_decrypted = cipher.decrypt(encodebytes)
unpad = lambda s: s[0:-s[-1]]
text_decrypted = unpad(text_decrypted)
# 去补位
text_decrypted = text_decrypted.decode('utf8')
return text_decrypted
key = '45ryu230a@n2x302'
data = '1633919358891'
AES_Encrypt(key, data)
enctext = AES_Encrypt(key, data)
print(enctext)
text_decrypted = AES_Decrypt(key, enctext)
print(text_decrypted)
# python实现的算法,和hook出来的是一摸一样的
最后试试请求可以成功不