我正在生成用于缓冲区溢出执行的机器代码,并希望有一种快速简便的方法将字节码插入程序,并查看其在我的主机上如何运行。
我寻找了在C ++中动态生成函数的方法,并在此very interesting answer中遇到了这个问题。它已经被否决了很多,似乎没有人质疑他们的话。
但是,当尝试实现他们在我自己的程序中编写的内容时,出现错误“表达式不能用作函数”。
这是我的代码:
int main()
{
uint8_t machinecode[] = {0x90, 0x0F, 0x01};
*reinterpret_cast<void**>(&machinecode)();
return 0;
}
答案 0 :(得分:2)
就编译的代码有效性而言,希望我能正确理解您的问题,您需要转换为可调用对象,在这种情况下,该对象为void(*)()
,而不仅仅是void*
,并且您需要额外的一组括号:
(*reinterpret_cast<void(*)()>(bytecode))();
请参见here live,但是即使在您提供的上下文中,我也不确定这是您实际上要运行的东西。
答案 1 :(得分:1)
SkepticalEmpiricist的回答是正确的,并解决了编译问题,因此我将其标记为正确。
但是,我要做的是创建一个函数,用于使用// OK \o/
type OmitLastArg<FnType> =
FnType extends () => infer R
? () => R :
FnType extends (last: infer L) => infer R
? () => R :
FnType extends (a: infer A, last: infer L) => infer R
? (a: A) => R :
FnType extends (a: infer A, b: infer B, last: infer L) => infer R
? (a: A, b: B) => R :
FnType extends (a: infer A, b: infer B, c: infer C, last: infer L) => infer R
? (a: A, b: B, c: C) => R :
FnType extends (a: infer A, b: infer B, c: infer C, d: infer D, last: infer L) => infer R
? (a: A, b: B, c: C, d: D) => R :
FnType extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, last: infer L) => infer R
? (a: A, b: B, c: C, d: D, e: E) => R :
any
分配可执行内存:
VirtualAlloc
我的uint8_t* alloc_executable(uint32_t alloc_size)
{
if(!alloc_size)
return nullptr;
return reinterpret_cast<uint8_t*>(VirtualAlloc(NULL, alloc_size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE));
}
函数:
main
流程返回int main()
{
/*
* nop - 0x90
* ret - 0xC3
*/
uint8_t machinecode[] = {0x90, 0xC3};
uint32_t machinecode_size = ARRAYSIZE(machinecode);
uint8_t* exec_mem = alloc_executable(machinecode_size);
memcpy(exec_mem, bytecode, machinecode_size);
FlushInstructionCache(GetCurrentProcess(), exec_mem, machinecode_size);
auto func = reinterpret_cast<void(*)()>(exec_mem);
func();
return 0;
}
,没有错误。
ALSO:显然,这是Windows特定的。我的 target 平台是x64 Windows 10。