mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-16 15:12:16 +00:00
trunk contents moved to root
This commit is contained in:
51
src/com/jpexs/process/Process.java
Normal file
51
src/com/jpexs/process/Process.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.process;
|
||||
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
import com.jpexs.helpers.Searchable;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface Process extends Comparable<Process>, Searchable {
|
||||
|
||||
public String getFilePath();
|
||||
|
||||
public String getFileName();
|
||||
|
||||
public BufferedImage getIcon();
|
||||
|
||||
@Override
|
||||
public String toString();
|
||||
|
||||
public String getPid();
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(byte[]
|
||||
|
||||
... data);
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(ProgressListener progListener, byte[]
|
||||
|
||||
... data);
|
||||
}
|
||||
41
src/com/jpexs/process/ProcessTools.java
Normal file
41
src/com/jpexs/process/ProcessTools.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.process;
|
||||
|
||||
import com.jpexs.process.win32.Win32ProcessTools;
|
||||
import com.sun.jna.Platform;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Tools for processes. You can add support for other platforms here, if you
|
||||
* want
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ProcessTools {
|
||||
|
||||
public static List<Process> listProcesses() {
|
||||
if (Platform.isWindows()) {
|
||||
return Win32ProcessTools.listProcesses();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean toolsAvailable() {
|
||||
return Platform.isWindows();
|
||||
}
|
||||
}
|
||||
94
src/com/jpexs/process/win32/Win32Process.java
Normal file
94
src/com/jpexs/process/win32/Win32Process.java
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.process.win32;
|
||||
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
import com.jpexs.process.Process;
|
||||
import com.sun.jna.platform.win32.WinDef.DWORD;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Win32Process implements Process {
|
||||
|
||||
public String filePath;
|
||||
public String fileName;
|
||||
public BufferedImage icon;
|
||||
public DWORD th32ProcessID;
|
||||
|
||||
@Override
|
||||
public String getPid() {
|
||||
return "" + th32ProcessID.longValue();
|
||||
}
|
||||
|
||||
public Win32Process(String filePath, String fileName, BufferedImage icon, DWORD th32ProcessID) {
|
||||
this.filePath = filePath;
|
||||
this.fileName = fileName;
|
||||
this.icon = icon;
|
||||
this.th32ProcessID = th32ProcessID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new File(filePath).getName() + " (pid " + th32ProcessID.longValue() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Process o) {
|
||||
if (!(o instanceof Win32Process)) {
|
||||
return -1;
|
||||
}
|
||||
Win32Process p = (Win32Process) o;
|
||||
int ret = fileName.toLowerCase().compareTo(p.fileName.toLowerCase());
|
||||
if (ret == 0) {
|
||||
ret = th32ProcessID.intValue() - p.th32ProcessID.intValue();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(byte[]
|
||||
... data) {
|
||||
return search(null, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, InputStream> search(ProgressListener progListener, byte[]
|
||||
... data) {
|
||||
return Win32ProcessTools.findBytesInProcessMemory(progListener, th32ProcessID, data);
|
||||
}
|
||||
}
|
||||
605
src/com/jpexs/process/win32/Win32ProcessTools.java
Normal file
605
src/com/jpexs/process/win32/Win32ProcessTools.java
Normal file
@@ -0,0 +1,605 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2014 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.process.win32;
|
||||
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
import com.jpexs.process.ProcessTools;
|
||||
import com.sun.jna.Memory;
|
||||
import com.sun.jna.NativeLong;
|
||||
import com.sun.jna.Pointer;
|
||||
import com.sun.jna.platform.win32.Advapi32;
|
||||
import com.sun.jna.platform.win32.BITMAP;
|
||||
import com.sun.jna.platform.win32.BaseTSD;
|
||||
import com.sun.jna.platform.win32.Gdi32;
|
||||
import com.sun.jna.platform.win32.ICONINFO;
|
||||
import com.sun.jna.platform.win32.Kernel32;
|
||||
import com.sun.jna.platform.win32.MEMORY_BASIC_INFORMATION;
|
||||
import com.sun.jna.platform.win32.PROCESSENTRY32;
|
||||
import com.sun.jna.platform.win32.Psapi;
|
||||
import com.sun.jna.platform.win32.SHFILEINFO;
|
||||
import com.sun.jna.platform.win32.Shell32;
|
||||
import com.sun.jna.platform.win32.User32;
|
||||
import com.sun.jna.platform.win32.WinBase;
|
||||
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.ptr.PointerByReference;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Win32ProcessTools extends ProcessTools {
|
||||
|
||||
private static long pointerToAddress(Pointer p) {
|
||||
String s = p.toString();
|
||||
s = s.replace("native@0x", "");
|
||||
return Long.parseLong(s, 16);
|
||||
}
|
||||
|
||||
public static List<MEMORY_BASIC_INFORMATION> getPageRanges(WinNT.HANDLE hOtherProcess) {
|
||||
List<MEMORY_BASIC_INFORMATION> ret = new ArrayList<>();
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
WinBase.SYSTEM_INFO si = new WinBase.SYSTEM_INFO();
|
||||
Kernel32.INSTANCE.GetSystemInfo(si);
|
||||
Pointer lpMem = si.lpMinimumApplicationAddress;
|
||||
while (pointerToAddress(lpMem) < pointerToAddress(si.lpMaximumApplicationAddress)) {
|
||||
mbi = new MEMORY_BASIC_INFORMATION();
|
||||
BaseTSD.SIZE_T t = Kernel32.INSTANCE.VirtualQueryEx(hOtherProcess, lpMem, mbi, new BaseTSD.SIZE_T(mbi.size()));
|
||||
if (t.longValue() == 0) {
|
||||
Logger.getLogger(Win32ProcessTools.class.getName()).log(Level.SEVERE, "Cannot get page ranges. Last error:" + Kernel32.INSTANCE.GetLastError());
|
||||
break;
|
||||
}
|
||||
ret.add(mbi);
|
||||
lpMem = new Pointer(pointerToAddress(mbi.baseAddress) + mbi.regionSize.longValue());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void printMemInfo(MEMORY_BASIC_INFORMATION mbi) {
|
||||
System.out.println("Region size:" + mbi.regionSize);
|
||||
String stateStr = "";
|
||||
if ((mbi.state.intValue() & Kernel32.MEM_COMMIT) == Kernel32.MEM_COMMIT) {
|
||||
stateStr += " commit";
|
||||
}
|
||||
if ((mbi.state.intValue() & Kernel32.MEM_FREE) == Kernel32.MEM_FREE) {
|
||||
stateStr += " free";
|
||||
}
|
||||
if ((mbi.state.intValue() & Kernel32.MEM_RESERVE) == Kernel32.MEM_RESERVE) {
|
||||
stateStr += " reserve";
|
||||
}
|
||||
stateStr = stateStr.trim();
|
||||
|
||||
String typeStr = "";
|
||||
if ((mbi.type.intValue() & Kernel32.MEM_IMAGE) == Kernel32.MEM_IMAGE) {
|
||||
typeStr += " image";
|
||||
}
|
||||
if ((mbi.type.intValue() & Kernel32.MEM_MAPPED) == Kernel32.MEM_MAPPED) {
|
||||
typeStr += " mapped";
|
||||
}
|
||||
if ((mbi.type.intValue() & Kernel32.MEM_PRIVATE) == Kernel32.MEM_PRIVATE) {
|
||||
typeStr += " private";
|
||||
}
|
||||
typeStr = typeStr.trim();
|
||||
|
||||
String protStr = "";
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_EXECUTE) == Kernel32.PAGE_EXECUTE) {
|
||||
protStr += " execute";
|
||||
}
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_EXECUTE_READ) == Kernel32.PAGE_EXECUTE_READ) {
|
||||
protStr += " execute_read";
|
||||
}
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_EXECUTE_READWRITE) == Kernel32.PAGE_EXECUTE_READWRITE) {
|
||||
protStr += " execute_readwrite";
|
||||
}
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_READONLY) == Kernel32.PAGE_READONLY) {
|
||||
protStr += " readonly";
|
||||
}
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_READWRITE) == Kernel32.PAGE_READWRITE) {
|
||||
protStr += " readwrite";
|
||||
}
|
||||
if ((mbi.allocationProtect.intValue() & WinNT.PAGE_WRITECOPY) == Kernel32.PAGE_WRITECOPY) {
|
||||
protStr += " writecopy";
|
||||
}
|
||||
|
||||
protStr = protStr.trim();
|
||||
System.out.println("State:" + stateStr);
|
||||
System.out.println("Type:" + typeStr);
|
||||
System.out.println("Protect:" + protStr);
|
||||
System.out.println("baseAddress:" + mbi.baseAddress);
|
||||
System.out.println("========================");
|
||||
}
|
||||
|
||||
private static byte[] mergeArrays(byte[] one, byte[] two) {
|
||||
byte[] combined = new byte[one.length + two.length];
|
||||
|
||||
System.arraycopy(one, 0, combined, 0, one.length);
|
||||
System.arraycopy(two, 0, combined, one.length, two.length);
|
||||
return combined;
|
||||
}
|
||||
|
||||
public static Map<String, Character> getDriveMappings() {
|
||||
Map<String, Character> ret = new HashMap<>();
|
||||
for (char d = 'A'; d <= 'Z'; d++) {
|
||||
char[] buf = new char[1024];
|
||||
int len = Kernel32.INSTANCE.QueryDosDevice("" + d + ":", buf, buf.length).intValue();
|
||||
String tar = new String(buf, 0, len);
|
||||
tar = tar.trim();
|
||||
if (!"".equals(tar)) {
|
||||
ret.put(tar, d);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static String ntPathToWin32(String path) {
|
||||
for (String dp : driveMappings.keySet()) {
|
||||
if (path.startsWith(dp)) {
|
||||
return driveMappings.get(dp) + ":" + path.substring(dp.length());
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
private static final Map<String, Character> driveMappings = getDriveMappings();
|
||||
|
||||
public static boolean drawIcon(BufferedImage ret, WinDef.HICON hIcon, int diFlags) {
|
||||
|
||||
WinDef.HDC hdcScreen = User32.INSTANCE.GetDC(null);
|
||||
WinDef.HDC hdcMem = Gdi32.INSTANCE.CreateCompatibleDC(hdcScreen);
|
||||
|
||||
WinDef.HBITMAP bitmap = Gdi32.INSTANCE.CreateCompatibleBitmap(hdcScreen, ret.getWidth(), ret.getHeight());
|
||||
|
||||
WinNT.HANDLE hbmOld = Gdi32.INSTANCE.SelectObject(hdcMem, bitmap);
|
||||
|
||||
WinNT.HANDLE hBrush = Gdi32.INSTANCE.CreateSolidBrush(new WinDef.DWORD(0xffffff));
|
||||
WinDef.RECT rect = new WinDef.RECT();
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = ret.getWidth();
|
||||
rect.bottom = ret.getHeight();
|
||||
User32.INSTANCE.FillRect(hdcMem, rect, hBrush);
|
||||
Gdi32.INSTANCE.DeleteObject(hBrush);
|
||||
|
||||
boolean ok = User32.INSTANCE.DrawIconEx(hdcMem, 0, 0, hIcon, ret.getWidth(), ret.getHeight(), new WinDef.UINT(0), new WinDef.HBRUSH(Pointer.NULL), diFlags);
|
||||
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int x = 0; x < ret.getWidth(); x++) {
|
||||
for (int y = 0; y < ret.getHeight(); y++) {
|
||||
int rgb = Gdi32.INSTANCE.GetPixel(hdcMem, x, y).intValue();
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb) & 0xff;
|
||||
rgb = (b << 16) + (g << 8) + r;
|
||||
ret.setRGB(x, y, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
Gdi32.INSTANCE.SelectObject(hdcMem, hbmOld);
|
||||
Gdi32.INSTANCE.DeleteObject(bitmap);
|
||||
Gdi32.INSTANCE.DeleteDC(hdcMem);
|
||||
User32.INSTANCE.ReleaseDC(null, hdcScreen);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void applyMask(BufferedImage image, BufferedImage mask) {
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int masked = mask.getRGB(x, y);
|
||||
int alpha = 255 - (masked & 0xff);
|
||||
if (alpha != 0 && alpha != 255) {
|
||||
System.out.println("a=" + alpha);
|
||||
}
|
||||
int rgb = image.getRGB(x, y);
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb) & 0xff;
|
||||
r = r * alpha / 255;
|
||||
g = g * alpha / 255;
|
||||
b = b * alpha / 255;
|
||||
|
||||
rgb = (r << 16) + (g << 8) + b;
|
||||
|
||||
rgb = (alpha << 24) | rgb;
|
||||
image.setRGB(x, y, rgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BufferedImage iconToImage(WinDef.HICON hIcon) {
|
||||
ICONINFO info = new ICONINFO();
|
||||
boolean ok = User32.INSTANCE.GetIconInfo(hIcon, info);
|
||||
if (!ok) {
|
||||
return null;
|
||||
}
|
||||
BufferedImage ret = null;
|
||||
BITMAP bmp = new BITMAP();
|
||||
if (info.hbmColor != null) {
|
||||
int nWrittenBytes = Gdi32.INSTANCE.GetObject(info.hbmColor, bmp.size(), bmp);
|
||||
if (nWrittenBytes > 0) {
|
||||
ret = new BufferedImage(bmp.bmWidth.intValue(), bmp.bmHeight.intValue(), BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
} else if (info.hbmMask != null) {
|
||||
int nWrittenBytes = Gdi32.INSTANCE.GetObject(info.hbmMask, bmp.size(), bmp);
|
||||
if (nWrittenBytes > 0) {
|
||||
ret = new BufferedImage(bmp.bmWidth.intValue(), bmp.bmHeight.intValue() / 2, BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
}
|
||||
if (ret == null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (info.hbmColor != null) {
|
||||
Gdi32.INSTANCE.DeleteObject(info.hbmColor);
|
||||
}
|
||||
if (info.hbmMask != null) {
|
||||
Gdi32.INSTANCE.DeleteObject(info.hbmMask);
|
||||
}
|
||||
|
||||
drawIcon(ret, hIcon, User32.DI_NORMAL);
|
||||
BufferedImage mask = new BufferedImage(ret.getWidth(), ret.getHeight(), BufferedImage.TYPE_INT_RGB);
|
||||
drawIcon(mask, hIcon, User32.DI_MASK);
|
||||
applyMask(ret, mask);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static BufferedImage getShellIcon(String path) {
|
||||
SHFILEINFO fi = new SHFILEINFO();
|
||||
BaseTSD.DWORD_PTR r = Shell32.INSTANCE.SHGetFileInfo(path, 0, fi, fi.size(), Shell32.SHGFI_ICON | Shell32.SHGFI_SMALLICON);
|
||||
if (r.intValue() == 0) {
|
||||
return null;
|
||||
}
|
||||
return iconToImage(fi.hIcon);
|
||||
}
|
||||
|
||||
public static BufferedImage extractExeIcon(String fullExeFile, int index, boolean large) {
|
||||
PointerByReference iconsLargeRef = new PointerByReference();
|
||||
PointerByReference iconsSmallRef = new PointerByReference();
|
||||
int cnt = Shell32.INSTANCE.ExtractIconEx(fullExeFile, index, iconsLargeRef, iconsSmallRef, new WinDef.UINT(1)).intValue();
|
||||
if (cnt == 0) {
|
||||
return null;
|
||||
}
|
||||
Pointer iconsLarge = iconsLargeRef.getPointer();
|
||||
Pointer iconsSmall = iconsSmallRef.getPointer();
|
||||
|
||||
WinDef.HICON icon;
|
||||
if (large) {
|
||||
icon = new WinDef.HICON(iconsLarge.getPointer(0));
|
||||
} else {
|
||||
icon = new WinDef.HICON(iconsSmall.getPointer(0));
|
||||
}
|
||||
|
||||
BufferedImage ic = iconToImage(icon);
|
||||
|
||||
User32.INSTANCE.DestroyIcon(icon);
|
||||
return ic;
|
||||
}
|
||||
|
||||
public static List<com.jpexs.process.Process> listProcesses() {
|
||||
if (!privAdjusted) {
|
||||
adjustPrivileges();
|
||||
}
|
||||
List<com.jpexs.process.Process> ret = new ArrayList<>();
|
||||
WinNT.HANDLE hSnapShot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(new WinDef.DWORD(Kernel32.TH32CS_SNAPPROCESS), new WinDef.DWORD(0));
|
||||
PROCESSENTRY32 pe = new PROCESSENTRY32();
|
||||
if (Kernel32.INSTANCE.Process32First(hSnapShot, pe)) {
|
||||
do {
|
||||
int i;
|
||||
i = 0;
|
||||
for (; i < pe.szExeFile.length; i++) {
|
||||
if (pe.szExeFile[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
String exeFile = new String(pe.szExeFile, 0, i);
|
||||
char[] outputnames = new char[1024];
|
||||
WinNT.HANDLE tempProcess = Kernel32.INSTANCE.OpenProcess(Kernel32.PROCESS_QUERY_INFORMATION, false, pe.th32ProcessID);
|
||||
if (tempProcess == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
int rn = Psapi.INSTANCE.GetProcessImageFileNameW(tempProcess, outputnames, 1024);
|
||||
if (rn == 0) {
|
||||
Logger.getLogger(Win32ProcessTools.class.getName()).log(Level.SEVERE, "Can't get EXE path");
|
||||
}
|
||||
} catch (Exception | UnsatisfiedLinkError e) {
|
||||
}
|
||||
|
||||
try {
|
||||
int rn = Kernel32.INSTANCE.GetProcessImageFileNameW(tempProcess, outputnames, 1024);
|
||||
if (rn == 0) {
|
||||
Logger.getLogger(Win32ProcessTools.class.getName()).log(Level.SEVERE, "Can't get EXE path");
|
||||
}
|
||||
} catch (Exception | UnsatisfiedLinkError e) {
|
||||
}
|
||||
i = 0;
|
||||
for (; i < outputnames.length; i++) {
|
||||
if (outputnames[i] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
String fullExeFile = new String(outputnames, 0, i);
|
||||
fullExeFile = ntPathToWin32(fullExeFile);
|
||||
ret.add(new Win32Process(fullExeFile, exeFile, getShellIcon(fullExeFile), pe.th32ProcessID));
|
||||
} while (Kernel32.INSTANCE.Process32Next(hSnapShot, pe));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean pageReadable(MEMORY_BASIC_INFORMATION mbi) {
|
||||
int iUnReadable = 0;
|
||||
iUnReadable |= (mbi.state.intValue() == Kernel32.MEM_FREE) ? 1 : 0;
|
||||
iUnReadable |= (mbi.state.intValue() == Kernel32.MEM_RESERVE) ? 1 : 0;
|
||||
iUnReadable |= (mbi.protect.intValue() & WinNT.PAGE_WRITECOPY);
|
||||
iUnReadable |= (mbi.protect.intValue() & WinNT.PAGE_EXECUTE);
|
||||
iUnReadable |= (mbi.protect.intValue() & WinNT.PAGE_GUARD);
|
||||
iUnReadable |= (mbi.protect.intValue() & WinNT.PAGE_NOACCESS);
|
||||
return iUnReadable == 0;
|
||||
}
|
||||
|
||||
public static Map<Long, InputStream> findBytesInProcessMemory(ProgressListener progListener, WinDef.DWORD dwProcessID, byte[][] findBytesAll) {
|
||||
int maxFindLen = 0;
|
||||
for (int i = 0; i < findBytesAll.length; i++) {
|
||||
if (findBytesAll[i].length > maxFindLen) {
|
||||
maxFindLen = findBytesAll[i].length;
|
||||
}
|
||||
}
|
||||
Map<Long, InputStream> ret = new HashMap<>();
|
||||
WinNT.HANDLE hOtherProcess = Kernel32.INSTANCE.OpenProcess(Kernel32.PROCESS_VM_READ | Kernel32.PROCESS_VM_WRITE | Kernel32.PROCESS_QUERY_INFORMATION | Kernel32.PROCESS_VM_OPERATION /*for VirtualProtectEx*/, false, dwProcessID);
|
||||
List<MEMORY_BASIC_INFORMATION> pages = getPageRanges(hOtherProcess);
|
||||
long totalMemLen = 0;
|
||||
int progress = 0;
|
||||
for (int pg = 0; pg < pages.size(); pg++) {
|
||||
totalMemLen += pages.get(pg).regionSize.longValue();
|
||||
}
|
||||
|
||||
long actualPos = 0;
|
||||
byte[] prevBytes = new byte[0];
|
||||
List<Integer> guardedPages = new ArrayList<>();
|
||||
for (int pg = 0; pg < pages.size(); pg++) {
|
||||
MEMORY_BASIC_INFORMATION mbi = pages.get(pg);
|
||||
if (pageReadable(mbi)) {
|
||||
int addr = (int) pointerToAddress(mbi.baseAddress);
|
||||
int maxsize = mbi.regionSize.intValue();
|
||||
int pos = 0;
|
||||
int bufSize = 1024;
|
||||
do {
|
||||
IntByReference bytesReadRef = new IntByReference();
|
||||
Memory buf = new Memory(bufSize);
|
||||
boolean ok = Kernel32.INSTANCE.ReadProcessMemory(hOtherProcess, addr + pos, buf, bufSize, bytesReadRef);
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
if (bytesReadRef.getValue() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
byte[] data = buf.getByteArray(0, bytesReadRef.getValue());
|
||||
|
||||
prevBytes = Arrays.copyOfRange(data, data.length - maxFindLen, data.length);
|
||||
byte[] dataPlusPrev = mergeArrays(prevBytes, data);
|
||||
loopi:
|
||||
for (int i = 0; i < dataPlusPrev.length - maxFindLen; i++) {
|
||||
loopk:
|
||||
for (int k = 0; k < findBytesAll.length; k++) {
|
||||
if (dataPlusPrev[i] == findBytesAll[k][0]) {
|
||||
for (int p = 1; p < findBytesAll[k].length; p++) {
|
||||
if (dataPlusPrev[i + p] != findBytesAll[k][p]) {
|
||||
continue loopk;
|
||||
}
|
||||
}
|
||||
long dataAddr = (long) (addr + pos - prevBytes.length + i);
|
||||
ret.put(dataAddr, new ProcessMemoryInputStream(pages, hOtherProcess, pg, pos - prevBytes.length + i));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
pos += bytesReadRef.getValue();
|
||||
if (progListener != null) {
|
||||
int newprogress = Math.round((actualPos + pos) * 100 / totalMemLen);
|
||||
if (newprogress != progress) {
|
||||
progress = newprogress;
|
||||
progListener.progress(progress);
|
||||
}
|
||||
}
|
||||
if (pos + bufSize >= maxsize) {
|
||||
bufSize = maxsize - pos;
|
||||
}
|
||||
} while (bufSize > 0);
|
||||
} else {
|
||||
if (hasGuard(mbi)) {
|
||||
if (unsetGuard(hOtherProcess, mbi)) {
|
||||
guardedPages.add(pg);
|
||||
pg--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
actualPos += mbi.regionSize.longValue();
|
||||
int newprogress = Math.round(actualPos * 100 / totalMemLen);
|
||||
if (newprogress != progress) {
|
||||
progress = newprogress;
|
||||
progListener.progress(progress);
|
||||
}
|
||||
}
|
||||
|
||||
//Set PAGE_GUARD back again
|
||||
for (int pg : guardedPages) {
|
||||
setGuard(hOtherProcess, pages.get(pg));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static boolean hasGuard(MEMORY_BASIC_INFORMATION mbi) {
|
||||
return (mbi.protect.intValue() & WinNT.PAGE_GUARD) == WinNT.PAGE_GUARD;
|
||||
}
|
||||
|
||||
private static boolean unsetGuard(HANDLE hOtherProcess, MEMORY_BASIC_INFORMATION mbi) {
|
||||
if (!hasGuard(mbi)) {
|
||||
return true;
|
||||
}
|
||||
int oldProt = mbi.protect.intValue();
|
||||
int newProt = oldProt - WinNT.PAGE_GUARD;
|
||||
IntByReference oldProtRef = new IntByReference();
|
||||
boolean ok = Kernel32.INSTANCE.VirtualProtectEx(hOtherProcess, new WinDef.LPVOID(pointerToAddress(mbi.baseAddress)), mbi.regionSize, newProt, oldProtRef);
|
||||
if (ok) {
|
||||
mbi.protect = new NativeLong(newProt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean setGuard(HANDLE hOtherProcess, MEMORY_BASIC_INFORMATION mbi) {
|
||||
if (hasGuard(mbi)) {
|
||||
return true;
|
||||
}
|
||||
int oldProt = mbi.protect.intValue();
|
||||
int newProt = oldProt | WinNT.PAGE_GUARD;
|
||||
IntByReference oldProtRef = new IntByReference();
|
||||
boolean ok = Kernel32.INSTANCE.VirtualProtectEx(hOtherProcess, new WinDef.LPVOID(pointerToAddress(mbi.baseAddress)), mbi.regionSize, newProt, oldProtRef);
|
||||
if (ok) {
|
||||
mbi.protect = new NativeLong(newProt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static boolean privAdjusted = false;
|
||||
|
||||
public static boolean adjustPrivileges() {
|
||||
|
||||
WinNT.TOKEN_PRIVILEGES tp = new WinNT.TOKEN_PRIVILEGES(1);
|
||||
WinNT.TOKEN_PRIVILEGES oldtp = new WinNT.TOKEN_PRIVILEGES(1);
|
||||
WinNT.LUID luid = new WinNT.LUID();
|
||||
WinNT.HANDLEByReference hTokenRef = new WinNT.HANDLEByReference();
|
||||
if (!Advapi32.INSTANCE.OpenProcessToken(Kernel32.INSTANCE.GetCurrentProcess(), WinNT.TOKEN_ADJUST_PRIVILEGES | WinNT.TOKEN_QUERY, hTokenRef)) {
|
||||
return false;
|
||||
}
|
||||
WinNT.HANDLE hToken = hTokenRef.getValue();
|
||||
if (!Advapi32.INSTANCE.LookupPrivilegeValue(null, WinNT.SE_DEBUG_NAME, luid)) {
|
||||
Kernel32.INSTANCE.CloseHandle(hToken);
|
||||
return false;
|
||||
}
|
||||
|
||||
tp.PrivilegeCount = new WinDef.DWORD(1);
|
||||
tp.Privileges = new WinNT.LUID_AND_ATTRIBUTES[1];
|
||||
tp.Privileges[0] = new WinNT.LUID_AND_ATTRIBUTES(luid, new WinDef.DWORD(WinNT.SE_PRIVILEGE_ENABLED));
|
||||
|
||||
IntByReference retSize = new IntByReference(0);
|
||||
if (!Advapi32.INSTANCE.AdjustTokenPrivileges(hToken, false, tp, tp.size(), oldtp, retSize)) {
|
||||
Kernel32.INSTANCE.CloseHandle(hToken);
|
||||
return false;
|
||||
}
|
||||
Kernel32.INSTANCE.CloseHandle(hToken);
|
||||
privAdjusted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class ProcessMemoryInputStream extends InputStream {
|
||||
|
||||
private final List<MEMORY_BASIC_INFORMATION> pages;
|
||||
private int currentPage = 0;
|
||||
private int pagePos = 0;
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
private byte[] buf;
|
||||
private int bufPos;
|
||||
private final HANDLE hOtherProcess;
|
||||
|
||||
public ProcessMemoryInputStream(List<MEMORY_BASIC_INFORMATION> pages, HANDLE hOtherProcess, int currentPage, int pagePos) {
|
||||
this.pages = pages;
|
||||
this.hOtherProcess = hOtherProcess;
|
||||
this.currentPage = currentPage;
|
||||
this.pagePos = pagePos;
|
||||
}
|
||||
|
||||
private boolean readNext() throws IOException {
|
||||
MEMORY_BASIC_INFORMATION mbi = pages.get(currentPage);
|
||||
if (!pageReadable(mbi)) {
|
||||
if (hasGuard(mbi)) {
|
||||
if (unsetGuard(hOtherProcess, mbi)) {
|
||||
boolean ret = readNext();
|
||||
setGuard(hOtherProcess, mbi);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (currentPage + 1 < pages.size()) {
|
||||
pagePos = 0;
|
||||
currentPage++;
|
||||
return readNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int addr = (int) pointerToAddress(mbi.baseAddress);
|
||||
int maxsize = mbi.regionSize.intValue();
|
||||
IntByReference bytesReadRef = new IntByReference();
|
||||
Memory membuf = new Memory(BUFFER_SIZE);
|
||||
int bufSize = BUFFER_SIZE;
|
||||
if (pagePos + bufSize > maxsize) {
|
||||
bufSize = maxsize - pagePos;
|
||||
}
|
||||
if (bufSize == 0) {
|
||||
if (currentPage + 1 < pages.size()) {
|
||||
pagePos = 0;
|
||||
currentPage++;
|
||||
return readNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean ok = Kernel32.INSTANCE.ReadProcessMemory(hOtherProcess, addr + pagePos, membuf, bufSize, bytesReadRef);
|
||||
if (!ok) {
|
||||
throw new IOException("Cannot read memory");
|
||||
}
|
||||
if (bytesReadRef.getValue() == 0) {
|
||||
return readNext();
|
||||
}
|
||||
pagePos += bytesReadRef.getValue();
|
||||
|
||||
buf = membuf.getByteArray(0, bytesReadRef.getValue());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if ((buf == null) || (bufPos >= buf.length)) {
|
||||
if (buf != null) {
|
||||
bufPos = 0;
|
||||
}
|
||||
if (!readNext()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return buf[bufPos++] & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user