(逆向思路)使小米路由器WIFI名称支持特殊字符

发布于 26 天前  98 次阅读


AI 摘要

这篇文章讲述了如何通过逆向工程绕过小米WiFi应用的限制,成功将WiFi名称修改为包含特殊字符🌟。尽管小米官方不允许🙅‍♂️,但通过分析和修改代码中的关键逻辑,最终实现了这个目标🎯。不过令人哭笑不得的是,最后发现其实在网页版后台可以直接修改带有特殊字符的WiFi名,感觉像是做了不少"无用功"。

前言

最近在宿舍搞了个路由器,之前一直用的是路由器默认的SSID (Xiaomi_xxxx),为了更好地辨别自己的Wifi,决定更改一个更有辨识度的名字。正在想取什么名字好的时候,正好在B站刷到了“Ciallo~(∠・ω< )⌒☆” (虽然我不知道这是什么意思bili_smilies),看起来很适合用于WiFi名,所以决定就这样修改。

修改遇阻

然而在小米WiFi app里尝试修改时,遇到了困难。

APP中提示“WiFi名称包含非法字符”,看来APP强制不能包含特殊字符,不能进行下一步修改。

尝试删除“☆”之后仍提示特殊字符,最后删到只有Ciallo~才允许继续修改。

实际上现在大多设备都支持特殊字符了,并不像以前的老设备上会乱码甚至崩溃,所以

正好最近学习了一些简单的安卓逆向,所以想尝试逆向看看能不能绕过这个限制。

分析安装包

先通过MT管理器提取 小米WiFi.apk

其中,classes.dex是java编译后的字节码(也就是源码编译后的产物),resources.arsc是记录所有字符串及其对应id的文件。

先反编译dex,可以看到源码结构只有abcd这样的名字,因此小米对源代码进行了一定程度的混淆,直接搜索方法名就不太合适了。

所以需要在.arsc中搜索对应的字符串,找到字符串对应的id,再回到dex中搜索id,才能开始分析代码逻辑。

搜索ARSC

在arsc中尝试搜索“非法字符”(因为刚刚报的错是“WiFi名称包含非法字符”)。

查找资源ID

顺利找到了字符串以及String name,接着搜索string name对应值(common_illegal_input_tips_ssid),找到对应的资源id.

得到了资源id(0x7f11037c),不过,也同时记录一下上一个id(0x7f11037b)意思是密码包含非法字符,等会说不定用得上。

有了id之后就可以开始分析代码了。

分析源码

“classes.dex是Android应用程序中的一个文件,它包含了Java编译后的字节码,用于在Dalvik虚拟机上执行。与Java中的class文件对应,Dex文件可以大大缩小体积,减少数据冗余,有利于在移动端中运行”

由于dex是java编译后的文件,所以查看的代码并不是java,而是反编译后得到的smail反汇编代码。

搜索ID

在smail代码中搜索0x7f11037c,发现有好几处地方涉及到了“WiFi名称含有非法字符”,查看方法名可以排除几个(guest访客WiFi什么的,因为我修改的并不是访客WiFi)。在可疑的方法名中,将id修改为刚刚记录的“密码包含非法字符”的id(0x7f11037b),逐个排除。

修改完之后保存工程,并回编译,安装apk,再次进入修改WiFi名称界面。

发现原本的WiFi名称包含非法字符 已经变成了 WiFi密码包含非法字符

通过修改id,这样就找到了要分析的代码所在的方法(method)里

位于“com.xiaomi.router.setting”下的“WiFiitemview”里,进入并分析。

源码解读

定位到代码位置,分析代码。

以下为节选的核心代码,已添加必要注释。

    :goto_50 
    const/4 v5, 0x0

    invoke-static {v0, v5}, Lcom/xiaomi/router/common/util/w0;->d(Ljava/lang/String;Ljava/lang/String;)Z           #判断某个布尔值的真假

    move-result v6          #将结果储存到变量名“v6”里,值只有0或1

    const v7, 0x7f11037c    #将字符串“WiFi名称含有非法字符”储存到变量v7中    



    if-eqz v6, :cond_6a      #如果v6 == 0(equal zero)就跳转到cond_6a,否则继续下面的代码,即v6为0就是没有非法字符,v6为1就接着下面的代码进行报错。

    invoke-virtual {p0}, Landroid/view/View;->getContext()Landroid/content/Context;

    move-result-object v2

    invoke-virtual {v2, v7}, Landroid/content/Context;->getString(I)Ljava/lang/String;

    move-result-object v2              #使用到了v7

    invoke-virtual {p2, v2}, Landroid/widget/TextView;->setError(Ljava/lang/CharSequence;)V

    invoke-virtual {p2}, Landroid/view/View;->requestFocus()Z       #这里就是控制报错的代码

    const/4 v2, 0x0

    :cond_6a      #cond_6a开始
    invoke-static {v1, v5}, Lcom/xiaomi/router/common/util/w0;->d(Ljava/lang/String;Ljava/lang/String;)Z     #判断一个布尔值

    move-result v5      

    const v6, 0x7f11037b          #将“密码含有非法字符串”保存到v6变量中

    if-eqz v5, :cond_82           #如果v5==0,转跳,否则继续

    invoke-virtual {p0}, Landroid/view/View;->getContext()Landroid/content/Context;

    move-result-object v2

    invoke-virtual {v2, v6}, Landroid/content/Context;->getString(I)Ljava/lang/String;

    move-result-object v2

    invoke-virtual {p3, v2}, Landroid/widget/TextView;->setError(Ljava/lang/CharSequence;)V

    invoke-virtual {p2}, Landroid/view/View;->requestFocus()Z
             #报错提示密码含有非法字符

    const/4 v2, 0x0
