Frida调用Swift实例方法:Swift String构建与签名验证问题
Swift方法Hook与调用问题解答
原始Swift代码
@objc public class Write: NSObject { public let db: Database init(db: Database) { self.db = db } } public extension Write { func execute(sql: String) { db.execute(sql); } }
尝试的Frida脚本
const writeBlock = new ObjC.Block({ retType: 'void', argTypes: ['object'], implementation: function(write) { // We get the write instance from the transaction block var executeAddressByName = Module.findExportByName("MyModule","$s23MyModule10WriteC7execute3sqlWlE"); // Build swift structs var StringStruct = Swift.structs.String; var executeSQL = Swift.NativeFunction(executeAddressByName, 'void', ['pointer', StringStruct]); const sqlCommand = `DROP TABLE 'tableName';`; // Allocate memory for the SQL string and encode it as UTF-8. var sqlStringPointer = Memory.allocUtf8String(sqlCommand); var NSString = ObjC.classes.NSString; // Convert the SQL command to an NSString. var sqlString = NSString["+ stringWithUTF8String:"] (sqlStringPointer); executeSQL(write.handle, sqlString); }
问题
- 显然NSString无法满足要求,请问如何构建Swift String?
- 由于execute是实例方法,当前的NativeFunction签名是否正确?
解答
1. 构建Swift String的正确方式
直接使用Frida提供的Swift.fromString()API即可将JavaScript字符串转换为符合要求的Swift String结构体,无需手动处理NSString的转换逻辑,这是最简便且可靠的方式:
const sqlCommand = `DROP TABLE 'tableName';`; const swiftSqlString = Swift.fromString(sqlCommand);
如果要手动构造(不推荐,易出错),需要注意Swift String是包含指针、长度等字段的结构体,需分配内存并严格按照Swift的字符串布局填充,但Swift.fromString()已经封装了这些细节,优先使用即可。
2. 实例方法的NativeFunction签名修正
当前签名存在问题,正确的处理方式如下:
- Swift实例方法的第一个参数默认是
self(即实例本身),对应到NativeFunction的第一个参数应为实例的指针(通过write.handle获取); - 必须使用
Swift.NativeFunction而非普通NativeFunction,它会自动处理Swift的调用约定,避免因调用规则不匹配导致的崩溃; - 第二个参数类型是
Swift.structs.String,返回值void是正确的。
修正后的调用代码片段:
const executeAddressByName = Module.findExportByName("MyModule","$s23MyModule10WriteC7execute3sqlWlE"); const executeSQL = Swift.NativeFunction(executeAddressByName, 'void', ['pointer', Swift.structs.String]); // 构建Swift String const sqlCommand = `DROP TABLE 'tableName';`; const swiftSqlString = Swift.fromString(sqlCommand); // 调用实例方法 executeSQL(write.handle, swiftSqlString);
内容的提问来源于stack exchange,提问作者Hans Daigle
相关产品推荐
相关产品推荐

