├── 1.png ├── 10.png ├── 11.png ├── 12.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png ├── 9.png ├── 11(1).png ├── 12(1).png ├── 8(1).png ├── 9(1).png ├── 9(2).png ├── 9(3).png ├── README.md └── mpaas_request.py /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/1.png -------------------------------------------------------------------------------- /10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/10.png -------------------------------------------------------------------------------- /11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/11.png -------------------------------------------------------------------------------- /12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/12.png -------------------------------------------------------------------------------- /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/2.png -------------------------------------------------------------------------------- /3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/3.png -------------------------------------------------------------------------------- /4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/4.png -------------------------------------------------------------------------------- /5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/5.png -------------------------------------------------------------------------------- /6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/6.png -------------------------------------------------------------------------------- /7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/7.png -------------------------------------------------------------------------------- /8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/8.png -------------------------------------------------------------------------------- /9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/9.png -------------------------------------------------------------------------------- /11(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/11(1).png -------------------------------------------------------------------------------- /12(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/12(1).png -------------------------------------------------------------------------------- /8(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/8(1).png -------------------------------------------------------------------------------- /9(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/9(1).png -------------------------------------------------------------------------------- /9(2).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/9(2).png -------------------------------------------------------------------------------- /9(3).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnmsec/MpaasPentestTool/HEAD/9(3).png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MpassPentestTool 2 | mpass移动开发框架ios端抓包hook脚本 3 | 4 | 5 | 6 | 使用方法:链接数据线,开启burp设置监听端口,修改attach app名称,打开app运行脚本,开始抓包。 7 | 8 | # mpaas移动开发框架 IDA + Frida + burp 抓包方法 9 | 10 | - 随着市面的APP五花八门的加固手段越来越多,对渗透测试人员测试APP时构成了极大的困扰,常用的抓包方法现在基本已经无法抓取到明文数据包,大多数APP使用通信加密的方式来进行隐藏自己的数据流量,从而导致就算渗透测试人员截取到了对应的数据包,也无法理解其中的内容,无法对APP进行漏洞挖掘,为此我在网络上参考学习了一段时间,得到了一种十分通用的抓包改包方法。 11 | - 大家都知道,当一个APP的数据流量加密之后我们在抓包软件中看到的是密文形式,若要想解密->修改->加密这个过程并不容易,甚至需要对APP深入逆向才能解密出明文,那么换个思路,我们可不可以越过加解密过程直接去寻找明文数据呢?答案是肯定的,hook为我们带来了十分开阔的解密思路,不需要逆向出加密算法只需要在送入加密函数之前将明文数据hook住,再其上最修改,再送入加密函数,便可以达到修改数据包的目的。 12 | - 现在的加固方式多种多样,但是我们这样来看,移动APP测试无非就是安卓阵营和IOS阵营,几乎所有的加固方式都是针对安卓阵营的,IOS极少会有,原因是Appstore对APP的审核非常严格,导致IOS应用加固后面临无法上架应用商店的问题。回过头来看,移动端测试可以拆解为Android客户端、IOS客户端、服务端三个部分来进行测试,所以在测试服务端的时候,我们尽可能的选择IOS APP来进行服务端的检测(虽然OC没有明显调用关系),下面我给大家举的实战的例子就是IOS APP中如何通过一种特定的思路甚至大部分代码都不需要变动的方式来抓取明文数据包。 13 | - Mpaas是蚂蚁金服的移动开发平台,使用该架构开发的应用在测试过程中发现根本无法抓取到业务通信数据包,这比加密数据做的更绝,既然渗透测试人员通过设置HTTP代理的方式对应用进行测试,那干脆就不使用HTTP通讯协议,但是使用该方法依旧可以对mpaas应用进行正常渗透测试。 14 | - 本片文章用到的技术主要是HOOK,工具主要是Frida、Frida-ios-dump、BurpSuite。 15 | - 本文章不会细致说明某项技术及工具的详细用法(客户授权测试APP,同是mpaas脚本完成后测试了一把支**) 16 | 17 | #### 一、 首先将需要测试的APP在已经越狱的手机中安装,然后运行该APP,数据线连接电脑命令行使用命令 “frida-ps -U” 查看frida环境是否正常 18 | 19 | ![MpaasPentestTool](1.png) 20 | #### 二、 使用frida-ios-dump 进行砸壳 21 | 22 | ![MpaasPentestTool](2.png) 23 | #### 三、 使用解压文件解压生成的ipa文件,按文件大小排序,一般最大的就是Unix可执行文件。 24 | 25 | ![MpaasPentestTool](3.png) 26 | #### 四、 将该文件拖入IDA,寻找明文数据位置,通常在字符串中搜索request、response等关键字进行第一步的模糊查找工作,找到可疑的类可以先记录下来,一般带有request等关键字的类或方法都是用来发送请求的,IDA寻找过程略,这里我找到了:DTURLRequestOperation 27 | 28 | ![MpaasPentestTool](4.png) 29 | #### 五、 使用frida-trace 跟踪该类的所有方法,这时使APP发送数据包,如果过程中调用了你跟踪的类,就会打印出调用堆栈,在其中寻找可能跟发送请求传送数据有关的方法,这里我找到了:-[DTURLRequestOperation addHTTPBodyParameter:0x102bc0a20 forKey:0x102bc0ec0] 30 | 31 | ![MpaasPentestTool](5.png) 32 | #### 六、 在执行frida-trace的目录下有__handlers__文件夹,在该文件夹下有frida已经选择hook的所有方法,每个方法对应一个js(frida是利用js来进行hook的,若有初学者可先学习一下frida)。找到[DTURLRequestOperation addHTTPBodyParameter:forKey:]该方法的js,编辑修改使frida打印出该方法的输入参数值与类型: 33 | 34 | ![MpaasPentestTool](6.png) 35 | #### 七、 运行 frida-trace 查看,hook到了对应的请求(不要在意那串长的字符串,那是base64,最终这些数据会映射到burp里不要担心) 36 | 37 | ![MpaasPentestTool](7.png) 38 | #### 八、 发送数据包明文位置已经找到了,接受数据包必然会变成明文,才能正常进入业务逻辑,这里我也已经知道了response明文的位置 [DTURLRequestOperation responseString],过程略,刚才hook的是输入参数,这个方法hook的返回值 39 | 40 | ![MpaasPentestTool](8.png) 41 | 42 | ![MpaasPentestTool](8(1).png) 43 | #### 九、 现在到了比较关键的一步,就是我们现在用frida hook到了APP的明文数据,那么如何进行渗透测试呢?这个问题很简单,frida已经给我们准备好了,怎么做?看下面: 44 | - 使用python启动一个镜像http服务器 我的端口起在28080(就是发什么回什么的服务器) 45 | 46 | ![MpaasPentestTool](9.png) 47 | 48 | ![MpaasPentestTool](9(1).png) 49 | - 构建python脚本,在脚本中使用frida hook到数据(hook到的数据在js中),发送给python,并且接受python回传的数据替换原来参数的值。 50 | 51 | ![MpaasPentestTool](9(2).png) 52 | - python从js中获取hook到的明文数据,使用requests将明文数据作为http请求的body发送至127.0.0.1:28080,也就是镜像服务器,并且设置代理为burp的8080(这样burp就能抓到明文数据了,并且可以修改) 53 | 54 | ![MpaasPentestTool](9(3).png) 55 | - 将requests的返回值也就镜像服务器返回回来的你修改过的数据包,赋给原来的变量,APP的业务逻辑会继续运行。 56 | #### 十、 整理思路至此,其实就可以正常的抓包改包了,只需要运行着该脚本,就像挂着代理一样burp发挥他应有的功能。(不要拔掉数据线哦哈哈) 57 | 58 | ![MpaasPentestTool](10.png) 59 | #### 十一、 思路理清楚之后,其实主要的难点在于找到到hook点以及OC与JS之间的数据类型转换,尽量寻找NSString类型的方法参数或者是返回值,这样修改起来出错的可能比较小,当然复杂数据类型也可以进行hook,frida是个十分强大的hook工具,官方提供了说明文档对于复杂类型的数据类型转换: 60 | - OC字典转JS Json: 61 | 62 | ![MpaasPentestTool](11.png) 63 | - JS Json转OC 字典: 64 | 65 | ![MpaasPentestTool](11(1).png) 66 | #### 十二、 效果图 随便修改一下数据包证明是可以修改的 67 | 68 | ![MpaasPentestTool](12.png) 69 | 70 | ![MpaasPentestTool](12(1).png) 71 | - 按照此类方法,只要hook到明文数据,稍微简单修改一下代码中的js部分,再结合burp就可以愉快的进行渗透测试喽,再也不用去管什么加密不加密,协议不协议。不过从我已经完成这个hook代码目前看来是通杀mpaas的,尝试了三款mpaas app均可正常抓包改包,只需要替换attach的app名称即可。 72 | 73 | 74 | - 邮箱:jiaxingl@126.com 75 | - Github: https://github.com/lijiaxing1997 76 | -------------------------------------------------------------------------------- /mpaas_request.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | from http.server import HTTPServer, BaseHTTPRequestHandler 3 | import sys 4 | import requests 5 | import frida 6 | 7 | #By:Gr33k 8 | #mail:jiaxingl@126.com 9 | 10 | 11 | ECHO_PORT = 28080 12 | BURP_PORT = 8080 13 | 14 | 15 | class RequestHandler(BaseHTTPRequestHandler): 16 | def do_REQUEST(self): 17 | content_length = int(self.headers.get('content-length', 0)) 18 | 19 | self.send_response(200) 20 | self.end_headers() 21 | self.wfile.write(self.rfile.read(content_length)) 22 | 23 | do_RESPONSE = do_REQUEST 24 | 25 | 26 | def echo_server_thread(): 27 | print('start echo server at port {}'.format(ECHO_PORT)) 28 | server = HTTPServer(('', ECHO_PORT), RequestHandler) 29 | server.serve_forever() 30 | 31 | 32 | t = Thread(target=echo_server_thread) 33 | t.daemon = True 34 | t.start() 35 | 36 | session = frida.get_usb_device().attach('支付宝') 37 | 38 | script = session.create_script(''' 39 | 40 | 41 | try{ 42 | var className = "DTURLRequestOperation"; 43 | var funcName = "- addHTTPBodyParameter:forKey:"; 44 | 45 | var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]'); 46 | console.log("[*] Class Name: " + className); 47 | console.log("[*] Method Name: " + funcName); 48 | Interceptor.attach(hook.implementation, { 49 | onEnter: function(args) { 50 | var v = new ObjC.Object(args[2]); 51 | send({type: 'REQ', data: v.toString()}) 52 | var op = recv('NEW_REQ', function(val) { 53 | var s = val.payload; 54 | var new_s = ObjC.classes.NSString.stringWithString_(s); 55 | args[2] = new_s; 56 | }); 57 | op.wait(); 58 | }, 59 | onLeave: function(retval) { 60 | } 61 | }); 62 | 63 | 64 | var className1 = "DTURLRequestOperation"; 65 | var funcName1 = "- responseString"; 66 | var err = ObjC.classes.NSError.alloc(); 67 | 68 | var hook1 = eval('ObjC.classes.' + className1 + '["' + funcName1 + '"]'); 69 | console.log("[*] Class Name: " + className1); 70 | console.log("[*] Method Name: " + funcName1); 71 | Interceptor.attach(hook1.implementation, { 72 | onEnter: function(args) { 73 | 74 | }, 75 | onLeave: function(retval) { 76 | var re = new ObjC.Object(retval); 77 | 78 | send({type: 'RESP', data: re.toString()}); 79 | var op = recv('NEW_RESP', function(val) { 80 | var new_data = val.payload; 81 | var new_ret = ObjC.classes.NSString.stringWithString_(new_data); 82 | retval.replace(new_ret); 83 | 84 | }); 85 | op.wait(); 86 | 87 | } 88 | }); 89 | 90 | } 91 | catch(err){ 92 | console.log("[!] Exception2: " + err.message); 93 | } 94 | ''') 95 | 96 | def on_message(message, data): 97 | if message['type'] == 'send': 98 | payload = message['payload'] 99 | _type, data = payload['type'], payload['data'] 100 | 101 | if _type == 'REQ': 102 | data = str(data) 103 | r = requests.request('REQUEST', 'http://127.0.0.1:{}/'.format(ECHO_PORT), 104 | proxies={'http': 'http://127.0.0.1:{}'.format(BURP_PORT)}, 105 | data=data.encode('utf-8')) 106 | 107 | script.post({'type': 'NEW_REQ', 'payload': r.text}) 108 | 109 | 110 | 111 | elif _type == 'RESP': 112 | r = requests.request('RESPONSE', 'http://127.0.0.1:{}/'.format(ECHO_PORT), 113 | proxies={'http': 'http://127.0.0.1:{}'.format(BURP_PORT)}, 114 | data=data.encode('utf-8')) 115 | 116 | script.post({'type': 'NEW_RESP', 'payload': r.text}) 117 | 118 | 119 | script.on('message', on_message) 120 | script.load() 121 | sys.stdin.read() 122 | --------------------------------------------------------------------------------