某教务管理系统APP逆向分析之协议漏洞 2018·2

0x01前言

马上开学了,整理一下假期自己研究的成果,希望在安卓逆向分析这条路上能走得更远。

声明:文章仅供技术研究,切勿非法利用!

0x02功能协议分析

app登录后进入appCenter的界面,内有九个图标

某教务管理系统APP逆向分析之协议漏洞 2018·2_第1张图片

 

1.“我的成绩”协议分析

用fd抓包工具,抓取手机的http和https协议。
这里我登录完帐号后,点击“我的成绩”按钮,fd抓到了这个url请求。

某教务管理系统APP逆向分析之协议漏洞 2018·2_第2张图片

发现这是一个GET包,我把链接地址贴出来,uid部分隐藏

http://ydjwapp.hznu.edu.cn/login_sso.aspx?procode=002&type=1&choice=XS0205&uid=20162104♦♦♦♦♦&role=XS&key=C3840551F78846DFAABA84C9A81B4F06&time=1520081445
 

2.分析url的参数

没错,key这个参数格外引人注目,前面的无非是uid不同,choice之类的是成绩查询的代号,time这个参数和现行时间戳很像,但是位数不够,等会分析。

0x03深入APK

首先用APK改之理载入分析我们分析的这个app

1.参数key的寻找

搜索结果太多了,于是我换个思路,上面既然是GET请求,那么会不会有&key这个常量的保存呢?于是很巧,找到了一处我们要找的关键地方

某教务管理系统APP逆向分析之协议漏洞 2018·2_第3张图片

 

2.进入这处的java源码
贴图部分为openURL()的部分源码,但是可以清除看到里面str1基本上就是刚才提交url的地址了。因为里面包含了procode,choice,uid,key,time这些参数,而这些参数正是上面url的get请求数据部分。

某教务管理系统APP逆向分析之协议漏洞 2018·2_第4张图片

这里贴上openURL()的全部代码:
 

  private void openURL()
  {
    this.time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    String str3 = this.url + "&" + "time=" + this.time;
    Object localObject = getMapParam(this.url);
    if (str3.indexOf("?") != -1)
    {
      str1 = (String)((Map)localObject).get("procode");
      String str2 = (String)((Map)localObject).get("choice");
      localObject = (String)((Map)localObject).get("uid");
      if ((str1 != null) && (str1.equals("002")))
      {
        str3 = String.valueOf(new Date().getTime()).substring(0, 10);
        Log.e("@@@@@@@@@@@@@@@@@@@@", String.valueOf(str3));
        str1 = o.a(str1 + str2 + (String)localObject + "DAFF8EA19E6BAC86E040007F01004EA" + str3);
        Log.e("@@@@@@@@@@@@@@@@@@@@", str1);
        str1 = this.url + "&" + "key=" + str1 + "&" + "time=" + str3;
        openUrlWithWebview(this.detailView, str1);
        Log.e("WebModuleOaActivity", str1);
        return;
      }
      if ((str1 != null) && (str1.equals("006")))
      {
        str1 = p.a(str1 + str2 + (String)localObject + this.time + "DAFF8EA19E6BAC86E040007F01004EA");
        Log.e("snstimepublickey", str1);
        str1 = new StringBuilder(String.valueOf(this.url)).append("&").append("key=").append(str1).append("&").append("time=").append(this.time).toString() + "&tgc=" + t.a(getApplicationContext(), "catgc", "tgc");
        openUrlWithWebview(this.detailView, str1);
        Log.e("WebModuleOaActivity", str1);
        return;
      }
      str1 = str3 + "&tgc=" + t.a(getApplicationContext(), "catgc", "tgc");
      openUrlWithWebview(this.detailView, str1);
      Log.e("WebModuleOaActivity", str1);
      return;
    }
    String str1 = this.url + "&tgc=" + t.a(getApplicationContext(), "catgc", "tgc");
    openUrlWithWebview(this.detailView, str1);
    Log.e("WebModuleOaActivity", str1);
  }

 

0x04HOOK关键函数

1.找到关键函数

某教务管理系统APP逆向分析之协议漏洞 2018·2_第5张图片

PartⅠ. a()方法

某教务管理系统APP逆向分析之协议漏洞 2018·2_第6张图片

Part Ⅱ . openUrlWithWebview()方法

某教务管理系统APP逆向分析之协议漏洞 2018·2_第7张图片

2.写hook模块准备拦截上述两个函数的传参和返回值

    static int i = 1;

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        if(!loadPackageParam.packageName.equals("com.hzsfdx.jw")){
            return;
        }
        XposedBridge.log("Load app:----->"+loadPackageParam.packageName+" 加载完毕");
        findAndHookMethod("com.zfsoft.core.d.o", loadPackageParam.classLoader, "a", String.class,  new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("----第"+(i++)+"次拦截----");
                XposedBridge.log("a方法 传入参数:"+param.args[0]);
                XposedBridge.log("a方法 返回参数:"+param.getResult());
            }
        });
        findAndHookMethod("com.zfsoft.webmodule.controller.WebModuleOaFun", loadPackageParam.classLoader, "openUrlWithWebview", WebView.class, String.class, new XC_MethodHook() {
            @Override
            protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                XposedBridge.log("openUrlWithWebview方法 传入参数:"+param.args[1]);
            }
        });

    }

 

