[color=rgba(0, 0, 0, 0.56)]我这里就拿国内一家安全公司出的一个入门级app的题目做分析 [color=rgba(0, 0, 0, 0.56)] 要求如下: [color=rgba(0, 0, 0, 0.56)] 1.有壳就脱壳 2.拿到此题的Flag
[color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]首先拿到一个app用工具查一下 这里提示没有壳
[color=rgba(0, 0, 0, 0.56)]那么我们安装一下看一下软件页面 [color=rgba(0, 0, 0, 0.56)]
[color=rgba(0, 0, 0, 0.56)]一打开就是如此 两个编辑框 然后点击登陆就跳转到另一个页面提示”Waiting fot you!”
[color=rgba(0, 0, 0, 0.56)]既然如此 打开jadx-gui工具反编译一波 从java层入手
[color=rgba(0, 0, 0, 0.56)]首先找到他的”AndroidManifest.xml” 里面有个”activity”标签里面就是他的活动页面的信息 [color=rgba(0, 0, 0, 0.56)]
[color=rgba(0, 0, 0, 0.56)]可以看到这里有3个活动页面信息 [color=rgba(0, 0, 0, 0.56)]<action android:name="android.intent.action.MAIN"/> [color=rgba(0, 0, 0, 0.56)]<category android:name="android.intent.category.LAUNCHER"/> [color=rgba(0, 0, 0, 0.56)]有这两个属性的值上面的活动页面就是我们的入口页面(一开打软件所显示的页面信息)
[color=rgba(0, 0, 0, 0.56)]既然如此我们之前看到过有个登陆的按钮在一启动的活动下 [color=rgba(0, 0, 0, 0.56)]那么我们到此活动页面看一下按钮下的逻辑事件(“com.tencent.testvuln.MainActivity”) [color=rgba(0, 0, 0, 0.56)]
[color=rgba(0, 0, 0, 0.56)]来到这个类里面找到按钮点击事件 也就是onClick事件下
[color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]首先一个switch语句获取view.id 进入第一个分支也就是 case R.id.button1
[color=rgba(0, 0, 0, 0.56)]然后接着判断我们输入的内容是不是为空 或者说输入的长度是否为0 如果条件成立就进行一个弹窗提示我们输入的内容”不能为空”
[color=rgba(0, 0, 0, 0.56)]然后定义两个string类型的变量接收我们输入的内容 [color=rgba(0, 0, 0, 0.56)]Obj是第一个编辑框的内容 obj2是第二个编辑框的内容
[color=rgba(0, 0, 0, 0.56)]然后startActivity跳转到另一个活动页面也就是”SecondActivity”并将我们输入的内容也传递过来 然后在onCreate初始化函数进行判断
[color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]这一块儿的逻辑就很清晰了
[color=rgba(0, 0, 0, 0.56)]if (Encryto.doRawData(this, stringExtra + stringExtra2).equals("VEIzd/V2UPYNdn/bxH3Xig=="))
[color=rgba(0, 0, 0, 0.56)]所有的比较逻辑都是在这里了
[color=rgba(0, 0, 0, 0.56)]调用一个Encryto类下的doRawData将this 以及stringExtra + stringExtra2).equals("VEIzd/V2UPYNdn/bxH3Xig=="传递进去
[color=rgba(0, 0, 0, 0.56)]我们现在跟踪到doRawData方法 [color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]发现System.loadLibrary("JNIEncrypt"); 加载了这样一个so库 此方法也是由native关键词所修饰的
[color=rgba(0, 0, 0, 0.56)]那么打开此app的lib文件夹发现也只有一个so文件库
[color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]拿出我们的ida工具反编译一波先 [color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]发现并没有java_ 静态注册的方法那么我们也只能找到JNI_OnLoad动态注册的位置 [color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]来到了 [color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]RegisterNatives就是注册的函数 他的第三个参数就是我们要找到的方法体 第四个参数就是他注册的个数
[color=rgba(0, 0, 0, 0.56)]
[color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]然后我们一步步跟踪到了这里 发现采用了一个AES/ECB/PKCS5Padding的加密方式
[color=rgba(0, 0, 0, 0.56)]Key勒就摆在面前的”thisisatestkey==”
[color=rgba(0, 0, 0, 0.56)]然后我们来解密一波 [color=rgba(0, 0, 0, 0.56)]将VEIzd/V2UPYNdn/bxH3Xig== 解密得出”aimagetencent” [color=rgba(0, 0, 0, 0.56)]
[color=rgba(0, 0, 0, 0.56)]第三个页面这里会解密一个9YuQ2dk8CSaCe7DTAmaqAA==值 [color=rgba(0, 0, 0, 0.56)] [color=rgba(0, 0, 0, 0.56)]将9YuQ2dk8CSaCe7DTAmaqAA== 解密得出”Cas3_0f_A_CAK3” [color=rgba(0, 0, 0, 0.56)] |