facebook 的 fishhook ,可在运行时,动态修改外部 c 函数

用 C 写的

本文剖析下,用 swift 写的 fishhook

本文首要参阅 woshiccm/FishHook, swift 写的

功能上,跟 Facebook 的 FishHo安全ok, 间隔大,

可用于了解 Facebook 的 FishHook

原理:

C 言语是静态言语,编译时决git教程议了函数的地址

由于 iOS 体系做了github一些 Mach-O 加载上的优化,即动态链接特性,

运用动态链接的特性,fishhook 在运行时,动态修改外部 c 函数

简略了解github是干什么的,动态链接 dynamic loader

C 言语是静态言语,编译时决议了内部的 C 言语函数的地址

外部的 C 言语函数,编译时没有决议啦,可修改其符号地址

外部的 C 言语函数,在同享缓存库里边

编译的时分,函数的完毕,指向一个符号,符号对应的地址不能供认

动态链接的时ios模拟器分,体系会修改符号对应的地址,为其实践地址

运行时,fishhook 动态修改外部 c 函数,也便是修改符号对应的地址

MachOView,学习 fishhook 的好帮手

MachOView 可在 Mac 上,检查 Mach-O 文件的格局信息

fishhook swift 源代码简略剖析,合作 MachOView

ios是什么意思单了解 Mach-O 文件的内部布局

Mach-O 文件,首要分为两种段 segment

放程序的, text 段

放数据的, data 段

fishhook 动态修改,当然只能修改 data 段

运用 fishhook 常缓存视频怎样转入本地视频见的有两个表,缓存整理加载表和懒github中文官网网页加载表

  • 加载表,Non-Lazy Symbol Pointers,

加载表的符号,一跑程序,体系把实践的函数地址,都处理好了

  • 懒加载表, La, Lazy Symbol Point缓存文件在哪里ers,

懒加载表的符号,当用到那个函数的时分,体系才去找实践的函数地址

完毕:

该 swift 写的,算初步 hook 住了

特征:
  • swift 言语, 去 hook ,调用常规不好写

函数的 convention,比 C 的 fishhook 稍费事些

  • swift 版,很多用到指针

由于 swift 是安全的言语,指针处理比 C 的fishhook 稍费事些

C 的 fishhook,转化便当

代码:

调用都是,

拿到旧的函数( 待替换 ),

拿到新的函数 ( 替换为,咱们需求的 )

再来个变量记载 ( 把待替换的函数地址,保存下 )

获取信息
pubgiteelic struct Rebinding {
let name: String   // 需 HOOK 的函数名称
let replacement: UnsafeMutaios最好玩的手游bleRawPointer    // 新函数的地址的ios模拟器指针
var replaced: UnsafeMutableRawPointer?   /ios14.4.1更新了什么/ 原始函数地址的指针
}
操作 Mach-O 二进制文件

拿到记载的信息,去 hook

public func _rebindSymbol(_ rebinding:安全座椅立法规则 Rebinding) {
// 判别是不是,第一次github是干什么的调用
if currentRebinding == nil {
currentRebinding = rebinding
// 第一次调用需求注册, dyld 关于镜像文件的回调
_dgithub是干什么的yld_register_func_for_add_image(rebindSymbolForImage)
} else {
currentRebinding = rebinding
// 遍历现已加载的 image, 进行 hook
for i in 0..<_dyld_imiOSage_count() {
rebindSymbolFor缓存视频怎样转入本地视频Image(_dyld_get_image_header(i), _dyld_get_image_vmaddr_slide(i))
}
}
}

进行 hook

首要从 Macho-O 文件中找到对应的懒加载符号安全教育渠道段、非懒加载符号段、符缓存视频兼并app下载号表、动态符号表和字符串表

由于苹果的规划,不能直接得到需求的内容github,只能沿着相应的途径一步步寻找,得到想要的值。

查表比较繁琐


