gpt4 book ai didi

c++ - 如何从数据缓冲区执行 x86 命令?

转载 作者:可可西里 更新时间:2023-11-01 18:37:50 24 4
gpt4 key购买 nike

我的问题主要针对教授,是关于以“奇怪”的方式使用 C++。在 C++ 中,变量指针和函数指针之间并没有太大区别。我们可以像这样做一些无用的事情:

char* buff     = new char[32];
void (*func)() = (void (*)())buff;

但我们几乎创建了一个从未存在过的函数,对吧?如果我们更进一步,在文件中用 x86 命令 stord 填充 buff 会怎样?操作系统永远不会知道函数已创建。

#include <iostream>
using namespace std;

// no stack push'ing or pop'ing, nothing to return
void func(void){cout << "Hello?";}

int main()
{
char* x86_code = new char[6];

x86_code[0] = 0x9A; // call (far)
*((__int32*)(x86_code + 1)) = (__int32)func; // load 32-bit address
x86_code[5] = 0xC3; // ret

void (*x86_func)(void) = (void (*)(void))x86_code;
x86_func();

return 0;
}

调用 x86_func() 会产生运行时错误(违规读取位置 0xFFFFFFFF)。如果不是以这种方式,操作系统如何在 RAM 中加载它的二进制文件或模块?非常感谢。

最佳答案

事实上,您可以用 x86 机器代码填充一个数组并尝试执行它。它被称为 shellcode 并且设法让应用程序或库在不希望的情况下执行此类代码被称为“漏洞利用”。

不幸的是,这并不容易,因为现代硬件和操作系统通常会阻止您从可写区域(例如非常量字符数组)执行代码。这称为 W^X(写入或执行权限,但不能两者兼而有之)但是可以请求 POSIX 兼容的操作系统使用 mprotect() 函数禁用此类保护。这是一个有效的示例,因为它启用了对相关机器代码字节数组的读取、写入和执行权限:

#include <stdio.h>
#include <stdint.h>
#include <sys/mman.h>


typedef int(*FUNKY_POINTER)(void);


char shellcode[] = {
0xb8, 0x2a, 0x00, 0x00, 0x00, //mov $0x2a,%eax
0xc3 //retq
};



int main(void){
uintptr_t pageSize = 4096;
uintptr_t shellcodeAddr = (uintptr_t)shellcode;
uintptr_t pageAlignedAddr = shellcodeAddr & ~(pageSize-1);
FUNKY_POINTER shellcodeFn = (FUNKY_POINTER)shellcode;

/* Magic */
mprotect((void*)pageAlignedAddr,
(shellcodeAddr - pageAlignedAddr) + sizeof(shellcode),
PROT_EXEC|PROT_WRITE|PROT_READ);

printf("The answer to the ultimate question of life, "
"the universe and everything is %d\n",
shellcodeFn());

return 0;
}

关于c++ - 如何从数据缓冲区执行 x86 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20028892/

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