如何将任意EXE转为可注入其他进程的字节并执行
进程注入:将EXE转换为可执行十六进制字节的正确方法
我需要把一个EXE文件转换为十六进制字节,注入到其他进程内存中执行,功能类似直接注入计算器的进程注入方案,但要支持任意EXE。之前尝试过十六进制编辑器复制内容、在线转换工具、C指令等方法都没成功,下面是我写的Go代码和注入用的C代码片段:
我的Go转换代码
file, err := ioutil.ReadFile("...\\helper.exe") if err != nil { } //fmt.Print(file) f, err := os.Create("...\\fileInByte.txt") if err != nil { } defer f.Close() _, err = f.Write([]byte(file)) file2, err2 := ioutil.ReadFile("...\\fileInByte.txt") if err2 != nil { } fmt.Print(file2)
我的C++注入代码片段
std::ifstream input("...\\fileInByte.txt", std::ios::binary); std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {}); unsigned char* my_payload; my_payload = &buffer[0]; unsigned int my_payload_len = sizeof(my_payload); ... ... ... // allocate memory buffer for remote process rb = VirtualAllocEx(ph, NULL, my_payload_len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // write payload to memory buffer if(!WriteProcessMemory(ph, rb, my_payload, my_payload_len, NULL))
问题分析
- Go代码逻辑错误:你只是把EXE的二进制内容直接写入文本文件,没有转换成十六进制字符串。二进制中的不可打印字符会在文本文件中丢失或乱码,导致后续读取无法还原正确数据。
- C++代码长度计算错误:
sizeof(my_payload)获取的是指针的内存大小(通常4/8字节),不是实际payload的长度,应该用buffer.size()。 - 核心认知误区:普通EXE是PE格式文件,直接注入内存后无法直接执行——PE需要加载器处理重定位、导入表等逻辑。你参考的计算器注入方案用的是shellcode(精简的可执行指令),不是完整EXE。
正确实现方案
方案1:直接二进制注入(高效无转换)
跳过十六进制转换步骤,直接读取EXE二进制内容注入,避免转换开销:
#include <fstream> #include <vector> // 读取EXE二进制内容 std::ifstream input("helper.exe", std::ios::binary); std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {}); input.close(); // 正确获取payload信息 unsigned char* my_payload = buffer.data(); unsigned int my_payload_len = buffer.size(); // 后续注入逻辑保持原代码 // rb = VirtualAllocEx(ph, NULL, my_payload_len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); // if(!WriteProcessMemory(ph, rb, my_payload, my_payload_len, NULL))
方案2:EXE转十六进制字符串再还原(按需使用)
如果必须用十六进制文本中转,修正Go和C++代码:
修正后的Go转换代码
package main import ( "encoding/hex" "io/ioutil" ) func main() { // 读取EXE二进制 fileBytes, err := ioutil.ReadFile("helper.exe") if err != nil { panic(err) } // 二进制转十六进制字符串 hexContent := hex.EncodeToString(fileBytes) // 写入文本文件 err = ioutil.WriteFile("fileInHex.txt", []byte(hexContent), 0644) if err != nil { panic(err) } }
修正后的C++解码注入代码
#include <fstream> #include <vector> #include <string> #include <cstdlib> // 十六进制字符串转二进制字节数组 std::vector<unsigned char> hexToBytes(const std::string& hexStr) { std::vector<unsigned char> bytes; for (size_t i = 0; i < hexStr.length(); i += 2) { std::string byteStr = hexStr.substr(i, 2); unsigned char byte = static_cast<unsigned char>(strtol(byteStr.c_str(), nullptr, 16)); bytes.push_back(byte); } return bytes; } int main() { // 读取十六进制文本 std::ifstream input("fileInHex.txt"); std::string hexStr((std::istreambuf_iterator<char>(input)), std::istreambuf_iterator<char>()); input.close(); // 还原为二进制 std::vector<unsigned char> buffer = hexToBytes(hexStr); unsigned char* my_payload = buffer.data(); unsigned int my_payload_len = buffer.size(); // 后续注入逻辑 // ... return 0; }
关键补充:完整EXE注入的必要步骤
如果要注入完整EXE并执行,必须实现反射式PE加载:
- 在目标进程内存中解析PE文件头
- 处理PE重定位表
- 解析并加载导入的DLL和函数
- 跳转到PE入口点执行
内容的提问来源于stack exchange,提问作者user16385455
相关产品推荐
相关产品推荐

