乐高LEGO得宝DUPLO智能火车拆解修复

宝宝的 LEGO 乐高智能火车(10874)在玩过一次之后就不能走了。症状是安上电池可以开机,可以出声,手机蓝牙可以连接,但车轮不走。在不通电的情况下用手去掰车轮也非常生硬,难以转动,初步判断是马达坏掉了。

出于对这个高级玩具的好奇心和对自己动手的兴趣,决定拆开来看看,试着修复一番。

1. 首先拆开电池仓,用六角星形 T8 螺丝刀拧开底部的六个螺丝。(包括电池仓内的两个)

2. 随后可以小心地取下底盖。就能看到内部结构了。中间是电路板,前部是导光条,用来显示车灯。马达齿轮箱和金属配重安装在后部。

3. 可以轻轻取下马达和齿轮箱。用手转一转,发现很生硬,于是上了一点润滑脂。

4. 马达箱和齿轮箱是通过卡扣连接在一起的,可以用镊子小心地取下。马达则先把输出齿轮取下,然后取下尾部,就可以把马达单独拿下了。过程中需要注意尽量不要把线弄断,否则就要重新焊接了。

5. 用小螺丝刀把马达尾部拆开,取下转子,仔细检查转子绕组是否断开,然后小心地装上。这个马达的碳刷是比较大的,在安装的时候要小心碳刷不要被卡住。装好以后用手转一转,发现比之前要灵活多了,可能是马达被宝宝在玩耍过程中弄得堵转导致内部卡住了。

6. 通电试机,这下发现马达恢复了运转。说明之前的确是内部卡住了。本来从淘宝上买了五个替换马达,这下也没有用上。

最后是一点运转原理分析:这个智能火车是乐高 DUPLO 于 2018 年下半年发布的新品,支持蓝牙连接,支持感应积木。通过拆解全面了解它的原理:

  • 前轮轴上装有磁环,主板上磁环对应的位置有霍尔传感器,用于转速检测。这样火车被宝宝推动(不论前后)的时候前轮会转,从而启动马达驱动火车运转。火车在运行中被提起来,前轮失去附着,会停转;或者是运行中遇到障碍物,前轮也会停转,传感器感应到转速为零后,主板会停止马达,实现自动停车。
  • 车底有一个 RGB 三色 LED 和一个颜色探头,LED 照亮物体,通过物体的反光来识别颜色。不同的感应积木有不同的颜色(如红色—停车、黄色—鸣笛,感应积木本身就是一个塑料片,没有任何的智能化功能),这样车辆在运行中通过颜色传感器来“识别”不同的积木,从而作出相应的动作,实现“智能化”。

最后不得不感慨,随着电子信息技术的进步,现在的小朋友好玩的玩具真是太多了。一个小小的乐高积木玩具,都能实现电子化智能化。

附记:关于喇叭不响的问题,可参见后面换喇叭的文章

12306手机版App逆向研究

抽空研究了一下 12306 放出的 Android 版手机 App,本想挖一挖有没有手机版协议可供调用,不过就结果来看意义已经不大。以下简单记一下过程。

12306 的 apk 安装包可以用 WinRAR 打开,解压出 classes.dex,然后用 dex2jar 转换成 jar 包,就可以放到 jd-gui 里看 java 源代码了,源代码未经混淆,看起来十分方便。