#################################################################################

实际上,看到这里,已经初步了解了控制报错的代码逻辑,只需要让v6永远等于0,if-eqz v6, :cond_6a无论如何都会运行cond_6a,不会运行报错的相关代码。

要让v6==0,只需要在if-eqz v6, :cond_6a的前一行加一句“const/4 v6, 0x0”就好,意思是将v6的值设置为4位的(dex中的数字用4或16位储存),这样无论v6之前的值是什么,在if判断之前都被重新赋值为0。

添加完之后,保存、回编译、安装应用。

然而事情并不是想象的那么容易,将v6固定为0之后,更改WiFi名仍与先前报错一致。

实际上,cond_6a下面的报错代码确实没有运行,而是if-eqz v5, :cond_82判断密码是否有非法字符时,cond_82中还存在冗余代码,重复判断了名称是否含有非法字符,因此还需要继续分析cond_82

##########################################################################     
    #接上井号处代码    
    :cond_82
    invoke-static {v0}, Lcom/xiaomi/router/common/util/w0;->a(Ljava/lang/String;)Z
      #此处又获取了某个布尔值,但与前两次不同,这次只带了一个参数
    move-result v5
      #将结果储存到v5,虽然不清楚这里判断了什么,但可以肯定如果v5==0,下面的if就不会跳转到cond_98
   

    if-eqz v5, :cond_98   #下面又是报错的代码

    invoke-virtual {p0}, Landroid/view/View;->getContext()Landroid/content/Context;

    move-result-object v2

    invoke-virtual {v2, v7}, Landroid/content/Context;->getString(I)Ljava/lang/String;
    #这里又用到了v7,“名称含有非法字符”,所以肯定要让v5等于0
    move-result-object v2

    invoke-virtual {p2, v2}, Landroid/widget/TextView;->setError(Ljava/lang/CharSequence;)V

    invoke-virtual {p2}, Landroid/view/View;->requestFocus()Z

    const/4 v2, 0x0
##########################################################################

可以在”if-eqz v5, :cond_98“的前一行添加 “const/4 v5, 0x0”

添加、保存、回编译、安装测试。

##########################################################################     
    #接上井号处代码
    :cond_98
    invoke-static {v1}, Lcom/xiaomi/router/common/util/w0;->a(Ljava/lang/String;)Z

    move-result v5
    #其实刚刚修改完已经成功绕过了,可以修改成特殊字符了,
    #但是cond_98又双叒叕获取了一个布尔值,下面的报错代码是判断密码是否有特殊字符的冗余代码,
    #所以不需要再改了,密码就没必要那么多特殊符号。

    if-eqz v5, :cond_ad

    invoke-virtual {p0}, Landroid/view/View;->getContext()Landroid/content/Context;
                  #悄悄的说,其实根本没办学校的宽带{doge}(60一个月又贵又慢),53号端口有新大陆
    move-result-object v2

    invoke-virtual {v2, v6}, Landroid/content/Context;->getString(I)Ljava/lang/String;

    move-result-object v2

    invoke-virtual {p3, v2}, Landroid/widget/TextView;->setError(Ljava/lang/CharSequence;)V

    invoke-virtual {p3}, Landroid/view/View;->requestFocus()Z

    const/4 v2, 0x0

    :cond_ad         #下面就是和路由器通信的代码,告诉路由器要修改成的名字。
    invoke-static {}, Lcom/xiaomi/router/common/application/RouterBridge;->E()Lcom/xiaomi/router/common/application/RouterBridge;

    move-result-object v5

    invoke-virtual {v5}, Lcom/xiaomi/router/common/application/RouterBridge;->x()Lcom/xiaomi/router/common/api/model/CoreResponseData$RouterInfo;

    move-result-object v5

    invoke-virtual {v5}, Lcom/xiaomi/router/common/api/model/CoreResponseData$RouterInfo;->isSupportTridBandRouter()Z
                  
    move-result v5

修改结果

可以看到不再报错,进入到了下一步。

在点击刚刚的确认后,又弹出了一个提示。

鸡贼的小米,在重启WiFi的代码里还判断了一次特殊字符,看来至少他们曾经 允许或想过支持修改特殊字符,但因为某些原因,强制不允许特殊字符了。

成功连接到含有特殊字符的WiFi

雷军!金凡!

干完小米WiFi app,想看看网页版后台上怎么显示的,才发现网页版可以直接修改含有特殊字符的ssid,我TM!

附录:

需要特殊版本的MT管理器请在评论区留言,我会分享到网盘里bili_smilies

初学逆向,如有不当之处,还请予以指正。