【发布时间】:2016-04-11 05:29:17
【问题描述】:
至少一天以来,我一直在尝试解决这个问题,研究所有转换它们的变量类型,查看我在网上找到的 24 个其他示例(甚至其中一个在 JNA github 上为 Kernel32 提供)。我正在尝试使用 JNA 在 java 中绘制 VirtualAllocEx 函数。我对如何做到这一点有一个大致的想法,这是我目前的课程:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
import com.sun.jna.platform.win32.Tlhelp32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
public class HelloWorld
{
public interface Kernel32 extends StdCallLibrary
{
public static final Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
public static final int PROCESS_CREATE_THREAD = 0x0002;
public static final int PAGE_EXECUTE_READWRITE = 0;
public static int PROCESS_QUERY_INFORMATION = 0x0400;
public static int PROCESS_VM_OPERATION = 0x0008;
public static int PROCESS_VM_WRITE = 0x0020;
public static int PROCESS_VM_READ = 0x0010;
public static int PAGE_READWRITE = 0x04;
public static int MEM_RESERVE = 0x2000;
public static int MEM_COMMIT = 0x1000;
//public Pointer VirtualAllocEx(int ProcessToAllocateRamIn, int AddresToStartAt, int DesiredSizeToAllocate, int AllocationType, int ProtectType);
int VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize, int flAllocationType, int flProtect);
//public int VirtualAllocEx(HANDLE hProcess,IntByReference lpAddress,int dwSize,int flAllocationType,int flProtect);
//public IntByReference VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize, int flAllocationType, int flProtect);
public WinNT.HANDLE CreateToolhelp32Snapshot(WinDef.DWORD var1, WinDef.DWORD var2);
public boolean Process32First(WinNT.HANDLE var1, Tlhelp32.PROCESSENTRY32 var2);
public boolean Process32Next(WinNT.HANDLE var1, Tlhelp32.PROCESSENTRY32 var2);
public WinNT.HANDLE OpenProcess(int var1, boolean var2, int var3);
public boolean CloseHandle(WinNT.HANDLE var1);
public boolean WriteProcessMemory(WinNT.HANDLE var1, Pointer var2, Pointer var3, int var4, IntByReference var5);
public int GetLastError();
}
public static void main(String[] args) throws Exception
{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("C:\\WINDOWS\\system32\\cmd.exe")));
byte[] buffer = new byte[1000000];
int read = bis.read(buffer);
bis.close();
byte[] nwBuff = Arrays.copyOfRange(buffer, 0, read);
Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();
WinNT.HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
try {
while (Kernel32.INSTANCE.Process32Next(snapshot, processEntry)) {
System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
}
}
finally {
Kernel32.INSTANCE.CloseHandle(snapshot);
}
HANDLE process = Kernel32.INSTANCE.OpenProcess(Kernel32.PROCESS_VM_OPERATION|Kernel32.PROCESS_VM_WRITE|Kernel32.PROCESS_VM_READ|Kernel32.PROCESS_CREATE_THREAD|Kernel32.PROCESS_QUERY_INFORMATION, false, 3756);
System.out.println((process != null));
writeMemory(process, nwBuff);
}
public static void writeMemory(HANDLE process, byte[] data)
{
int size = data.length;
Memory toWrite = new Memory(size);
for(int i = 0; i < size; i++)
toWrite.setByte(i, data[i]);
System.out.println("Memory size: "+size+"\t"+toWrite.size());
SIZE_T a = new SIZE_T();
a.setValue(toWrite.size());
int x = Kernel32.INSTANCE.VirtualAllocEx(process, Pointer.NULL, a, Kernel32.MEM_RESERVE|Kernel32.MEM_COMMIT, Kernel32.PAGE_EXECUTE_READWRITE);
int c = Kernel32.INSTANCE.GetLastError();
System.out.println(x+"\t"+c);
Pointer pros = process.getPointer();
Pointer buffer = toWrite.getPointer(0);
IntByReference z = new IntByReference();
boolean b = Kernel32.INSTANCE.WriteProcessMemory(process, pros, buffer, size, z);
c = Kernel32.INSTANCE.GetLastError();
System.out.println(b+"\t"+c+"\t"+z.getValue());
}
}
所以你可以忽略打印行(我的调试信息)和我正在创建的所有随机未使用或不必要的变量。所以我的第一个问题:我是否正确构建了我的 Kernel32 接口? (它工作得很好,但是;我已经看到很多其他例子只是扩展了其他库等等......)。第二个问题:我发布这个的原因......我无法让 VirtualAllocEx 工作。我从 MSDN 中查找了方法定义并自己转换了类型,并查看了我在网上找到的 23 个其他示例: Example directly from JNA repo [链接已删除]。
如您所见,我还注释掉了我尝试过的其他一些函数头(我还有很多,但我删除了我尝试映射到的其他函数头,以便稍微清理一下。)
基本上我在这里要完成的是打印所有正在运行的进程(工作得很好......),然后为 firefox 获取 pid(作为测试......)[我现在对 pid 进行硬编码]并打开进程,然后将 cmd.exe 注入(或其他相关的 shellcode)以运行该代码。 (我也有执行 CreateRemoteThread 的代码,并且应该用于生成 cmd.exe。)但为了这个示例,我只是保持简短,因为 VirtualAllocEx 不起作用......(我什至需要 Alloc运行进程中的内存以使其工作?)。
还要注意关于这个例子的一些事情:现在已经很晚了,我知道我的程序内部仍然有一些有缺陷的逻辑(比如我传递给 WriteProcessMemory 的项目,我得到一个 487 表示“尝试访问无效地址。 " 但那是因为我无法让 VirtualAllocEx 向我返回一个地址以放入其中,所以我只是传递了任何可用的地址。
我现在愿意接受有关如何继续的任何建议或我可能尚未访问的任何链接,以便让我更好地了解我做错了什么。
编辑:忘记提及程序的输出:
[All processes [cut out for space]]
true
Memory size: 232448 232448
0 87
false 487 0
这就是它的输出。 VirtualAllocEx 函数调用之后的错误代码 87,因为我无法在 Write 调用之后得到它,然后是 487,因为我还没有来自 VirtualAllocEx 的有效地址。谢谢!
【问题讨论】:
-
先在 C 中尝试相同的代码,看看是否可行。
-
@Voo 确实如此,但无论出于何种原因,VirtualAllocEx 仍然无法映射。
-
问题可能是您已将
VirtualAllocEx的返回类型声明为int,即32 位,而(假设为64 位JRE)实际返回类型为64位指针。 -
@HarryJohnston 这就是我的想法,但我也尝试过指针的返回类型,它只是指针还是有一些特殊的类?
标签: java c++ windows native jna