func rebindSymbolForIios8备忘录mage(_ mh: UnsafePoiios最好玩的手游nter<m缓存视频兼并ach_header>?, _ slide:Int) {
guaios下载rd let mh = mh else { return安全教育渠道登录进口 }
// 界说几个变量,从 Mach缓存文件在哪里O 里边找
var curSegCmd: UnsafeMut安全ablePointer<segment_command_64>!
var linkeditSegment: UnsafeMutablePointer<segment_command_64>!
var symtabC缓存整理md: Unsafioslauncher14安卓版eMutablePointer<symtab_command>!
var dysymtabCmd: UnsafeM安全utablePointegithub中文官网网页r<dysymtab_command>!
// cur 是一个指针,寄存的地址 = pageZero + ASLR的值 + mach_header_64 的大小,
// 可得 Lo缓存整理ad Commands 的地址
var cur = UnsafeRawPointer(mh).advanced(by: Memogit命令ryLayoutGit<ma缓存视频兼并app下载ch_header_64>.stride)
// 遍历 commands ,
// 供认 linkedit、symtab、dysymtab
// 这几个 command 的方位
for _: UInt32 in 0 ..< mh.pointee.ncmds {
curSegCmd = UnsafeMutableRawPointer(mutating: cur).assumingMemoryBound(to: segmios是什么意思ent_command_64.self)
cur = UnsafeRawPointer(cur).advanced(by: Int(curSegCmd.pointee.cmdsize))
if curSegCmd.pointee.cmd == LC_SEGMENT_64 {
let segname = String(cStr安全教育ing: &ampgiti;curSegCmd.pointee.segname, maxLength:github中文官网网页 16)
if segname == SEG_LINKEDIT {
linkeditSegment = curSegCmd
}
}安全期计算器 else if curSegCmd.pointee.cmd == LC_SYMTAB {
symtabCmd = UnsafeMutablgithub永久回家地址eRawPointer(mutating: curSegCmd).assumingMemoryBound(ios模拟器to: symtab_command.self)
} eios模拟器lse if curSegCmd.pointee.cmd == LC_DYSYMTAB {
dygitlabsymtabCmd = UnsafeMutableRawPointer(mutating: curSegCmd).assgit教程umingMemoryBound(to: dysymtab_command.self)
}
}
// 方才获取的,有一项为空, 直接返回
guard linkeditSeg缓存视频怎样转入相册ment != nil, symtabCmd != nil, dysymtabCmd != nil else {
return
}
// 链接时程序的基址 = __git教程LINKEDIT.VM_Address + silde的改动值 -__LINKEDIT.Fileios最好玩的手游_Offset
let linkeditBase = slide + Int(linkeditSegment.point安全教育ee.vmaddr) - Int(linkeditSegment.pointee.缓存视频兼并f安全ileoff)
// 符号表的地址 = 基址 + 符号表偏移量
let sy安全期计算器mtab = UnsafeMutablePointer<nlist_64>(bitPattern: linkeditBase + Int(symtagiti轮胎bCmd.ioslauncher14安卓版pointee.symoff))
// 字符串表的地址 = 基址 + 字符串表偏移量
let strtab = UnsafeMutablePointer<UInt8>(bitPattern: linkeditBase + Int(symtabCmd.pointee.stroff))
// 动态符号表地址 = 基址 + 动态符号表gitee偏移量
let indirectSymtab = UnsafeMutablePointer<UInt3安全教育2>(bitPattern: linkeditBase + Int(dysymtabCmd.pointee.indirectsymoff))
guard let _symtagithub怎样下载文件b = symtab, let _strtab = strtab, let _indirectSymtab = indirectSymtab e缓存视频怎样转入本地视频lse {
returnios是什么意思
}
// 重置 cur,
// 回到 logithub直播渠道永久回家adCommand 初步的方位
cur = UnsafeRawPointer(mh).advanced(by: MemoryLayout<mach_header_64>.stride)
for _: UI安全出产法nt32 in 0 ..<git教程 mh.pointee.ncmds {
curSegCmd = UnsafeMutableRawPointer(mutating: cur)ios模拟器.assumingMemoryBound(to: segment_command_64.self)
cur = UnsafeRawPoiios下载nter(cur).advanced(by: Int(curSegCmd.pointee.cmdsizeios体系))
if curSegCmd.pointee.cmd == LC_SEGMENT_64 {
let segname = String(cString: &curSegCmGitHubd.pointee.segname, maxLength: 16)
if segname == SEG_DATA {
// 寻找到 data 段
forioslauncher下载 j in 0..<curSegCmd.pointee.nsect安全座椅立法规则s {
// 遍ios下载历每一缓存的视频怎样保存到本地个 section header
let cur = UnsafeRawPointer(curSegCmd).advanced(by: MemoryLayout<segment_comGitHubman安全教育d_64>.size + Int(j))
let section = UnsafeMutableRagithub中文官网网页wPointer(mutating: cur).assumingMemoryBound(to: section_64github官网.self)
if sect缓存视频变成本地视频ion.pointee.flags == S_LAZY_SYMBOL_POINTERS || section.pointee.flags == S_NON_LAZY_SYMBios8备忘录OL_POINTERS {
// 找懒加载表
// 和非懒加载表
performRebindingWithSection(section, slide: slide, symtab: _symtab, strtab: _strtab, indirectSios下载ymtab: _indirectSymtabgithub打不开)
}
}
}
}
}
}

