【PoRE】Lab7: Packet Sniffing

回到目录

内容总结

  • 这一课主要围绕着应用层协议HTTP、传输层协议TCP和UDP展开的,并且介绍了BurpSuite这一工具。大部分内容应该和《计算机网络安全》(名字可能每届会改)课程有所重复。

Lab简介与参考

  • 这个Lab一共分成两个部分,都会围绕着BurpSuite展开。
  • Task 1.1: Find two secrets in the app
      Task 1需要我们输入一个用户名和密码。
    【PoRE】Lab7: Packet Sniffing
      最开始漫无头绪,先随意输入一个内容后发送,用BurpSuite拦截返回的应答包,发现是一串没有意义的字符串,这就联想到可能有加密和解密的操作。于是使用jadx反编译apk,发现有调用BabyCipher.decode()进行解密。将返回到的内容解密一下:
    【PoRE】Lab7: Packet Sniffing
      提示我们,试图用GUEST进行登录。于是继续试探,将用户名改为GUEST,密码随意输入:
    【PoRE】Lab7: Packet Sniffing
      发现还有提示,提示我们密码是TEMP_PASSWD!是不是觉得这个Task 1就如此简单呢?显然并不可能。将用户名和密码改为提示一致时,发现每次返回的结果仍是图3所示的结果。
      这就十分令人震惊了,但事出有因——代码里一定有“陷阱”!于是查看代码,发现了一个问题:
    【PoRE】Lab7: Packet Sniffing
      这里调用的一个replace十分显眼,而我们输入的密码(TEMP_PASSWD)中,恰有下划线’_’,这就会被换成’#’,于是我们屡次尝试只能屡次失败。之后就要解决这个问题。
      事实上这个问题至少可以有两种解决方案:一个是通过BurpSuite拦截和修改报文,这个方案应该是本Lab的初衷。不过我当时没有想到这一点,现在也没有进行测试,将发送报文中的被替换成#的密码换回去。
      这里我当时使用了第二个方案:修改代码。既然罪魁祸首是这个replace,把它给换了就行。于是前往修改Smali代码:
    【PoRE】Lab7: Packet Sniffing
      将这里面万恶的replace()调用给注释掉。随后运行就能顺利得到flag了!

  关于BurpSuite拦截和修改报文的方法,大家可以查看另一篇学姐写的博客。链接见注释1

  • Task 1.2: Buy secret
      进入Task 1的第二个阶段,需要我们去“购买”密钥。
    【PoRE】Lab7: Packet Sniffing
      此时点击按钮,会显示“WHO ARE YOU?”。这个结果也不奇怪,因为上面页面显示的学号有误。同样地,也可以通过修改发送的报文以修改学号,但这里与之前一致,诉诸Smali代码的修改来实现。
    【PoRE】Lab7: Packet Sniffing
      随后继续发送,返回的报文会提示金钱不够。于是去修改代码中的金钱部分。
    【PoRE】Lab7: Packet Sniffing
      继续发送,发现返回的flag仍不理想,并且得到了来自助教的嘲讽(这张图一定得贴出来!)!
    【PoRE】Lab7: Packet Sniffing
      问题在哪呢?发现在启动的SecretActivity中的onClick()函数内,找到了一个is_fake的选项,并且初始化还是1。这个应该就是问题所在了……继续修改Smali代码:
    【PoRE】Lab7: Packet Sniffing
      最后就能成功了!

  以修改Smali代码的方法破解的话,最后的UI会显示出我们修改的学号、金钱数。这个与Task 2就会产生冲突。使用BurpSuite拦截修改的话就不会有这个问题。

  • Task 2: Write a Burp Suite extension
      这个Task可能是继Android Programming之后最难的一个Task了,因为要求我们去写一个BurpSuite的插件。尽管助教很善良地给了我们一些参考文档,但是想要迅速地啃懂那些参考文档,的确需要耐心。
      关于BurpSuite插件的一些参考文档,BurpSuite本身就已经提供了不少。在Extender - APIs下可以找到。
    【PoRE】Lab7: Packet Sniffing
      因此对于我来说,这一个Task也是一次学习的经历:组织已有的APIs进行开发,这个也更符合真实情境。因此我也建议读者们能够自己尝试一次,如果尝试有误再诉诸帮助。如果您看到了这里,建议暂停,自己尝试一次。
      助教本身提供了一个实现IHttpListener接口的类的“模板”,不过当时我没有看到,于是从零开始写了一个实现IProxyListener接口的类,也是可以跑通的。这里不多做解释,直接贴代码了。如果有关于函数本身的问题,可以在图11所示的BurpSuite提供的APIs里查阅。2
