宁可枝头抱香死,何曾吹落北风中。这篇文章主要讲述JNA实现远程线程注入相关的知识,希望能为你提供帮助。
首先准备一个dll,为了能看到效果最好是dllMain返回一个对话框或者窗口,可以很明显的看出注入是否成功。
下面的??WxDemoDll.dll?
? 一个64位的dll
主界面如下,如果注入成功会在目标进程起一个线程跑这个对话框,然后在这个dll里面写代码就是代码注入。相当于自己调自己
JNA实现注入:
package top.yumbo.demo.inter.x64;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.*;
import static com.sun.jna.Pointer.NULL;
import static com.sun.jna.platform.win32.Tlhelp32.TH32CS_SNAPPROCESS;
import static com.sun.jna.platform.win32.WinNT.*;
public class JNADllx64InjectDemo
private static final User32 user32 = User32.INSTANCE;
private static final Kernel32 kernel32 = Kernel32.INSTANCE;
public static void main(String[] args)
//System.load("D:\\\\Jetbrains\\\\ClionProject\\\\WxDemoDll\\\\WxDemoDll\\\\x64\\\\Debug\\\\WxDemoDll.dll");
// 注入的进程
String processName = "XMind.exe";
// x64
// dll的路径,最好是将dll路径所在目录放到环境变量Path中,这样可以用LoadLibrary名称即可加载dll
String dllPath = "WxDemoDll.dll";
// 1.使用最高权限打开进程
int pid = getPidByProcessName(processName);
System.out.println(pid);
WinNT.HANDLE process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (process == null)
System.out.println("打开" + processName + "进程失败");
return;
Pointer virtualAllocEx = kernel32.VirtualAllocEx(process, NULL, new SIZE_T(dllPath.length()), MEM_COMMIT, PAGE_READWRITE);
if (virtualAllocEx == null)
System.out.println("向目标进程" + processName + "分配虚拟内存失败");
return;
// 字符串转Pointer
Pointer bufferPointer = new Memory(dllPath.length() + 1);
// WARNING: assumes ascii-only string
bufferPointer.setString(0, dllPath);
boolean writeFlag = kernel32.WriteProcessMemory(process, virtualAllocEx, bufferPointer, dllPath.length(), null);
if (!writeFlag)
//为true表示写入成功,所以需要非一下表示写入失败
System.out.println("写入内存失败");
return;
HMODULE k32module = kernel32.GetModuleHandle("Kernel32.dll");
/**ordinal序号
* 969LoadLibraryA
* 970LoadLibraryExA
* 971LoadLibraryExW
* 972LoadLibraryW
*/
Pointer loadLibraryAddress = kernel32.GetProcAddress(k32module, 969);
HANDLE handle = kernel32.CreateRemoteThread(process, null, 0, loadLibraryAddress, virtualAllocEx, 0, null);
if (handle == null)
System.out.println("注入失败");
return;
/**
* 获取进程id
*
* @param processName 进程名
* @return 进程id
*/
public static int getPidByProcessName(String processName)
// 1、得到系统进程快照
WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, null);
// 2、遍历快照找到进程名为processName的进程id
Tlhelp32.PROCESSENTRY32 processentry32 = new Tlhelp32.PROCESSENTRY32();
do
if (new String(processentry32.szExeFile).contains(processName))
return processentry32.th32ProcessID.intValue();
while (kernel32.Process32Next(snapshot, processentry32));
return -1;
注入成功截图
【JNA实现远程线程注入】
推荐阅读
- Redis(开发与运维):13---哈希/散列对象
- Kubernetes——对外服务之Ingress
- Linux 内核 内存管理Linux 内核内存布局 ④ ( ARM64 架构体系内存分布 | 内核启动源码 start_kernel | 内存初始化 mm_init | mem_init )
- 我的Linux,我做主!IT技术专家带你飞--银河麒麟 kylin server v10上创建虚拟机-戴尔R720
- python3调用cmd执行命令报乱码问题
- Redis(开发与运维):01---Redis简介特性使用场景使用建议历史版本
- Linux 内核 内存管理虚拟地址空间布局架构 ① ( 虚拟地址空间布局架构 | 用户虚拟地址空间划分 )
- Redis(开发与运维):03---Windows下安装Redis数据库
- Cluster介绍(集群) DRS介绍(分布式资源调度)EVC技术介绍