不知道从什么时候开始,学校的体育理论考试搞成了下载一个app然后在这上面考。。。本来觉得没什么,然后突然爆出这个app有一坨bug,安卓端多选题只能提交一个答案(后来发现原因是多选题提交答案时的while循环里多写了一个break。。。),导致分数奇低。虽然后来做了一个紧急修复,但从这也能看出开发人员的尿性。。。再后来,有个专门搞app的同学说他能够刷到满分,我稍微想了下,这种考试型app的逻辑能够被破解,无非有两个方法:第一种就是记录所有模拟题库中的题目和答案,然后比对考题进行提交;第二种就是他在把题目发送过来的时候顺带把答案也发送过来了,然后在本地做的成绩校验,最后把结果发回服务器。后来实际操作了下,发现app中的题库在考试阶段是关闭的,那么只就剩下第二种可能了。不得不说开发的同行们也是人才,发送考试卷子还会把答案发过来,而且报文还是明文未加密的,这不是成心勾人犯罪么。。。
这样,思路有了,下面就是操作了。说白了,我们需要做的就是抓包分析,分析他前后台传送的http报文,然后模拟考试。
跟抓网页不一样,这次是抓手机的包,那么就需要用电脑来代理手机的网络,具体做法详见Fiddler代理如何配置。这里讲的很清楚了,不过需要注意的是默认的端口8888可能会被一些程序占用,无法使用的时候换一个端口号即可。
当然首先电脑跟手机得是一个局域网,我这里当然是校园网。
顺便提一句,这个方法还可以用一个网关登陆N多个终端。。。不过目测是分享带宽的。。。
代理配置好之后,打开app,考一次试(这将浪费一次考试机会),记录下fiddler抓到的报文:
request
POST http://appsrv.ihodoo.com/login HTTP/1.1
If-Modified-Since: Sat, 18 Jun 2016 03:36:12 GMT+00:00
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
User-Agent: Dalvik/2.1.0 (Linux; U; Android 5.1.1; Mi-4c MIUI/V7.3.2.0.LXKCNDD)
Host: appsrv.ihodoo.com
Connection: Keep-Alive
Accept-Encoding: gzip
Content-Length: 46
username=17751129083&password=*************** (密码不给看)
respond
{
"uid":"17751129083",
"user_id":39052,
"sno":"1427406034",
"portalUserId":115982,
"isBindSchool":true,
"isMasterMass":false,
"loginStatus":true,
"bindDto":{
"sno":"1427406034",
"name":"丁庆祝",
"school":{
"id":26,
"name":"苏州大学"
},
"schoolId":26,
"schoolName":"苏州大学",
"currentAdclassId":0,
"currentAdclassName":""
},
"token":"afa6da18-0fd2-476c-93df-4a2e3b0263eb"
}
登陆的过程就是把用户名密码post过去,然后他会返回给你一堆信息,这里显示了json数据部分,意思也都很清楚,尤其注意那个token。
request
GET http://appsrv.ihodoo.com/auth/exam/enterIndex?uid=17751129083&token=afa6da18-0fd2-476c-93df-4a2e3b0263eb HTTP/1.1
respond
{
"id" : 10,
"notices" : "",
"startTime" : "2016年06月13日 00时05分",
"endTime" : "2016年06月26日 23时55分",
"totalSubCount" : 50,
"examPaperId" : 318367,
"examPaperName" : "试题来源:篮球21二年级",
"subjectScore" : 2.0,
"studentName" : "丁庆祝",
"studentSno" : "1427406034",
"itemName" : "篮球21",
"examMinutes" : 60,
"isAllowExam" : true,
"isDuring" : true,
"message" : "丁庆祝_篮球21二年级_20160614尚未交卷,请在规定的时间内完成考试!",
"scores" : { }
}
这是进入考试的提醒,把uid和token用Get方法传过去,他会返回你即将得到的考卷的信息,包括某编号(id)、题目数(totalSubCount)、试卷编号(examPaperId)。
request
GET http://appsrv.ihodoo.com/auth/exam/start/10/318367?uid=17751129083&token=afa6da18-0fd2-476c-93df-4a2e3b0263eb&totalCount=50 HTTP/1.1
respond
{
"dtos": [
{
"subName": "在体育锻炼过程中,使外环境与内环境在时间上协调起来,才能达到最佳的体育锻炼效果。",
"subId": 38667,
"sort": 6,
"totalCount": 50,
"options": [
{
"id": 121582,
"optValue": "A",
"optLabel": "√"
},
{
"id": 121583,
"optValue": "B",
"optLabel": "×"
}
],
"answers": [
{
"optionValue": "A"
}
],
"selects": [ ],
"isMarked": false
},
......
......
......
{
"subName": "秋季的人体新陈代谢活动比较弱,对有害物质的抵抗力较低,更容易危害人体健康。",
"subId": 38668,
"sort": 8,
"totalCount": 50,
"options": [
{
"id": 121584,
"optValue": "A",
"optLabel": "√"
},
{
"id": 121585,
"optValue": "B",
"optLabel": "×"
}
],
"answers": [
{
"optionValue": "B"
}
],
"selects": [ ],
"isMarked": false
},
{
"subName": "从文化的视角探讨奥林匹克运动,对___、___、吸收奥林匹克先进文化、加强社会主义精神文明建设,具有重要意义。",
"subId": 39050,
"sort": 29,
"totalCount": 50,
"options": [
{
"id": 122844,
"optValue": "A",
"optLabel": "A 了解奥林匹克运动"
},
{
"id": 122845,
"optValue": "B",
"optLabel": "B 进行奥林匹克比赛"
},
{
"id": 122846,
"optValue": "C",
"optLabel": "C 弘扬奥林匹克精神"
},
{
"id": 122847,
"optValue": "D",
"optLabel": "D 开展奥林匹克教育"
}
],
"answers": [
{
"optionValue": "C"
},
{
"optionValue": "D"
}
],
"selects": [ ],
"isMarked": false
}
],
"message": "",
"isSuccess": true
}
这是获得考卷的过程,把id、examPaperId、uid、token、totalSubCount传过去即可,得到一堆试题。。。。。。这里取三种典型题目,第一个是单选题,第二个是判断题,第三个是多选题。每道题都有题目内容,题目编号,题目顺序(由于json是不保证顺序的,因此需要有个sort来控制顺序)、题目选项、以及题目答案。。。
request
GET http://appsrv.ihodoo.com/auth/exam/select/318367/38861?selectOptions=B,C&token=afa6da18-0fd2-476c-93df-4a2e3b0263eb&uid=17751129083
返回结果大概就是提交成功之类的。
这个过程其实就是把每道题的id、答案加上自己的uid和token一起发过去,非常简单。
request
GET http://appsrv.ihodoo.com/auth/exam/submit/318367?uid=17751129083&token=afa6da18-0fd2-476c-93df-4a2e3b0263eb HTTP/1.1
respond
{
"score" : 6.0,
"times" : 1,
"totalRank" : 0,
"scoreRank" : 11395,
"message" : "试卷提交成功!",
"rankMessage" : "您本次考试成绩还没有以前考得高,需要继续加油!",
"isSuccess" : true
}
套路跟上面一样。。。最后发现我得了6.0分。。。