3.在模拟器中测试查看拦截数据

 

某教务管理系统APP逆向分析之协议漏洞 2018·2_第8张图片

 

第一次拦截参数分析
str1 002
str2 XS0205
(String)localObject 20162104♦♦♦♦♦
const str DAFF8EA19E6BAC86E040007F01004EA
time 1520088144

----->com.hzsfdx.jw 加载完毕

----第1次拦截----
a方法 传入参数:002XS020520162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088144
a方法 返回参数:ECC9D8F62A45091ED3EA35B691105318
openUrlWithWebview方法 传入参数:
http://ydjwapp.hznu.edu.cn/login_sso.aspx?procode=002&type=1&choice=XS0205&uid=20162104♦♦♦♦♦&role=XS&key=ECC9D8F62A45091ED3EA35B691105318&time=1520088144
----第2次拦截----
a方法 传入参数:002XS020820162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088165
a方法 返回参数:818348171E471F392C23CBFF99EA3E36
openUrlWithWebview方法 传入参数:
http://ydjwapp.hznu.edu.cn/login_sso.aspx?procode=002&type=1&choice=XS0208&uid=20162104♦♦♦♦♦&role=XS&key=818348171E471F392C23CBFF99EA3E36&time=1520088165
----第3次拦截----
a方法 传入参数:002XS020420162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088169
a方法 返回参数:1CE6D9F428DF5294E66D88C0653574BC
openUrlWithWebview方法 传入参数:

http://ydjwapp.hznu.edu.cn/login_sso.aspx?procode=002&type=1&choice=XS0204&uid=20162104♦♦♦♦♦&role=XS&key=1CE6D9F428DF5294E66D88C0653574BC&time=1520088169

 

0x05核心加密算法

1.明确加密方法a()

借用上面第一次a方法拦截到的参数

002XS020520162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088144
可知这个参数包含5个参数,进入到o这个类中的a()加密运算后返回给str1,后面str1再拼接成完整的GET请求的url。

某教务管理系统APP逆向分析之协议漏洞 2018·2_第9张图片

2.用Elipse模拟a()方法

 

来到com.zfsoft.core.d.o这个类,在Elipse中新建类,命名为o,拷贝通过jd-gui反编译过来的java源码,会发现很多处不合理的代码,如:

	    if (paramInt >= j)
	    {
	      a(e, paramArrayOfByte, i, 0, j);
	      a(e);
	      i = j;
	      if (i + 63 >= paramInt)
	      {
	        j = i;
	        i = k;
	      }
	    }
	    for (;;)
	    {
	      a(e, paramArrayOfByte, i, j, paramInt - j);
	      return;                                   //这里return显然不合理,后面的操作会影响结果的。
	      a(arrayOfByte, paramArrayOfByte, 0, i, 64);
	      a(arrayOfByte);
	      i += 64;
	      break;
	      j = 0;
	    }

这里我是用到了JEB 1.5强大的反编译工具,

上面的代码变成了如下:

	    if(paramInt >= j) {
            o.a(o.e, paramArrayOfByte, i, 0, j);
            o.a(o.e);
            for(i = j; i + 63 < paramInt; i += 64) {
                o.a(arrayOfByte, paramArrayOfByte, 0, i, 64);
                o.a(arrayOfByte);
            }
        }
        else {
            int v10 = i;
            i = 0;
            k = v10;
        }

        o.a(o.e, paramArrayOfByte, k, i, paramInt - i);

可读性变强了很多,这里要修改的地方还有别的三处,就不一一陈列了,当时调试了一个下午,才改完的。

3.执行Main函数测试a方法

	public static void main(String[] args) {
		System.out.println(o.a("002XS020520162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088144"));
	}

前面记录的数据:
a方法 传入参数:002XS020520162104♦♦♦♦♦DAFF8EA19E6BAC86E040007F01004EA1520088144
a方法 返回参数:ECC9D8F62A45091ED3EA35B691105318
测试成功截图:

某教务管理系统APP逆向分析之协议漏洞 2018·2_第10张图片

 

0x06实战协议

通过学号和当前时间戳取前十位以及前面的固定参数做一个key的加密计算,
拼接url提交网页即可访问到正确的结果。

0x07总结

明确关键位置,Hook拦截传参,以及加密结果返回值,能为我们更好分析部分参数的生成以及提交GET请求参数的拼接。
后面要学习安卓动态调试了,Hook要先放一段落。
加油,每天进步一点点!
今天开学第一天,2018年3月5日 14:38:08。
安卓逆向,我在路上!

你可能感兴趣的:(安卓逆向,安卓HOOK)