JNA实现远程线程注入

Posted 诗水人间

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JNA实现远程线程注入相关的知识,希望对你有一定的参考价值。


首先准备一个dll,为了能看到效果最好是dllMain返回一个对话框或者窗口,可以很明显的看出注入是否成功。

下面的​WxDemoDll.dll​​ 一个64位的dll

主界面如下,如果注入成功会在目标进程起一个线程跑这个对话框,然后在这个dll里面写代码就是代码注入。相当于自己调自己

JNA实现远程线程注入_注入原理

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序号
* 969 LoadLibraryA
* 970 LoadLibraryExA
* 971 LoadLibraryExW
* 972 LoadLibraryW
*/
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实现远程线程注入_注入原理_02



以上是关于JNA实现远程线程注入的主要内容,如果未能解决你的问题,请参考以下文章

远程线程注入代码

远程线程注入

安全之路 —— 利用远程线程注入的方法(使用DLL)实现穿墙与隐藏进程

远程线程DLL注入, 如何释放DLL和结束DLL的线程

动态库注入--远程线程

突破SESSION 0隔离的远程线程注入