使用Golang通过CreateRemoteThread实现DLL注入无报错未生效问题求助
核心失效原因
- 写入目标进程的DLL路径没有NULL终止符:
LoadLibraryA依赖字符串末尾的\0判断路径结束,你直接转换[]byte(dllPath)没有追加终止符,导致函数读取到非法内存的乱码,加载路径错误直接失败。 - 路径受Windows文件系统重定向影响:32位程序在64位系统下访问
C:\Windows\System32会被自动重定向到C:\Windows\SysWOW64,如果目标路径下不存在对应DLL会加载失败。 - 未等待远程线程执行完成:
CreateRemoteThread是异步调用,你没有等待线程执行完毕就结束了注入进程,可能出现线程还没完成DLL加载就被系统回收资源的情况。 - 内存分配大小不合理:你用
LoadLibraryA(ANSI版本)不需要分配len(dllPath)*2的空间,该大小是给宽字符版本LoadLibraryW使用的,多余分配无意义,反而增加出错概率。 - 缺少有效返回值校验:你只校验了error返回,没有判断Win32 API返回的句柄/地址是否为无效值,部分API执行失败时error可能为nil,但返回值为NULL代表执行失败。
- 权限不足:注入其他进程需要管理员权限运行注入程序,普通用户权限下OpenProcess会静默获取到无效句柄,后续操作全部失效但无明显报错。
修复方案
- 给DLL路径追加NULL终止符
- 关闭文件系统重定向,或者改用
Sysnative别名访问真实System32目录,或者直接把目标DLL放到不受重定向影响的路径(比如C:\test.dll) - 调用
WaitForSingleObject等待远程线程执行完成,再释放资源 - 校验所有Win32 API的返回值是否为无效值
- 以管理员身份运行编译后的注入程序
- 确认目标进程ID确实为32位Notepad++的进程ID
修复后参考代码
package main import ( "fmt" "github.com/JamesHovious/w32" "syscall" ) func main() { // 建议先把测试dll放到C盘根目录避免重定向问题 dllPath := "C:\\wevtapi.dll" // 给路径追加NULL终止符 dllPathBytes := append([]byte(dllPath), 0) procID := 8124 // 请确认这里是32位Notepad++的正确进程ID hProc, handleErr := w32.OpenProcess(w32.PROCESS_ALL_ACCESS, false, uint32(procID)) if handleErr != nil || hProc == 0 { fmt.Println("OpenProcess失败:", handleErr) return } defer w32.CloseHandle(hProc) kernel32DLL, dllLoadErr := syscall.LoadLibrary("kernel32.dll") if dllLoadErr != nil || kernel32DLL == 0 { fmt.Println("加载kernel32失败:", dllLoadErr) return } defer syscall.FreeLibrary(kernel32DLL) addr, addrErr := syscall.GetProcAddress(syscall.Handle(kernel32DLL), "LoadLibraryA") if addrErr != nil || addr == 0 { fmt.Println("获取LoadLibraryA地址失败:", addrErr) return } // 分配大小改为带终止符的实际路径长度 arg, allocErr := w32.VirtualAllocEx(hProc, 0, len(dllPathBytes), w32.MEM_RESERVE|w32.MEM_COMMIT, w32.PAGE_READWRITE) if allocErr != nil || arg == 0 { fmt.Println("VirtualAllocEx失败:", allocErr) return } writeErr := w32.WriteProcessMemory(hProc, uint32(arg), dllPathBytes, 0) if writeErr != nil { fmt.Println("WriteProcessMemory失败:", writeErr) w32.VirtualFreeEx(hProc, arg, 0, w32.MEM_RELEASE) return } hThread, _, threadErr := w32.CreateRemoteThread(hProc, nil, 0, uint32(addr), arg, 0) if threadErr != nil || hThread == 0 { fmt.Println("CreateRemoteThread失败:", threadErr) w32.VirtualFreeEx(hProc, arg, 0, w32.MEM_RELEASE) return } defer w32.CloseHandle(hThread) // 等待远程线程执行完成,超时时间5秒 w32.WaitForSingleObject(hThread, 5000) // 释放分配的远程内存 w32.VirtualFreeEx(hProc, arg, 0, w32.MEM_RELEASE) fmt.Println("注入执行完成") }
内容的提问来源于stack exchange,提问作者pepperoni
相关产品推荐
相关产品推荐

