验证试验 - 探求 fishhook 原理(二)

订阅的读者可加入 wechat 群,一起交流。发现小专栏的 LaTeX 偶现无法渲染,如果显示有问题再刷新一次即可。

示例 Demo Code

继续使用上一篇文中的代码示例:

#include <stdio.h>
#include "fishhook.h"
static int (*original_strlen)(const char *_s);
int new_strlen(const char *_s) {
    return 666;
}

int main(int argc, const char * argv[]) {
    struct rebinding strlen_rebinding = { "strlen", new_strlen,
        (void *)&original_strlen };
    rebind_symbols((struct rebinding[1]){ strlen_rebinding }, 1);
    char *str = "hellolazy";
    printf("%d\n", strlen(str));
    return 0;
}

运行之后将其生成的执行文件拖入 MachOView 中。对 Mach-O 进行解析。

Linkedit Base Address 计算

MachOViewLoad Commands -> LC_SEGMENT_64(__LINKEDIT) 中获取到以下值:

进行下列式(1)式(2)的计算:

$$
\begin{equation}
\left\{
\begin{array}{l@{\;=\;}l}
vmaddr=1000030000_{(hex)}\\
file\ offset=30000_{(hex)}
\end{array}
\right.
\end{equation}
$$

$$
\begin{equation}
\begin{aligned}
base\_address&=slide+vmaddr-file\ offset \\
&=slide+1000000000_{(hex)}
\end{aligned}
\end{equation}
$$

符号表、字符表和跳转表

继续看上文的这张图片:

此时,我们已经获取到了 Base Address,根据之前的流程,需要找到 __LINKEDIT Section 中的 Symbols 表、Indirect Symbols 表和 String 字符串表,这些地址我们需要在 Load Commands 中来获取。找到 LC_SYMTABLC_DYSYMTAB 这两个 Commaneds。

$$
\begin{equation}
\left\{
\begin{array}{l@{\;=\;}l}
symbol\_offset=symtab\_cmd\to symoff=12680_{(oct)}=3188_{(hex)}\\
indirect\_symbol\_offset=dysymtab\_cmd\to symoff =14008_{(oct)}=35B8_{(hex)}\\
string\_table\_offset=symtab\_cmd\to stringoff=13864_{(oct)}=3628_{(hex)}
\end{array}
\right.
\end{equation}
$$

$$
\begin{equation}
\left\{
\begin{array}{l@{\;=\;}l}
symbol\_base=base\_address+symbol\_offset=slide+100003188_{(hex)}\\
indirect\_symbol\_base=base\_address+indirect\_symbol\_offset=slide+1000035B8_{(hex)}\\
string\_table\_base=base\_address+string\_table\_offset=slide+100003628_{(hex)}
\end{array}
\right.
\end{equation}
$$

跳转表 nl 和 la 绑定符号基址

我们在 MachOView 中验证了三个表的位置。之后继续跟随着 fishhook 的思路来进行验证。下面将进入二尺遍历 Load Command 流程。这一次需要拿出的 Command 是 LC_SEGMENT(__DATA),目的是为了找到 __nl_symbol_ptr__la_symbol_ptr 这两个 Section 的位置。

$$
\begin{equation}
\left\{
\begin{array}{l@{\;=\;}l}
nl\_indirect\_sym\_index=13_{(oct)}\\
la\_indirect\_sym\_index=15_{(oct)}\\
\end{array}
\right.
\end{equation}
$$

$$
\begin{equation}
\left\{
\begin{array}{l@{\;=\;}l}
nl\_sym\_base\_addr&=nl\_indirect\_sym\_index\times size+indirect\_symbol\_base\\
&=13_{(oct)}\times 4 + (1000035B8_{(hex)}+slide)=1000035EC_{(hex)}+C\\
la\_sym\_base\_addr&=la\_indirect\_sym\_index\times size+indirect\_symbol\_base\\
&=15_{(oct)}\times 4 + (1000035B8_{(hex)}+slide)=1000035F4_{(hex)}+C\\
\end{array}
\right.
\end{equation}
$$

这里的 C 其实是上方 slide 常量的运算结果,由于在这个场景下 MachOView 验证时发现 slide = 0,但不意味着 slide 是一个恒为 0 的值。vmaddr_slide 的取值其实是地址空间布局随机化(ASLR)机制的结果,这是一种针对缓冲区溢出的安全保护技术,这里不再赘述。

top Created with Sketch.