zldtb19931116 发表于 2018-9-21 11:31

Android逆向中的加密问题解决办法

第一次发帖,纯理科生死宅文笔不好请见谅。本文仅仅适合新人阅读。



在web和android逆向分析或抓包过程经常遇到加密字段:如下图不少新人遇到加密字段只会找在线加解密网站如cmd5尝试,现在的互联网还在只用md5、sha1这种简单加密方式的网站和app都少之又少,所以在线解密的成功率往往都很低。所以,想要摆脱脚本小子的称号,还是需要自己学会解密的,下面介绍我常用的解密(或绕过加密)的方式。1、 自己编写加解密脚本:通过分析反编译java、JS或者反编译so查看加密过程和密钥,如果是对称加密,如AES、DES等,可以自己用java或者python等熟悉的编程语言写一个加解密工具,这种方法是最直接的,但是非常考验编程水平,因为经常能遇到混淆的代码,分析难度特别大,甚至很多app直接加固了,还需要先脱壳才能逆向出源代码。另外,android里面的so通常只能反编译出汇编指令,对于不懂汇编的新人来说也只能望而却步。2、 使用xposed框架hook加解密过程:Xposed框架是一款不需要修改apk代码即可改变apk的运行方式的框架,框架本身不具备各种功能,但是我们可以安装各种模块,也可以自己开发模块。官网有开发文档,基本上只要有一点android开发基础即可学会,零基础话费2天时间也能编写一些简单实用的模块。理论上,我们可以通过xposed框架去hook任意一个java方法,让app以我们想要的方式去运行。比如之前很流行的微信运动记录修改,不少人的微信运动记录每天都是上十万步,大多都是通过hook方式去修改的。进入正题,首先不少app的加密过程都是通过java类里的Cipher.doFinal(param)方法去加密的。这个方法的参数即为明文,返回值为密文。在这里推荐一个开源的xposed模块:“inspeckage”,这个模块可以hook大部分app的加解密过程、网络通信、hash算法等。这个模块的好用之处在于作者将这个模块做成了一个BS结构的软件,将手机和电脑置于同一局域网或者使用adb端口转发,即可在电脑上使用浏览器查看hook结果:上图中Hash页面展示了hash的明文和结果,例如第一行,该app计算了“9900073656931102:00:00:00:00:00”的md5值为“ccdac0f4704675079478df7a6e4fe00b”,这个模块可以直接hook到。如上图,在Crypto页面,该模块打印了加密过程,包括加密方式AES、秘钥/Mrglo2oc2afc82a、加密明文和加密的密文结果。除了这两个功能,该模块还能HTTP、文件系统、webview等。另外,该模块提供了界面让用户输入想要hook的类和方法,可以帮我们省下部分编码的时间。该模块为开源模块,大家可到GitHub学习原理。上述模块能为我们带来方便,但是,不能解决所有问题。我们需要破解加密过程就需要自己动手了。在开始之前,大家可以先思考一下加密的过程:app将一堆参数拼接在一起,然后调用某个加密函数,将这一对明文作为参数,然后这个函数返回加密的结果,即密文。所以我想说的破解过程就是去hook这个加密函数,修改明文参数,这样我们可以不用管加密算法是什么,直接在加密之前先将明文打印出来,修改成我们想要的值,再让这个值去继续完成加密过程:为了更直观,用伪代码展示一下,比如我们发现发现某app将abc123加密成了一堆密文“kjaflasflkajsflkalfjalks”,我们现在想将abc123篡改成abc124,尝试是否存在越权等漏洞,又看不到加密的具体算法:String pass = “”;   //pass为密文pass = Cipher.doFinal(“abc123”);System.out.println( pass);我们需要做的就是hook这个dofinal方法,将参数abc123改成abc124。@override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        String packagename = "com.zl.test";
        String param1 = "abc123";
        String param2 = "abc124";
      if (loadPackageParam.packageName.equals(packagename)) {

            log("ineed--开始hook " + loadPackageParam.packageName);

            XposedHelpers.findAndHookMethod(Cipher.class, "doFinal", byte[].class, new XC_MethodHook() {
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                  getvalue();
                  if (byteArrayToString((byte[]) param.args).contains(param1) && !param1.equals("")) {
                        param.args = byteArrayToString((byte[]) param.args).replace(param1, param2).getBytes();
                        log("--ineed--beforhookedmethod--" + param1 + "成功修改为" + param2);
                  }
                }

                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                  getvalue();
                  if (!byteArrayToString((byte[]) param.getResult()).equals("")) {
                        log(sb1 + "--ineed--加解密前:" + byteArrayToString((byte[]) param.args));
                        log("--ineed--加解密后:" + byteArrayToString((byte[]) param.getResult()));
                  }
                }
            });
      }
    }
