将 Dylib 注入到 Rosetta 下运行的进程中

问题描述 投票:0回答:1

我需要将动态库注入专门针对 x86_64 指令集的进程中。我的主机架构是aarch64。

我尝试使用以下 C++ 代码进行注入...


#define CHKERR(x) if (kr != KERN_SUCCESS) {std::cout << kr << std::endl; return x;};

#define STACK_SIZE 0x1000

#define asm_pthread_offset 6
#define asm_dylib_offset 19
#define asm_dlopen_offset 39
#define asm_mach_thread_self_offset 51
#define asm_thread_suspend_offset 66


inject_result inject_dylib(int pid, const char *dylib_path) {

    task_t remoteTask;
    struct stat buf;

    // check if the dynamic library exists...
    int check = stat(dylib_path, &buf);
    if (check != 0)
        return INJECT_ERROR_NOT_FOUND;

    mach_error_t kr = 0;

    // request the task port of the target process...
    kr = task_for_pid(mach_task_self(), pid, &remoteTask);
    CHKERR(INJECT_ERROR_MACH_TASK);

    // allocate space for library path in the task
    mach_vm_address_t dylib_address;
    kr = mach_vm_allocate(remoteTask, &dylib_address, strlen(dylib_path) + 1, 1);
    CHKERR(INJECT_ERROR_GENERIC)

    // write library path into the task
    kr = mach_vm_write(remoteTask, dylib_address, (vm_offset_t)dylib_path, strlen(dylib_path)+1);
    CHKERR(INJECT_ERROR_GENERIC)

    mach_vm_address_t stack_address;
    kr = mach_vm_allocate(remoteTask, &stack_address, STACK_SIZE, 1);
    CHKERR(INJECT_ERROR_STACK_ALLOC)

    unsigned char asm_instructions[ 100 ] =
            "\x55"                                          // push %rbp
            "\x48\x89\xe5"                                  // mov %rbp, %rsp
            "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00"      // mov %rax, _pthread_set_self
            "\xff\xd0"                                      // call %rax
            "\x5d"                                          // pop %rbp
            "\x48\xbf\x00\x00\x00\x00\x00\x00\x00\x00"      // mov %rdi, dylib_address
            "\x48\xbe\x02\x00\x00\x00\x00\x00\x00\x00"      // mov %rsi, 2
            "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00"      // mov %rax, dlopen
            "\xff\xd0"                                      // call %rax
            "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00"      // mov %rax, mach_thread_self
            "\xff\xd0"                                      // call %rax
            "\x48\x89\xc7"                                  // mov %rdi, %rax
            "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00"      // mov %rax, thread_suspend
            "\xff\xd0"                                      // call %rax
    ;

    // allocate space for assembly instructions...
    mach_vm_address_t code_address;
    kr = mach_vm_allocate(remoteTask, &code_address, sizeof(asm_instructions), 1);
    CHKERR(INJECT_ERROR_CODE_ALLOC)

    // set some values in our assembly instructions...
    mach_vm_address_t pthread_set_self_address = (mach_vm_address_t) dlsym(RTLD_DEFAULT, "_pthread_set_self");
    mach_vm_address_t mach_thread_self_address = (mach_vm_address_t) mach_thread_self;
    mach_vm_address_t thread_suspend_address = (mach_vm_address_t) thread_suspend;
    mach_vm_address_t dlopen_address = (mach_vm_address_t) dlopen;

    memcpy(&asm_instructions[asm_pthread_offset], &pthread_set_self_address, sizeof(mach_vm_address_t));
    memcpy(&asm_instructions[asm_dylib_offset], &dylib_address, sizeof(mach_vm_address_t));
    memcpy(&asm_instructions[asm_dlopen_offset], &dlopen_address, sizeof(mach_vm_address_t));
    memcpy(&asm_instructions[asm_mach_thread_self_offset], &mach_thread_self_address, sizeof(mach_vm_address_t));
    memcpy(&asm_instructions[asm_thread_suspend_offset], &thread_suspend_address, sizeof(mach_vm_address_t));


    kr = mach_vm_write(remoteTask, code_address, (vm_offset_t)asm_instructions, sizeof(asm_instructions));
    CHKERR(INJECT_ERROR_GENERIC)

    kr = mach_vm_protect(remoteTask, code_address, sizeof(asm_instructions), 0, VM_PROT_EXECUTE | VM_PROT_READ);
    CHKERR(INJECT_ERROR_GENERIC)

    // create thread, set registers, and start
    thread_t thread = {0};

    x86_thread_state64_t thread_state = {0};
    thread_state.__rip = code_address;
    thread_state.__rdi = stack_address;
    thread_state.__rsp = stack_address;
    thread_state.__rbp = stack_address;

    kr = thread_create_running(remoteTask, x86_THREAD_STATE64, (thread_state_t) &thread_state, x86_THREAD_STATE64_COUNT, &thread);
    CHKERR(INJECT_ERROR_CREATE_THREAD)

    mach_port_deallocate(mach_task_self(), remoteTask);

    return INJECT_SUCCESS;
}

函数

create_thread_running
出现问题,始终返回错误 4 (
KERN_INVALID_ARGUMENT
)。这是因为arm64版本的XNU内核不支持
x86_THREAD_STATE64
作为线程状态风格。

我通过挖掘内核源代码确认了这是问题。您可以看到

x86_THREAD_STATE64
不包含在任何 switch case 中,它默认为
KERN_INVALID_ARGUMENT

此功能或注入方法有任何兼容的替代方案吗?

c++ apple-m1 dylib xnu rosetta
1个回答
0
投票

GitHub用户LIJI32成功实现Rosetta注入。

他们的代码是这里。

© www.soinside.com 2019 - 2024. All rights reserved.