逆向so_某一次APP的so层算法逆向
“ 前言:初学逆向 请多多指教”
01
—
这里直接通过雷电模拟器进行抓包,app登陆口如下:

发现这个app是不走代理的流量的,一般这里的解决方法可以对app的Http请求框架进行hook或者是进行全局抓包,这里使用的是HttpAnalyzer工具进行抓包
POST /login?vno=4.3.0 HTTP/1.1Content-Type: application/x-www-form-urlencoded; charset=UTF-8Connection: Keep-AliveCookie: acw_tc=76b20ffb16013794385115226e24d8b09a821decabf8df74edf907e1974f93Cookie2: $Version=1Accept-Encoding: gzip, deflateContent-Length: 213data={"user_name":"19817353426","password":"1352483351"}&sign=33B71735C957E28217BE2FD72082CFD1&channel=360_25&client=android&type=1&deviceid=865166020084722×tamp=1601379470963&token=
观察可知是一个POST数据包,并且有对应的签名参数,所以需要进行逆向来分析这个数据包
sign=33B71735C957E28217BE2FD72082CFD1
这里直接拖进JEB进行反编译来进行查看,因为是login的活动处,所以尝试直接去login的的活动处进行寻找,发现找了半天混淆的代码不好看,跟到最后发现也没找到啥,于是直接搜索字符串关键词sign,发现相关的sign的字符串很多,那只能一个一个慢慢看了,如下是最一开始找的:
com.XXXX.XXX.ui.widget.webview.a 函数
public void a(SignParams arg7) { String v1 = ""; String v0 = ""; if(Login相关.getInstsance().getLoginResultBool()) { v1 = String.valueOf(Login相关.getInstsance().getLoginResult().user_id); // v1为当前user_id的值 v0 = Login相关.getInstsance().getLoginResult().token; // // v0为当前user_token的值 } this.a(arg7.callback, "{\"sign\":\"" + SignManager.getSign(v1, v0, arg7.timestamp + "") + "\"}"); }
继续走,SignManager.getSign(v1, v0, arg7.timestamp + "")这个的实现是在so层的,先继续跟SignManager类
public class SignManager { static { System.loadLibrary("wtf"); } public static native String getSign(String arg0, String arg1, String arg2) { }}
静态代码块加载wtf.so文件,然后getSign是native的函数,那么就需要分析wtf.so的文件了

函数窗口如下:

可以发现确实是存在的

这里为了方便观察可以还原JNI函数方法名

MD5Digest(v18, v23, &v33);
继续观察日志:
_android_log_print( 6, "theCover", "app sign :%s \naccount : %s\ntoken : %s\nts : %s\nsrc %s \n result %s", the_sign, user_id_1, user_token_1, timestamp_1, md5_value, &Fina_Md5_String);10-02 20:52:17.533: E/theCover(2782): app sign :0093CB6721DAF15D31CFBC9BBE3A2B7910-02 20:52:17.533: E/theCover(2782): account : 10-02 20:52:17.533: E/theCover(2782): token :10-02 20:52:17.533: E/theCover(2782): ts : 1601643137533 // 原md5加密 06f67a7b9c4f432261bffd893c50d57510-02 20:52:17.533: E/theCover(2782): src 0093CB6721DAF15D31CFBC9BBE3A2B79160164313753310-02 20:52:17.533: E/theCover(2782): result 6C15C455919F98E70763D893A73888E3
可以发现:
0093CB6721DAF15D31CFBC9BBE3A2B79+当前时间戳
进行md5得到最终的数据包中的sign
6C15C455919F98E70763D893A73888E3
public static String getAppSign() { String v0_2; try { Signature[] v1 = CGApplication.a().getPackageManager().getPackageInfo("com.XXXX.XXX", 64).signatures; StringBuilder v2 = new StringBuilder(); int v3 = v1.length; int v0_1; for(v0_1 = 0; v0_1 < v3; ++v0_1) { v2.append(v1[v0_1].toCharsString()); } v0_2 = LogShutDown.shut(v2.toString()); } catch(Exception v0) { v0.printStackTrace(); y.a("getAppSign", "Exception:" + v0); v0_2 = ""; } return v0_2; }这里就看到了一段如下代码,可以发现是跟 PackageManager对象有关系的,该对象可以获取当前APP的相关信息等等
Signature[] v1 = CGApplication.a().getPackageManager().getPackageInfo("com.XXXX.XXX", 64).signatures;v0_2 = LogShutDown.shut(v2.toString()); //
getPackageInfo的第二个参数为64则是获取相关的signatures

那么sign的加密方法就是:MD5(MD5(当前app的signatures) + 当前时间戳))
然后最后面发现的其实还有个Http请求的实体类,这里面正好描述了Http所用到的参数
com.XXXX.XXX.data.entity; public HttpRequestEntity(Context arg5, HashMap arg6) { super(); this.token = ""; String v1 = arg5.getString(2131296456); String v0 = ""; if(Login相关.getInstsance().getLoginResultBool()) { v0 = String.valueOf(Login相关.getInstsance().getLoginResult().user_id); this.token = Login相关.getInstsance().getLoginResult().token; } this.timestamp = String.valueOf(new Date().getTime()); this.sign = this.getSign(v1, v0, this.token, this.timestamp); this.data = new e().a(arg6); this.client = "android"; this.vno = "4.3.0"; this.deviceid = u.a(arg5); this.channel = com.XXXX.XXX.util.e.a(arg5); this.type = 1; }
因为还不太会hook所以这里没有尝试进行hook,后面的文章都会慢慢来写的,谢谢大家观看文章了!

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)