get process mdoules c# with kernel.dll - c#

I'm getting some trouble while running this:
public MODULEENTRY32 getModule(String ModuleName)
{
MODULEENTRY32 module32;
module32.dwSize = (uint) Marshal.SizeOf(typeof(MODULEENTRY32));
IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.TH32CS_SNAPMODULE | SnapshotFlags.TH32CS_SNAPMODULE32, (uint) process.Id);
Module32First(hSnap, out module32);
if (hSnap == IntPtr.Zero)
{
return new MODULEENTRY32();
}
do
{
if (module32.szModule.Equals(ModuleName))
{
CloseHandle(hSnap);
return module32;
}
} while (Module32Next(hSnap, out module32));
return new MODULEENTRY32();
}
I was trying to get modules from a process but it always return 0,
I'm sure that the module name is corrent and the process id too

I don't think you have provided enough information to determine what the problem is.
If you read the CreateToolHelp32Snapshot documentation you should check if hSnap returned is INVALID_HANDLE_VALUE (-1). If it is, you need to call GetLastError to determine the reason for the failure.
Possible reasons for failures are documented:
If the specified process is the Idle process or one of the CSRSS
processes, this function fails and the last error code is
ERROR_ACCESS_DENIED because their access restrictions prevent
user-level code from opening them.
If the specified process is a 64-bit process and the caller is a
32-bit process, this function fails and the last error code is
ERROR_PARTIAL_COPY (299).
and:
When taking snapshots that include heaps and modules for a process
other than the current process, the CreateToolhelp32Snapshot function
can fail or return incorrect information for a variety of reasons. For
example, if the loader data table in the target process is corrupted
or not initialized, or if the module list changes during the function
call as a result of DLLs being loaded or unloaded, the function might
fail with ERROR_BAD_LENGTH or other error code. Ensure that the target
process was not started in a suspended state, and try calling the
function again. If the function fails with ERROR_BAD_LENGTH when
called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the
function again until it succeeds.

Related

How to run windows automation application in AWS window server

If I run window automation application in AWS window server, then SendInput or SendKeys method are not working. The message of below is recieved error message, when I call SendInput and Sendkeys method in WPF application on AWS window.
System.Exception: Some simulated input commands were not sent successfully. The most common reason for this happening are the security features of Windows including User Interface Privacy Isolation (UIPI). Your application can only send commands to applications of the same or lower elevation. Similarly certain commands are restricted to Accessibility/UIAutomation applications. Refer to the project home page and the code samples for more information.
location: WindowsInput.WindowsInputMessageDispatcher.DispatchInput(INPUT[] inputs)
location: WindowsInput.MouseSimulator.MoveMouseTo(Double absoluteX, Double absoluteY)
When the my window automation application is running without RDP Session. It crashes.
I think, It is related RDP session. If I'm connecting RDP Session, my application is working very well.
You should provide more information than "RDP session".
You are using native function, SendInput.
[DllImport("user32.dll", SetLastError = true)]
public static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] inputs, Int32 sizeOfInputStructure);
According to Microsoft document,
The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. If the function returns zero, the input was already blocked by another thread. To get extended error information, call GetLastError. This function fails when it is blocked by UIPI. Note that neither GetLastError nor the return value will indicate the failure was caused by UIPI blocking.
Please provide GetLastError result.
You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data.
public void DispatchInput(INPUT[] inputs)
{
if (inputs == null) throw new ArgumentNullException("inputs");
if (inputs.Length == 0) throw new ArgumentException("The input array was empty", "inputs");
try
{
var successful = NativeMethods.SendInput((UInt32)inputs.Length, inputs, Marshal.SizeOf(typeof (INPUT)));
}
catch
{
// if you execute any function that communicate with OS before here, LastError might be lost.
error = Marshal.GetLastWin32Error();
Console.WriteLine("The last Win32 Error was: " + error);
}
if (successful != inputs.Length)
throw new Exception("Some simulated input commands were not sent successfully. The most common reason for this happening are the security features of Windows including User Interface Privacy Isolation (UIPI). Your application can only send commands to applications of the same or lower elevation. Similarly certain commands are restricted to Accessibility/UIAutomation applications. Refer to the project home page and the code samples for more information.");
}

GetGuiResources returns 0 (error 87) or nonsense value

