APP签名算法提取之曲线救国
本帖最后由 n0elle 于 2017-2-26 00:17 编辑现在,绝大多数apk在数据签名验证方面,采用了jni+so的方式增加安全性。
上次遇到一个app,360加固+native签名算法函数,这里不对脱壳做过多的描述。
用Charles对app进行抓包,多次抓包发现FuncTag是每个事件处理函数的一个标识,用于区分请求的模块功能。
发现有一个参数sv,应该是数据的签名字段,应该就是我们的目标。
在Android Killer打开工程,搜索40000020的16进制0x2625A14 定位到该处。
计算sv的区域,包名已经除去。
new-instance v0, Ljava/lang/StringBuilder;
invoke-direct {v0}, Ljava/lang/StringBuilder;-><init>()V
const-string v1, "a:"
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
sget v1, Lcom/xxxx/xxxx/a/g;->d:I
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v0
const-string v1, "c"
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v1, ":"
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
.line 4636
invoke-static {}, Lcom/xxxx/xxxx/y;->d()Lcom/xxxx/xxxx/y;
move-result-object v1
invoke-virtual {v1}, Lcom/xxxx/xxxx/y;->ap()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
/*
省略部分
*/
.line 4643
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
const-string v2, ""
invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v1
invoke-static {}, Lcom/xxxx/xxxx/y;->d()Lcom/xxxx/xxxx/y;
move-result-object v2
invoke-virtual {v2}, Lcom/xxxx/xxxx/y;->aB()J
move-result-wide v2
invoke-virtual {v1, v2, v3}, Ljava/lang/StringBuilder;->append(J)Ljava/lang/StringBuilder;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v1
invoke-static {v0, v1}, Lcom/xxxx/xxxx/utils/EncodeString;->EncodeMD5(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
在这里可以看出,sv的计算方法是把每个参数按照一定的顺序排列拼接起来,再进行EncodeMD5。
转换成java代码验证一下,没有错。 Object localObject = "a:" + com.xxxx.xxxx.a.g.d + "c" + ":" + com.xxxx.xxxx.y.d().ap();
localObject = (String)localObject + "FuncTag" + ":" + 40000020;
localObject = (String)localObject + "ir" + ":" + paramInt2;
localObject = (String)localObject + "phoneNum" + ":" + paramString;
localObject = (String)localObject + "platform" + ":" + 2;
localObject = (String)localObject + "smsType" + ":" + paramInt1;
String str = EncodeString.EncodeMD5((String)localObject + "userId" + ":", "" + com.xxxx.xxxx.y.d().aB());
str 就是我们要的sv值,他是通过EncodeString类里的EncodeMD5方法来加密的,跟过去看看。
发现都是static native的方法。
.method public static native EncodeMD5(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
.end method
.method public static native EncodeMD5ByByte([BLjava/lang/String;)Ljava/lang/String;
.end method
.method public static native EncodeUserNameAndPassword(Ljava/lang/String;)Ljava/lang/String;
.end method
继续找下,看下是加载哪个so库。
搜索关键字 loadLibrary ,发现在app初始化时加载了两个动态库,很明显,EncodeString类应该在encode这个动态库里面。
private static void b(Context paramContext)
{
int i = Build.VERSION.SDK_INT;
y.a(d, "loadSo , SDK Version: " + i);
System.loadLibrary("encode");
System.loadLibrary("game");
}
找到so文件拖入IDA,搜索 encode。
看了很久不是很明白他的算法到底是怎么实现的,他修改了MD5的算法,并不是一般的(数据+key)再进行原生的MD5加密。
在导出表里面发现这几个导出函数,想到了一个办法。
找到了函数注册到java里的包名,这里就跟上面在java代码里面看到的包名路径是一样的。
打开Android Studio,新建一个项目。
在main下新建jniLibs目录,把上面的so库放入armeabi中
在上面jni映射过来的方法在com.xxxx.engine.utils中,这里新建一个包,包名路径相同。
写一个EncodeString类,函数申明在上面反编译出来的代码里面已经有了,直接照搬过来。
在函数前装载so库
static {
System.loadLibrary("encode");
}
在Oncreate下面调用EncodeMD5方法,debug打印出来。
运行一遍,看调试器里面,so已经加载成功。
String str = EncodeString.EncodeMD5((String)localObject + "userId" + ":", "" + com.xxxx.xxxx.y.d().aB());
最后按照原来的参数打印出来sv。其实这样相当于是曲线救国,可以把一台手机用于签名,连接电脑进行生产工作。
但是这样的效率相对来说低一点,对模拟器的兼容也不太好。
所以只能当做下下策来使用。 n0elle 发表于 2017-2-27 13:23
其实,我发出来也是想学习下各位大神在处理相似问题时的应对方法,但是好像大神并不在:-(
大神都 是忙的,但是你我要想成大神只有不断摸索了
zxg1987 发表于 2017-2-27 13:04
希望可以有更好 的方法发出来
其实,我发出来也是想学习下各位大神在处理相似问题时的应对方法,但是好像大神并不在:-( 不明觉厉!!!!!!!!!!!!! 谢谢分享 过来瞅瞅 感谢分享,支持~ 很是厉害 很是厉害 有意思。 感谢分享,长知识 涨姿势啊 谢谢分享