-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WinAPI] Wrong declaration of CreateRemoteThread in Kernel32 interface #1115
Labels
Comments
Can you suggest a minimal sample, that could be turned into a unittest for this? |
Yes, here is the test: import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;
import junit.framework.Assert;
import org.junit.Test;
import static com.sun.jna.platform.win32.WinNT.*;
public class CreateRemoteThreadTest {
interface MyKernel32 extends Kernel32 {
MyKernel32 INSTANCE = Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
Pointer VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
HANDLE CreateRemoteThread(HANDLE hProcess, SECURITY_ATTRIBUTES attr, int stackSize,
Pointer startAddr, Pointer param, DWORD flags, Pointer threadId);
boolean GetExitCodeThread(HANDLE hThread, IntByReference exitCode);
}
@Test
public void myCreateRemoteThread() {
Pointer addr = MyKernel32.INSTANCE.VirtualAlloc(null, new SIZE_T(4096),
new DWORD(MEM_COMMIT | MEM_RESERVE), new DWORD(PAGE_EXECUTE_READWRITE));
// mov eax, ecx; ret; int3
addr.setInt(0, 0xccc3c18b);
HANDLE hThread = MyKernel32.INSTANCE.CreateRemoteThread(
MyKernel32.INSTANCE.GetCurrentProcess(),
null, 0, addr, new Pointer(12345), new DWORD(0), null);
Assert.assertNotNull(hThread);
int waitResult = MyKernel32.INSTANCE.WaitForSingleObject(hThread, 10_000);
Assert.assertEquals(WAIT_OBJECT_0, waitResult);
IntByReference exitCode = new IntByReference();
boolean exitResult = MyKernel32.INSTANCE.GetExitCodeThread(hThread, exitCode);
Assert.assertTrue(exitResult);
Assert.assertEquals(12345, exitCode.getValue());
}
@Test
public void platformCreateRemoteThread() {
Pointer addr = MyKernel32.INSTANCE.VirtualAlloc(null, new SIZE_T(4096),
new DWORD(MEM_COMMIT | MEM_RESERVE), new DWORD(PAGE_EXECUTE_READWRITE));
// mov eax, ecx; ret; int3
addr.setInt(0, 0xccc3c18b);
FOREIGN_THREAD_START_ROUTINE startRoutine = new FOREIGN_THREAD_START_ROUTINE();
startRoutine.foreignLocation.setPointer(addr);
HANDLE hThread = Kernel32.INSTANCE.CreateRemoteThread(
MyKernel32.INSTANCE.GetCurrentProcess(),
null, 0, startRoutine, new Pointer(12345), new DWORD(0), null);
Assert.assertNotNull(hThread);
int waitResult = MyKernel32.INSTANCE.WaitForSingleObject(hThread, 10_000);
Assert.assertEquals(WAIT_OBJECT_0, waitResult);
IntByReference exitCode = new IntByReference();
boolean exitResult = MyKernel32.INSTANCE.GetExitCodeThread(hThread, exitCode);
Assert.assertTrue(exitResult);
Assert.assertEquals(12345, exitCode.getValue());
}
}
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
CreateRemoteThread
is currently declared asWin API expects a pointer as a start address argument. However, in the above declaration it is
FOREIGN_THREAD_START_ROUTINE
which is a structure with a pointer. Therefore JNA creates an extra level of indirection when passinglpStartAddress
, and this leads to an immediate crash of the target process with EXCEPTION_ACCESS_VIOLATION.FOREIGN_THREAD_START_ROUTINE
should extendPointerType
rather thanStructure
.See https://twitter.com/rafaelcodes/status/1152682931569274881?s=20 for an example.
The text was updated successfully, but these errors were encountered: