Python 爬虫进阶必备 | 某公司爬虫工程师机试题解析第二部分( app逆向部分)

举报
xianyuplus 发表于 2021/10/24 15:07:52 2021/10/24
【摘要】 前奏上次写了某公司一面的机试题的前半部分,基础和 Js 逆向剩下的一题 app 的题目留在今天写 正文先看看题目下载并打开这个android app,点击send request按钮会发送http请求,请找出http请求中puzzle-sign header 字段的生成算法现在很明确就是这个 app 会发起请求,在请求的 header 中会有一个加密字段puzzle-sign,我们要把这个...

前奏

上次写了某公司一面的机试题的前半部分,基础和 Js 逆向

剩下的一题 app 的题目留在今天写

正文

先看看题目

下载并打开这个android app,点击send request按钮会发送http请求,请找出http请求中puzzle-sign header 字段的生成算法

现在很明确就是这个 app 会发起请求,在请求的 header 中会有一个加密字段puzzle-sign,我们要把这个字段的逻辑搞出来

下载完这个 app,先查个壳(没啥必要)

查壳结果没有加壳

拖到jadx里面反编译一下

直接检索关键词puzzle-sign

找到结果如下

只有一个匹配项,跟进去看下

这个就比较简单了,是对当前请求的 URL 地址进行了编码和拼接,之后再进行了 Base64 编码得出了Puzzle-Sign的值

现在我们用 frida hook 下okhttp3.Interceptor打印下request.url

直接用下面的脚本即可

function hook_okhttp3() {
    // 1. frida Hook java层的代码必须包裹在Java.perform中,Java.perform会将Hook Java相关API准备就绪。
    Java.perform(function () {

        // 2. 准备相应类库,用于后续调用,前两个库是Android自带类库,后三个是使用Okhttp网络库的情况下才有的类
        var ByteString = Java.use("com.android.okhttp.okio.ByteString");
        var Buffer = Java.use("com.android.okhttp.okio.Buffer");
        var Interceptor = Java.use("okhttp3.Interceptor");
        var ArrayList = Java.use("java.util.ArrayList");
        var OkHttpClient = Java.use("okhttp3.OkHttpClient");

        //  注册一个Java类
        var MyInterceptor = Java.registerClass({
            name: "okhttp3.MyInterceptor",
            implements: [Interceptor],
            methods: {
                intercept: function (chain) {
                    var request = chain.request();
                    try {
                        console.log("MyInterceptor.intercept onEnter:", request, "\nrequest headers:\n", request.headers());
                        var requestBody = request.body();
                        var contentLength = requestBody ? requestBody.contentLength() : 0;
                        if (contentLength > 0) {
                            var BufferObj = Buffer.$new();
                            requestBody.writeTo(BufferObj);
                            try {
                                console.log("\nrequest body String:\n", BufferObj.readString(), "\n");
                            } catch (error) {
                                try {
                                    console.log("\nrequest body ByteString:\n", ByteString.of(BufferObj.readByteArray()).hex(), "\n");
                                } catch (error) {
                                    console.log("error 1:", error);
                                }
                            }
                        }
                    } catch (error) {
                        console.log("error 2:", error);
                    }
                    var response = chain.proceed(request);
                    try {
                        console.log("MyInterceptor.intercept onLeave:", response, "\nresponse headers:\n", response.headers());
                        var responseBody = response.body();
                        var contentLength = responseBody ? responseBody.contentLength() : 0;
                        if (contentLength > 0) {
                            console.log("\nresponsecontentLength:", contentLength, "responseBody:", responseBody, "\n");

                            var ContentType = response.headers().get("Content-Type");
                            console.log("ContentType:", ContentType);
                            if (ContentType.indexOf("video") == -1) {
                                if (ContentType.indexOf("application") == 0) {
                                    var source = responseBody.source();
                                    if (ContentType.indexOf("application/zip") != 0) {
                                        try {
                                            console.log("\nresponse.body StringClass\n", source.readUtf8(), "\n");
                                        } catch (error) {
                                            try {
                                                console.log("\nresponse.body ByteString\n", source.readByteString().hex(), "\n");
                                            } catch (error) {
                                                console.log("error 4:", error);
                                            }
                                        }
                                    }
                                }

                            }

                        }

                    } catch (error) {
                        console.log("error 3:", error);
                    }
                    return response;
                }
            }
        });

        OkHttpClient.$init.overload('okhttp3.OkHttpClient$Builder').implementation = function (Builder) {
            console.log("OkHttpClient.$init:", this, Java.cast(Builder.interceptors(), ArrayList));
            this.$init(Builder);
        };

        var MyInterceptorObj = MyInterceptor.$new();
        var Builder = Java.use("okhttp3.OkHttpClient$Builder");
        console.log(Builder);
        Builder.build.implementation = function () {
            this.interceptors().clear();
            this.interceptors().add(MyInterceptorObj);
            var result = this.build();
            return result;
        };

        Builder.addInterceptor.implementation = function (interceptor) {
            this.interceptors().clear();
            this.interceptors().add(MyInterceptorObj);
            return this;
        };

        console.log("hook_okhttp3...");
    });
}
hook_okhttp3();

hook结果如下

这里打印了url地址,然后我们直接用 Python写好算法就可以了,这里的算法和上一篇的 sign 的算法类似,只不过最后的编码换成了Base64

这个可以参考上次的代码然后改改

def get_sign(time1, itemid):
    str1 = str(itemid) + 'easy' + str(time1)
    sign = ''
    for str_ in str1:
        sign = sign + chr(ord(str_) + 5)
    return sign

这个的一面的机试题还是比较简单的,不过覆盖的方面比较全,可以通过这套机试题筛选,节省面试双方的时间

这个点赞!!!

以上就是这个系列的全部内容了

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。