gpt4 book ai didi

c - osx - 在分配的内存页上写入和执行

转载 作者:太空宇宙 更新时间:2023-11-04 03:37:42 25 4
gpt4 key购买 nike

我遇到了一个关于 OS X 上内存映射的问题。

我正在使用 mmap 调用来映射特定函数附近的内存区域。这个想法是稍后使用相对跳转jmp到这个分配的内存区域。代码:

void *alloc;
if((alloc = mmap((void*)func, 12, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0)) == MAP_FAILED)
printf("failed\n");

暂时没有问题。内存被映射到 func 附近,通过避免使用 MAP_FIXED 标志,内核将它放在附近的位置。

然后我简单地用E9操作码(jmp)+相对偏移量,通过减去函数(func)计算出一个shellcode地址和分配的区域(alloc)地址。

char jmp32[] = {
'\xE9', '\x00', '\x00', '\x00', '\x00'
};

int *offset = malloc(4);
*offset = (int)(alloc-func);

memcpy(jmp32+1, offset, 4);

shellcode 制作精良,可以放入内存中。

vm_protect(mach_task_self(), (vm_address_t)func, 16, 0, VM_PROT_ALL); //make function area writable

memcpy(func, jmp32, sizeof(jmp32)); // place the jmp

现在,一切似乎都很好,但是当我执行程序时(显然调用了 func):

(lldb) r
Process 3563 launched: './mempool' (x86_64) // don't mind the name, was using an old Xcode project
ffffffe9 //
60 //
43 // output there, as you can see, the shellcode is crafted fine!
03 //
00 //
Process 3563 stopped
* thread #1: tid = 0x15f3e, 0x0000000100035fff, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100036000)
frame #0: 0x0000000100035fff

因此,进一步调查:

(lldb) d -F intel -n test
mempool`test at main.c:97:
0x100000ca0: or dword ptr [rax + 0x43], esp //OR?!?
0x100000ca3: add eax, dword ptr [rax]
0x100000ca5: sub esp, 0x10
0x100000ca8: lea rdi, qword ptr [rip + 0x2c3] ; "culo here: %p\n"
0x100000caf: lea rax, qword ptr [rip - 0x16] ; test at main.c:97
0x100000cb6: mov rsi, rax
0x100000cb9: mov al, 0x0
0x100000cbb: call 0x100000ee4 ; symbol stub for: printf
0x100000cc0: mov dword ptr [rbp - 0x4], eax
0x100000cc3: add rsp, 0x10
0x100000cc7: pop rbp
0x100000cc8: ret

指令就在那里,在函数的开头,但它是一个OR。不是 JMP。更深入:

(lldb) mem read 0x100000ca0
0x100000ca0: 09 60 43 03 00 83 ec 10 48 8d 3d c3 02 00 00 48 .`C...?.H.=?...H
0x100000cb0: 8d 05 ea ff ff ff 48 89 c6 b0 00 e8 24 02 00 00 ..????H.ư.?$...

我们实际上可以看到 E9,又名 JMP 操作码被损坏为 09 操作码,代表 指令。

我得到了各种结果,但 E9 操作码总是被修改。我必须假设这是我前段时间读到的W^X 内存保护机制,对吧?另外,猜猜看,删除 mmap 调用中的 PROT_EXEC 标志会使操作码保持原样。

我真的不知道是否有任何方法可以解决这个问题,但我认为是有的,因为 mach_override完全按照我的意愿行事,从我在代码中看到的一点点来看,它使用内存分配在内存中跳转。我会进一步阅读代码,并尝试理解如何去做,但我很想听听这里有人的一个很好的解释!具体来说:

  1. 这是 W^X 特征吗?
  2. 是否有任何解决方法?
  3. 如果不是,mach_override 是怎么做的?

抱歉发了这么长的帖子,但我想清除所有内容。感谢任何能帮助我的人!

最佳答案

所以经过几个小时的代码阅读,我解决了它。正如我所料,答案在 mach_override 代码中。它使用了这段代码:

jumpRelativeInstruction |= 0xE900000000000000LL;
jumpRelativeInstruction |= ((uint64_t)offset & 0xffffffff) << 24;
jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);

手动制作一条 JMP 指令,准备好放入内存,并具有正确的字节顺序和所有内容。它完全避免了内存写入函数,例如可能执行检查的memsetmemcpy。然后,它最终使用指针解引用将其写入内存:

*originalFunctionPtr = jumpRelativeInstruction;

这会溢出到下一个函数操作码,覆盖它们。

因此,通过调整代码,我能够将其放入我的代码中,并最终将 JMP 放入分配的区域!

(lldb) r
Process 869 launched: './mempool' (x86_64)
alloc: 0x100035000
func: 0x100000bf0
hooked!
Process 869 exited with status = 0 (0x00000000)

关于c - osx - 在分配的内存页上写入和执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31038216/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com