上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

记一次逆向拆包的过程(一)

[复制链接]
  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    21

    主题

    624

    帖子

    1080

    积分

    荣誉开发者

    Rank: 10Rank: 10Rank: 10

    积分
    1080

    卓越贡献活跃会员热心会员突出贡献三好学生荣誉开发者喜迎中秋油中2周年

    发表于 2022-11-4 23:36:30 | 显示全部楼层 | 阅读模式

    最近想做个中国移动APP的签到脚本,研究了一下签到请求发现还挺复杂,涉及各种加密、反编译,遂记录此文,以作参考。
    首先是手机抓包,大体流程就是电脑抓包软件设置好代理端口,然后手机wifi连接代理,安装好证书就可以抓包了。详细流程网上都有,可以参考下论坛的这篇文章。这里也用Charles这个工具为例进行分析,注意关掉windows代理,只打开代理端口,这样只会抓手机上的包。抓取完整的签到流程后,点击“序列”,让请求按时间排序,从后往前找响应数据,可以看出这个是关键签到请求:
    https://wx.10086.cn/qwhdhub/api/mark/do/mark
    尝试在脚本里复现这个请求,注意尽可能带上一样的header,尤其是User-Agent,cookie我们先不带上。请求发出后,被重定向到下面这个登录请求(最好去脚本管理器的background页看实际请求):
    https://wx.10086.cn/qwhdsso/login?dlwmh=true&actUrl=https%3A%2F%2Fwx.10086.cn%2Fqwhdhub%2Fqwhdmark%2F1021122301
    这说明缺少cookie,服务端认为我们需要登录,而这个登录请求在我们前面抓的包里也能找到,其响应是一个html页面。html的代码里包含了基本的登录逻辑:
    1.png
    大致分析一下,将UID加密后发出一个chinaMobileApp的post请求,猜测该请求起到关键的登录验证。在登录请求和签到请求之间的包里找一找,可以找到这个:
    2.png
    请求的响应数据包含了一个新的url,在下方就可以找到访问这个url的请求,其响应是另一个html页面。如果深入研究一下这个html,可以发现签到请求就是这个页面发出的。回到脚本的签到请求,我们可以逐个尝试一下,发现加上SESSION这个cookie以后,可以得到“今日已签”的成功响应。注意反复测试这类有cookie的请求时,最好带上anonymous: true,因为多次测试可能会改变cookie干扰结果,甚至某次失败了写入一个错误的cookie,可能导致后续一直失败无法更新cookie。
    在Charles中按ctrl+f搜索,设置如下搜索规则:
    2.1.png
    由于cookie不是凭空产生的,通常是由某些响应头的Set-Cookie字段设置,这个搜索的意思就是查找哪个请求设置了SESSION。找到2个结果,注意我们的签到请求作用域是/qwhdhub/,可以确定是这个请求设置了SESSION:
    https://wx.10086.cn/qwhdhub/qwhdmark/1021122301?XXX
    是不是很眼熟?他跟chinaMobileApp响应的那个url非常接近,对比一下发现只多了token,而这个没token的版本,正好重定向到了我们前面的登录页面。至此签到流程可以基本确定为:首先请求1021122301,该请求会设置SESSION(此时这个SESSION还是无效的),然后重定向到登录请求,登录请求的html发出chinaMobileApp,返回一个带token版的1021122301(此时SESSION正式生效),最后发出签到请求。
    显然chinaMobileApp是最关键的请求,我们在脚本里尝试复现一下,发现无需cookie也能得到正确结果(很多数据是有时效的,如果间隔时间太长需要重新抓包)。观察html代码,可以看出核心是他的data,其中openid属性明文写在前面的html代码里,mobile是对UID的加密结果,其他属性我们排除法测试一下,发现加不加没有影响。openid可以对html做正则获取,UID的加密由leadeon.encryptString这个函数完成,前后翻一翻发现,页面引入了这个js文件:
    https://app.10086.cn/appother/js/public/leadeon.js
    打开看看源码,确实可以搜索到encryptString,大胆一点,直接在脚本里引入这个js,然后模仿着写一下leadeon.encryptString,运行后报错:newSdkInterface is not defined。在leadeon.js里搜索newSdkInterface,可以大致看出,我们的加密函数在这个对象上,html里找不到该对象的定义,引入的js文件也只剩一个jquery。看起来卡住了,我们换个思路,往Charles里写入一条重写规则:
    3.png
    这里的想法是chinaMobileApp这个请求是由登录请求的html发出的,所以我们改写登录请求的响应结果,让其发出的chinaMobileApp额外带上我们需要的数据,从而暴露出加密函数源码,顺便我把UID明文也带上了。手机APP清除一下缓存,然后重新签到抓包,看看这个新的chinaMobileApp。结果发现,fn是[native code],UID倒是带上了。这个native code可能是人为改写的结果,换一种写法试试:

    Function.prototype.toString.call(newSdkInterface.encryptString)

    结果还是没变,说明一个问题:加密函数并非来自js,而是其他语言写的。这不难理解,请求是手机客户端发出的,客户端又不是js写的,关键函数可能会放到客户端内由Java实现。这又涉及客户端反编译的问题了,我这里用的安卓,关于apk反编译的教程网上很多,大致就是解压apk得到classes.dex,dex2jar反编译为jar,再用jd-gui查看源码。至于apktool,那主要是用来修改smali再重新打包回去的,由于我们的目的只是看源码,不关心打包,故可以跳过这一步。
    这里额外说一点我的经验,jd-gui的不同版本查看效果是有差异的,最新的1.6.6看有些函数会变成一堆注释,换较低的1.4.0反而能解析出来,而1.4.0看别的有更大概率变注释,也有可能两个版本都解析不出来,具体原理我也不懂,建议多下几个版本换着看。
    class.dex有80多M,dex2jar转换后却只有15K,jd-gui查看效果是这个鬼样子:
    4.png
    从包名可以看出,这个dex被加壳了。常见的脱壳方式是安装运行apk,然后从内存里dump出实际的dex。我试过在安卓模拟器里搞这些,但32位和64位的兼容问题相当麻烦,遂放弃,直接在实机上操作。这是我找到的一个工具,特点是无需root,操作简单:
    BlackDex
    中国移动的apk是64位的,要用BlackDex64打开,这个工具不是很完美,每次脱出的dex数量有限,最好多试几次得到尽可能多的dex(数字相同的就是同一个)。最终我得到了19个,可以分别用dex2jar转为jar再全拖进jd-gui里查看,不过可能会出现同一个包分散在不同文件,找起来很不方便,我写了个批处理来合并:

    rem 这里填d2j-dex2jar路径
    set DEX2JAR="D:\dex-tools\d2j-dex2jar.bat"
    rem 这里填WinRAR路径
    set WINRAR="C:\Program Files (x86)\WinRAR\WinRAR.exe"
    
    for /r %%i in (*.dex) do call %DEX2JAR% "%%i"
    if exist package rd /s /q package
    if exist package.jar del /q package.jar
    md package
    for /r %%i in (*.jar) do %WINRAR% x -o+ "%%i" package
    %WINRAR% a -afzip -df -ep1 -r -m0 package.jar package\
    rd /s /q package

    使用方法是复制到记事本,改好你自己的dex2jar和WinRAR路径,保存后修改后缀为bat,再放到与dex文件同一目录下运行即可。由于jar的本质就是zip压缩包,合并的原理即解压后合并目录,再重新压缩成一个。如果有配置好java环境,用jar命令也能做,WinRAR的好处是可以指定压缩级别,我设置为存储,这样速度最快,生成的文件也最大(其实就是没压缩)。由于我们不打算打包回去,只要jd-gui能打开就行,所以大小无所谓。如果你使用其他压缩软件,也可以尝试自己改压缩命令。
    打开合并后的jar就可以看Java源码了,有Java基础的可以自己先研究一下,篇幅所限,有关加密的分析我们就且听下文分解吧。

    已有2人评分好评 油猫币 理由
    tfsn20 + 1 + 5 学到了学到了
    陈公子的话 + 5 赞一个!

    查看全部评分 总评分:好评 +1  油猫币 +10 

  • TA的每日心情
    开心
    昨天 23:59
  • 签到天数: 170 天

    [LV.7]常住居民III

    470

    主题

    4281

    帖子

    4322

    积分

    管理员

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    4322

    喜迎中秋国庆纪念章荣誉开发者管理员油中2周年

    发表于 2022-11-4 23:51:02 | 显示全部楼层
    脱壳好像也可以试试反射大师
    在对应页面长按导出可以导出全部Class
    貌似用反射大师没碰到过导出不全的情况
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2022-3-8 11:41
  • 签到天数: 2 天

    [LV.1]初来乍到

    21

    主题

    624

    帖子

    1080

    积分

    荣誉开发者

    Rank: 10Rank: 10Rank: 10

    积分
    1080

    卓越贡献活跃会员热心会员突出贡献三好学生荣誉开发者喜迎中秋油中2周年

    发表于 2022-11-5 20:29:30 | 显示全部楼层
    李恒道 发表于 2022-11-4 23:51
    脱壳好像也可以试试反射大师
    在对应页面长按导出可以导出全部Class
    貌似用反射大师没碰到过导出不全的情况 ...

    反射大师需要xposed框架,我手机没root,一开始用模拟器就是root比较方便,可惜兼容问题有点多。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    昨天 23:59
  • 签到天数: 170 天

    [LV.7]常住居民III

    470

    主题

    4281

    帖子

    4322

    积分

    管理员

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    4322

    喜迎中秋国庆纪念章荣誉开发者管理员油中2周年

    发表于 2022-11-5 20:32:08 | 显示全部楼层
    cxxjackie 发表于 2022-11-5 20:29
    反射大师需要xposed框架,我手机没root,一开始用模拟器就是root比较方便,可惜兼容问题有点多。 ...

    是,而且好像反射大师还不支持安卓高版本...
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    3

    帖子

    3

    积分

    助理工程师

    Rank: 1

    积分
    3
    发表于 2022-12-14 21:46:35 | 显示全部楼层
    BlackDex能脱棒棒加固企业版?我草
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表