C++中动态字节数组形式Shellcode执行失败问题排查与优化咨询
让我来帮你排查这个问题,你的动态版本代码里有两个关键问题导致shellcode无法正常执行:
1. sizeof(shellcode)的致命误用
当shellcode是char*类型的指针时,sizeof(shellcode)返回的是指针本身的大小(32位系统是4字节,64位系统是8字节),而不是你实际分配的shellcode缓冲区的长度。这就导致你只把前4/8字节复制到了可执行内存区域,完整的shellcode根本没拷贝过去,执行自然会出错。
2. 可选但需要注意的细节:null字节的处理
如果你的shellcode包含\x00字节,虽然std::string可以正常存储它们,但要注意:不要用strlen这类依赖字符串结束符的函数获取长度,而要始终用test.size()——它会返回字符串实际存储的字节数,包括所有null字节。
修正后的可行代码
我直接帮你简化并修复了代码,去掉了没必要的手动堆内存分配,同时添加了错误检查方便调试:
#include <windows.h> #include <iostream> #include <string> using namespace std; int main(int argc, char** argv) { std::string test = "..snip..\xa0\x4e\xbc\x0b\x45\xee\xb3\x1b\xf9..snip.."; // 分配可执行内存,使用shellcode的实际长度 void* exec = VirtualAlloc(0, test.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (exec == nullptr) { cerr << "VirtualAlloc failed with error code: " << GetLastError() << endl; return 1; } // 直接从std::string复制完整的shellcode到可执行内存 memcpy(exec, test.data(), test.size()); // 执行shellcode ((void(*)())exec)(); // 注:如果shellcode执行后会退出进程,下面的代码可能不会执行 VirtualFree(exec, 0, MEM_RELEASE); return 0; }
如果你确实需要手动分配堆缓冲区(比如有特殊需求)
如果一定要保留手动堆分配的逻辑,记得用test.size()代替sizeof(shellcode):
int main(int argc, char** argv) { std::string test = "..snip..\xa0\x4e\xbc\x0b\x45\xee\xb3\x1b\xf9..snip.."; char* shellcode = new char[test.size()]; memcpy(shellcode, test.data(), test.size()); // 关键:用test.size()作为内存分配和拷贝的长度 void* exec = VirtualAlloc(0, test.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (exec == nullptr) { cerr << "VirtualAlloc failed: " << GetLastError() << endl; delete[] shellcode; return 1; } memcpy(exec, shellcode, test.size()); ((void(*)())exec)(); delete[] shellcode; VirtualFree(exec, 0, MEM_RELEASE); return 0; }
核心修复点就是把所有依赖sizeof(shellcode)的地方替换成test.size(),确保完整的shellcode被复制到可执行内存区域。
内容的提问来源于stack exchange,提问作者P_n
相关产品推荐
相关产品推荐

