某APP的sDjcSign加密
1.抓包,经过多次抓包以后得到sDjcSign每次加密结果都不一样,初步怀疑RSA

2.反编译搜索
这结果简单明了啊,就两个,那第一个remove肯定不是了,那就看看第二个。
3.正式开始逆向之旅
可以看到这个sb2是上面sb.toString得来的,那具体内容不知道是什么一会用frIDA看看,我们先看o.a(sb2, “se35d32s63r7m23m”)这个函数是干什么的。
好消息,这就是一个aes加密,那我们先翻译一下代码,现在的代码不就是这样的么
|
1
|
tVar.a("sDjcSign", o.b(o.a(AES(sb2, "se35d32s63r7m23m")))); |
那还有两个参数不知道干什么的对不对,重复刚才的操作,接着看o.a
这个o.a进来以后还调用了一个a,那就继续进这个a
|
1
|
tVar.a("sDjcSign", o.b(RSA(AES(sb2, "se35d32s63r7m23m")))); |
就剩一个o.b了。最后一个了,继续往下看
这个如果看不懂没关系,我们使用frida hook,正好这个sb2这个值也需要用frida去看一下对吧。
|
01
02
03
04
05
06
07
08
09
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
|
function b() { Java.perform(function() { var i = Java.use("com.tencent.djcity.util.o"); i.b.overload('[B').implementation = function (arg1) { console.log('b.arg1 = ' + ByteString.of(arg1).hex()) // console.log('arg2 = ' + arg2) var ret = this.b(arg1) console.log('b.ret = ' + ret) return ret } });}function AES() { Java.perform(function() { var i = Java.use("com.tencent.djcity.util.o"); i.a.overload('java.lang.String','java.lang.String').implementation = function (arg1,arg2) { console.log('AES.arg1 = ' + arg1) console.log('AES.arg2 = ' + arg2) var ret = this.a(arg1,arg2) console.log('AES.ret = ' + ByteString.of(ret).hex()) return ret } });}function main() { AES() b()}main() |
|
1
2
3
4
5
|
AES.arg1 = 8C571443167953BCC67294D143B97FDA+5d73310d28a1a02929aea12667e64edb0dd356c592261249d47bf75e134efe2a+1709772579610+148AES.arg2 = se35d32s63r7m23mAES.ret = 778e7eb1fbad4a871b360bf31dbc5502b3d3c8fcfe60f34b6d7d6f7f1a91fabd04132463e13bc07364588f7a84118593bdb207adefd92823c81d0483319b8b88009c2905303978d2c8fa58480957eb005a73d5cb79a338b9c43fafe0de6c06bde254f1d3ce9d09a723d30c2337be860cb144864c4c69eeb190f1f19b4b6f3196b.arg1 = 20b7bf49b0c8979e04a41474bc74d5acf6efa672a06fe78ea2e415bb929ea20e25a14316f7706e870664b95ba116b35448628b75c776188546b7291c27e05d7d963375c8a8a22e95ab6833a957e75a0f515f1b012f9e1ae6bf49c815c9b09afa1aabea8bb8df1651c073bec595cb235b6f3c6e0f385f291d242c6e2fd185af8d4336b33c2a5d24f7239a4a5d9587dc53acc686e0a2ede36c1d892d804f65d540474256902eca1fd7847fee066c5e2d70371b4e99015afb3c69b7dddfbeac87cc311654dd71ec220b54b84e76ccd46b08b16c71fce279f32a1d9cdb761a00383a8b17b6bb7b36602ffcc4fb2dd1b705530bdb379c3532d2cb22b6fbd89f0aabfab.ret = 20b7bf49b0c8979e04a41474bc74d5acf6efa672a06fe78ea2e415bb929ea20e25a14316f7706e870664b95ba116b35448628b75c776188546b7291c27e05d7d963375c8a8a22e95ab6833a957e75a0f515f1b012f9e1ae6bf49c815c9b09afa1aabea8bb8df1651c073bec595cb235b6f3c6e0f385f291d242c6e2fd185af8d4336b33c2a5d24f7239a4a5d9587dc53acc686e0a2ede36c1d892d804f65d540474256902eca1fd7847fee066c5e2d70371b4e99015afb3c69b7dddfbeac87cc311654dd71ec220b54b84e76ccd46b08b16c71fce279f32a1d9cdb761a00383a8b17b6bb7b36602ffcc4fb2dd1b705530bdb379c3532d2cb22b6fbd89f0aabfa |
我们先看AES.arg1这个是什么意思。这个要结合抓包看,当时我研究了很久这个是啥意思
8C571443167953BCC67294D143B97FDA,这个意思是openid,自己无法生成,系统生成给你的
5d73310d28a1a02929aea12667e64edb0dd356c592261249d47bf75e134efe2a,这个是你的sDeviceID,都是固定的。
1709772579610,这个很明显吧,时间戳148,这个嘛,忘记当时怎么找的了,但是测试的时候感觉所有都可以,那干脆就当他是随机数了。
在看b.arg1和b.ret,注意在frida的js文件中写的脚本,arg1是'[B’,ret是string,那这个函数就是byte2string函数。4.复现加密我们从前面知道了这个参数的各个意思,因为他经过了一个读文件进行rsa加密嘛,所以我选择直接用java写。
|
01
02
03
04
05
06
07
08
09
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
public class test { private static PublicKey RSA() { String baseDir = System.getProperty("user.dir"); byte[] bArr; Exception e; try { InputStream open = new FileInputStream(baseDir + "\\djc_rsa_public_key_new.der"); try { bArr = new byte[open.available()]; do { try { } catch (Exception e2) { e = e2; System.out.println("Got exception while is -> bytearr conversion: " + e); return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(bArr)); } } while (open.read(bArr) != -1); } catch (Exception e3) { e = e3; bArr = null; } return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(bArr)); } catch (Exception e4) { System.out.println("cuole"); return null; } } public static byte[] AES(String str, String str2) throws Exception { if (str == null) { return null; } Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding"); instance.init(1, new SecretKeySpec(str2.getBytes(StandardCharsets.UTF_8), "AES")); return instance.doFinal(str.getBytes(StandardCharsets.UTF_8)); } public static byte[] toRSA(byte[] bArr) throws Exception { Cipher instance = Cipher.getInstance("RSA/ECB/PKCS1Padding"); instance.init(1, RSA()); return instance.doFinal(bArr); } public static String bytesToHex(byte[] bytes) { StringBuilder buf = new StringBuilder(bytes.length * 2); for(byte b : bytes) { // 使用String的format方法进行转换 buf.append(String.format("%02x", Integer.valueOf(b & 0xff))); } return buf.toString(); } public static void main(){ String time = String.valueOf(System.currentTimeMillis()); System.out.println(bytesToHex3(toRSA(AES(openid + "+5d73310d28a1a02929aea12667e64edb0dd356c592261249d47bf75e134efe2a+" + time + "+" + new Random().nextInt(1000),"se35d32s63r7m23m")))); }} |
这时候我们得到了一条加密因为存在RSA了,我们需要发包验证才行,先对比一下长度对不对吧。
一旦您浏览本站,即表示您已接受以下条约:
1.使用辅助可能会违反游戏协议,甚至违法,用户有权决定使用,并自行承担风险;
2.本站辅助严禁用于任何形式的商业用途,若被恶意贩卖,利益与本站无关;
3.本站为非营利性网站,但为了分担服务器等运营费用,收费均为赞助,没有任何利益收益。
死神科技 » 某APP的sDjcSign加密