Hello World级shellcode在Visual Studio C++编译报错C2440如何解决
报错原因
C2440错误由Visual Studio的强类型校验机制触发:C++标准不允许直接将指向数据存储区的指针(此处的char数组默认位于不可执行的静态数据段)强制转换为函数指针,编译器默认会阻断这种不安全的类型转换。
解决方案
方法1:代码层绕过类型校验(快速修复编译报错)
将指针转换拆分为两步,先转通用void*指针再转函数指针,即可绕过直接转换的校验:
int main(int argc, char **argv) { int (*f)(); f = (int (*)())(void*)shellcode; return (*f)(); }
注意:该方法仅解决编译报错,运行时大概率会崩溃,因为默认静态数据段没有执行权限,Windows的DEP(数据执行保护)会拦截非法内存执行。
方法2:合规申请可执行内存运行(推荐,可正常运行)
通过Windows API申请带执行权限的内存页,拷贝shellcode后再执行,完全符合Windows内存管理规则,不会触发权限拦截:
#include <windows.h> char shellcode[] = "\x31\xd2\xb2\x30\x64\x8b\x12\x8b\x52\x0c\x8b\x52\x1c\x8b\x42" "\x08\x8b\x72\x20\x8b\x12\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03" "\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x31\xed\x8b" "\x34\xaf\x01\xc6\x45\x81\x3e\x46\x61\x74\x61\x75\xf2\x81\x7e" "\x08\x45\x78\x69\x74\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c" "\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x68\x79\x74" "\x65\x01\x68\x6b\x65\x6e\x42\x68\x20\x42\x72\x6f\x89\xe1\xfe" "\x49\x0b\x31\xc0\x51\x50\xff\xd7"; int main(int argc, char **argv) { // 申请可读可写可执行的内存空间 void* exec_buf = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); // 拷贝shellcode到可执行内存 memcpy(exec_buf, shellcode, sizeof(shellcode)); // 转为函数指针执行 int (*shell_func)() = (int (*)())exec_buf; return shell_func(); }
额外说明:这段shellcode为32位架构编写,编译时必须将VS的目标平台切换为
x86,选择x64平台运行会直接崩溃。
方法3:修改编译选项降低校验等级
如果不需要修改代码,可调整VS项目配置关闭严格类型校验:
- 打开项目属性→C/C++→常规→将「SDL检查」设置为否
- 打开项目属性→C/C++→语言→将「符合模式」设置为否
- 重新编译即可通过
内容的提问来源于stack exchange,提问作者plagiarism
相关产品推荐
相关产品推荐

