本帖最后由 mistaked 于 2024-04-13 22:37 编辑
一、控制台启动 这部分和4.6.2的差别不大 主要做两件事,一是去除Fiddler.WebUi.dll中的对文件篡改的校验,二是去除Fiddler.WebUi.dll文件自身被篡改的校验 虽然修改的地方变了,但是调试方式是一致的,所以过程就不赘述了,大家可以直接参考4.6.2的,这里直接贴出修改点 1. 文件篡改校验修改点 从下面的参数可以看到,A_0和A_1就是要进行对比的两个Hash值,通过修改二进制,直接将它变成A_0与A_0的对比 2. Fiddler.WebUi.dll自篡改校验修改点 这里粗暴点,直接将它变成 null == null,即永远返回 true 改完之后成功开启控制台 二、代{过}{滤}理服务器 4.6.2中,接口数据没有详细说是怎么抓的,在处理5.7.1过程中,这部分自己摸索了一遍
首先,在Network中可以看到,是有两个接口的,分别是 /versions和 /users,这两个接口也可以看到一些关于试用时间的相关数据, 只不过伪造了这两个接口后并不能进入到首页页面
而后在调试过程中,发现有些接口是直接从后端,也就是dll文件中直接发起的,这部分接口控制台无法抓取, 好在后端发起的接口的域名部分,依旧是前端 main.*.js 中控制的, 所以就有了个思路:起个代{过}{滤}理服务,将域名改成代{过}{滤}理服务地址,也就是127.0.0.1:port,代{过}{滤}理中将其转到真实地址,期间输出相关返回信息,用以构造接口数据
代{过}{滤}理转发可以继续使用node.js,不过要注意,如果需要引入非node自身的依赖包,需要手动到npm资源站下载js版依赖(ts的es6语法会引发报错), 下载后install下,通过绝对路径进行引入,方便起见,本人使用了flask,通过设置请求拦截器,转发并输出响应信息 @server.before_request def handle_before_request(): print('请求:(%s)%s' % (request.method, request.url)) print('请求路径:%s' % request.path) url = request.url.replace('http://127.0.0.1:56789', URL) headers = {'Host': 'api.getfiddler.com'} keys = [ 'Host', 'Api-Version', 'Authorization', 'Accept-Encoding', 'Traceparent', 'Content-Type', 'Content-Length', 'Connection', 'Sec-Ch-Ua', 'Accept', 'Sec-Ch-Ua-Mobile', 'User-Agent', 'Sec-Ch-Ua-Platform', 'Sec-Fetch-Site', 'Sec-Fetch-Mode', 'Sec-Fetch-Dest', 'Accept-Encoding', 'Accept-Language' ] for key in keys: if request.headers.get(key) is not None: headers[key] = request.headers.get(key) if 'Host' in headers: headers['Host'] = 'api.getfiddler.com' res = {} if request.method == "GET": res = requests.get(url, headers=headers) elif request.method == "POST": data = request.get_json() res = requests.post(url, json=data, headers=headers) g.res_headers = dict(res.headers) print('响应头(%s):%s' % (request.path, res.headers)) # 最开始['/versions', '/users'],后续拿到一个接口就把该接口加上 if request.path not in ['/versions', '/users', '/users/sign-in', '/trials/Everywhere/availability', '/push-notifications-configuration', '/composer-collections', '/snapshots', '/events', '/rulesets' ]: r = None try: r = res.json() except Exception as e: ... if r is not None: print('响应数据-json(%s):%s' % (request.path, r)) print('----------------------------------------------------------------------------') # h = dict(res.headers) # del h['Content-Encoding'] # del h['Vary'] # return res.content, 200, h return jsonify(r), 200, { 'Content-Type': 'application/json; charset=utf-8', # 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'Date': 'Fri, 05 Apr 2024 10:21:02 GMT', 'Server': 'Kestrel', # 'Content-Encoding': 'gzip', # 'Vary': 'Accept-Encoding', 'X-Date': 'Fri, 05 Apr 2024 10:21:02 GMT', 'Signature': 'SignedHeaders=content-type;x-date, Signature=AAAAWzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNsAzGwa7Q3iTZFqv3xYHemw/qxkwk0sIC/usJVi7713VJv0B1JbfuiDXxHfScNyyQjkuaHKtwbn5qUeHjFwpGYeSjYg07lS2j6uB6+K9EvBaf20D/Ra5CEA54/wqToSaXObvZFcZktqPq1rJ6ZbzEo4fljlk/ys8UzMje/YD0lz', 'api-supported-versions': '1.0', 'X-Cache': 'Miss from cloudfront', 'Via': '1.1 88cabd6b8652306789c6bc8090fbcb1a.cloudfront.net (CloudFront)', 'X-Amz-Cf-Pop': 'FRA56-P6', 'Alt-Svc': 'h3=":443"; ma=86400', 'X-Amz-Cf-Id': '9-7P1_bxpKtz2Vfu8sxbarAPcigAEdVVOiVWgzICZuYgZvZm3Z_crA==' } else: print('响应数据-text(%s):%s' % (request.path, res.text)) print('----------------------------------------------------------------------------') return res.text
调试过程中的几个问题 1. 转发时的报错 转发时的请求头选项Host要修正为api.getfiddler.com,而不是127.0.0.1 2. 响应结果被篡改 找到报错位置,最后一行改成返回true 3. FiddlerBackendSDK.dll的自篡改校验 4. 返回值引起的报错 接口/trials/Everywhere/availability的返回值要改成true,表示还在试用期,false会触发报错
5. 响应头引起的报错 开始想着尽量不动响应头,其实是给自己挖了坑 首先是"Content-Encoding": "gzip",这个响应头会触发后端采用```zip```算法去解析结果,而我们是直接构造的数据返回,显然无法被解析; 还有就是/snapshots和/composer-collections这两接口一直提示System.InvalidOperationException: The stream was already consumed. It cannot be read again.费了好大劲,最后发现是响应头引起的,只保留签名相关响应头就可以了
三、伪造服务器 将代{过}{滤}理服务器抓取的数据,重新构造成相关json文件,开启main.js中的伪造服务器,好了,完工
注:若转载请注明大神论坛来源(本贴地址)与作者信息。
|