package burp;

import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

public class BurpExtender implements IBurpExtender, IProxyListener {
    private static final String SecretChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
    private IExtensionHelpers helpers;
    private int flag;
    private final String name = "PoRE's BurpExtender";

    private static String encode(byte[] bArr) {
        int i;
        StringBuffer stringBuffer = new StringBuffer(((bArr.length + 7) * 8) / 5);
        int i2 = 0;
        int i3 = 0;
        while (i2 < bArr.length) {
            int i4 = bArr[i2] >= 0 ? bArr[i2] : bArr[i2] + 256;
            if (i3 > 3) {
                i2++;
                i3 = (i3 + 5) % 8;
                i = ((i4 & (255 >> i3)) << i3) | ((i2 < bArr.length ? bArr[i2] >= 0 ? bArr[i2] : bArr[i2] + 256 : 0) >> (8 - i3));
            } else {
                int i5 = i3 + 5;
                i = (i4 >> (8 - i5)) & 31;
                i3 = i5 % 8;
                if (i3 == 0) {
                    i2++;
                }
            }
            stringBuffer.append(SecretChars.charAt(i%32));
        }
        return stringBuffer.toString();
    }

    @Override
    public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
        helpers = callbacks.getHelpers();
        callbacks.setExtensionName(name);
        callbacks.registerProxyListener(this);
    }

    @Override
    public void processProxyMessage(boolean messageIsRequest, IInterceptedProxyMessage message) {
        IHttpRequestResponse request = message.getMessageInfo();
        if (messageIsRequest) {
            IRequestInfo analyzedRequest = helpers.analyzeRequest(request);
            String url = analyzedRequest.getUrl().toString();
            if ("http://49.235.197.28:80/lab7/login.php".equals(url)) {
                //TASK 2.1
                flag=0;
                byte[] requestBytes =
                        helpers.updateParameter(request.getRequest(), helpers.buildParameter("msg",
                                encode(helpers.stringToBytes("username=GUEST&password=TEMP_PASSWD")),
                                IParameter.PARAM_BODY));
                request.setRequest(requestBytes);
            }
            else if ("http://49.235.197.28:80/lab7/buySecret.php".equals(url)) {
                //TASK 2.2
                flag=1;
                byte[] requestBytes =
                        helpers.updateParameter(request.getRequest(), helpers.buildParameter("msg",
                                encode(helpers.stringToBytes("user_id=19307130005&money=12345&is_fake=0")),
                                IParameter.PARAM_BODY));
                request.setRequest(requestBytes);
            }
            else {
                // Other cases. Ignore it.
                return;
            }
        }
        else {
            if (flag == 1) {
                return;
            }
            byte[] responseBytes = request.getResponse();
            IResponseInfo analyzedResponse = helpers.analyzeResponse(responseBytes);
            int offset = analyzedResponse.getBodyOffset();
            StringBuilder stringBuilder = new StringBuilder();
            for (int i=0;i<offset;i++) {
                stringBuilder.append((char)responseBytes[i]);
            }
            String body = "{\"result\":1,\"message\":\"success\",\"id\":\"19307130005\",\"Secret1\":\"flag{e43y_p4ck37_sn1ff1Ng}\",\"money\":1}";
            stringBuilder.append(encode(helpers.stringToBytes(body)));
            byte[] returnResponse = helpers.stringToBytes(stringBuilder.toString());
            request.setResponse(returnResponse);
        }
    }
}

  至此完成了本Lab的所有内容。


  1. 请点击我 ↩︎

  2. 如果您和我一样,也是在Task 1中通过修改Smali代码实现的,那么请在Task 2中使用最初始的apk,否则会有干扰。 ↩︎

上一篇:lombok 实验性注解之 @Helper


下一篇:自定义laravel 辅助函数,模板调用