完毕函数交流,与保存旧的函数地址指安全期是哪几天

func performRebiioslauncher下载ndingWithS安全期计算器ection(_ section: UnsafeMutablePointer<section_64>,
slide: Int,
symtab: UnsafeMutablePointer<nlist_64>,github是干什么的
strtab: Unsaf安全手抄报eMutablePointer<UInt8>,
indirectSymtab: Unsafgithub中文官网网页eMutablePointer<UInt32>) {
guard var rebigiti轮胎nding = currgithub怎样下载文件entRebinding, let symbolBytes = rebinding.name.data(using: String.Enco安全教育渠道登录ding.utf8)?.map({ $0 }) else {
return
}
//   nl_symbol_ptr ( 加载表 )github中文官网网页 和 la_symbol_ptr  ( 懒加载表 )section 中的 reserved1 字段,iOS
//   标明对应的 indirect symbol tabios下载le 起始的 index
let indirecioslauncher14安卓版tSymboGitlIndices = indirectSymtab缓存.advanced(by: Int(section.pointee.reserved1))
//  slide + section->addr ,  便是
// 符号对应的函数完毕的数组,
// 即找到了相应的 __nl_symbol_ptr 和 __la_symbol_ptr 表里边的函数git命令指针,可去找函数的地址
let indgithub直播渠道永久回家irectSymbolBindings = UnsafeMutablePointer<UnsafeMutableRawPointer>(bitPattern: slide+Int(secti安全出产法on.pointee.addr))
gu安全教育渠道登录ard let _indirectSymbolBindigit教程ngs = indiregithub中文社区ctSymbolBindings else {
rgithub敞开私库eturn
}
// 遍历 section 里边的每一个符号
for i in 0..<Int(section.pointee.size)/MemoryLayout&github官网lt;Unsagithub永久回家地址feMutableRgithub永久回家地址awPointer>.size {
//  找到符号在 Indrect Sym安全座椅立法规则bol Table 表的值
//  读取 indirect table 的数据,得到符号在 DATA 段中 section 的方位 (gitee 适用于懒加载表,和非懒加载表github中文官网网页)
let symtabIndex = indirectSymbolIndices.advanced(by: i)
if symtagiti轮胎bIndex.pointee == INDIRECT_SYMBOL_ABS || symtabIndgithub永久回家地址ex.pointee == INDIRECT_SYgithub怎样下载文件MBOL_LiOSOCAL {
continue;
}
// 以 sgithub永久回家地址ymtab_index 作为安全教育下标,访问 symbol table
let strtabOffset = symtgit教程ab.advanced缓存视频变成本地视频(by: Int(symtabIndex.pointee)).pointee.n_un.n_strx
// 获取符号名 symbol_ios14name
lgithub下载et symbolNam缓存视频在手机哪里找e = strtab.advan安全座椅立法规则ced(by: Int(strtgitiabOffset))
var isEqual = true
for i in 0..<symb安全出产法olBytes.count {
if symbolBytes[iGitHub] != s缓存的视频怎样保存到本地ymbolName.adgitivan安全期计算器ced(by: i+1).pointee {
//  判别旧方法名,和符号名不一致
isEquaios体系l = false
}
}
if isEqual {
// 保存的旧函数的完毕,有了
rebinding.replaced = _indirectSymbolBindings.advanced(by缓存视频变成本地视频: i).pointee
// 新函缓存视频数,交流好了
_igithub永久回家地址ndirectSymbolBindings.advanced(by: i).initialize(to: rebindgithub是干什么的ing.replacement)
}
}
}
看作用:

image list , 拿程序的首地址ios最好玩的手游

MachOView 拿符号的偏移

x/1gx, 找到符号的地址

dis, 反汇编下

材料挺多的

github repo