前言
声明,本文与该软件仅用于学习技术交流,请勿将软件用于非法途径,本作者不承担一切法律责任,望使用者须知。若影响到贵公司正常运行,请联系本人删除。
使用语言
有人会很好奇这个软件到底是怎么运行的,为啥可以实现自动完成视频,作业。借此写个完整的该软件开发过程,供各位学习,整个开发过程真不算的难,听我慢慢道来(尽可能详细),但你看完后,写不出来,大概率也不会想写。
既然是写软件,那怎么能不说说编程语言,首先这个软件是基于易语言开发的,初学易语言的三个月所写的练手项目,本是写来给我自用的,不过确实好用,那为啥不分享出去呢。
实际上我也考虑过开源,奈何多次审核不通过,累了,就懒得 开源了。
首先,说说为啥会选择易语言,有一部分原因是因为我那时候正好在学易语言,哪怕现在如果要开发一个类似于这样的软件,我也会优选易语言(在不考虑兼容与报毒情况下)。原因其实非常简单,好写,太好写了,我记得那时候的第一版超星刷课只花了一周时间,实现了自动完成视频,那还只是我没什么开发经验的前提下(借鉴了外面的一份源码)。再者也是最主要的一部分,写的软件是基于什么平台,很显然,桌面级应用 Windows 平台。那就少不了交互界面了,而正是这个交互界面,让我劝退了 javascrpit 与 python。不是说他们不行,而是写起来绝对比易语言复杂。如果你有接触过这两者相关的估计会知道,尤其还是实现自动完成任务的功能,基本上是不提供界面而言。也就让代码的可操作性少了非常多,这还不是最致命的,致命的是使用者不是人人都学程序了,即使发你一个 python 文件,但他大概率是不会听你大费周章的安装,输入,原因就是麻烦(如果这份代码好用的话当我没说过)。
说这些都不如直接来一个 exe 可执行文件,让用户去点击操作,然后通过一个日志输出显示给用户,告知用户当前程序执行进度。可能有人又会问,那为啥不用 C#,VB.net,QT 等,我 tm 要是会的话,也不会用易语言来写了,易语言敲代码体验很差,如果用过其他的文本编辑器,就特别不想用易语言(反正我是这样,真的难用),毕竟易语言都是 20 年前的产物了,能活到现在就不错了。但不得不说,易语言是真的好写,好用,好上手。
语言不分贵贱,能写出好的程序都是好语言,所以本文都是以本人从易语言开发角度来讲述,如果你恰好有程序开发经验,或有想接触的,本文或许能给予你一些帮助。
找源码
既然介绍完所用语言,那么就开始编写代码吧,不过在此之前先别急,这一步尤为关键,能极大的节省你所开发的效率,那就是搜索是否的相关源码或者软件。最好是与自己所开发的语言一致。
这是我当时编写软件前在吾爱破解论坛上搜索到的相关源码,如下:
看看软件源码的界面
在比对一下我的修改了数十次的。
没错,我就是基于这个软件改的,还是有点相似之处的。但事实上这个原作者的代码在我翻阅到时就已经不能用了,并且还有很多弊端,例如还需要输入学校名称,输入验证码,这对用户体验来说的是非常烦人的。
同时在这份源码上只能说是一份临时品,几乎没有维护可言(虽然易语言写的软件多半都不好维护),不过有一个核心加密算法,也就是最终提交视频的一个核心算法,让我省去 JS 逆向分析的时间(后文会说到,不过以我那时候来看,这个 JS 自行解决也不成问题)
那时候搜索到的还有其他的相关脚本,例如大多数人都了解过的油猴插件。后文有简单讲述到,因为和本文涉及到的不相关。
执行流程
找到相关源码或软件,就已经离项目完成快了一半了,接着只需要在该软件上进行修改,已达到自己的目的。当然,如果要补充一些功能还需要花费很多时间的。
页面设计
我优先做的就是修改 UI 界面,做到竟可能的不丑,且符合个人风格。而这部分就是拖拽组件,移动组件,微调组件,平行垂直等操作,没啥可言的。我所用的都是 windows 自带的组件,加上我不会自绘组件,只好借助皮肤模块来美化界面了。美化的效果如下图
实际上,页面设计相关就到此结束了,我能做的也只是尽量不丑,毕竟不会自绘组件,用原生自带的组件就这样了。当然,后面关于怎么数据渲染到组件这些会写到的。
登录
接着就是要说实现原理,首先回想一下,我们如果手动去一个个看视频,答题,需要干嘛,那肯定是登录了,不登录学习通那边怎么知道是你,那么在浏览器中,登录只是输入下账号,密码,然后点击登录按钮就完事了。然而实际原理不只是点击按钮这么简单,实则是发送一个 http 请求给后端,后端进行效验结果比对,返回结果,我简单叙述一下,放 js 代码来看看:
具体看图片
完整关键代码如下:(已删除不必要代码)
//手机号+密码登录
function loginByPhoneAndPwd() {
var phone = $('#phone').val().trim()
var pwd = $('#pwd').val()
var fid = $('#fid').val()
var refer = $('#refer').val()
if (util.isEmpty(phone)) {
util.showMsg(true, 'phoneMsg', '请输入手机号', true)
return
}
if (util.isEmpty(pwd)) {
util.showMsg(true, 'pwdMsg', '请输入密码', true)
return
}
var t = $('#t').val()
if (t == 'true') {
pwd = $.base64.btoa(pwd, 'UTF-8')
}
// --------------------------------------------------------
$.ajax({
url: '/fanyalogin',
type: 'post',
dataType: 'json',
data: {
fid: fid,
uname: phone,
password: pwd,
refer: refer,
t: t,
},
success: function (data) {
if (data.status) {
var url = ''
if (data.tochaoxing) {
var path = window.location.protocol + '//' + window.location.host
url =
path +
'/towriteother?name=' +
encodeURIComponent(data.name) +
'&pwd=' +
encodeURIComponent(data.pwd) +
'&refer=' +
data.url
} else {
url = decodeURIComponent(data.url)
}
if (top.location != self.location && $('#_blank').val() == '1') {
top.location = url
} else {
window.location = url
}
} else {
if (data.weakpwd) {
window.location =
'/v11/updateweakpwd?uid=' +
data.uid +
'&oldpwd=' +
encodeURIComponent($('#pwd').val()) +
'&refer=' +
refer
} else {
var msg = util.isEmpty(data.msg2) ? '登录失败' : data.msg2
msg = '密码错误' == msg || '用户名或密码错误' == msg ? '手机号或密码错误' : msg
util.showMsg(true, 'err-txt', msg)
}
}
},
})
}
代码并不长,一个很简单的 post 登录,这里我会一一进行分析
var phone = $('#phone').val().trim()
var pwd = $('#pwd').val()
var fid = $('#fid').val()
var refer = $('#refer').val()
if (util.isEmpty(phone)) {
util.showMsg(true, 'phoneMsg', '请输入手机号', true)
return
}
if (util.isEmpty(pwd)) {
util.showMsg(true, 'pwdMsg', '请输入密码', true)
return
}
var t = $('#t').val()
if (t == 'true') {
pwd = $.base64.btoa(pwd, 'UTF-8')
}
在分割符的前一部分,获取我们表单中的手机号(phone),密码(pwd),学校 id(fid),以及不重要的 refer,同时判断手机号,密码是否为空,并给出相应提示,同时这里的 pwd 还进行了 base64.btoa,也就是 Base64 编码处理过。这里我就模拟一下这些数据
phone = '15212345678'
pwd = 'a123456'
pwd = 'YTEyMzQ1Ng==' // Base64编码后的结果
fid = '12345' // 也可以不指定学校 填-1
refer = 'http://passport2.chaoxing.com'
然后再看剩余的一部分,主要就关注这些:
$.ajax({
url: '/fanyalogin',
type: 'post',
dataType: 'json',
data: {
fid: fid,
uname: phone,
password: pwd,
refer: refer,
t: t,
},
success: function (data) {
//....
}
}
也正是因为这几行代码,将我们的数据发送给了学习通的服务端,并将数据返回给我们,这里我抓个数据包看看数据是怎么样的
POST /fanyalogin HTTP/1.1
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded; Charset=UTF-8
Accept: */*
Referer: https://passport2.chaoxing.com/login?&newversion=true
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
Origin: https://passport2.chaoxing.com
x-requested-with: XMLHttpRequest
Host: passport2.chaoxing.com
Content-Length: 94
fid=12345&uname=15212345678&password=YTEyMzQ1Ng==&refer=http://passport2.chaoxing.com&t=true
认真看上面最后一行,有没有发现这些数据不就是我们刚刚上面模拟的数据。再来看返回数据
HTTP/1.1 200 OK
Server: Tengine
Date: Fri, 25 Sep 2020 11:50:30 GMT
Content-Type: text/html;charset=utf-8
Connection: keep-alive
Set-Cookie: JSESSIONID=625EBEBB8C9A307910975B8A6306EE13; Path=/; HttpOnly
Set-Cookie: lv=3; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/
Set-Cookie: uf=b2d2c93beefa90dcc0dd308bdb4e3ac7c15d612bf3f08318fdb57793f3e0b0e8e06d6354b86e5f8c6733e63a87a57410913b662843f1f4ad6d92e371d7fdf644cb407fe2f4a1b7e3102289339c6dea121471850d8bf7e34cbde8ab62ef4efbfc29d661c57520821b; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/
Set-Cookie: _d=1601034630583; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/
Set-Cookie: vc=D117659BD1295E4489AED8ED14E8A8D8; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/; HttpOnly
Set-Cookie: vc2=5B73047EF8C636D19D282B878FC42D4A; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/; HttpOnly
Set-Cookie: vc3=Lptknj6gO2EVnnAWOW0A1O0d0RGWzgO1jVDtKiGtxlqX7dH5uAz84KoWDf2Y9v%2Biw2V3RyKd2gNXf%2BMVKt2HKmJzYK1vt%2BBHu%2B%2BXwG3NtJAWvXygxxcRYlSwCt%2BDv0r8JkrhqgJxJQV2VkMVMon8PABIuJdJKudVTQR%2FP6u2pfY%3D2dd5ab18abc4e7b47fdeb363a13a7c64; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/; HttpOnly
Set-Cookie: xxtenc=0fd26095d768e519a53edd2f4ba4c9e9; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/
Set-Cookie: DSSTASH_LOG=C_38-UN_9502-US_42736002-T_1601034630584; Domain=.chaoxing.com; Expires=Sun, 25-Oct-2020 11:50:30 GMT; Path=/
Set-Cookie: route=1b37a788fe3a8c39de935217be0d9f7a;Path=/
Content-Length: 56
{"url":"http%3A%2F%2Fi.mooc.chaoxing.com","status":true}
现在只要注意最后一行,这是登录成功的返回结果,那如果密码错误呢,返回的结果如下
{ "msg2": "用户名或密码错误", "status": false }