I'm currently coding a windows service (installed as LocalSystem) that monitors several things on a pc/server including processes. For the processes, I'm watching the memory usage and also "try" to get the number of GDI Objects per process (as can be seen in task manager).
Sadly, C# Process objects don't have the gdi count built-in so I'm using the GetGuiResources method from 'user32.dll' as shown in this example:
https://www.pinvoke.net/default.aspx/user32.getguiresources.
Basically I have a list of executable names, for each of them I use GetProcessesByName to retrieve all process instances, and then for each unique process I take the handle and send it to the function to get the Gdi objects count back.
When I try this on my local machine as a simple console app (feeding a name through Console.ReadLine), it works no problem as long as the console app is launched as administrator; i get the same numbers as task manager.
However, when the monitoring service calls this function, I get either 0s (returning error code 87) or worse: processes tied to services (no gui) return me some random numbers (12, 7, 4, etc.) when the task manager actually shows 0 (and last error = 0).
So in summary, every process that shows some GID objects in Task Manager returns 0 (error 87), and each process who has 0 returns me a number (no error, or error 183 for the monitoring service itself).
I've tried this on Windows 10, Windows Server 2012, Windows Server 2008, Windows Server 2003, Windows Server 2016. On windows 10 (my machine) I get 0s everywhere, on other OS I get the mentionned results.
Here's a shortened version of the code I use:
// Monitoring processes exeName example: ssms, sqlbrowser
List<Process> result = Process.GetProcessesByName(exeName).ToList();
if (processes != null)
{
for (int i = 0; i < processes.Count; i++)
{
int gdiCount = processes[i].GetGDIObjectsCount(); // extension method
// logging and doing stuff with gdi count here (but i get 0s or random numbers as I told)
}
}
// Process extension method
public static class CProcessExtensions
{
[DllImport("User32", SetLastError = true)]
extern private static int GetGuiResources(IntPtr hProcess, int uiFlags);
private static int GetGDICount(IntPtr processHandle)
{
if (processHandle == IntPtr.Zero)
{
return -1;
}
int count = GetGuiResources(processHandle, 0);
// Logging Marshal.GetLastWin32Error() here
return count;
}
public static int GetGDIObjectsCount(this Process process)
{
IntPtr handle;
process.Refresh();
try
{
handle = process.Handle;
}
catch (Exception ex)
{
handle = IntPtr.Zero;
}
return GetGDICount(handle);
}
}
I've also tried getting the process handles with the OpenProcess dll method but had the same results.
Anyone faced this kind of problem before?
So, thanks to Jeremy Thompson's comment leading me to info about the session 0, and with further research, I was able to solve my problem.
References:
Application Loader to launch process in another session
Wait for process exit (ProcessWaitHandle)
Get Exit code
What I did is modify the sample code from the first reference to provide a process ID (the one I want the GDI objects count of) and launch my little console app (which takes the same process ID also, and returns the GDI count as exit code) in the same session by duplicating the token of the provided process and call CreateProcessAsUser.
By launching the console app in the same session I was able to retrieve the correct info on GDI objects on every OS I previously tested except Win Server 2003, which I can totally live without.

Windows: Delete EXE after execution

