一个小任务,然而却踩了个大坑,幸亏没有造成损失,赶紧记录一下这个悲伤的故事

前因

接到的是一个类似爬虫的任务,需要获取某个 app 的数据,解析后取出存到数据库的两三张表内,其中一个数据字段是 url 资源,需要下载保存到磁盘内

接口的数据格式不复杂,很好模拟,也没有什么反爬虫限制,理论上相当简单,但还是花了三四天的时间才搞完上机器然后造成 bug 惨剧

过程

第一天

因为 app 只有移动端没有 web 端,所以主要在自己的 iPhone 上抓包分析,用的 Thor+Anubis(没有用 Charles 是因为还没学,而且抓到的包导出通过 iPhone 隔空投送到 Mac 也挺方便)

thor

抓包后发现所有传输的数据都加密了,大概是这样的密文:

encrypted

一眼看上去觉得肯定跟 base64 脱不了干系,解开后发现果然没有那么简单,还有一层加密……

起初我天真的以为密钥是在初始连接的时候传递共享的,然而卸了应用清了缓存重装打开从头抓包抓到的也全都是密文,说明密钥并没有出现在传输过程中

咨询老司机得知要获得密钥跟加密方法恐怕需要逆向一波……犹豫自己用的是 iPhone,自然而然想先逆向 ios,苦于没有相关知识,直接搜索而来的方法都因为各种条件限制(比如没有转换数据线连接到 mac)操作不了。此时有经验的同事告知 ios 破解会比较难,建议试试 Android

……然后 Android 的大佬就过来拿了 apk 文件,转头操作两分钟扒出了密钥和加密方法丢给了我(此处应跪😂),据说是因为源码没有混淆,结构也很清晰所以非常容易

事实再一次雄辩的证明了 Android 的安全性令人头秃

第二天

搞清楚数据结构后第二天就主要在编写加密解密和请求的逻辑代码了,这部分不复杂,也耗了一天主要是因为用了全新的技术栈:

  • 要求用 go 语言,完美避开了我碰过的六七种编程语言……从零开始两天速成系列
  • 编辑器从 sublime 转向 vscode,快捷键、插件什么的用法都不熟悉
  • 多年 win 党一朝转 mac,才过两天,仍处在适应期,操作也是各种不熟练

第三天

最后一天理所当然在修 bug 和准备丢到机器上爬,修 bug 时在两个地方被卡住:

vscode 调试过程中因为表达式无法执行导致的监视变量显示错误:

x := []byte("{  xxxxxxxxxx  \"page\" : " + fmt.Sprint(page) + "}") // xxxx省略

WATCH 一栏中添加监视 string(x) 预览显示的值为 "{ xxxxxxxxxx \"pa",由于这个显示的误导我一直以为自己的值传错了……

还有一个就是错误的数字转字符方式:string(number),这种转码方式不会得到正确的结果而且转码失败也不会报错,也因为没报错的缘故一直没注意到……,最后改成了 fmt.Sprint(number) 形式

惨剧

基本上每个脚本循环请求
简单在本地测试后准备上机,此时的我很英勇的没有用同事给的爬虫框架,也没有优化代码控制并发,而是图方便定了个 crontab,每两分钟跑一次,当晚大概十一点设置好就跑路了

后果与处理

第二天过来被告知起了将近 200 个进程,服务器资源占满,几乎无法登陆;数据库连接过多导致 mysql 拒绝连接,其他任务进程无法操作数据库;磁盘爆满空间严重不足……

一首凉凉送给自己.jpg

过来发现出事后有点慌没控制住,一时不知道怎么把 crontab 的任务给停下来,激动之下一个 rm -rf 把整个 go 代码和可执行文件目录全给删了……连同里面下载好的 url 资源一起……

再来一首凉凉给自己.jpg

残余的进程一个命令全部删除(xx 为进程关键字)

ps -ef | grep xx | awk '{print $2}' | xargs kill -9

不过幸好 url 还是正常的存在数据库里,再从中提取出来重新下载保存资源就行了;服务器是测试机,也没有损失什么数据,算是万幸吧

反思与解决

次要原因如下

  • 开发环境不熟悉
  • 毛躁,图方便,没有深思
  • 代码粗糙,操作粗暴

主要原因:

说来尴尬,代码里忘了释放数据库连接了……【尴尬到变形