fishhook

动态符号绑定:
__nl_symbol_ptr是指向非延迟绑定数据的指针数组(这些指针在加载库时绑定)。
__la_symbol_ptr是指向导入函数的指针数组,通常在第一次调用该符号时由名为dyld_stub_binder的例程填充(也可以在启动时告诉dyld绑定这些指针)。

!symtab_cmd || !dysymtab_cmd || !linkedit_segment || !dysymtab_cmd->nindirectsyms

// 找到linkedit的头地址
uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;

dyld: the dynamic link editor

动态链接的基本实现:
LC_LOAD_DYLINKER 指定dyld路径
LC_LOAD_DYLIB 加载dylib

dyld加载命令:

struct dylinker_command {
	uint32_t	cmd;				/* LC_ID_DYLINKER, LC_LOAD_DYLINKER or  LC_DYLD_ENVIRONMENT */
	uint32_t	cmdsize;			/* includes pathname string */
	union lc_str    name;		/* dynamic linker's path name */
};

dylib加载命令

struct dylib_command {
	uint32_t	cmd;			/* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, LC_REEXPORT_DYLIB */
	uint32_t	cmdsize;		/* includes pathname string */
	struct dylib	dylib;		/* the library identification */
};

//name 放在加载命令最后,lc_str是告诉偏移位置。加载命令是4字节倍数,字符串填充后,不满足这要求,填充0来满足4字节倍数。
struct dylib {
    union lc_str  name;						/* library's path name 名字*/
    uint32_t timestamp;						/* library's build time stamp 构建的时间戳*/
    uint32_t current_version;			/* library's current version number 版本号*/
    uint32_t compatibility_version;	/* library's compatibility vers number 兼容的版本号*/
};

加载命令 dylinker_command(LC_LOAD_DYLINKER) dylib_command(LC_LOAD_DYLIB)

加载命令 dysymtab_command(LC_DYSYMTAB)

struct dysymtab_command {
	uint32_t	cmd;
	uint32_t	cmdsize;
	
	...
	uint32_t	indirectsymoff;	// 指向间接符号表位置
	uint32_t	nindirectsyms; // 间接符号表里元素的个数
};

got la_symbol_ptr

外部数据地址放到got(Non-Lazy Symbol Pointers)
外部函数地址都放到la_symbol_str(Lazy symbol Pointers)

fishhook

A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.

fishhook 用到LINKEDIT去计算基址。LC_SEGMENT_64 (_LINKEDIT)

LINKEDIT segment是link editor在链接时创建生成的segment, 这个段包含了符号表(symtab), 间接符号表(dysymtab),字符串表(string table)等

找nl_symbol_ptr(got)/la_symbol_ptr

#define S_NON_LAZY_SYMBOL_POINTERS 	0x6
#define S_LAZY_SYMBOL_POINTERS			0x7

value = IndirectSymbolTable[got.section_64.reserved1];

计算基址
找到符号表、字符串表、间接符号表
找到nl_symbol_ptr(got), la_smbol_ptr

  // 本来是:基址=linkedit内存地址 - linkedit的fileoff
  //由于ASLR:真实基址 = 基址 + slide
  uintptr_t linkedit_base = (uintptr_t)slide + linkedit_segment->vmaddr - linkedit_segment->fileoff;
  
  //根据真实基址,得到符号表、间接符号表、字符串表的虚拟内存地址
  nlist_t *symtab = (nlist_t *)(linkedit_base + symtab_cmd->symoff);
  
  char *strtab = (char *)(linkedit_base + symtab_cmd->stroff);
  uint32_t *indirect_symtab = (uint32_t *)(linkedit_base + dysymtab_cmd->indirectsymoff);

x64 传参

当参数少于7个时, 参数从左到右放入寄存器: rdi, rsi, rdx, rcx, r8, r9。
当参数为7个以上时, 前 6 个与前面一样, 但后面的依次从 “右向左” 放入栈中,即和32位汇编一样。

ref

https://juejin.cn/post/6844903922654511112 MachO动态链接
https://juejin.cn/post/6844903926051897358 fishhook原理
http://abcdxyzk.github.io/blog/2012/11/23/assembly-args/ x64传参
https://blog.csdn.net/liaoshengshi/article/details/39989797

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值