I am working on an application in C# which does the following things:
Write an EXE to disk
Execute the EXE through Process.Start()
I am now trying to ensure that the EXE will be deleted once it is closed.
The easiest way to do so is to set the FileOptions.DeleteOnClose parameter when creating the EXE using File.Create.
However, this means that the EXE can not be executed while is in use. Once the file handle is closed, the EXE is immediately deleted before it can be executed.
Is there any way to retain a "weak reference" to the EXE in my application which does not lock the file and allows it to be executed? Alternatively, is there any way to unlock the EXE for execution with the file handle still open? Are there any other obvious solutions I am missing?
CLARIFICATION A: I am aware of other methods to delete files in use which will delete the file eventually (e.g. upon reboot). I am however looking for a method to delete the file immediately once it starts executing which is handled by the OS (e.g. when running a batch that first executes the file and then deletes it, the file would remain on disk if the batch job is terminated).
CLARIFICATION B: To explain the bigger picture: The application receives and decrypts an executable file. After decryption, the file should be executed. However, I want to make sure the decrypted version of the EXE does not stay on disk. Ideally, I also want to prevent users from copying the decrypted EXE. However, since the decryption application runs as the same user, this will be impossible to achieve in a truly secure fashion as both have the same privileges on the system.
You could use Process.WaitForExit:
var process = Process.Start(processPath);
process.WaitForExit();
// File.Delete(processPath); // Not strong enough (thanks to Binary Worrier)
DeleteOrDie(processPath); // Will attempts anything to delete the file.
But it gives the possibility to copy the exe from where you writed it.
A good solution is to run it from memory.
If your target exe is a CLR program, you can use the Assembly.Load function:
// read the file and put data in bin
...
Assembly a = Assembly.Load(bin);
MethodInfo method = a.EntryPoint;
if (method == null) throw new NoEntryPointException();
object o = a.CreateInstance(method.Name);
method.Invoke(o, null);
More details here.
If you want to load/execute any exe in memory, you could use the Nebbett’s Shuttle approach but you will need to code it in C/C++ and make a call to it from C#.
Also it looks like Microsoft doesn't like it (security issues) and I don't think you can achieve it from C# only. Good anti-virus will probably detect it.
In a not very good way but a way that can give you what you want, I suggest this solution:
(I use a Console Application with some input arguments for this solution)
[1: ] Write a function to check opened processes:
/// <summary>
/// Check application is running by the name of its process ("processName").
/// </summary>
static bool IsProcessOpen(string processName)
{
foreach (Processing.Process clsProcess in Processing.Process.GetProcesses())
{
if (clsProcess.ProcessName.ToUpper().Contains(processName.ToUpper()))
return true;
}
return false;
}
[2: ] Define some variables:
static bool IamRunning = true;
static int checkDuration = 1; // in seconds
[3: ] Use a Thread for run a loop for checking:
Thread t = new Thread(delegate() {
DateTime lastCheck = DateTime.MinValue;
while (IamRunning)
{
var now = DateTime.Now;
int dd = (now.Hour - lastCheck.Hour) * 3600 + (now.Minute - lastCheck.Minute) * 60 + now.Second - lastCheck.Second;
if (dd >= checkDuration)
if (!IsProcessOpen("ProcessName"))
{
delApplication(); // You have a function to delete ...
break;
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
[4: ] Use a loop at the end of the program:
while (t.ThreadState == ThreadState.Running)
{
// just wait.
}
Note: This solution by Console Application in my low computer have 50% usage of CPU.

To whom static int Main return value?

I have written a program by changing void to int
class Program
{
static int Main(string[] args)
{
return -1;
}
}
To whom this value will get return ...is it CLR? If so, how... because a called function can return a value to a calling function.
If this is the called function, then who is the calling function..is it CLR?
How it is happening ?
Does CLR returns any value to someone, e.g. OS?
If this is the called function, then who is the calling function..is
it CLR? How it is happening ?
The Main method is called by the CLR. How is this happpening?
Initially, windows examines the exe's file's header to determine whether to create a 32-bit process or a 64-bit process, or a WoW64 process.
Then windows loads the x86, x64, or IA64 version of MSCorEE.dll into process's address space.
After this, the process's primary thread calls a method defined inside MSCorEE.dll. This method initializes the CLR, loads the exe assembly, and then calls its entry point method Main.
The method Main can return nothing, void or and int. If we choose to return an int, then usually we select to return 0, at the end of Main, which means that the execution of the Program was successful. If Main return another negative int, then we have an error. Both of them are conventions that are used widely.
That being said, it is clear that the value that Main returns is returned to the process's primary thread.
Update
How we could read this value?
We could build a batch file that will execute our executable. (I have given it the name ExecutableName, you should change it correspondingly.) We can read the value that Main returns using the %ERRORLEVEL%. If it is not 0, then the message Failed with error code with the corresponding error value will be printed to the screen.
#echo off
ExecutableName.exe
IF NOT %ERRORLEVEL% == 0 goto error
echo OK
goto end
:error
echo Failed with error code %ERRORLEVEL%.
:end
If you compile this piece of code it will produce a .exe program.
This is called by the operating system.
The return value will be passed back to the operating system when your program terminates.
You can use this return value for example in a batch script (*.bat) by observing %ERRORLEVEL%
If you start your .exe from another .Net program using the Process class, you'll find this return value in Process.ExitCode after your .exe has finished.

OpenProcessToken fails when querying process running as NETWORK SERVICE

I have code which needs to query the process token (specifically the SID) of several processes, at least one of which is running as the built-in NETWORK SERVICE account. I'm using .NET to get the process ID, and then p/invoke to advapi32 methods to open the process and the token. All of this code runs as an administrator on the machine.
The issue is that I get ERROR_ACCESS_DENIED (return code 5) from OpenProcessToken every time.
What am I doing wrong? This must be possible (for example, Process Explorer shows the SID and other token information of the target process), so I figure I'm missing something. One thought is that perhaps I need SeDebugPrivilege. (EDIT: Doesn't work -- doing Process.EnterDebugMode to set SeDebugPrivilege on the current thread doesn't change behavior).
My code looks like this:
Process[] procs = Process.GetProcessesByName("processname");
Process process = procs[0];
IntPtr processHandle = NativeMethods.OpenProcess(
ProcessAccessFlags.QueryInformation,
false,
process.Id);
if (
!NativeMethods.OpenProcessToken(
processHandle,
(uint)(TokenAccessLevels.Read),
out tokenHandle))
{
int err = Marshal.GetLastWin32Error();
// fails with err = 5
throw new Win32Exception(err, "Failed to get process token. Error: " + err);
}
Note: I have tried a few other combinations of the access flags on both native calls, including using the PROCESS_ALL_ACCESS.
EDIT: One additional point, querying the same process running as a local limited-access user works fine.

Categories

Resources