运行期修改 iOS 进程中的指令或数据

| 分类 文档  | 标签 分享  iOS 

做个 mobile substrate 插件,然后用下面的方法在运行时修改指令或者数据,需要做 memory patch 外挂内挂倒挂什么的,直接看代码了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//
extern "C" kern_return_t mach_vm_region
(
 vm_map_t target_task,
 vm_address_t address,
 vm_size_t size,
 vm_region_flavor_t flavor,
 vm_region_info_t info,
 mach_msg_type_number_t infoCnt,
 mach_port_t object_name
 );

// template <typename TYPE> NS_INLINE bool FakeCode(TYPE *addr, TYPE code) { mach_port_t task; vm_size_t region_size = 0; vm_address_t region = (vm_address_t)addr;

<span class="cm">/* Get region boundaries */</span>

#if defined(MAC64) || defined(LP64) vm_region_basic_info_data_64_t info; mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64; if (mach_vm_region(mach_task_self(), &region, &region_size, flavor, (vm_region_info_t)&info, (mach_msg_type_number_t)&info_count, (mach_port_t)&task) != KERN_SUCCESS) { return false; } #else vm_region_basic_info_data_t info; mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT; vm_region_flavor_t flavor = VM_REGION_BASIC_INFO; if (vm_region(mach_task_self(), &region, &region_size, flavor, (vm_region_info_t)&info, (mach_msg_type_number_t)&info_count, (mach_port_t)&task) != KERN_SUCCESS) { return false; } #endif / Change memory protections to rw- / if (vm_protect(mach_task_self(), region, region_size, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY) != KERN_SUCCESS) { LineLog(); return false; }

<span class="cm">/* Actually perform the write */</span>
<span class="o">*</span><span class="n">addr</span> <span class="o">=</span> <span class="n">code</span><span class="p">;</span>

<span class="cm">/* Flush CPU data cache to save write to RAM */</span>
<span class="n">sys_dcache_flush</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">code</span><span class="p">));</span>

<span class="cm">/* Invalidate instruction cache to make the CPU read patched instructions from RAM */</span>
<span class="n">sys_icache_invalidate</span><span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">code</span><span class="p">));</span>

<span class="cm">/* Change memory protections back to r-x */</span>
<span class="n">vm_protect</span><span class="p">(</span><span class="n">mach_task_self</span><span class="p">(),</span> <span class="n">region</span><span class="p">,</span> <span class="n">region_size</span><span class="p">,</span> <span class="nb">false</span><span class="p">,</span> <span class="n">VM_PROT_EXECUTE</span> <span class="o">|</span> <span class="n">VM_PROT_READ</span><span class="p">);</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>

}

好了,修改方法有了,ARM64也支持了。但 Module Base 是变化的,对一个模块逆向工程后,如何确定运行时模块的基址呢?

——我也想知道……,不过我想了一个山寨的方法,先看到一个导出符号,作为参照基准,运行期获取这个导出符号,然后做一个差值计算,搞定:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
NS_INLINE uint8_t ModuleBase(NSString path, NSString refFunc, unsigned int refAddr = 0x1000)
{
    unsigned char base = (unsigned char *)dlsym(dlopen(path.UTF8String, RTLD_LAZY), refFunc.UTF8String);
    if (base == nil)
    {
        _Log(@"HOOK Base symbol not found");
        return nil;
    }

<span class="k">if</span> <span class="p">(((</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span><span class="n">base</span> <span class="o">&amp;</span> <span class="mh">0x0FF0</span><span class="p">)</span> <span class="o">!=</span> <span class="p">(</span><span class="n">refAddr</span> <span class="o">&amp;</span> <span class="mh">0x0FF0</span><span class="p">))</span>
<span class="p">{</span>
    <span class="n">_Log</span><span class="p">(</span><span class="err">@</span><span class="s">"HOOK Base symbol miss match: %p !=! %08X"</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="n">refAddr</span><span class="p">);</span>
    <span class="k">return</span> <span class="n">nil</span><span class="p">;</span>
<span class="p">}</span>

<span class="n">base</span> <span class="o">-=</span> <span class="n">refAddr</span><span class="p">;</span>
<span class="n">_Log</span><span class="p">(</span><span class="err">@</span><span class="s">"HOOK Base: %@ at %p"</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">base</span><span class="p">);</span>
<span class="k">return</span> <span class="n">base</span><span class="p">;</span>

}


上一篇     下一篇