在 jd-gui 里可以看到有好几个 java package,cn.domob 这个包是多盟的广告联盟代码,12306 App 的界面上未见到有广告,估计是用来做统计分析的。有 com.worklight 这个包,可以证明是用了 IBM Worklight 这个框架。真正实打实有内容的就是 com.MobileTicket 这一个包,其它的都是引入的库,并非 12306 相关的程序代码。阅读入口类 MobileTicket.class 的代码,可以发现其调用了本地的浏览器显示一个网页。也就是说:12306 App 的主界面其实是由网页组成的,整个程序的逻辑实现也都放在网页里了,java 源代码的干货其实很少。

  protected void bindBrowser(CordovaWebView paramCordovaWebView, boolean paramBoolean)
  {
    super.bindBrowser(paramCordovaWebView, paramBoolean);
    mDService = new DService(this, "56OJyf1IuNPVnYbzz4", "16TLwHboApIGwNU-ypi0ThBk");
    mDViewManager = new DViewManager(this, mDService);
    mDViewManager.doAppStartReport();
    paramCordovaWebView.pluginManager.addService("WebResourcesDownloader", "com.worklight.androidgap.plugin.SSLWebResourcesDownloaderPlugin");
    paramCordovaWebView.pluginManager.addService("NativeBusyIndicator", "com.worklight.androidgap.plugin.MyBusyIndicator");
  }

  public void init()
  {
    SSLWLWebView localSSLWLWebView = new SSLWLWebView(this);
    if (Build.VERSION.SDK_INT < 11) {}
    for (Object localObject = new CordovaWebViewClient(this, localSSLWLWebView);; localObject = new IceCreamCordovaWebViewClient(this, localSSLWLWebView))
    {
      super.init(localSSLWLWebView, (CordovaWebViewClient)localObject, new CordovaChromeClient(this, localSSLWLWebView));
      return;
    }
  }

知道是怎么回事,就得提取网页资源了。apk 安装包中的 assets/www 目录里有两个 resources.zip 文件,但似乎经过特殊处理,直接用 WinRAR 解压缩无法打开。另辟奚径,把手机程序安装到 Android 手机里(模拟器也行),然后用手机文件管理器打开 /data/data/com.MobileTicket 这个数据目录,就能看到程序使用的关键数据了。网页就存在 files/www/default 这里。

看了看代码,是基于 worklight 框架用 MVC 的方式实现的,view 都是 html 网页,js 来实现 model 和 controller,12306 的程序猿很厚道,js 都没有混淆,连中文注释都在,读起来十分方便,嘿嘿。比较关键的有 MobileTicket.js util.js 还有 controller 目录里的各个 js,看看文件名就知道是用来干什么的很好读。

这里有一个比较关键的 CheckCodePlugin(此 check code 并非我们看到的四位验证码,而是请求里自带的一个参数),通过网络抓包也会发现每次都会提交一个请求的参数是check_code,而这个东东实现上貌似是由 libcheckcode.so 这个 native 库来实现的(CheckCodePlugin.js 中有一份调试版本,但未可知调试版本与实现版本有何不同)。把 libcheckcode.so 放到 IDA Pro 里进行反汇编分析,在导出表中能看到 main, MD5_Init, MD5_Update 等几个模块,看了看汇编代码,也就是简单地做了个 MD5 Hash,看来 libcheckcode.so 与 js 的行为应该是一致的。很好奇为什么做 MD5 这活儿非要用一个 native 的库来完成,为了故弄玄虚?也许是为了保密或者准备以后换成更复杂的 checkcode 算法。

关于抓包,12306 App 需要读取本地网页,单纯给 Android 设置系统级代理然后在 PC 上用 Fiddler 抓包的话,打开程序便会跳出错误,因为无法读取本地的 file:/// 开头的 URL (其实就是本地网页)。如此,需要用 ProxyDroid 这样的代理 App,使之忽略掉 localhost 和 intranet address,然后在 Fiddler 中启用 HTTPS 分析,就可以轻松抓到 12306 手机 App 的协议。

协议中最开始有 IBM Worklight 框架自带的验证过程,由于此验证过程由 Worklight 框架实现,分析起来较为复杂。App 里用到了 wl_antiXSRFRealm,wl_deviceNoProvisioningRealm 和 wl_authenticityRealm,这些实现都可以在 apk java 源代码的 com.worklight.wlclient.challengehandler 包中找到。

以上是主要的研究心得。最开始以为 libcheckcode.so 是用来生成图片验证码的,这样 12306 App 实际上不需要从服务器取得验证码,而是在本地完成,没想到这个猜测是错误的。实际上 App 仍然要从服务器请求验证码,这一流程在 orderManager.js 中可以看到 refreshCaptcha() 即是。总结一下,手机协议的优势是验证码简单容易破解,但是代价是 worklight 框架复杂,初始验证过程不好模拟,且容易被服务器端的协议升级所反制,写一个手机协议的刷票软件仍然是十分费力且不讨好的事。