I am trying to allocate space in memory with ntdll.dll. I am using the NtApi and winapi crates.
When I try to allocate, I get the next error:
exit code: 0xc0000005, STATUS_ACCESS_VIOLATION
How do I need to send the pointer to NtAllocateVirtualMemory()?
Why does VirtualAllocEx() work?
I understand when I call VirtualAllocEx(), the process is kernel32.dll -> ntdll.dll, so why doesn't this work when I send this to NtAllocateVirtualMemory()?
main.rs
use ntapi::ntmmapi::NtAllocateVirtualMemory;
use ntapi::ntpsapi::NtCurrentProcess;
use ntapi::winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_READWRITE};
use winapi::shared::ntdef::{NT_SUCCESS};
use ntapi::_core::ptr::null_mut;
fn main() {
unsafe {
// let null_ptr=std::ptr::null();
// let null_base:*const winapi::ctypes::c_void=null_ptr as *const _;
let mut buffer=null_mut();
let status = NtAllocateVirtualMemory(
NtCurrentProcess,
*buffer,
0,
0x1000 as *mut _,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE,
);
if !NT_SUCCESS(status) {
// if status as usize == 0x0 {
println!("Allocation Fails");
} else {
println!("Allocation Success");
}
}
}
Cargo.toml
[package]
name = "allocate_null"
version = "0.1.0"
edition = "2018"
[dependencies]
winapi = {version="0.3.9", features=["ntdef","winnt","memoryapi"]}
ntapi = "0.3.6"
Related
When I use the ReadProcessMemory function from the windows-rs package it returns 0. This is wrong, so I used the GetLastError() function and it returned "Only part of a ReadProcessMemory or WriteProcessMemory request was completed."
Here is the code for ReadProcessMemory:
unsafe{
let mut healthValue: i32 = 0;
ReadProcessMemory(
hProcess,
0xE6A848 as *mut c_void,
healthValue as *mut c_void,
std::mem::size_of::<i32> as usize,
&mut 0
);
println!("{}", healthValue);
match GetLastError().ok() {
Ok(_) => println!("no eror"),
Err(t) => println!("error: {}", t),
}
};
The code to get handle to the process:
let hProcess: HANDLE;
unsafe{
match OpenProcess(PROCESS_ALL_ACCESS, false, procId as u32) {
Ok(T) => hProcess = T,
Err(A) => {
hProcess = INVALID_HANDLE_VALUE;
println!("hproc is INVALID");
}
}
}
I have checked and the ProcId is right, I have used cheat engine to get the memory address, both apps are run in 32-bit, and my trainer is being run as admin. None of these have helped.
Fixed it by changing healthValue as *mut c_void to ptr::addr_of_mut!(healthValue) as *mut c_void.
I am trying to make application state working in Rust.
I got the Rust application state part from windows-rs sample line 357 and modified it a little to work with my code. The only problem is, it did not work as expected...
As you can see from the comments in the code below, my problem is that after using the mentioned two functions my pointer (state) loses its first two digits.
Every time I run this, the first two digits are always missing.
How can I solve this?
extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
unsafe {
match message as u32 {
WM_NCCREATE => {
// ORIGINAL address given to CreateWindowExW: 0xb678ddf730
let cs = lparam as *const CREATESTRUCTW;
let state = (*cs).lpCreateParams as *mut State;
println!("{:?}", state); // OUTPUT: 0xb678ddf730 (correct)
// After using the two functions:
SetWindowLongW(window, GWLP_USERDATA, state as i32);
let state = GetWindowLongW(window, GWLP_USERDATA) as *mut State;
println!("{:?}", state); // OUTPUT: 0x78ddf730 (missing first 2 digits "b6")
1
}
...
Full code:
#![allow(dead_code)]
//#![allow(unused_)]
#![allow(unused_variables)]
use windows_sys::{
Win32::Foundation::*,
Win32::Graphics::Gdi::ValidateRect,
Win32::System::LibraryLoader::GetModuleHandleW,
Win32::UI::WindowsAndMessaging::*,
};
fn u16_str(string: &str) -> Vec<u16> {
let mut result: Vec<u16> = string.encode_utf16().collect();
result.push(0);
result
}
#[derive(Debug)]
struct State {
name: String,
}
fn main() {
unsafe {
let instance = GetModuleHandleW(std::ptr::null());
let wc = WNDCLASSEXW {
cbSize: std::mem::size_of::<WNDCLASSEXW>() as u32,
hCursor: LoadCursorW(0, IDC_ARROW),
hInstance: instance,
lpszClassName: u16_str("asd").as_ptr(),
style: CS_HREDRAW | CS_VREDRAW,
lpfnWndProc: Some(wndproc),
cbClsExtra: 0,
cbWndExtra: 0,
hIcon: 0,
hbrBackground: 0,
lpszMenuName: std::ptr::null(),
hIconSm: 0,
};
RegisterClassExW(&wc);
let mut state = State {
name: String::from("name"),
};
println!("{:?}", &mut state as *mut _);
CreateWindowExW(
0,
u16_str("asd").as_ptr(),
u16_str("Ablak 1 áéőüűö").as_ptr(),
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0, 0, instance, &mut state as *mut _ as _,
);
let mut message = std::mem::zeroed();
while GetMessageW(&mut message, 0, 0, 0) != 0 {
DispatchMessageW(&message);
}
}
}
extern "system" fn wndproc(window: HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
unsafe {
match message as u32 {
WM_NCCREATE => {
let cs = lparam as *const CREATESTRUCTW;
let state = (*cs).lpCreateParams as *mut State;
println!("{:?}", state);
SetWindowLongW(window, GWLP_USERDATA, state as i32);
let state = GetWindowLongW(window, GWLP_USERDATA) as *mut State;
println!("{:?}", state);
1
}
WM_PAINT => {
//let state = GetWindowLongPtrW(window, GWLP_USERDATA) as *mut State;
//println!("{:?}", state);
//println!("{}", GetLastError());
println!("paint");
ValidateRect(window, std::ptr::null());
0
}
WM_DESTROY => {
println!("WM_DESTROY");
PostQuitMessage(0);
0
}
_ => DefWindowProcW(window, message, wparam, lparam),
}
}
}
Cargo.toml:
...
[dependencies.windows-sys]
version = "0.36.1"
features = [
"Win32_Foundation",
"Win32_System_LibraryLoader",
"Win32_Graphics_Gdi",
"Win32_Graphics_Direct2D",
"Win32_UI_WindowsAndMessaging",
]
The GetWindowLongW and SetWindowLongW API calls can only store 32-bit values. 32 bits is the size of a pointer for 32-bit architectures. Since you are targeting a 64-bit architecture, you'll have to follow the advice from the documentation:
If you are retrieving a pointer or a handle, this function has been superseded by the GetWindowLongPtrW function. (Pointers and handles are 32 bits on 32-bit Windows and 64 bits on 64-bit Windows.) To write code that is compatible with both 32-bit and 64-bit versions of Windows, use GetWindowLongPtrW.
and
This function has been superseded by the SetWindowLongPtr function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use the SetWindowLongPtr function.
You'll have to replace
SetWindowLongW(window, GWLP_USERDATA, state as i32);
// ^^^^^^ truncates pointer to 32 bits
with
SetWindowLongPtrW(window, GWLP_USERDATA, state as isize);
The GetWindowLongW calls merely need to be replaced with GetWindowLongPtrW calls. Other changes aren't required here.
Note that while the -Ptr variants are immediately available through the windows and windows-sys crates when targeting a 64-bit architecture, they are missing for 32-bit targets (see this GitHub issue). You can provide your own implementation, e.g.
#[allow(non_snake_case)]
#[cfg(target_pointer_width = "32")]
unsafe fn SetWindowLongPtrW(window: HWND, index: WINDOW_LONG_PTR_INDEX, value: isize) -> isize {
SetWindowLongW(window, index, value as _) as _
}
#[allow(non_snake_case)]
#[cfg(target_pointer_width = "32")]
unsafe fn GetWindowLongPtrW(window: HWND, index: WINDOW_LONG_PTR_INDEX) -> isize {
GetWindowLongA(window, index) as _
}
With that in place you can simply call GetWindowLongPtrW/SetWindowLongPtrW irrespective of target architecture, same as when writing C/C++ code using the Windows SDK headers.
.. Hi, I have this code :
#[cfg(windows)] extern crate winapi;
use winapi::um::winuser::{FindWindowW, GetClientRect, GetWindowDC, GetDC, ReleaseDC};
use winapi::um::wingdi::{CreateBitmap, CreateCompatibleBitmap, CreateCompatibleDC, SelectObject, GetObjectW, SaveDC, DeleteDC, DeleteObject};
use std::ptr::null_mut;
use std::mem::zeroed;
use std::ffi::OsStr;
use std::iter::once;
use std::os::windows::ffi::OsStrExt;
#[cfg(windows)]
fn find_window(name: &str) {
let window: Vec<u16> = OsStr::new(name).encode_wide().chain(once(0)).collect();
let hwnd = unsafe { FindWindowW(null_mut(), window.as_ptr()) };
if hwnd != null_mut() {
println!("Window found");
let mut my_rect = unsafe { zeroed::<winapi::shared::windef::RECT>() };
let _client_rect = unsafe { GetClientRect(hwnd, &mut my_rect) };
let w = my_rect.right - my_rect.left;
let h = my_rect.bottom - my_rect.top;
let hwnd_dc = unsafe { GetWindowDC(hwnd) };
let mem_dc = unsafe { CreateCompatibleDC(hwnd_dc) };
let bmp = unsafe { CreateCompatibleBitmap(mem_dc, w, h) };
//SelectObject(mem_dc, bmp); <== Problem is here
//DeleteObject(bmp); <== Same problem here
unsafe { DeleteDC(mem_dc) };
unsafe { ReleaseDC(hwnd, hwnd_dc) };
}
else {
println!("Window not found");
}
}
fn main() {
find_window("Firefox"); // just for test
}
If I cargo run this, I get :
SelectObject(mem_dc, bmp);
| ^^^ expected enum `std::ffi::c_void`, found enum `winapi::shared::windef::HBITMAP__`
So I get it, it doesn't want that bitmap pointer, but in the win32 documentation, it says that this function (SelectObject) accepts a Device Context (mem_dc) and an object created by some function like CreateCompatibleBitmap.
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject
The binding in Rust accepts the two same arguments but it seems to want that std::ffi::c_void but looking a the Rust doc, I don't get what it is exactly.
Can you help me finding what's wrong ? Thanks.
Add:
use winapi::shared::windef::{HBITMAP, HBITMAP__, HGDIOBJ, HWND, POINT, RECT, SIZE};
...
unsafe {SelectObject(mem_dc, bmp as HGDIOBJ)};
unsafe {DeleteObject(bmp as HGDIOBJ)};
Error message:
error: linking with `x86_64-w64-mingw32-gcc` failed: exit code: 1
|
<a lot of paths and args>
C:\Users\wikto\IdeaProjects\test/src/main.rs:297: undefined reference to `WaitForDebugEventEx'
Part of main.rs, I can share the rest if needed.
mod winapi;
use winapi::*;
unsafe fn debug_loop(&mut self, process_id: DWORD) {
let mut continue_status = DBG_CONTINUE;
let mut debug_event = std::mem::zeroed::<DEBUG_EVENT>();
let debug_event = &mut debug_event;
while WaitForDebugEventEx(debug_event, INFINITE) != 0 {
//something
}
}
Part of winapi.rs
#[link(name = "Kernel32")]
extern "C" {
pub fn WaitForDebugEventEx(
lpDebugEvent: *mut DEBUG_EVENT,
dwMilliseconds: DWORD,
) -> BOOL;
}
Is there anything I'm doing wrong or maybe it's a problem with mingw32-gcc?
#[cfg(windows)] extern crate winapi;
#[cfg(windows)] use winapi::shared::windef::HWND;
#[cfg(windows)] use winapi::shared::windef::HMENU;
#[cfg(windows)] use winapi::shared::windef::HBRUSH;
#[cfg(windows)] use winapi::shared::minwindef::HINSTANCE;
#[cfg(windows)] use winapi::shared::minwindef::UINT;
#[cfg(windows)] use winapi::shared::minwindef::DWORD;
#[cfg(windows)] use winapi::shared::minwindef::WPARAM;
#[cfg(windows)] use winapi::shared::minwindef::LPARAM;
#[cfg(windows)] use winapi::shared::minwindef::LRESULT;
#[cfg(windows)] use winapi::um::winnt::LPCWSTR;
#[cfg(windows)] use winapi::um::winuser::WS_OVERLAPPEDWINDOW;
#[cfg(windows)] use winapi::um::winuser::WS_VISIBLE;
#[cfg(windows)] use winapi::um::winuser::WNDCLASSW;
#[cfg(windows)] use std::os::windows::ffi::OsStrExt;
#[cfg(windows)] use std::ffi::OsStr;
#[cfg(windows)] use std::os::raw::c_void;
#[cfg(windows)] use winapi::um::libloaderapi::GetProcAddress;
#[cfg(windows)] use gl::types::*;
// Vertex data
static VERTEX_DATA: [GLfloat; 6] = [0.0, 0.5, 0.5, -0.5, -0.5, -0.5];
// Shader sources
static VS_SRC: &'static str = "
#version 150
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}";
static FS_SRC: &'static str = "
#version 150
out vec4 out_color;
void main() {
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}";
mod gl
{
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
#[cfg(windows)]
fn to_wstring(str : &str) -> Vec<u16>
{
let v : Vec<u16> =
OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
v
}
#[cfg(windows)]
pub unsafe extern "system" fn window_proc(h_wnd :HWND,
msg :UINT, w_param :WPARAM, l_param :LPARAM) -> LRESULT
{
if msg == winapi::um::winuser::WM_DESTROY {
winapi::um::winuser::PostQuitMessage(0i32);
}
return winapi::um::winuser::DefWindowProcW(h_wnd, msg, w_param, l_param);
}
fn draw_gl_scene(window_width: i32, window_height: i32,
h_dc: winapi::shared::windef::HDC)
{
unsafe
{
let module = winapi::um::libloaderapi::LoadLibraryW(to_wstring("opengl32.dll") .as_ptr());
// gl::load_with(|s| GetProcAddress(module,
// s.as_ptr() as *const i8) as *const c_void);
gl::Viewport::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::Viewport::is_loaded() {
gl::Viewport(0, 0, window_width, window_height);
} else {
panic!("gl::Viewport was not loaded")
}
gl::ClearColor::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::ClearColor::is_loaded() {
gl::ClearColor(0.12109375f32, 0.12109375f32, 0.12109375f32, 1.0f32);
} else {
panic!("gl::ClearColor was not loaded")
}
gl::GetError::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
let error_check_value: GLenum = gl::GetError();
/*
gl::CreateShader::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
let mut vertex_shader_id = 0u32;
if gl::CreateShader::is_loaded() {
vertex_shader_id = gl::CreateShader(gl::VERTEX_SHADER);
} else {
panic!("gl::CreateShader was not loaded")
}
*/
/*
let c_str = std::ffi::CString::new(VS_SRC.as_bytes()).unwrap();
gl::ShaderSource::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::ShaderSource::is_loaded() {
gl::ShaderSource(vertex_shader_id, 1, &c_str.as_ptr(), std::ptr::null_mut());
} else {
// panic!("gl::ShaderSource was not loaded")
}
gl::CompileShader::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::CompileShader::is_loaded() {
gl::CompileShader(vertex_shader_id);
} else {
// panic!("gl::CompileShader was not loaded")
}
let mut vertex_array_id: GLuint = 0u32;
gl::GenVertexArrays::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::GenVertexArrays::is_loaded() {
gl::GenVertexArrays(1, &mut vertex_array_id as *mut u32);
} else {
panic!("gl::GenVertexArrays was not loaded")
}
*/
gl::Clear::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::Clear::is_loaded() {
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
} else {
panic!("gl::Clear was not loaded")
}
winapi::um::wingdi::SwapBuffers(h_dc);
}
}
fn main()
{
unsafe
{
let class_name = to_wstring("OpenGL");
let h_instance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null_mut());
let wnd = WNDCLASSW {
style: 0,
lpfnWndProc: Some(window_proc),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: h_instance,
hIcon: winapi::um::winuser::LoadIconW(0 as HINSTANCE,
winapi::um::winuser::IDI_APPLICATION),
hCursor: winapi::um::winuser::LoadCursorW(0 as HINSTANCE,
winapi::um::winuser::IDI_APPLICATION),
hbrBackground: 16 as HBRUSH,
lpszMenuName: 0 as LPCWSTR,
lpszClassName: class_name.as_ptr(),
};
winapi::um::winuser::RegisterClassW(&wnd);
let window_width = 640;
let window_height = 480;
let h_wnd_window = winapi::um::winuser::CreateWindowExW(0, class_name.as_ptr(),
to_wstring("OpenGL Example").as_ptr(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, window_width, window_height, 0 as HWND, 0 as HMENU, h_instance,
std::ptr::null_mut());
let mut msg = winapi::um::winuser::MSG {
hwnd : 0 as HWND,
message : 0 as UINT,
wParam : 0 as WPARAM,
lParam : 0 as LPARAM,
time : 0 as DWORD,
pt : winapi::shared::windef::POINT { x: 0, y: 0, },
};
let h_dc = winapi::um::winuser::GetDC(h_wnd_window);
let pfd = winapi::um::wingdi::PIXELFORMATDESCRIPTOR {
nSize: std::mem::size_of::<winapi::um::wingdi::PIXELFORMATDESCRIPTOR>() as u16,
nVersion: 1,
dwFlags: winapi::um::wingdi::PFD_DRAW_TO_WINDOW
| winapi::um::wingdi::PFD_SUPPORT_OPENGL | winapi::um::wingdi::PFD_DOUBLEBUFFER,
iPixelType: winapi::um::wingdi::PFD_TYPE_RGBA,
cColorBits: 64,
cRedBits: 0,
cRedShift: 0,
cGreenBits: 0,
cGreenShift: 0,
cBlueBits: 0,
cBlueShift: 0,
cAlphaBits: 0,
cAlphaShift: 0,
cAccumBits: 0,
cAccumRedBits: 0,
cAccumGreenBits: 0,
cAccumBlueBits: 0,
cAccumAlphaBits: 0,
cDepthBits: 32,
cStencilBits: 8,
cAuxBuffers: 0,
iLayerType: winapi::um::wingdi::PFD_MAIN_PLANE,
bReserved: 0,
dwLayerMask: 0,
dwVisibleMask: 0,
dwDamageMask: 0,
};
let pixel_format = winapi::um::wingdi::ChoosePixelFormat(h_dc,
&pfd as *const winapi::um::wingdi::PIXELFORMATDESCRIPTOR);
winapi::um::wingdi::SetPixelFormat(h_dc, pixel_format,
&pfd as *const winapi::um::wingdi::PIXELFORMATDESCRIPTOR);
let h_rc = winapi::um::wingdi::wglCreateContext(h_dc);
winapi::um::wingdi::wglMakeCurrent(h_dc, h_rc);
winapi::um::winuser::ShowWindow(h_wnd_window, winapi::um::winuser::SW_SHOW);
loop
{
if winapi::um::winuser::PeekMessageW(&mut msg, 0u32 as HWND, 0u32, 0u32,
winapi::um::winuser::PM_REMOVE) > 0i32 {
if msg.message == winapi::um::winuser::WM_QUIT {
break;
} else {
winapi::um::winuser::TranslateMessage(&mut msg);
winapi::um::winuser::DispatchMessageW(&mut msg);
}
} else {
draw_gl_scene(window_width, window_height, h_dc);
}
}
}
}
The above code is the version of my implementation of the outdated project located here: https://www.codeproject.com/tips/1053658/win-gui-programming-in-rust-language/
Using the latest version of winapi and gl_generator as the sole two dependencies, I expanded on the starter code to successfully render an OpenGL context in tandem with the Win32 API as opposed to the glfw as suggested by the contributors of the cargo crate gl-rs. When run on a Windows machine, this project as it is presents a dark screen, as seen in this link.
Any further attempt to render something more substantial has been fruitless thus far, due to an inability to load any function pointers that relate to shaders or vertex buffer objects.
If you comb over the function draw_gl_scene, you'll see that I have a generic "load_with" function commented out and a series of function-specific "load_with" functions alongside execution code or panics depending on whether the function in question "is_loaded". The generic "load_with" I've curbed for the time being until writing function-specific "load-with" functions is no longer tenable.
As for CreateShader, ShaderSource, CompileShader, and GenVertexArrays, none of them successfully load if I uncomment any of them. I'm sure this is a user error, The odds that one of winapi and gl-rs or an anomalistic interaction between winapi and gl_generator is the cause is unlikely. I'm at my wit's end as to how to resolve this. I appreciate your time if you've read this far.
Read the wiki and this too about loading OGL pointers.
Briefly, for Windows:
GetProcAddress is only valid for OpenGL <= 1.1
wglGetProcAddress is only valid for OpenGL > 1.1
Also, the use of shaders requires OpenGL >= 2.0. Better go with OGL >= 3.2 Core Profile. For this context:
You need a proper context for OpenGL >= 3.0, which is created with the use of wglCreateContextAttribsARB.
You need a valid and current context to get the pointer to wglCreateContextAttribsARB itself by using wglGetProcAddress.
This context may be temporary. It can be created with wglCreateContext. You can delete it after you got that pointer; and the create the "real" context.
.