去哪儿APP 算法初探窥镜

前言

  1. 本文仅供学习参考,如有侵权,请私信删除。
  2. 由于版权问题,本文所展示的代码并非完整代码,也不提供相关工具。

初探

拿到APP后,首先就是抓个包看看,到底有哪些参数。结果啥参数也没有,所有请求全部加密~如图所示!
抓包截图

根据抓包,可以发现请求URL格式为:https://slugger.qunar.com/slugger-proxy+服务接口名称,并且POST数据均加密,将POST数据强转为字符串发现前面均为a1907开头。

代码分析定位

  1. 以截图的请求为例:https://slugger.qunar.com/slugger-proxy?qrt=f_flight_rn_domestic_flightlist,请求中的接口服务名称为f_flight_rn_domestic_flightlist。
  2. 将APP反编译后在某类中发现如下可疑代码:
public enum FlightServiceMap implements IServiceMap {

	FLIGHT_LIST_RN_INLAND("f_flight_rn_domestic_flightlist", "com.mqunar.atom.flight.modules.search.searchforward.entity.CloneableBaseResult");
	
	private final String mClassName;
    private Class<? extends BaseResult> mClazz;
    private final Class<? extends AbsConductor> mTaskType;
    private final String mType;

    private FlightServiceMap(String str, String str2) {
        this(r7, r8, str, str2, PatchHotdogConductor.class);
    }

    private FlightServiceMap(String str, String str2, Class<? extends AbsConductor> cls) {
        this.mType = str;
        this.mClassName = str2;
        this.mTaskType = cls;
    }

    public final String getDesc() {
        return this.mType;
    }

    public final Class<? extends BaseResult> getClazz() {
        if (this.mClazz == null) {
            try {
                this.mClazz = getClass().getClassLoader().loadClass(this.mClassName);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return this.mClazz;
    }

    public final Class<? extends AbsConductor> getTaskType() {
        return this.mTaskType;
    }
}

可以看见这段代码中有几个方法,根据这几个方法反跟,在某类中发现如下代码:

    public static boolean b(PSearchParams pSearchParams) {
        return fa.contains(pSearchParams.serviceMap.getDesc());
    }

在继续反跟上面的b方法,在某类中发下如下代码:

public final void b(HotdogConductor hotdogConductor, boolean z) {
                    if (a.b(pSearchParams)) {
                        try {
                            this.d.jsonResult = new String(hotdogConductor.getResult(), "utf-8");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                        QLog.d("presearch-remote-onMsgResult", "rn接口-结果:" + this.d.jsonResult, new Object[0]);
                    }
                    super.onMsgResult(hotdogConductor, z);
                }

到这里发现了可疑代码hotdogConductor.getResult(),紧接着跟进这个hotdogConductor对象的类中看看,发现了一段加密代码,此时终于感觉到了一丝光明~~

    private byte[] encodeContent(byte[] bArr) {
        if (bArr == null) {
            bArr = new byte[0];
        }
        return Goblin.sand(bArr);
    }

好了,Goblin.sand(bArr)方法就是加密的,跟进去这个对象类看下,发现是调用的so库(正常操作,一般加密算法都在so库中),以下是该类的完整代码:

public class Goblin {
    public static native String SHR();

    public static native String d(String str, String str2);

    public static native String dPoll(String str);

    public static native byte[] da(byte[] bArr);

    public static native String dn(byte[] bArr, String str);

    public static native byte[] dn1(byte[] bArr, String str);

    public static native byte[] drift(byte[] bArr);

    public static native String duch(String str);

    public static native String e(String str, String str2);

    public static native String ePoll(String str);

    public static native byte[] ea(byte[] bArr);

    public static native byte[] eg(byte[] bArr);

    public static native String es(String str);

    public static native String espirt(String str);

    public static native int getCrc32(String str);

    public static String getLibName() {
        return "goblin_6_1_1";
    }

    public static native String getPayKey();

    public static native String roller(String str);

    public static native byte[] sand(byte[] bArr);

    public static native String ve(String str);

    public static native String version();

    static {
        try {
            System.loadLibrary(getLibName());
        } catch (UnsatisfiedLinkError e) {
            e.printStackTrace();
        }
    }
}

方法是不是有点多?不知道到底哪个方法对我们有用?这里经过一系列测试验证,最后得出了结论,“da”方法用于解密,“ea”方法用于加密,“sand”方法用于加密POST数据,另外APP还调用了“drift”方法,用于不明,感觉也是加密,以及“version”方法只返回了“alpha”字符串。

测试结果图,可以发现“sand”方法返回的和POST数据是一样的。
res
参考资料:
https://www.52pojie.cn/thread-805388-1-1.html
https://www.uedbox.com/post/11146/
https://wooyun.js.org/drops/%E4%B8%80%E6%AC%A1app%E6%8A%93%E5%8C%85%E5%BC%95%E5%8F%91%E7%9A%84Android%E5%88%86%E6%9E%90%EF%BC%88%E7%BB%AD%EF%BC%89.html

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值