-
-
[原创]齐齐直播算法解密还原
-
发表于:
2018-8-24 10:16
9208
-
每每看到大佬在刷ollvmp我这个还只会smali层小菜鸡混日子的小菜鸡今天就来刷刷存在感。
h函数经过测试是HashMap,从上方的图看出phone,logintype,password,code这些参数都有了sign呢?我们跟进去看看有什么信息。
继续跟进
到这里已经很明显了检测有没有sign如果没有l.a方法进去处理,我们继续跟进看看。
看到没有map.put()这个方法,从上面一直传下来的hashmap在这里再次的put说明sign值已经被put进去。
我们仔细分析这个函数
齐齐直播是一次偶然的机会让我接触到的。没有太大的难度,加密都是存在于smali层的。so层只是处理其他逻辑的,反正我不懂也没进去看。
GET /mobileuser/user/phonelogin?phone=18077945493&password=p9039942&sign=49B29A29E9563808C074E8153688B0D1738330F9&code=&logintype=1 HTTP/1.1
Referer: http://tiantian.qq.com
mobile: samsung SM-G930F
did: 862453342448758
meck:
oemid: 15
userid: 98535355
platform: 1
network: wifi
cleartext: 1534326647250
version: 1.5.0.0
sy: 5.1.1
fromid:
language: CN
ciphertext: JO4B788C76DCFC23F049F1A9CC63BA39E63SA2
channel: 51
dt: 2
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G930F Build/LMY48Z)
Host: hall-m.qxiu.com
Connection: close
Accept-Encoding: gzip, deflate
首先拿到登录包(哎呀账号密码都放出来了,给你们测试用吧,反正不重要)
Referer: http://tiantian.qq.com
mobile: samsung SM-G930F
did: 862453342448758
meck:
oemid: 15
userid: 98535355
platform: 1
network: wifi
cleartext: 1534326647250
version: 1.5.0.0
sy: 5.1.1
fromid:
language: CN
ciphertext: JO4B788C76DCFC23F049F1A9CC63BA39E63SA2
channel: 51
dt: 2
这些参数必须要有,测试过了,虽然没啥用处但是必须存在,一些参数看看就能出来了。下面是返回包
HTTP/1.1 200 OK
Server: NWSs
Date: Wed, 15 Aug 2018 09:52:00 GMT
Content-Type: application/json;charset=utf-8
Connection: close
X-Daa-Tunnel: hop_count=1
X-NWS-LOG-UUID: 63147941-cec1-4af6-b9fb-8fe5d97a9a24
Content-Length: 258
{
"message": "",
"content": {
"ischannel": 0,
"accesstoken": "18077945493",
"nickname": "",
"navip": ["navigate.qxiu.com"],
"userid": "98535355",
"isnp": 0,
"openid": "18077945493",
"isnew": 0,
"meck": "909516b5ba28ed8374edc72ea4b930d7c4f3cda76e42f5320e14f6182bf772b1"
},
"state": 0
}
返回包一旦不正缺无非就是sign问题,在齐齐中sign占了很大的比分。
GET /mobileuser/user/phonelogin?phone=18077945493&password=p9039942&sign=49B29A29E9563808C074E8153688B0D1738330F9&code=&logintype=1 HTTP/1.1
然后我们在jaxd里面搜索/mobileuser/user/phonelogin
h函数经过测试是HashMap,从上方的图看出phone,logintype,password,code这些参数都有了sign呢?我们跟进去看看有什么信息。
继续跟进
到这里已经很明显了检测有没有sign如果没有l.a方法进去处理,我们继续跟进看看。
看到没有map.put()这个方法,从上面一直传下来的hashmap在这里再次的put说明sign值已经被put进去。
我们仔细分析这个函数
b(d(c(map)) + "&" + "qiqiMobile!)5865#$%^7")
其实还挺简单的,下面只需要把函数拷贝下来带入进去,即可实现加密。然后sign就可以制作出来,达到模拟协议的功能。
下面放入方法,有兴趣的可以带入试试看
public static String a(String str) {
int i = 0;
if (TextUtils.isEmpty(str)) {
return "";
}
try {
MessageDigest instance = MessageDigest.getInstance("MD5");
char[] toCharArray = str.toCharArray();
byte[] bArr = new byte[toCharArray.length];
for (int i2 = 0; i2 < toCharArray.length; i2++) {
bArr[i2] = (byte) toCharArray[i2];
}
byte[] digest = instance.digest(bArr);
StringBuffer stringBuffer = new StringBuffer();
while (i < digest.length) {
int i3 = digest[i] & 255;
if (i3 < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(i3));
i++;
}
return stringBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private static Map<String, String> c(Map<String, String> map) {
HashMap hashMap = new HashMap();
if (map == null || map.size() <= 0) {
return hashMap;
}
for (String str : map.keySet()) {
String str2 = (String) map.get(str);
if (!(str2 == null || str2.equals("") || str.equalsIgnoreCase("sign") || str.equalsIgnoreCase("sign_type"))) {
hashMap.put(str, str2);
}
}
return hashMap;
}
private static String d(Map<String, String> map) {
if (map == null) {
return null;
}
List arrayList = new ArrayList(map.keySet());
Collections.sort(arrayList);
int i = 0;
String str = "";
while (i < arrayList.size()) {
String str2 = (String) arrayList.get(i);
String str3 = (String) map.get(str2);
if (i == arrayList.size() - 1) {
str2 = str + str2 + "="+ str3;
} else {
str2 = str + str2 +"="+ str3 + "&";
}
i++;
str = str2;
}
return str;
}
private static String b(String str) {
if (TextUtils.isEmpty(str)) {
return "";
}
String str2 = "";
try {
MessageDigest instance = MessageDigest.getInstance("SHA-1");
instance.update(str.getBytes("UTF-8"));
byte[] digest = instance.digest();
StringBuffer stringBuffer = new StringBuffer();
for (byte b : digest) {
int i = b & 255;
if (i < 15) {
stringBuffer.append(0);
}
stringBuffer.append(Integer.toHexString(i));
}
return stringBuffer.toString().toUpperCase();
} catch (Exception e) {
e.printStackTrace();
return str2;
}
}
下面放入我制作的小软件测试一下
好了到这里也差不多结束了,解密好这个算法还原成功,很多地方都会用到sign。大家如果有兴趣的话可以加入q群:572186496一起探讨学习。
GET /mobileuser/user/phonelogin?phone=18077945493&password=p9039942&sign=49B29A29E9563808C074E8153688B0D1738330F9&code=&logintype=1 HTTP/1.1
Referer: http://tiantian.qq.com
mobile: samsung SM-G930F
did: 862453342448758
meck:
oemid: 15
userid: 98535355
platform: 1
network: wifi
cleartext: 1534326647250
version: 1.5.0.0
sy: 5.1.1
fromid:
language: CN
ciphertext: JO4B788C76DCFC23F049F1A9CC63BA39E63SA2
channel: 51
dt: 2
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; SM-G930F Build/LMY48Z)
Host: hall-m.qxiu.com
Connection: close
Accept-Encoding: gzip, deflate
首先拿到登录包(哎呀账号密码都放出来了,给你们测试用吧,反正不重要)
Referer: http://tiantian.qq.com
mobile: samsung SM-G930F
did: 862453342448758
meck:
oemid: 15
userid: 98535355
platform: 1
network: wifi
cleartext: 1534326647250
version: 1.5.0.0
sy: 5.1.1
fromid:
language: CN
ciphertext: JO4B788C76DCFC23F049F1A9CC63BA39E63SA2
channel: 51
dt: 2
这些参数必须要有,测试过了,虽然没啥用处但是必须存在,一些参数看看就能出来了。下面是返回包
HTTP/1.1 200 OK
Server: NWSs
Date: Wed, 15 Aug 2018 09:52:00 GMT
Content-Type: application/json;charset=utf-8
Connection: close
X-Daa-Tunnel: hop_count=1
X-NWS-LOG-UUID: 63147941-cec1-4af6-b9fb-8fe5d97a9a24
Content-Length: 258
{
"message": "",
"content": {
"ischannel": 0,
"accesstoken": "18077945493",
"nickname": "",
"navip": ["navigate.qxiu.com"],
"userid": "98535355",
"isnp": 0,
"openid": "18077945493",
"isnew": 0,
"meck": "909516b5ba28ed8374edc72ea4b930d7c4f3cda76e42f5320e14f6182bf772b1"
},
"state": 0
}
返回包一旦不正缺无非就是sign问题,在齐齐中sign占了很大的比分。
GET /mobileuser/user/phonelogin?phone=18077945493&password=p9039942&sign=49B29A29E9563808C074E8153688B0D1738330F9&code=&logintype=1 HTTP/1.1
然后我们在jaxd里面搜索/mobileuser/user/phonelogin
h函数经过测试是HashMap,从上方的图看出phone,logintype,password,code这些参数都有了sign呢?我们跟进去看看有什么信息。
继续跟进
到这里已经很明显了检测有没有sign如果没有l.a方法进去处理,我们继续跟进看看。
看到没有map.put()这个方法,从上面一直传下来的hashmap在这里再次的put说明sign值已经被put进去。
我们仔细分析这个函数
b(d(c(map)) + "&" + "qiqiMobile!)5865#$%^7")
其实还挺简单的,下面只需要把函数拷贝下来带入进去,即可实现加密。然后sign就可以制作出来,达到模拟协议的功能。
下面放入方法,有兴趣的可以带入试试看
public static String a(String str) {
int i = 0;
if (TextUtils.isEmpty(str)) {
return "";
}
try {
MessageDigest instance = MessageDigest.getInstance("MD5");
char[] toCharArray = str.toCharArray();
byte[] bArr = new byte[toCharArray.length];
for (int i2 = 0; i2 < toCharArray.length; i2++) {
bArr[i2] = (byte) toCharArray[i2];
}
byte[] digest = instance.digest(bArr);
StringBuffer stringBuffer = new StringBuffer();
while (i < digest.length) {
int i3 = digest[i] & 255;
if (i3 < 16) {
stringBuffer.append("0");
}
stringBuffer.append(Integer.toHexString(i3));
i++;
}
return stringBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
private static Map<String, String> c(Map<String, String> map) {
HashMap hashMap = new HashMap();
if (map == null || map.size() <= 0) {
return hashMap;
}
for (String str : map.keySet()) {
String str2 = (String) map.get(str);
if (!(str2 == null || str2.equals("") || str.equalsIgnoreCase("sign") || str.equalsIgnoreCase("sign_type"))) {
hashMap.put(str, str2);
}
}
return hashMap;
}
private static String d(Map<String, String> map) {
if (map == null) {
return null;
}
List arrayList = new ArrayList(map.keySet());
Collections.sort(arrayList);
int i = 0;
String str = "";
while (i < arrayList.size()) {
String str2 = (String) arrayList.get(i);
String str3 = (String) map.get(str2);
if (i == arrayList.size() - 1) {
str2 = str + str2 + "="+ str3;
} else {
str2 = str + str2 +"="+ str3 + "&";
}
i++;
str = str2;
}
return str;
}
private static String b(String str) {
if (TextUtils.isEmpty(str)) {
return "";
}
String str2 = "";
try {
MessageDigest instance = MessageDigest.getInstance("SHA-1");
instance.update(str.getBytes("UTF-8"));
byte[] digest = instance.digest();
StringBuffer stringBuffer = new StringBuffer();
for (byte b : digest) {
int i = b & 255;
if (i < 15) {
stringBuffer.append(0);
}
stringBuffer.append(Integer.toHexString(i));
}
return stringBuffer.toString().toUpperCase();
} catch (Exception e) {
e.printStackTrace();
return str2;
}
}
下面放入我制作的小软件测试一下
好了到这里也差不多结束了,解密好这个算法还原成功,很多地方都会用到sign。大家如果有兴趣的话可以加入q群:572186496一起探讨学习。
Referer: http://tiantian.qq.com
mobile: samsung SM-G930F
did: 862453342448758
meck:
oemid: 15
userid: 98535355
platform: 1
network: wifi
cleartext: 1534326647250
version: 1.5.0.0
sy: 5.1.1
fromid:
language: CN
ciphertext: JO4B788C76DCFC23F049F1A9CC63BA39E63SA2
channel: 51
dt: 2
这些参数必须要有,测试过了,虽然没啥用处但是必须存在,一些参数看看就能出来了。下面是返回包
HTTP/1.1 200 OK
Server: NWSs
Date: Wed, 15 Aug 2018 09:52:00 GMT
Content-Type: application/json;charset=utf-8
Connection: close
X-Daa-Tunnel: hop_count=1
X-NWS-LOG-UUID: 63147941-cec1-4af6-b9fb-8fe5d97a9a24
Content-Length: 258
{
"message": "",
"content": {
"ischannel": 0,
"accesstoken": "18077945493",
"nickname": "",
"navip": ["navigate.qxiu.com"],
"userid": "98535355",
"isnp": 0,
"openid": "18077945493",
"isnew": 0,
"meck": "909516b5ba28ed8374edc72ea4b930d7c4f3cda76e42f5320e14f6182bf772b1"
},
"state": 0
}
返回包一旦不正缺无非就是sign问题,在齐齐中sign占了很大的比分。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-5-29 18:33
被飞翔的小菜鸟编辑
,原因: