找到加密的smile具体位置
抓包查看参数
/v2/member?password=abc123456&clientid=1&device_id=865166029891887&ip=172.16.2.15&system_name=android&sign=a6ed53f3ff9ad4fd0727d277711d9c57&siteid=10001&time=1650617846325&type=android&account=18235673456&modules=cloudlogin%3A1
只有sign
是加密的,所以分析sign
就好
搜出来肯定很多,所以我想到了结合链接,找位置
/v2/member
和sign
找了半天,好像都是差不多的地方,于是找到了这里,只有这里最像
以下是我找到的具体代码,有很多跟第一个函数很像的
我的疑问:确定不了的话,只能下断点,hook,但是还有其他方法吗
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| private Params createParams(Params arg8) { if(arg8 == null) { arg8 = new Params(); }
arg8.put("device_id", DeviceUtils.getDeviceId(this.ctMediaCloudConfig.mContext)); arg8.put("clientid", "1"); arg8.put("ip", NetworkUtil.getLocalIP()); long v0 = System.currentTimeMillis(); arg8.put("siteid", this.ctMediaCloudConfig.siteId); arg8.put("system_name", "android"); arg8.put("type", "android"); arg8.put("sign", SignUtil.getSignStr(arg8.getUrlParams(), this.ctMediaCloudConfig.secretSign, v0 + "")); arg8.put("time", v0 + ""); return arg8; }
private Params getRequestParams(Params arg10, String arg11) { Params v1 = new Params(); v1.put("device_id", DeviceUtils.getDeviceId(this.ctMediaCloudConfig.mContext)); v1.put("siteid", this.ctMediaCloudConfig.siteId); v1.put("clientid", "1"); v1.put("ip", NetworkUtil.getLocalIP()); v1.put("system_name", "android"); v1.put("modules", arg11); long v2 = System.currentTimeMillis(); v1.put("type", "android"); Params v0 = new Params(v1.getUrlParams()); v0.putAll(arg10.getUrlParams()); v1.put("sign", SignUtil.getSignStr(v0.getUrlParams(), this.ctMediaCloudConfig.secretSign, v2 + "")); v1.put("time", v2 + ""); return v1; }
|
CTRL+B下断点在每个sign
的地方,例如这样:
然后打开模拟器,点击jeb的debug
附加上了后会出来这么一个界面
然后点击模拟器中的登录
password:abc123456
然后就找到了这里sign
的具体位置
1 2 3 4 5 6 7 8 9 10 11 12 13
| public RequestParams a(RequestParams arg7, Context arg8) { arg7.put("device_id", PhoneInfoUtils.getDeviceId(arg8)); arg7.put("clientid", "1"); arg7.put("ip", AppUtil.getLocalIP()); long v0 = System.currentTimeMillis(); arg7.put("siteid", "10001"); arg7.put("system_name", "android"); arg7.put("type", "android"); arg7.put("sign", b.a(arg7.getURLHashMap(), v0 + "")); arg7.put("time", v0 + ""); return arg7; }
|
总结:我们要找的就是arg7.put("sign", b.a(arg7.getURLHashMap(), v0 + ""));
这一串
函数分析
v0看代码可以知道是时间戳
关键在于分析b.a(arg7.getURLHashMap(), v0 + "")
1.getURLHashMap()
1 2 3
| public HashMap getURLHashMap() { return this.l; }
|
2.arg7应该是前面涉及的集合
3.a()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public static String a(HashMap arg14, String arg15) { LinkedHashMap v8 = new LinkedHashMap(); Object[] v3 = arg14.keySet().toArray(); Arrays.sort(v3); int v11 = v3.length; int v10; for(v10 = 0; v10 < v11; ++v10) { Object v2 = v3[v10]; try { v8.put(v2.toString(), URLEncoder.encode(arg14.get(v2).toString(), "UTF-8")); } catch(UnsupportedEncodingException v0) { v0.printStackTrace(); } }
StringBuilder v5 = new StringBuilder(); Iterator v10_1 = v8.entrySet().iterator(); while(v10_1.hasNext()) { Object v1 = v10_1.next(); if(v5.length() > 0) { v5.append("&"); }
v5.append(((Map$Entry)v1).getKey()); v5.append("="); v5.append(((Map$Entry)v1).getValue()); }
String v9 = v5.toString().replace("*", "%2A").replace("%7E", "~").replace("+", "%20"); crack.log(v9); String v6 = MD5.md5(v9); crack.log(v6); v9 = v6 + "1fa50ba25ed527f3fd1eb9467686f2bb" + arg15; crack.log(v9); String v4 = MD5.md5(v9); crack.log(v4); return v4; }
|
如果分析起来很麻烦,逆向思维,从下往上找,从结果找开始
String v4 = MD5.md5(v9);
v9 = v6 + "1fa50ba25ed527f3fd1eb9467686f2bb" + arg15;
String v6 = MD5.md5(v9);
且 String arg15
String v9 = v5.toString().replace("*", "%2A").replace("%7E", "~").replace("+", "%20");
1 2 3 4 5 6 7 8 9 10 11 12
| StringBuilder v5 = new StringBuilder(); Iterator v10_1 = v8.entrySet().iterator(); while(v10_1.hasNext()) { Object v1 = v10_1.next(); if(v5.length() > 0) { v5.append("&"); }
v5.append(((Map$Entry)v1).getKey()); v5.append("="); v5.append(((Map$Entry)v1).getValue()); }
|
这串代码,大概就是把
{x:1,y:2,z:3}
变为
x=1&y=2&z=3
结果(例如):
v5 = “x=1&y=2&z=3”
v9 = (v5).toString()
v6 = md5(v9)
v9 = v6 + “1fa50ba25ed527f3fd1eb9467686f2bb” + arg15
v4 = md5(md5(v9) + “1fa50ba25ed527f3fd1eb9467686f2bb” + arg15)
然后结合断点,看加密前和加密后的样子,就可以了,不用真的去找参数
4.b
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class b { private static b a;
static { b.a = null; }
public b() { super(); }
public static b a() { if(b.a == null) { Class v1 = b.class; __monitor_enter(v1); try { if(b.a == null) { b.a = new b(); }
__monitor_exit(v1); } catch(Throwable v0) { try { label_13: __monitor_exit(v1); } catch(Throwable v0) { goto label_13; }
throw v0; } }
return b.a; }
|
总结:
arg7.getURLHashMap()
就是对arg7内容进行哈希加密
arg7
目前由以下构成:
device_id
+ PhoneInfoUtils.getDeviceId(arg8)
+ clientid
+ 1 + ip
+ AppUtil.getLocalIP()
+ siteid
+ 10001 + system_name
+ android
+ type
+ android
以上字段加密后 + 时间戳v0 + “” 就是完整字段
然后由b.a()处理,得出sign
然后结合断点,看加密前和加密后的样子,就可以了,不用真的去找参数
下断点开始调试
a.()
里存在两个md5,下断点查看md5前后的值
点击进入下一个断点
这两个断点都是关于v9的,所以看v9的值就好
又因为v9是string类型,当出现以下这个界面时,只要把type
改为string就好,
得到account=2771773446%40qq.com&clientid=1&device_id=865166029891887&ip=172.16.2.15&modules=cloudlogin%3A1&password=abc123456&siteid=10001&system_name=android&type=android
然后跳过两次,查看v6的值
v6:20655d14e9879f20d1c68abc51b8d34b
然后直接跳过下一个断点
因为v9刚刚已经改成string类型,可以直接查看内容
20655d14e9879f20d1c68abc51b8d34b1fa50ba25ed527f3fd1eb9467686f2bb1650868912338
这一串1fa50ba25ed527f3fd1eb9467686f2bb1650868912338
是后边加的东西
1650868912338
就是传入的值(arg15)
然后就是查看v4的值,可以用终端输入readvar v4 string
445bed8c9b9a4bab252c255510233869
这个就是返回的值,跟上边分析的一样。
验证一下,于是网上把字符串md5加密了一下:
学一下log输出(smile插桩)(略)
1.将classes.dex
和classes2.dex
提出来,用apk助手反编译
然后就是要去找到函数所在的类,也就是路径,去用工具输出结果
做好准备工作后, 用apk助手重打包dex
,将dex放回apk中,这里不会改变签名。