上述代码即为我自己写的某个破解加解密过程的xposed模块部分代码,其中的packagename、param1、param2可以开发一个界面,随时修改,这样就不用每次遇到app都重新编写代码。由于懒得开发界面,直接使用了log打印,所以需要用eclipse或者androidstudio的logcat来查看,在打印log时添加一个关键词,比如我添加的“-ineed-”,这样在查看logcat时,可以搜索ineed,屏蔽无关log:当然,hook Cipher.doFinal()方法只能hook到部分app的加解密过程,因为不是所有app都用了这个方式。部分app的加密过程可能藏到了JNI(so文件)里,但是也有一个问题是,app必须先从java将明文作为参数传进JNI,通过某个接口调用JNI,返回加密的结果,我们可以去hook该接口。如下图,我分析某app反编译的源代码(混淆过)时发现,该app加密过程放进了JNI,加密的时候使用了com.csii.aesencryption.PEJniLib里的a方法(混淆过)调用csii_AESTelecomModule_v1.0.so对敏感参数进行加密,第一个参数为待加密的明文,返回值即为加密后的密文:于是,我开始编写hook代码,hook该方法。Hook代码与前面的代码相似,就不贴代码了,以一张截图来代替:我自己写了一个界面,可以在界面上输入要修改的明文参数,上图中的getvalue即从界面上获取param1和param2。比如我想将abc123修改成abc124:这种方法的优点是我们可以不用去查看加密的代码,不用管加密的算法是对称还是非对称,是aes还是什么开发自创的算法,只需要去hook加密的函数,直接替换参数,打印结果,简单粗暴,屡试不爽!3. JS弹窗       Web通常都是采用js进行加密操作(现在除了web,越来越多的移动app也开始采用H5来开发,使用js代码进行逻辑处理)。即使使用了安全控件,也一定有某个js方法去调用安全控件,通常这个方法的参数就包含加密的明文和密钥等,return返回值即为加密的密文,利用方式和前面第2种hook法类似,我们在这个这个方法里面加一行弹窗代码即可。比如如下js加密过程代码:Pass = Myencrypt(pass);Function Myencrypt(a){       …..}上述代码将密码输入框里面的密码pass加密成了密文Pass。我们的破解方式同样不需要管Myencrupt()方法里面的具体代码,只需要在该方法内第一行加入弹窗代码:Pass = Myencrypt(pass);FunctionMyencrypt(a){       a = window.prompt(“明文”,a);       …..}Window.prompt()的作用是弹出一个输入框,输入框的标题和默认值可以自定义,我们将a设置为默认值,这样就可以弹窗弹出输入的明文密码,同时可以任意修改这个明文,效果如下图所示:上图中,该app就使用了JS加密,将这一串报文内容加密后发往服务器。使用这一行代码,我们就能省去先抓包,分析代码,在写解密脚本,每次都把抓到的数据拿去解密的复杂操作过程。 以上就是3个我总结的破解加密的小技巧。文笔不够还请见谅。当然方式有很多,太晚了,今天就写到这儿,其他方式下次接着介绍。未完待续。。。

zldtb19931116 发表于 2018-9-25 11:26

Super_G. 发表于 2018-9-21 15:35
请问如果我的代码中想要使用app其中的加密方法,应该怎么做?

首先可以直接反编译app,把加密过程的代码拿出来直接调用,当然前提是app没有加固,其次,可以使用hook,hook这个加密过程,把加密的参数换成你想要加密的参数。

zldtb19931116 发表于 2018-9-25 11:27

凌乱的暖风 发表于 2018-9-21 11:57
看了第一次没看懂,但是我会继续看……

由于是word写完直接贴上来的,格式有点乱,把其中的代码格式化一下应该很容易懂

zldtb19931116 发表于 2018-9-21 11:33

格式有点乱,我是用word写了贴上来的,还请见谅

leonqp1030 发表于 2018-9-21 11:53

有干货,支持楼主!{:1_921:}

凌乱的暖风 发表于 2018-9-21 11:57

看了第一次没看懂,但是我会继续看……

wdlcshpzjfxx 发表于 2018-9-21 12:15

学习了,谢谢

mango88 发表于 2018-9-21 12:54

谢谢分享~

抱书人人 发表于 2018-9-21 12:57

谢谢分享,辛苦了

xeldax 发表于 2018-9-21 13:12

讲的很好,学习了。

飞翔的路灯 发表于 2018-9-21 13:21

夜夜终尽晨 发表于 2018-9-21 13:40

学习学习
共勉共勉
{:301_1009:}
页: [1] 2 3 4 5
查看完整版本: Android逆向中的加密问题解决办法