返回
Swift的开端:打造Alamofire抓包工具的初始步骤
IOS
2023-12-02 22:18:51
#Swift的开端:打造Alamofire抓包工具的初始步骤
了解Swift Runtime是跨越Swift开发难题的一项必备技能。加入我,利用Frida实现抓包工具,探究Swift HTTP库Alamofire的运作。
Swift Runtime是一个复杂而又全面的系统,它在很大程度上影响着Swift程序的行为。当涉及到网络通信时,Alamofire是一个很受欢迎的HTTP库,它为HTTP请求提供了便捷的方法。然而,Alamofire并不能提供抓包的功能,这使得调试和分析网络通信变得困难。
本文将介绍如何利用Frida实现一个简单的Alamofire抓包工具,这个工具可以打印GET/POST请求,并屏蔽SSL Pinning。
工具及环境
- Xcode 13
- Swift 5.5
- Frida 16.1.10
- python 3.9.12
创建Frida脚本
首先,我们需要创建一个Frida脚本来注入到Alamofire进程中。这个脚本将负责拦截网络请求并打印请求信息。
# Frida脚本
import frida
def on_message(message, data):
if message['type'] == 'send':
print("[*] Request:")
print(" Method:", message['payload']['method'])
print(" URL:", message['payload']['url'])
print(" Headers:")
for header in message['payload']['headers']:
print(" ", header, ":", message['payload']['headers'][header])
print(" Body:")
print(" ", message['payload']['body'])
elif message['type'] == 'reply':
print("[*] Response:")
print(" Status:", message['payload']['status_code'])
print(" Headers:")
for header in message['payload']['headers']:
print(" ", header, ":", message['payload']['headers'][header])
print(" Body:")
print(" ", message['payload']['body'])
# Attach to the Alamofire process
process = frida.get_usb_device().attach("Alamofire")
script = process.create_script("""
var URLRequest = ObjC.classes.NSURLRequest;
var NSURLConnection = ObjC.classes.NSURLConnection;
URLRequest.prototype.original_initWithURL = URLRequest.prototype['initWithURL:cachePolicy:timeoutInterval:'];
URLRequest.prototype.swizzled_initWithURL = function(url, cachePolicy, timeoutInterval) {
send({'type': 'send', 'payload': {
'url': url.toString(),
'method': this.HTTPMethod(),
'headers': this.allHTTPHeaderFields(),
'body': this.HTTPBody()
}});
return this.original_initWithURL.apply(this, arguments);
};
URLRequest.prototype.initWithURL = URLRequest.prototype.swizzled_initWithURL;
NSURLConnection.prototype.original_sendAsynchronousRequest = NSURLConnection.prototype['sendAsynchronousRequest:queue:completionHandler:'];
NSURLConnection.prototype.swizzled_sendAsynchronousRequest = function(request, queue, completionHandler) {
var task = this.original_sendAsynchronousRequest.apply(this, arguments);
task.original_completionHandler = completionHandler;
task.swizzled_completionHandler = function(response, data, error) {
send({'type': 'reply', 'payload': {
'status_code': response.statusCode(),
'headers': response.allHeaderFields(),
'body': data
}});
this.original_completionHandler.apply(this, arguments);
};
task.completionHandler = task.swizzled_completionHandler;
return task;
};
NSURLConnection.prototype.sendAsynchronousRequest = NSURLConnection.prototype.swizzled_sendAsynchronousRequest;
""")
script.on('message', on_message)
script.load()
# Start the Frida server
frida.run()
使用抓包工具
接下来,我们需要使用Frida服务器来注入脚本到Alamofire进程中。
- 打开终端,进入Frida服务器所在的目录。
- 执行以下命令来启动Frida服务器:
frida-server
- 打开Xcode,创建一个新的Swift项目。
- 在项目中导入Alamofire库。
- 在项目中添加以下代码:
import Alamofire
Alamofire.request("https://example.com") { (response, data, error) in
print(response)
print(data)
print(error)
}
-
运行项目。
-
在终端中,你会看到Frida服务器打印出请求和响应的信息。
屏蔽SSL Pinning
Alamofire默认情况下会对HTTPS请求进行SSL Pinning,这可以防止中间人攻击。然而,在某些情况下,我们可能需要屏蔽SSL Pinning。我们可以通过修改Frida脚本来实现这一点。
# Frida脚本
import frida
def on_message(message, data):
if message['type'] == 'send':
print("[*] Request:")
print(" Method:", message['payload']['method'])
print(" URL:", message['payload']['url'])
print(" Headers:")
for header in message['payload']['headers']:
print(" ", header, ":", message['payload']['headers'][header])
print(" Body:")
print(" ", message['payload']['body'])
elif message['type'] == 'reply':
print("[*] Response:")
print(" Status:", message['payload']['status_code'])
print(" Headers:")
for header in message['payload']['headers']:
print(" ", header, ":", message['payload']['headers'][header])
print(" Body:")
print(" ", message['payload']['body'])
# Attach to the Alamofire process
process = frida.get_usb_device().attach("Alamofire")
script = process.create_script("""
var URLRequest = ObjC.classes.NSURLRequest;
var NSURLConnection = ObjC.classes.NSURLConnection;
URLRequest.prototype.original_initWithURL = URLRequest.prototype['initWithURL:cachePolicy:timeoutInterval:'];
URLRequest.prototype.swizzled_initWithURL = function(url, cachePolicy, timeoutInterval) {
send({'type': 'send', 'payload': {
'url': url.toString(),
'method': this.HTTPMethod(),
'headers': this.allHTTPHeaderFields(),
'body': this.HTTPBody()
}});
return this.original_initWithURL.apply(this, arguments);
};
URLRequest.prototype.initWithURL = URLRequest.prototype.swizzled_initWithURL;
NSURLConnection.prototype.original_sendAsynchronousRequest = NSURLConnection.prototype['sendAsynchronousRequest:queue:completionHandler:'];
NSURLConnection.prototype.swizzled_sendAsynchronousRequest = function(request, queue, completionHandler) {
var task = this.original_sendAsynchronousRequest.apply(this, arguments);
task.original_completionHandler = completionHandler;
task.swizzled_completionHandler = function(response, data, error) {
send({'type': 'reply', 'payload': {
'status_code': response.statusCode(),
'headers': response.allHeaderFields(),
'body': data
}});
this.original_completionHandler.apply(this, arguments);
};
task.completionHandler = task.swizzled_completionHandler;
return task;
};
NSURLConnection.prototype.sendAsynchronousRequest = NSURLConnection.prototype.swizzled_sendAsynchronousRequest;
Interceptor.attachLoad()
""")
script.on('message', on_message)
script.load()
# Start the Frida server
frida.run()
然后,我们需要重新运行项目。在终端中,你会看到Frida服务器打印出请求和响应的信息,即使对于HTTPS请求也是如此。
结语
本文介绍了如何利用Frida实现一个简单的Alamofire抓包工具,这个工具可以打印GET/POST请求,并屏蔽SSL Pinning。希望本文能对你有所帮助。