逆向APK进行smali注入实现“秒破WIFI”

  近期开始关注手机安全了,以往都是在PC上玩,对这个领域也想了解一下,可是拿什么来开刀呢?突然想起Wifi万能钥匙这个神器了,这个软件的wifi分享模式鄙人非常喜欢,装了这货基本上很多地方都有免费的WIFI用!(这并非植入广告!是真心话!)鄙人也把自己的家用wifi给共享了,10M的带宽欢迎你连进来(只要你敢,嘿嘿)。不过这个软件还是有美中不足的地方,软件提供wifi连接的功能,但是并不会告诉你wifi的密码是什么,估计厂家也是基于安全和隐私的角度考虑,这样做也是对的,但其实密码应该就在软件的某个地方,只要想找肯定会找到(在data/misc/wifi/wpa_supplicant.conf文件中),但这不是本文的重点,本文主要讨论的是apk软件的逆向和修改打包技术,纯技术交流用途。

  好了,开始说干货了(高手直接飘过吧),这次开刀的版本是官方2.9.27版本。首先APKTOOL反编译安装包,请注意版本号Apktool 2.0.0-Beta9。

  得到smali源码后开始找关键代码,我们的主要目的是让wifi万能钥匙把从服务器传回来的密码显示出来,这样我们不但能连入wifi,而且还能知道明文密码。

  首先与PC端软件逆向的流程应该是一样的,找关键字定位关键代码,这软件每次连wifi都会显示一些日志,其中有一条很关键,“尝试获取网络密码成功”,这应该是成功获取到了密码之后的日志,这个字符串位于资源目录中的strings.xml文件里。

  依据XML的name字段"act_autoconnect_state_get_net_pwd_success"我们可以继续搜索到位于public.xml中对应的字符串ID。

  依据这个 id="0x7f0d051e",我们能定位到关键的smali代码,WiFiMastersmalicomsndawifilocatinguiactivityfc.smali这里使用了这个字符串,代码如下:

  const v1, 0x7f0200bdconst v2, 0x7f0d051e    invoke-virtual {v0, v1, v2}, Lcom/snda/wifilocating/ui/activity/fe;->b(II)V     iget-object v0, p0, Lcom/snda/wifilocating/ui/activity/fc;->a:Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;     iget-object v1, p0, Lcom/snda/wifilocating/ui/activity/fc;->a:Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;     invoke-static {v1}, Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;->i(Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;)Lcom/snda/wifilocating/f/s;    move-result-object v1可以从代码中看到0x7f0d051e字符串作为参数传递进了b方法中,而后又被AutoConnectActivityWithStateList这个类进行了多次调用,看来AutoConnectActivityWithStateList类是个非常关键的环节,我们不如直接找到这个类的实现代码进去看看。

  这个类的smali代码路径如下:WiFiMastersmalicomsndawifilocatinguiactivityAutoConnectActivityWithStateList.smali

  为了节省篇幅,省去读这个类代码的过程描述,直接粘贴关键代码如下(大概1500行的位置):

  .method private a(Lcom/snda/wifilocating/ui/activity/support/AccessPoint;Ljava/lang/String;)Lcom/snda/wifilocating/ui/activity/fd;    .locals 5     const/4 v4, -0x1    new-instance v0, Ljava/lang/StringBuilder;    const-string v1, "connect ap:"    invoke-direct {v0, v1}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V    iget-object v1, p1, Lcom/snda/wifilocating/ui/activity/support/AccessPoint;->b:Ljava/lang/String;    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;    move-result-object v0    const-string v1, " with pwd:"    invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;    move-result-object v0    invoke-virtual {v0, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;    move-result-object v0    invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;    invoke-static {p2}, Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z    move-result v0    if-nez v0, :cond_0这是一个非常关键的方法的实现,我们看到该方法有两个参数,一个是AccessPoint类的对象,另一个是String字符串,方法的一开始就实例化了一个StringBuilder的对象,然后使用append不断的拼接该字符串,大概的拼接规则是这样的:

  “connect ap: ”+ “AccessPoint;->b”+“with pwd:”+“String”

  看到了这里似乎就已经明朗了,意思就是 连接热点:XXX 使用密码:XXX。

  所以我们完全有理由相信,这个String类型的参数实际上就是wifi热点的密码!

  OK,到了这里,我们要做一些工作来进行验证,你可以选择使用ADB调试然后跟踪到这里,或者干脆修改smali,让它输出这里的String给我们看,我选择第二种方法,因为本来我们也是为了要让它显示密码。

  手动输入如下的代码插入到该方法中(smali有很严格的语法规则,拿到一段代码先要搞清楚含义,随意插在什么地方几乎是跑不通的,关于smali的语法网上有很多资料了,建议先学习懂了以后再去写,当然如果你是高手就飘过吧)

  new-instance v5,Landroid/app/AlertDialog$Builder;invoke-direct {v5,p0}, Landroid/app/AlertDialog$Builder;-><init>(Landroid/content/Context;)Vconst-string v6, "|Cracked by u6210u738Bu8D25u5BC7| PASSWORD IS:"invoke-virtual {v5,v6}, Landroid/app/AlertDialog$Builder;->setTitle(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;invoke-virtual {v5,p2},Landroid/app/AlertDialog$Builder;->setMessage(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;invoke-virtual {v5},Landroid/app/AlertDialog$Builder;->create()Landroid/app/AlertDialog;move-result-object v6invoke-virtual {v6},Landroid/app/AlertDialog;->show()V这段代码就是使用AlertDialog类的一系列方法弹出对话框,把密码显示出来。(真搞不懂java弹个对话框怎么要用到这么多方法,这里怀念一下windows的MessageBoxA。)

  插入过后就是对整个代码进行编译打包的工作了,不要以为这个活就干完了,真正闹心的还在后面呢!

  我们使用apktool b [反编译后的目录] 进行打包,多数情况你会发现打包过程是会报错的,千奇百怪的错!只有少数APK会成功打包。后来我专门研究了一下这个问题,主要其实是资源出的错,当然前提是要先把smali代码编译过去,剩下再解决资源的问题。本例中的这个APK也是有报错的,好在还不多,都一一解决了。其实我本来想把资源报错这个问题的细节写进来,但其实这是个体力活!而且每款软件都不同,几乎没有借鉴意义。所以我准备把一些方法性的东西告诉大家,具体问题你只能具体分析了。

  解决打包报错问题的基本思路就是先看报错内容(这不是废话么~),因为这是我们唯一的线索,先搞清楚问题的原因再去对症下药,smali报错我就不说了,因为这多数是语法的问题,只能好好学学了。如果报错类型是资源文件出错,例如string.xml、public.xml什么的,那你就把原始的apk资源解包出来,然后把反编译的对照原始资源文件进行参考修改,缺啥就补啥,多啥就删啥,引用错了啥就改啥,这也是需要你对安卓的整个打包文件结构有一定的了解才行,具体问题具体分析。

  好了,此处省略一万次报错修改的过程……(真心希望google能把apktool好好做做,这么多bug不像是google的产品作风啊!)最后终于生成出了打包好的文件,它在你反编译后的dist目录中。

  先别急,我们还要对这个APK进行签名,否则安装不了。

  OK,我们下面安装这个APK,来看看效果。

  安装后开启wifi,然后点击一键查询万能钥匙,搜出来个901,估计是门牌号,信号很好并且已经共享了wifi,我们连进去看看。

  点击“万能钥匙自动连接”,顺利的话就应该能爆出密码了。

  OK,密码已经成功弹出,大功告成!有了这货你基本上就可以秒破很多WIFI了!对于已经修改好的APK我就不提供下载了,我们的目的是纯技术交流,你懂的。

 

上一篇:智能无惧挑战 山石网科轰动RSA2015

下一篇:窃听风云:生活中无处不在的间谍设备