您的位置:首页 > 移动开发

破解某APP登录协议并编写批量发包工具

2016-10-12 12:11 225 查看
首先安装apk到手机上,抓取登录包和获取验证码的包。 

获取验证码的包如下:

POST\http://00.00.00.00/v2//mapi/index.php?requestData=eyJhY3QiOiJzZW5kX3Ntc19jb2RlIiwiY2l0eV9pZCI6LTEsImNsYXNzdHlwZSI6MywiY3RsIjoi%0Ac21zIiwiZnJvbSI6ImFuZHJvaWQiLCJtX2xhdGl0dWRlIjoyMi42MDExNzIsIm1fbG9uZ2l0dWRl%0AIjoxMTQuMDExMDI3LCJtb2JpbGUiOiIxODgyMDI5NDM5MSIsInNlc3NfaWQiOiJyZXI2czJybzkw%0AdTE3aTN1dDJzZzlzY2RoMyIsInVuaXF1ZSI6MCwidmVyc2lvbiI6IjEuMS42In0%3D%0A&i_type=0&r_type=1&ctl=sms&act=send_sms_code HTTP/1.1
Content-Length: 0
Host: 00.00.00.00
Connection: Keep-Alive
User-Agent: Mozilla/5.0 (Linux; U; Android 4.4; zh-cn; AOSP on HammerHead Build/KRT16M) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Cookie: PHPSESSID=rer6s2ro90u17i3ut2sg9scdh3
Cookie2: $Version=1
Accept-Encoding: gzip

登录包如下:

POST\http://00.00.00.00/v2//mapi/index.php?requestData=eyJhY3QiOiJkb3BobG9naW4iLCJjaXR5X2lkIjotMSwiY3RsIjoidXNlciIsImZyb20iOiJhbmRy%0Ab2lkIiwiaXNfbG9naW4iOjEsIm1fbGF0aXR1ZGUiOjIyLjYwMTMzMiwibV9sb25naXR1ZGUiOjEx%0ANC4wMTExMjQsIm1vYmlsZSI6IjEzMzE2NDUzNzQ3Iiwic2Vzc19pZCI6InJlcjZzMnJvOTB1MTdp%0AM3V0MnNnOXNjZGgzIiwic21zX3ZlcmlmeSI6IjU2MzM2OSIsInZlcnNpb24iOiIxLjEuNiJ9%0A&i_type=0&r_type=1&ctl=user&act=dophlogin HTTP/1.1
Content-Length: 0
Host: 00.00.00.00
Connection: Keep-Alive
User-Agent: Mozilla/5.0 (Linux; U; Android 4.4; zh-cn; AOSP on HammerHead Build/KRT16M) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
Cookie: PHPSESSID=rer6s2ro90u17i3ut2sg9scdh3
Cookie2: $Version=1
Accept-Encoding: gzip

可以看到"requestData"后那一串字符为加密后的字串,所以我们可以把”requestData”作为关键字,放到androdKiller中进行搜索,搜索结果如下,很多类中都包含了“requestData”关键字,但是我们要搜索的是字符串,所以以此关键字作为函数名的都排除,如下:

然后点击如下按钮查看源码,

到这我准备结合工具jeb一起进行分析,因为androidkiller在把smali反编译成java的时候有些逻辑会比较混乱。

如上图存在几个关键字“i_type”,“r_type”,“ctl”,“act”是不是很熟悉,没错,就在我们开始抓取的post url中“&i_type=0&r_type=1&ctl=sms&act=send_sms_code”所以能看出来,这里就是发送请求之前获取post参数的的函数。"requestData"的值 requestData = SDBase64.encode(json); base64加密得到,而json值是String json =
JsonUtil.object2Json(data);  得到的,而data由 model.getmData()既然找到了关键的函数,那么我们动态调试一下,在“getRequestParams”函数下断,进行单步调度

单步调度之前,我们应该提取smali,并用“IDEA”新建工程把提取的smali所有文件放到src目录下
不会动态调度的同学可以参考前辈写的文章:[smali动态调试教程](http://bbs.pediy.com/showthread.php?t=195660&highlight=idea+apktool)

如下图把所有文件和文件夹复制到"IDEA"工程目录“SRC”目录下。

找到“getRequestParams”函数下断点,然后连接手机通过下面的命令启动app进入等待调试状态

<span style="font-size:14px;">adb shell am start -D -n 包名/第一个activity名称</span>
注:如果显示没有找到手机,请安装手机驱动 

打开ddms可以看到有一个APP前面有一个红色的蜘蛛的标志,其后面就是通信端口,记住待会会用

然后新建远程调试:点击菜单run-> edit configuration->“+”号->Remote,选中第6步中新建的项目,填写刚才看到的端口号

接下来点击:run->debug->unameed待进入如下界面,点击“获取验证码”这里IDEA就会断在我们下断的地方,在下方的“variables”栏中会显示当前方法中的局部“变量名“和“值”

如上图显示 “json”就是请求参数未加密的状态,而”requestData”为加密后的数据,也就是我们开始获取到的url后面“requestData”显示的那一串字符。

找到加密后的字符串后,跟踪一下加密的方法,在“getRequestParams”方法有一条语句“v6=SDBase64.encode(v3)”,显然只是用base64对参数进行简单的加密,然后接下来会把v6的值 添加到v7 中,找到关键的方法后,我们就可以构造我们自己的发包程序。把把关键的函数提取出来 ,
新建一个java工程,提取源代码进修改得到如下代码:

public class main
{
public final String requestData = "1";
public static String jStr = "{\"act\":\"send_sms_code\",\"city_id\":-1,\"classtype\":3,\"ctl\":\"sms\",\"from\":\"android\",\"m_latitude\":22.601172,\"m_longitude\":114.011027,\"mobile\":\"133000000\",\"sess_id\":\"rer6s2ro90u17i3ut2sg9scabc\",\"unique\":0,\"version\":\"1.1.6\"}";

blic static void main(String[] args) {
// TODO Auto-generated method stub
StringBuffer valiteParame = new StringBuffer(getValiteCode("18820294391"));

//System.out.println(sendGet("http://00.00.00.00/v2//mapi/index.php",valiteParame.toString()));;

System.out.println(sendGet("http://00.00.00.00/v2//mapi/index.php",getLoginParam("13300000000","123456").toString()));

}

public static StringBuffer getValiteCode(String PhoneNum){

int i = 76;
String a = "%0A";
String b = "%3D%0A";
String firstString = "{\"act\":\"send_sms_code\",\"city_id\":-1,\"classtype\":3,\"ctl\":\"sms\",\"from\":\"android\",\"m_latitude\":22.601172,\"m_longitude\":114.011027,\"mobile\":\"";
String endString = "\",\"sess_id\":\"rer6s2ro90u17i3ut2sg9scdh3\",\"unique\":0,\"version\":\"1.1.6\"}";

@SuppressWarnings("deprecation")
StringBuffer dataString = new StringBuffer(URLEncoder.encode(encode(firstString + PhoneNum +endString)));

dataString.insert(i, a);
i += 79;
dataString.insert(i, a);
i += 79;
dataString.insert(i, a);
dataString.insert(dataString.length(), a);

return dataString.insert(dataString.length(), "&i_type=0&am
4000
p;r_type=1&ctl=sms&act=send_sms_code");
}

//{"act":"dophlogin","city_id":-1,"ctl":"user","from":"android","is_login":1,"m_latitude":4.9E-324,"m_longitude":4.9E-324,"mobile":"13316453747","sess_id":"rer6s2ro90u17i3ut2sg9scdh3","sms_verify":"123565","version":"1.1.6"}
public static StringBuffer getLoginParam(String phoneNum,String valiteCode){

int i = 76;
String a = "%0A";
String firstString = "{\"act\":\"dophlogin\",\"city_id\":-1,\"ctl\":\"user\",\"from\":\"android\",\"is_login\":1,\"m_latitude\":4.9E-324,\"m_longitude\":4.9E-324,\"mobile\":\"";

String secondString = "\",\"sess_id\":\"rer6s2ro90u17i3ut2sg9scdh3\",\"sms_verify\":\"";

String endString = "\",\"version\":\"1.1.6\"}";

StringBuffer dataString = new StringBuffer(URLEncoder.encode(encode(firstString + phoneNum + secondString + valiteCode + endString)));

dataString.insert(i, a);
i += 79;
dataString.insert(i, a);
i += 79;
dataString.insert(i, a);
dataString.insert(dataString.length(), a);

return dataString.insert(dataString.length(), "&i_type=0&r_type=1&ctl=user&act=dophlogin");
}

public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" +"requestData="+ param;
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/5.0 (Linux; U; Android 4.4; zh-cn; AOSP on HammerHead Build/KRT16M) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1");
connection.connect();
Map<String, List<String>> map = connection.getHeaderFields();
for (String key : map.keySet()) {
System.out.println(key + "--->" + map.get(key));
}
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("∑¢ÀÕGET«Î«Û≥ˆœ÷“Ï≥££°" + e);
e.printStackTrace();
}
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}

public static String encode(String content) {
String v1;
try {
v1 = Base64.getEncoder().encodeToString(content.getBytes("UTF-8"));
}
catch(Exception v0) {
v1 = null;
}
return v1;
}

public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
// ∂®“ÂBufferedReader ‰»Î¡˜¿¥∂¡»°URLµƒœÏ”¶
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("∑¢ÀÕ POST «Î«Û≥ˆœ÷“Ï≥££°"+e);
e.printStackTrace();
}
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  andr android 破解 apk