MacOS动态注入的三种方式及hook方案

1.静态注入

https://cloud.tencent.com/developer/article/1193647
insert_dylib 将dylib注入到二进制文件中生成新的二进制。

2.DYLD_INSERT_LIBRARIES动态注入

https://blog.nswebfrog.com/2018/02/09/make-injection-app-for-mac/

  1. xcode创建一个dynamic的的项目

主要注入的代码如下:

#import "libwechatInject.h"

@implementation libwechatInject

__attribute__((constructor)) void myentry() {
    NSLog(@"AAAAAAAAAAAAAAAAAAAAAAA!!!");
}

@end
  1. 新建要重启动的项目app

放置我们要注入的动态链接库,新建一个文件夹,命名为 WeChatInject.app,并创建一个子文件夹,名字叫 Contents 在 WeChatInject.app/Contents 下创建一个名为 Frameworks 的文件夹,将动态链接库 libQQInject.dylib 拷贝到这个文件夹中。
在这里插入图片描述
编写好启动脚本
在 WeChat.app/Contents 下新建文件夹 MacOS,然后在这个文件夹下新建一个 shell 脚本文件,名字为 WeChatInject 并赋予执行权限

#!/bin/sh
CurrentAppPath=$(cd $(dirname $0) && cd .. && pwd)
DYLD_INSERT_LIBRARIES=${CurrentAppPath}/Frameworks/liblibwechatInject.dylib     /Applications/WeChat.app/Contents/MacOS/WeChat

在这里插入图片描述
3.运行App
双击WeChatInject运行即可。最后可以在系统控制台打印的日志中看到我们的自定义的hook消息。注意有时消息出现在控制台。

4.修改系统 Dock 图标
首先发现的一个问题就是,App 运行后,系统 Dock 图标不是 WeChat 的图标,而是一个默认的应用图标。解决这个问题办法就是在 WeChatInject.app/Contents 下新建一个 Info.plist 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>LSUIElement</key>
	<true/>
</dict>
</plist>

再次运行 WeChatInject.app 后,系统 Dock 上已经是 WeChat 的图标了。

3.使用动态库注入

osx dylib injection 向进程中注入dylib 不动原二进制,高权限无修改的注入。
https://github.com/scen/osxinj
用法:Usage: ./osxinj [proc_name] [lib]


一种hook方案

计算新旧函数之间的距离 进行跳转
http://thomasfinch.me/blog/2015/07/24/Hooking-C-Functions-At-Runtime.html

#include <stdio.h>
#include <dlfcn.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

//Set this to 0 if you don't want to see log messages
const int PRINT_INFO = 1;

int hookReplacementFunction() {
    printf("Calling replacement function!\n");
    return 3;
}

//Print the first 16 bytes after the given address
static void printBytes(int64_t *address) {
	int i;
    for (i = 0; i < 4; i++) {
        printf("*(address+%d):\t%08x\n", i * 4, htonl((int)*(address+i)));
    }
}

__attribute__((constructor))
static void ctor(void) {
    if (PRINT_INFO)
        printf("Injection dylib constructor called.\n");

    //"If filename is NULL, then the returned handle is for the main program."
    void *mainProgramHandle = dlopen(NULL, RTLD_NOW);

    //Get a pointer to the original function using dlsym
    int64_t *origFunc = dlsym(mainProgramHandle , "hookTargetFunction");
    if (PRINT_INFO)
        printf("Original function address: 0x%llx\n", (int64_t)origFunc);

    //Get a pointer to the replacement function
    int64_t *newFunc = (int64_t*)&hookReplacementFunction;
    if (PRINT_INFO)
        printf("Replacement function address: 0x%llx\n", (int64_t)newFunc);

    //Calculate the relative offset needed for the jump instruction
    //Since relative jumps are calculated from the address of the next instruction,
    //  5 bytes must be added to the original address (jump instruction is 5 bytes)
    int32_t offset = (int64_t)newFunc - ((int64_t)origFunc + 5 * sizeof(char));
    if (PRINT_INFO)
        printf("Offset: 0x%x\n", offset);

    //Make the memory containing the original funcion writable
    //Code from http://stackoverflow.com/questions/20381812/mprotect-always-returns-invalid-arguments
    size_t pageSize = sysconf(_SC_PAGESIZE);
    uintptr_t start = (uintptr_t)origFunc;
    uintptr_t end = start + 1;
    uintptr_t pageStart = start & -pageSize;
    mprotect((void *)pageStart, end - pageStart, PROT_READ | PROT_WRITE | PROT_EXEC);
    
    if (PRINT_INFO) {
        printf("Before replacement: \n");
        printBytes(origFunc);
    }

    //Set the first instruction of the original function to be a jump
    //  to the replacement function.
    //E9 is the x86 opcode for an unconditional relative jump
    int64_t instruction = 0xe9 | offset << 8;
    *origFunc = instruction;

    if (PRINT_INFO) {
        printf("After replacement: \n");
        printBytes(origFunc);
    }
}

参考:
https://www.exchen.net/ios-hacker-动态库-dylib-注入.html

https://wooyun.js.org/drops/OS X平台的Dylib劫持技术(下).html

hook:
https://theevilbit.github.io/posts/dyld_insert_libraries_dylib_injection_in_macos_osx_deep_dive/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值