EnumProcessModules returns 0 with error 299

1

I'm currently trying to enumerate all the modules of a supsended 32-bits process I've previously created from my 32-bits program, my Windows is 64-bits. (I've already read all the other topics on that problem).

Here is the code:

let a = CreateProcessA(
    "C:\\Program Files (x86)\\GlassWire\\GlassWire.exe\0".as_ptr(),
    null_mut(), null_mut(), null_mut(),
    false,
    0x00000004,
    null_mut(), null_mut(), SI, PI);
println!("{}", GetLastError());

let mut buffer: [*mut c_void;10] = [0 as *mut c_void;10];
WaitForInputIdle((*PI).hProcess as *mut c_void, -1);
let result = EnumProcessModules(
    (*PI).hProcess as *mut c_void,
    buffer.as_ptr() as *mut c_void,
    10, null_mut());

println!("EnumProcessModules([...]) = {} - {}", result, GetLastError());

let mut index: usize = 0x0; 
let mut modname: [u8;1024] = [0;1024];
while(transmute::<*mut c_void, u32>(buffer[index]) != 0x0){
    GetModuleFileNameExA((*PI).hProcess as *mut c_void, buffer[index], modname.as_ptr() as *mut c_void, 1024);
    println!("module: {}", std::str::from_utf8_unchecked(&modname));
    modname = [0;1024];
    index += 1;
}
println!("Dump: {:?}", buffer.to_vec());

I saw that I had to use WaitForInputIdle() after using CreateProcessA before enumerating modules because the process doesn't have the time to "initialize", well when I do that, whatever the process I create (it successfully creates it) the program wait forever.

And when I try to do the same on the main process by replacing all the (*PI).hProcess by GetCurrentProcess() (I removed the WintForInputIdle() line), EnumProcessModules() still returns 0 but now GetLastError() returns 998 (ERROR_NOACCESS), but the modules handles are successfully written in buffer.

So the program output:

A:\Encrypted\Temp\injector\target\i686-pc-windows-msvc\debug\main.exe // (the program)
C:\WINDOWS\SYSTEM32\ntdll.dll

Dump: [0x920000, 0x77180000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]

And if I specify the path of the running program in CreateProcessA(), it will also return 0 with 299 as the windows error code.

I'm really confused...Thanks for reading, I hope I've been clear enough.

winapi
rust
asked on Stack Overflow Dec 24, 2019 by Aleister Crowley • edited Dec 24, 2019 by Aleister Crowley

1 Answer

0

First, use the CREATE_NEW_CONSOLE or CREATE_NO_WINDOW instead of CREATE_SUSPENDED(0x00000004), as @Jonathan Potter, the suspend state will block the function WaitForInputIdle.

Second, make sure that the process is not a console application or has a message queue, otherwise WaitForInputIdle returns immediately.

Then, you can try to call SuspendThread after WaitForInputIdle to suspend the process to prevent it from ending.

EDIT:

Pay attention to the last two parameters of EnumProcessModules:

cb

The size of the lphModule array, in bytes.

lpcbNeeded

The number of bytes required to store all module handles in the lphModule array.

Here is a good sample on msdn: Enumerating All Modules For a Process. Just replace hProcess.

answered on Stack Overflow Dec 25, 2019 by Drake Wu • edited Dec 26, 2019 by Drake Wu

User contributions licensed under CC BY-SA 3.0