超星的接口分析了很久,分析到這個接口的時候才想到寫篇博客,之前的一些接口和分析就沒寫下來
先開倆坑在這里,等以后再填
1.如何抓安卓APP上HTTPS的包(需ROOT)
2.如何逆向安卓APP
本次分析的接口是這個
http://data.xxt.aichaoxing.com/analysis/course/tab
參數 u=224217004&sign=task&description=%E4%BB%BB%E5%8A%A1&enc=E783557848978DAFBC36732F63E554E9&personid=243104286&classid=49650050&courseid=220816469
接口大致分析
這個接口在課程頁面點擊tab切換時會被調用一次
先看參數
參數名 | 值 |
---|---|
u | 224217004 |
sign | task |
description | 任務 |
enc | E783557848978DAFBC36732F63E554E9 |
personid | 243104286 |
classid | 49650050 |
courseid | 220816469 |
根據之前抓包的內容可以得到除了enc以外的內容,再看enc長度是32位,可以猜一手MD5
反編譯
反編譯看下代碼
反編譯用了MT管理器
脫殼用了Arm Pro
都是要付費的,怎么操作就省略,相信你們都會
用MT管理器搜索接口關鍵字analysis/course/tab
,只搜索到一個結果,好的開頭是成功的一半
點進去看下,反編譯成,java代碼很明顯代碼被混淆了,
包名都變成了單個的英文字母,先不管,試試繼續分析下去
看到方法上的注解,返回參數還用了泛型,很明顯是Retrofit2框架了,enc參數在這里
手機上截圖有點小,把代碼粘出來
@f(value="analysis/course/tab")
public b<String> a(
@t(value="u") String var1,
@t(value="sign") String var2,
@t(value="description") String var3,
@t(value="enc") String var4,
@t(value="personid") String var5,
@t(value="classid") String var6,
@t(value="courseid") String var7
);
已經找到源頭,那看看哪里會調用這個接口就行了
搜索調用這個類的代碼,看這個類的包名和類名方法名分別是e.g.u.h2.b、d和a
有好幾個同名的重載方法,先不管,搜索smali調用的代碼e/g/u/h2/b;->a
找到了20多個結果,不好辦
看一下這個方法有7個String類型的參數,超過4個參數smali里面就會用invoke-interface/range
調用
用正則來搜索一下代碼invoke-interface/range.*?e/g/u/h2/b/d;->a
結果沒減少多少,還是有21個
不過我們知道參數有7個,看哪里有調用7個參數的方法好了,range后面大括號里的就是參數,v1-v6就是6個參數,快速找一下
還是沒法找出來,不過還有別的方法,搜一下字符串任務
完全匹配,這個是抓包抓到的參數
運氣不錯只搜索到2個結果,看了下第一個沒看出啥,看第二個,很明顯對應的是課程界面的tab,里面還有接口的域名
public void run() throws Throwable {
String string;
String string2;
if (Objects.equals("任務", this.a)) {
string2 = "task";
string = "任務";
} else if (Objects.equals("章節", this.a)) {
string2 = "chapters";
string = "章節";
} else if (Objects.equals("更多", this.a)) {
string2 = "more";
string = "更多";
} else {
string2 = "";
string = "";
}
if (g.b((CharSequence)string)) {
return;
}
String string3 = URLEncoder.encode(string, "utf-8");
string3 = b.a((b)this.f, (String)this.b, (String)string2, (String)string3, (String)this.c, (String)this.d, (String)this.e);
((d)s.a((String)"http://data.xxt.aichaoxing.com/").a(d.class)).a(this.b, string2, string, string3, this.c, this.d, this.e).a((o.d)new a(this));
}
前面的代碼就是接口參數里的sign和description,string2就對應參數里的sign了,string對應參數里的description
先看這兩行
String string3 = URLEncoder.encode(string, "utf-8");
string3 = b.a(
(b)this.f,
(String)this.b,
(String)string2,
(String)string3,
(String)this.c,
(String)this.d,
(String)this.e
);
看前面代碼可以知道這里string是tab的名字,就是任務、章節、更多
這三個其中一個
隨后對string進行了一次url編碼
最后調用了b.a
方法,傳入了7個參數,上下文並不存在名稱為b的對象,因此可以斷定b是一個類名
查看import,定位到了e.g.k.e.b
這個類
點進去查看一下
public static String a(b b2, String string, String string2, String string3, String string4, String string5, String string6) {
return b2.a(string, string2, string3, string4, string5, string6);
}
private String a(String string, String string2, String string3, String string4, String string5, String string6) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(string5);
stringBuilder.append(string6);
stringBuilder.append(string3);
stringBuilder.append(string4);
stringBuilder.append(string2);
stringBuilder.append(string);
stringBuilder.append("qK`b3XjC");
return m.a((String)stringBuilder.toString()).toUpperCase();
}
調用了b2.a
方法,b2的類型是b,其實就是自身了,傳遞了6個參數,也就是調用了下面的a方法
可以看到就是按 5 6 3 4 2 1的順序將參數進行拼接,最后拼上一個鹽,最后調用一個m.a
方法
m.a
其實就是一個md5的方法
根據參數順序,最后可以分析出 string3 = md5(this.e + this.d + string3 + this.c + string2 + this.b + salt)
,其中salt是一個字符串qK`b3XjC
查看代碼發現下面調用了接口
((d)s.a((String)"http://data.xxt.aichaoxing.com/").a(d.class)).a(this.b, string2, string, string3, this.c, this.d, this.e).a((o.d)new a(this));
根據接口定義的參數順序就可以得到這樣一個參數對應表
變量名 | 接口參數名 |
---|---|
this.b | u |
string2 | sign |
string | description |
string3 | enc |
this.c | personid |
this.d | classid |
this.e | courseid |
那么可以得到偽代碼enc = md5(classid + courseid + URLEncoder.encode(description) + personid + sign + u + salt).toUpperCase()
最后根據以上的分析,編寫出對應的代碼,驗證分析結果
和抓包時得到的參數一致。