本人是小白一枚,最近看到有人在看雪上分享了一个apk,是关于注册机的闯关游戏,虽然才疏学浅,也准备来玩玩。但是由于代码都在JAVA层,所以没有实际价值,爆破可以轻松解决,但是可以用来熟悉smali语言,所以现在只分析第一关。反编译apk,得到smali,当然也可以通过jd-gui得到java源代码。找到关键代码,在Challenge1Verifier.smali中的isValid函数代码如下:
.method public isValid(Ljava/lang/String;Ljava/lang/String;)Z
.locals 5
.parameter "name"
.parameter "serial"
.prologue
.line 16
const-string v0,"3"
const/4 v0, 0x0
.line 18
.local v0, answer:I
const/4 v3, 0x0
.local v3, x:I
:goto_0
invoke-virtual {p1}, Ljava/lang/String;->length()I
move-result v4
if-ge v3, v4, :cond_0
.line 20
invoke-virtual {p1, v3}, Ljava/lang/String;->charAt(I)C
move-result v1
.line 21
.local v1, current:C
mul-int v4, v1, v1
add-int/2addr v0, v4
.line 22
xor-int/2addr v0, v1
.line 18
add-int/lit8 v3, v3, 0x1
invoke-static {v0}, Lcrack;->log_int(I)V
goto :goto_0
.line 26
.end local v1 #current:C
:cond_0
:try_start_0
invoke-static {p2}, Ljava/lang/Integer;->parseInt(Ljava/lang/String;)I
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_0
move-result v2
.line 27
.local v2, numericSerial:I
if-ne v2, v0, :cond_1#判断注册码
.line 29
const/4 v4, 0x1
.line 32
.end local v2 #numericSerial:I
:goto_1
return v4
.line 31
:catch_0
move-exception v4
.line 32
:cond_1
const/4 v4, 0x0
goto :goto_1
.end method
可以看到,算法主要思想是根据输入的用户名计算得到一个值,存在寄存器v0里面,然后判断v0和v2(输入的密码)是否相等,相等则通过,返回值v4为1,否则不通过,v4值为0。通过返回V4记
现在三种方法,方法一是暴力破解,直接将 v4寄存器的值改为0x01,不管v0和v2的判断结果是什么,都是返回1,那么就自然破解了.。
方法二,让程序自己吐出密码
if-ne v2, v0, :cond_1#判断注册码 ,程序主要是通过判断计算出来的值(存在v0)与输入的密码v2,是否相等来判断是否通过,那么我们只需要在这条语句前读取v0寄存器的值就可以了。加上invoke-static {v0}, Lcrack;->log_int(I)V。
这里的invoke-static {v0}, Lcrack;->log_int(I)V是我自己定义的一个类,作用是方便打印调试信息,因为大家知道,在smali里面添加简单的一句log都要好几行,特别麻烦,在这里我将它包装成了一个类,也就是说,可以自己DIY自己的各种插入的代码。具体实现如下:
.method public static log_int(I)V
.locals 2
.prologue
const-string v0, "info"
invoke-static {p0}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v1
invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
return-void
.end method
这样我们只要调用invoke-static {v0}, Lcrack;->log_int(I)V就可以打印了。
方法三:用apktool 2.0+netbeans 7.3调试apk。
Apktool 2.0优化了调试的支持,相对1.5.3的版本,主要做了以下改进:
1. 可以配合Netbeans 7.3调试apk
2. 支持显示寄存器的值,这是非常好的改进(1.5.3只可以显示函数参数P的值)
目前2.0还没有release,这是我自己编译的版本,下载地址:http://pan.baidu.com/share/link?shareid=1438815794&uk=369410799
netbeans 7.3下载地址:https://netbeans.org/downloads/
具体调试方法,以test.apk为例:
步骤1:生成支持调试的apk
1. 反编译:
java -jar apktool-2.0.0.jar d -d test.apk -o test.debug
2. 找到入口activity的oncreate()函数,在
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
后添加:
invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
3. 回编:
java -jar apktool-2.0.0.jar b -d test.debug -o test.debug.apk
4. 签名
5. 安装
步骤2:netbeans设置
1. 删除test.debug目录下的build文件夹
2. 打开netbeans,选择“文件”-“新建项目”-“基于现有源代码的java项目”
3. 在“项目文件夹处”选择test.debug目录
4. 在“源包文件夹”出选择test.debug.smali目录
5. 点击完成,项目创建完毕
步骤3:调试
1. 在模拟器中运行重新打包的test.apk,test.apk会处于挂起状态
2. 在netbeans中找到入口activity的oncreate函数,在刚才invoke-static {}, Landroid/os/Debug;->waitForDebugger()V
下一行下断点
3. 在netbeans中,选择“调试”-“连接调试器”
4. 依次设置:
调试器:JPDA
连接器:SocketAttach
传输:dt_socket
主机:127.0.0.1
端口:8700
超时:[可不填]
5. 确定,即完成连接调试,可以发现IP停在了刚才下断点的地方。
6. 可以看到,apktool2.0+netbeans7.3支持显示寄存器的值:
设置成功后,同样是在if-ne v2, v0, :cond_1语句出设置断点,可以看到效果如下图:
可以看到v0的值为9376,就就是我们要输入的密码了。
另:感谢丶0n1y3nd 对我这小菜鸟的帮助= =
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!