When I start my application, I try to figure out if there is another process of the application. I also try to figure out if it runs in a different user session.
So far so good, that's what it looks like in C#:
private static bool isThereAnotherInstance() {
string name = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
Process[] pAll = Process.GetProcessesByName(name);
Process pCurrent = Process.GetCurrentProcess();
foreach (Process p in pAll) {
if (p.Id == pCurrent.Id) continue;
if (p.SessionId != pCurrent.SessionId) continue;
return true;
}
return false;
}
But the requirements has changed, I need this piece of code in C++ using plain WinAPI.
Until now, I'm able to find a process that has the same executable path by using CreateToolhelp32Snapshot, OpenProcess, etc.
The missing part is how to get the session id of a process (current and other processes, AND current and other session)
How to do this?
The ProcessIdToSessionId function maps a process ID to a session ID.
You note that this seems to require excessive permissions that aren't needed by .Net.
.Net does get some of its process data from HKEY_PERFORMANCE_DATA in the registry, but this doesn't include the session ID. The session ID is obtained using NtQuerySystemInformation to return an array of SYSTEM_PROCESS_INFORMATION structures. This structure is not well documented, but the session ID immediately follows the handle count (i.e. it is the field currently declared as BYTE Reserved4[4];). Microsoft do not guarantee that this will continue to be true in future versions of Windows.
As mentioned by arx, ProcessIdToSessionId should do the job.
But unfortunately, in my case it tells me ACCESS_DENIED for the processes I'm interested in.
It DOES its job for the current process.
So here's my solution, using NtQuerySystemInformation.
.NETs Process class uses the same function internally .
typedef struct _SYSTEM_PROCESS_INFORMATION_BUG {
//...
}
typedef NTSTATUS (WINAPI *PNtQuerySystemInformation) (
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
#ifndef NT_ERROR
#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3)
#endif
#define PROCESSINFO_BUFFERSIZE (256*1024)
DLL_EXPORT int GetProcessIdFromPath2(char *exePath, int flags) {
char exe[MAX_PATH], *exeName, file[MAX_PATH], *fileName;
DWORD pidCurrent, sessionIdCurrent;
int ret=-1;
strcpy(exe, exePath);
strupr(exe);
exeName=getFileName(exe);
pidCurrent = GetCurrentProcessId();
if (!ProcessIdToSessionId(pidCurrent, &sessionIdCurrent)) sessionIdCurrent=0;
HMODULE hNT = LoadLibrary("Ntdll.dll");
if (hNT) {
PNtQuerySystemInformation pNtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(hNT, "NtQuerySystemInformation");
if (pNtQuerySystemInformation) {
SYSTEM_PROCESS_INFORMATION_BUG* processInfo;
char *buffer = (char*)malloc(PROCESSINFO_BUFFERSIZE);
if (!buffer) {
ret=-3;
}
else {
char *current=buffer;
DWORD len;
int count=0;
NTSTATUS s = pNtQuerySystemInformation(SystemProcessInformation, buffer, PROCESSINFO_BUFFERSIZE, &len);
if (NT_ERROR(s)) {
ret=-2;
}
else {
ret=0;
while(1) {
processInfo = (SYSTEM_PROCESS_INFORMATION_BUG*)current;
if (processInfo->ImageName.Buffer!=NULL){
wcstombs(file, processInfo->ImageName.Buffer, MAX_PATH-1);
strupr(file);
fileName=getFileName(file);
if (strcmp(fileName, exeName)==0) {
if (processInfo->UniqueProcessId!=pidCurrent) {
if (processInfo->SessionId==sessionIdCurrent) {
ret = processInfo->UniqueProcessId;
}
}
}
}
if (processInfo->NextEntryOffset==0) break;
current+=processInfo->NextEntryOffset;
count++;
}
}
free(buffer);
buffer=NULL;
}
}
FreeLibrary(hNT);
}
return ret;
}
Code for listing all PID, SID, EXE ("ala" Task Manager, sort of)
Works for me (Windows 7 64b) VS2012 Express
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Winternl.h>
#pragma comment( lib, "ntdll.lib" )
typedef LONG KPRIORITY; // Thread priority
typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD;
int _tmain(int argc, _TCHAR* argv[]) {
SYSTEM_PROCESS_INFORMATION aSPI[ 1024 ];
// could ask for actual needed size size and malloc (with few extra new processes bonus...)
NTSTATUS nts = NtQuerySystemInformation( SystemProcessInformation, aSPI, sizeof( aSPI ), NULL );
if ( NT_ERROR( nts ) ) return -1;
char * pSPI = reinterpret_cast<char*>( &aSPI[ 0 ] );
while ( true ) {
SYSTEM_PROCESS_INFORMATION_DETAILD * pOneSPI = reinterpret_cast<SYSTEM_PROCESS_INFORMATION_DETAILD*>( pSPI );
WCHAR * pwch = pOneSPI->ImageName.Buffer;
if ( pwch == 0 || pOneSPI->ImageName.Length == 0 ) pwch = TEXT( "Unknown" );
_tprintf( TEXT( "PID %d - SID %d EXE %s\n" ), pOneSPI->UniqueProcessId, *reinterpret_cast<LONG*>( &pOneSPI->Reserved4 ), pwch );
if ( pOneSPI->NextEntryOffset ) pSPI += pOneSPI->NextEntryOffset;
else break;
}
return 0;
}
Many thanks to #Oleg for documentation of the SPI structure on SO here
Related
If I have the following C# DllImport which is importing a non-C# DLL and I want to port it over to Go, how would I go about doing that?
[DllImport("my.dll", EntryPoint = "Greet", CallingConvention = CallingConvention.Cdecl)]
public static extern int Greet(IntPtr name, ref IntPtr greetings);
I've run into problems figuring out how to pass a pointer to a pointer which is needed for the greetings parameter (I assume since the type is ref IntPtr, I'm not that familiar at all with C#). The dll function will populate the memory pointed to by the pointer that I provide which I'll use in subsequent syscalls. Here's what I've got so far,
package main
import (
"fmt"
"syscall"
"unsafe"
)
var (
MyDll = syscall.MustLoadDLL("my.dll")
greet = MyDll.MustFindProc("Greet")
)
func Greet(name string) error {
nameP, err := syscall.UTF16PtrFromString(name)
if err != nil {
return err
}
// I need to provide a pointer to a pointer for greetings. How can I allocate some memory here
// then pass a pointer to its pointer? I tried this: create a handle with a zero-value, then
// take a pointer to it, then pass a pointer to the pointer as the second parameter to Call but
// the pointer becomes nil after the Call.
handle := syscall.Handle(0)
handleP := &handle
r1, _, _ := greet.Call(uintptr(unsafe.Pointer(nameP)), uintptr(unsafe.Pointer(&handleP)))
if r1 == 0 {
return fmt.Errorf("there was an error")
}
return nil
}
I'm open to any and all suggestions including links and resources that might help me get a better grasp on this syscall and unsafe stuff. Thanks!
Firstly, it would help if you could show how the C# Greet method is used. A method in isolation its quite hard to understand especially when the parameter is the equivalent of void ** which means anything can go in.
TL;DR
ref IntPtr is probably just a **struct{} where you don't have to allocate any struct. The library will simply manage the memory for you. You just need to give it a pointer to "*MyStruct" so that it can change you "*MyStruct" to actually point to the internal resource.
REF
The C# ref keyword is quite well explained in the docs. Basically it allows a pass by reference for any type.
The following declaration in C#
void Increment(ref value) { ... }
int counter = 10;
Increment(ref counter);
// counter is now 11
Increment(counter); // won't compile must be passed with 'ref'
Increment(null); // won't compile
is equivalent to C++
void Increment(int& value) { ... }
int counter;
Increment(counter);
// counter is now 11
Increment(null); // won't compile
A reference which should not be null.
IntPtr
IntPtr is usually used to represent pointers and allows for interop between native and CLR (C#) programs.
If a C program has the following signature
void Increment(int* value);
a C# program could call it in one of a few ways
[DllImport("example.dll")]
static unsafe extern void Increment(int* value); // this way allows null to be passed in
unsafe {
int counter = 10;
Increment(&10);
}
,
[DllImport("example.dll")]
static extern void Increment(ref int value);
int counter = 10;
Increment(ref counter);
If a C program has the following signature
void AllocateStruct(struct MyStruct** ppStruct);
void IncrementStruct(struct MyStruct* pStruct);
then
[DllImport("example.dll")]
static extern void AllocateStruct(ref IntPtr ppStruct);
// static unsafe extern void AllocateStruct(MyStruct** ppStruct)
[DllImport("example.dll")]
static extern void IncrementStruct(IntPtr pStruct);
// static unsafe extern void IncrementStruct(MyStruct* pStruct);
IntPtr pMyStruct;
AllocateStruct(ref pMyStruct);
IncrementStruct(pMyStruct);
// Free My Struct
// If you need to get inside the struct then
// MyStruct myStruct = Marshal.StructureToPtr<MyStruct>(pMyStruct)
// Often you don't (need to) or (should not) manipulate the struct directly so keeping it as IntPtr is perfectly acceptable.
From the example above you can see MyStruct is more of a token/reference than anything else. ref IntPtr allows you to pass a reference to the location which you will use to store your token/reference after the library allocates it on your behalf. Then all the other methods will usually just use the reference IntPtr to perform subsequent manipulations on it. Basically Object Orientated Programming without classes.
"Real" Life Example with ref IntPtr
It is a bit quick and dirty and error handling leave a lot to be desired.
It shows the C, C# and Go versions which call the same GetSecurityInfo
and LookupAccountSid Win32 library functions.
The only real use case I can find for ref IntPtr is type**/void** so that the library can allocate the memory for you or give you a pointer to memory it has already allocated.
C
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include "accctrl.h"
#include "aclapi.h"
#pragma comment(lib, "advapi32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
// --- get the executing program's file path and handle -----
LPTSTR executablePath = argv[0];
_tprintf(TEXT("Opening File %s\n"), executablePath);
HANDLE hFile = CreateFile(
executablePath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
// -------------------------------------------------
// --------- Get the owner SID of the file ---------
PSID pSidOwner = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
DWORD dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
&pSidOwner,
NULL,
NULL,
NULL,
&pSD);
if (dwRtnCode != ERROR_SUCCESS) return EXIT_FAILURE;
// -------------------------------------------------
// -------
TCHAR AcctName[MAX_PATH];
DWORD dwAcctName = MAX_PATH;
TCHAR DomainName[MAX_PATH];
DWORD dwDomainName = MAX_PATH;
SID_NAME_USE eUse = SidTypeUnknown;
BOOL bRtnBool = LookupAccountSid(
NULL, // local computer
pSidOwner,
&AcctName,
&dwAcctName,
DomainName,
&dwDomainName,
&eUse);
if (bRtnBool == FALSE) return EXIT_FAILURE;
_tprintf(TEXT("Account Owner = %s\n"), AcctName);
_tprintf(TEXT("Account Owner's Domain = %s\n"), DomainName);
return 0;
}
C#
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
public class Example
{
[DllImport("advapi32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
static extern uint GetSecurityInfo(
IntPtr handle,
uint ObjectType,
uint SecurityInfo,
ref IntPtr ppsidOwner, // <-- HERE
IntPtr ppsidGroup, // bit hacky (in safe C# you must "pass a reference" in C you can pass a pointer to a pointer or null)
IntPtr ppDacl,
IntPtr ppSacl,
ref IntPtr ppSecurityDescriptor // <-- HERE
);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
string lpSystemName,
IntPtr Sid,
StringBuilder lpName,
ref uint cchName,
StringBuilder ReferencedDomainName,
ref uint cchReferencedDomainName,
out uint peUse);
const uint ERROR_SUCCESS = 0;
const uint OWNER_SECURITY_INFORMATION = 0x00000001;
const uint SE_FILE_OBJECT = 1;
public static void Main()
{
// get the executing program's file path and handle
string executablePath = Environment.GetCommandLineArgs().GetValue(0).ToString();
IntPtr hFile = File.Open(executablePath, FileMode.Open, FileAccess.Read, FileShare.Read)
.SafeFileHandle.DangerousGetHandle();
IntPtr pSidOwner = IntPtr.Zero; // some internal struct you shouldn't allocate or modify (acts like a token)
IntPtr pSD = IntPtr.Zero; // some internal struct you shouldn't allocate or modify (acts like a token)
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
uint dwRtnCode = GetSecurityInfo(
hFile,
SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
ref pSidOwner, // <-- HERE
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
ref pSD // <-- HERE
);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (dwRtnCode != ERROR_SUCCESS) throw new InvalidOperationException("GetSecurityInfo Failed");
StringBuilder name = new StringBuilder(50);
uint cchName = (uint)name.Capacity;
StringBuilder domainName = new StringBuilder(50);
uint cchDomainName = (uint)domainName.Capacity;
uint sidUse;
LookupAccountSid(
null,
pSidOwner,
name,
ref cchName,
domainName,
ref cchDomainName,
out sidUse);
Console.WriteLine("Account Owner = {0}", name);
Console.WriteLine("Account Owner's Domain = {0}", domainName);
// PLEASE FREE pSD once done
}
}
Go
my second Go program I have ever written so there are probably some blaring mistakes (other than the lack of error checking)
package main
import (
"fmt"
"syscall"
"unsafe"
"os"
)
var (
advapi32, _ = syscall.LoadLibrary("advapi32.dll")
kernel32, _ = syscall.LoadLibrary("kernel32.dll")
createFileW, _ = syscall.GetProcAddress(kernel32, "CreateFileW")
getSecurityInfo, _ = syscall.GetProcAddress(advapi32, "GetSecurityInfo")
lookupAccountSidW, _ = syscall.GetProcAddress(advapi32, "LookupAccountSidW")
)
type SE_OBJECT_TYPE uint32
const (SE_FILE_OBJECT = 1)
type SECURITY_INFORMATION uint32
const (OWNER_SECURITY_INFORMATION = 0x00000001)
const (
GENERIC_READ = 0x80000000
FILE_SHARE_READ = 0x00000001
OPEN_EXISTING = 0x00000003
FILE_ATTRIBUTE_NORMAL = 0x00000080
)
type Handle uintptr
func CreateFile(
name string,
access uint32,
mode uint32,
sa *uint, // *SecurityAttributes,
createmode uint32,
attrs uint32,
templatefile *uint,
) (handle Handle, err error) {
utf16name, _ := syscall.UTF16PtrFromString(name)
r0, _, _ := syscall.Syscall9(
uintptr(createFileW), 7,
uintptr(unsafe.Pointer(utf16name)),
uintptr(access),
uintptr(mode),
uintptr(unsafe.Pointer(sa)),
uintptr(createmode),
uintptr(attrs),
uintptr(unsafe.Pointer(templatefile)),
0, 0)
handle = Handle(r0)
return
}
func GetSecurityInfo(
handle Handle,
objectType SE_OBJECT_TYPE,
securityInformation SECURITY_INFORMATION,
owner **struct{},
group **struct{},
dacl **struct{},
sacl **struct{},
sd **struct{}, //**SECURITY_DESCRIPTOR,
) (ret error) {
r0, _, _ := syscall.Syscall9(
uintptr(getSecurityInfo), 8,
uintptr(handle),
uintptr(objectType),
uintptr(securityInformation),
uintptr(unsafe.Pointer(owner)),
uintptr(unsafe.Pointer(group)),
uintptr(unsafe.Pointer(dacl)),
uintptr(unsafe.Pointer(sacl)),
uintptr(unsafe.Pointer(sd)),
0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
func LookupAccountSid(
systemName *uint16,
sid *struct{}, // *SID,
name *uint16,
nameLen *uint32,
refdDomainName *uint16,
refdDomainNameLen *uint32,
use *uint32,
) (err error) {
r, _, e := syscall.Syscall9(
uintptr(lookupAccountSidW), 7,
uintptr(unsafe.Pointer(systemName)),
uintptr(unsafe.Pointer(sid)),
uintptr(unsafe.Pointer(name)),
uintptr(unsafe.Pointer(nameLen)),
uintptr(unsafe.Pointer(refdDomainName)),
uintptr(unsafe.Pointer(refdDomainNameLen)),
uintptr(unsafe.Pointer(use)),
0, 0)
if r == 0 {
err = e
}
return
}
func main() {
defer syscall.FreeLibrary(advapi32)
defer syscall.FreeLibrary(kernel32)
// get the executing program's file path and handle
var hFile, _ = CreateFile(os.Args[0], GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nil);
// defer LocalFree(Handle(unsafe.Pointer(pSD))) // PLEASE FREE pSD once done
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
var pSD *struct{} //*SECURITY_DESCRIPTOR
var pSidOwner *struct{}
GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, nil, nil, nil, &pSD)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
nameLen := uint32(50)
name := make([]uint16, nameLen)
domainLen := uint32(50)
domainName := make([]uint16, domainLen)
var sidUse uint32
LookupAccountSid(nil, pSidOwner, &name[0], &nameLen, &domainName[0], &domainLen, &sidUse)
var n = syscall.UTF16ToString(name)
var dn = syscall.UTF16ToString(domainName)
fmt.Printf("Account Owner = %s\n", n)
fmt.Printf("Account Owner's Domain = %s\n", dn)
}
I have a function in a C++ DLL that takes one input. I'm trying to have that input be used as an output to the C# call.
Here is my C++ function:
MYAPI int testStuff3(unsigned char* str)
{
printf("%s\n", str);
str = (unsigned char*)malloc(9);
str[0] = 'G';
str[1] = 'o';
str[2] = 'o';
str[3] = 'd';
str[4] = 'b';
str[5] = 'y';
str[6] = 'e';
str[7] = '!';
str[8] = '\0';
return 1;
}
Here is the C# code:
public class Program
{
[DllImport("NativeLib.dll")]
private static extern int testStuff3([In, Out] IntPtr str);
static void Main(string[] args)
{
IntPtr junk3 = IntPtr.Zero;
int ret = testStuff3(junk3);
Byte[] stuff3 = new byte[9];
Marshal.Copy(junk3, stuff3, 0, 9);
}
}
When the Marshal.Copy is called, it gives an error saying that the source (junk3) can not be null.
Will this not work, sending a null pointer to C++ DLL from C# and having the DLL allocate the memory and store something inside and return it to the caller? I want to keep it an IntPtr and not a StringBuilder because the data won't necessarily be a string in the final code. Just an unsigned char array in C++ and I want the IntPtr to point to it.
I've tried different variations of [In, Out], [Out], out and ref for the IntPtr passing.
Never ever allow memory allocations to cross a DLL boundary. That way lies madness, and/or Sparta.
(For the pedantic: you can allocate memory and then pass a pointer across, as long as you either pass ownership back to free it, or guarantee that the same allocator is used as part of a contract. But it's still something to avoid when possible.)
Typically to use a string output parameter you should pass a StringBuilder as the argument, setting its capacity to the maximum expected length. Then in the native code you simply fill this existing buffer.
See the "Fixed length string buffers" section here for an example.
Thanks for the help!
Here's what I ended up with.
C++ function:
MYAPI int testStuff4(wchar_t* str)
{
unsigned char* stuff = (unsigned char*)malloc(10);
stuff[0] = 'G';
stuff[1] = 'o';
stuff[2] = 'o';
stuff[3] = 'd';
stuff[4] = 'b';
stuff[5] = 'y';
stuff[6] = 'e';
stuff[7] = '!';
stuff[8] = '\0';
mbstowcs(str, (const char*)stuff, 1024);
free(stuff);
return 1;
}
C# function:
public class Program
{
[DllImport("NativeLib.dll")]
private static extern int testStuff4(IntPtr str);
static void Main(string[] args)
{
IntPtr junk4 = Marshal.AllocHGlobal(1024);
int ret = testStuff4(junk4);
string junkString = Marshal.PtrToStringUni(junk4);
Console.WriteLine(junkString);
Marshal.FreeHGlobal(junk4);
}
}
Your C++ function doesn’t modify the passed string. It allocates a new one with malloc, stores it in a local variable forgetting the passed value, then returns leaking the memory.
If for some reason you want to do manual marshalling, you probably want something like this (assuming this is for Windows):
MYAPI BOOL __stdcall testStuff3( char** pp )
{
if( nullptr == pp )
return FALSE; // null pointer
if( nullptr != *pp )
{ // Print & release an old string
printf( "%s\n", *pp );
CoTaskMemFree( *pp );
*pp = nullptr;
}
// Allocate a new one
const char* const str = CoTaskMemAlloc( 9 );
if( nullptr == str ) return FALSE;
strncpy( str, "Goodbye!", 9 );
*pp = str;
return TRUE;
}
C#:
public class Program
{
[DllImport( "NativeLib.dll" )]
private static extern bool testStuff3( [In, Out] ref IntPtr str );
static void Main( string[] args )
{
IntPtr ptr = IntPtr.Zero;
if( testStuff3( ref ptr ) )
{
Console.WriteLine( Marshal.PtrToStringAnsi( ptr ) );
Marshal.FreeCoTaskMem( ptr );
}
}
}
However, this is not something I recommend doing unless you have very good reasons. In most cases automatic marshalling is better. For C# -> C++ way it’s trivially simple, const char* or const wchar_t* in C++, string (with correct attributes) in C#. For C++ -> C# you can allocate a StringBuilder in C#, pass char* or wchar_t* to C++, and buffer length in another argument.
Is there any way how to enumerate process with given PID in windows, and get list of all his opened handles(locked files, etc.)?
EDIT: I dont care about language. If it is in .NET, I'd be glad, if in WinApi (C), it won't hurt. If in something else, I think I can rewrite it :-)
I did a deep googling and found this article.
This article gave a link to download source code:
I tried method in NtSystemInfoTest.cpp ( downloaded source code ) and it worked superbly.
void ListHandles( DWORD processID, LPCTSTR lpFilter )
The code has following declaimer:
// Written by Zoltan Csizmadia, zoltan_csizmadia#yahoo.com
// For companies(Austin,TX): If you would like to get my resume, send an email.
//
// The source is free, but if you want to use it, mention my name and e-mail address
//
//////////////////////////////////////////////////////////////////////////////////////
//
I hope this helps you.
The command-line 'Handle' tool from Sysinternals does this, if you just want a tool. This won't help you if you're looking for a code solution, though.
Here is an example using ZwQueryProcessInformation from the DDK. The DDK is now known as the "WDK" and is available with MSDN. If you don't have MSDN, apparantly, you can also get it from here.
I haven't tried it, I just googled your question.
#include "ntdll.h"
#include <stdlib.h>
#include <stdio.h>
#include "ntddk.h"
#define DUPLICATE_SAME_ATTRIBUTES 0x00000004
#pragma comment(lib,"ntdll.lib")
BOOL EnablePrivilege(PCSTR name)
{
TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
BOOL rv = GetLastError() == ERROR_SUCCESS;
CloseHandle(hToken);
return rv;
}
int main(int argc, char *argv[])
{
if (argc == 1) return 0;
ULONG pid = strtoul(argv[1], 0, 0);
EnablePrivilege(SE_DEBUG_NAME);
HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
ULONG n = 0x1000;
PULONG p = new ULONG[n];
while (NT::ZwQuerySystemInformation(NT::SystemHandleInformation, p, n * sizeof *p, 0)
== STATUS_INFO_LENGTH_MISMATCH)
delete [] p, p = new ULONG[n *= 2];
NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p + 1);
for (ULONG i = 0; i < *p; i++) {
if (h[i].ProcessId == pid) {
HANDLE hObject;
if (NT::ZwDuplicateObject(hProcess, HANDLE(h[i].Handle), NtCurrentProcess(), &hObject,
0, 0, DUPLICATE_SAME_ATTRIBUTES)
!= STATUS_SUCCESS) continue;
NT::OBJECT_BASIC_INFORMATION obi;
NT::ZwQueryObject(hObject, NT::ObjectBasicInformation, &obi, sizeof obi, &n);
printf("%p %04hx %6lx %2x %3lx %3ld %4ld ",
h[i].Object, h[i].Handle, h[i].GrantedAccess,
int(h[i].Flags), obi.Attributes,
obi.HandleCount - 1, obi.PointerCount - 2);
n = obi.TypeInformationLength + 2;
NT::POBJECT_TYPE_INFORMATION oti = NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);
NT::ZwQueryObject(hObject, NT::ObjectTypeInformation, oti, n, &n);
printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
n = obi.NameInformationLength == 0
? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
NT::POBJECT_NAME_INFORMATION oni = NT::POBJECT_NAME_INFORMATION(new CHAR[n]);
NTSTATUS rv = NT::ZwQueryObject(hObject, NT::ObjectNameInformation, oni, n, &n);
if (NT_SUCCESS(rv))
printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
printf("\n");
CloseHandle(hObject);
}
}
delete [] p;
CloseHandle(hProcess);
return 0;
}
I want to read the arguments I have send through CreateRemoteThread to my injected DLL inside another process.
I can call the function without problem, I just don't know how to cast LPVOID to a struct.
This is a example:
#pragma pack(push,1)
struct tagRemoteThreadParams
{
int Param1;
int Param2;
} RemoteThreadParams, *PRemoteThreadParams;
#pragma pack(pop)
DWORD WINAPI testfunction(LPVOID param)
{
// cast LPVOID to tagRemoteThreadParams (param)
WriteToLog("YES YOU CALLED THE FUNCTION WITH PARAM: ");
return 0;
}
This is my struct and how I have allocated the mem inside the process:
[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct RemoteThreadParams
{
[MarshalAs(UnmanagedType.I4)]
public int Param1;
[MarshalAs(UnmanagedType.I4)]
public int Param2;
}
public uint CallFunction(int _arg1)
{
RemoteThreadParams arguments = new RemoteThreadParams();
arguments.Param1 = 1;
arguments.Param2 = 2;
//pointer to the function im trying to call
IntPtr _functionPtr = IntPtr.Add(this.modulePtr, 69772);
// Allocate some native heap memory in your process big enough to store the
// parameter data
IntPtr iptrtoparams = Marshal.AllocHGlobal(Marshal.SizeOf(arguments));
// Copies the data in your structure into the native heap memory just allocated
Marshal.StructureToPtr(arguments, iptrtoparams, false);
//allocate som mem in remote process
IntPtr lpAddress = VirtualAllocEx(this.processHandle, IntPtr.Zero, (IntPtr)Marshal.SizeOf(arguments), AllocationType.Commit | AllocationType.Reserve, MemoryProtection.ExecuteReadWrite);
if (lpAddress == IntPtr.Zero)
{
return 0;
}
if (WriteProcessMemory(this.processHandle, lpAddress, iptrtoparams, (uint)Marshal.SizeOf(arguments), 0) == 0)
{
return 0;
}
//Free up memory
Marshal.FreeHGlobal(iptrtoparams);
uint threadID = 0;
IntPtr hThread = CreateRemoteThread(this.processHandle, IntPtr.Zero, 0, _functionPtr, lpAddress, 0, out threadID);
if (hThread == IntPtr.Zero)
{
//throw new ApplicationException(Marshal.GetLastWin32Error().ToString());
throw new Win32Exception();
}
WaitForSingleObject(hThread, 0xFFFFFFFF);
// wait for thread to exit
// get the thread exit code
uint exitCode = 0;
GetExitCodeThread(hThread, out exitCode);
// close thread handle
CloseHandle(hThread);
return exitCode;
}
If I understand your code correctly, you inject UT8 encoded string into the other's process memory (I'm kind of surprised that it works).
Assuming it does work, in your C++ code you need to convert the UTF8 encoded byte array pointed by param to some kind of string that C++ understands.
One way to do it is to use MultiByteToWideChar
Another way is to use STL. I found a question about it here.
And the answer to the cast problem was:
struct tagRemoteThreadParams *tData = (struct tagRemoteThreadParams *)param;
Thank you for the help guys
I have 2 DLLs. One is PrimaryDLL.dll and the other is DLLWrap.dll. The PrimaryDLL has an object a function named DiversifyKeyset which is decalred like so in the class constructor:
static PRIMARYDLL_API std::string DiversifyKeyset(std::string Key1, std::string Key2, std::string Key3);
and here is the method defined:
std::string tKeyset::DiversifyKeyset(std::string Key1, std::string Key2, std::string Key3)
{
tKeyset* keyset = new tKeyset();
keyset ->Key1 = "12345678";
keyset ->Key2 = "23456789";
keyset ->Key3 = "34567890";
//return keyset --eventually I want to return this
return 0;
}
My DLLWrap.dll calls this function like so in its .cpp file:
cout << "Here is what is returned: " <<
firstDllLayer::tKeyset::DiversifyKeyset(a,b,c) << endl;
Now this all compiles fine and the libraries are built. My error comes when I call the C# code to call the second DLLWrap.dll. I receieve the error:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
So I have been racking my brain as to why this is not working. I am under alot of pressure but cannot seem to find why I am receieveing this memory write error.
So to help I am providing my code.
My C++ PrimaryDLL.h file:
#pragma once
#include "stdafx.h"
#include <string>
#include <stdexcept>
extern "C"{
#ifdef PRIMARYDLL_EXPORT
#define PRIMARYDLL_API __declspec(dllexport)
#else
#define PRIMARYDLL_API __declspec(dllimport)
#endif
namespace firstDllLayer
{
class tKeyset
{
public:
tKeyset();
std::string Key1;
std::string Key2;
std::string Key3;
tKeyset(std::string _key1, std::string _key2, std::string _key3);
static PRIMARYDLL_API std::string DiversifyKeyset(std::string Key1, std::string Key2, std::string Key3);
};
tKeyset::tKeyset()
{
Key1 = "";
Key2 = "";
Key3 = "";
}
tKeyset::tKeyset(std::string _Key1, std::string _Key2, std::string _Key3)
{
Key1 = _Key1;
Key2 = _Key2;
Key3 = _Key3;
}
}
}
Here is the PrimaryDll.cpp file:
// PrimaryDll.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "PrimaryDll.h"
#include <stdexcept>
#include <string>
using namespace std;
namespace firstDllLayer
{
tKeyset* MasterKeyset = new tKeyset("1234","5678","0910");
std::string tKeyset::DiversifyKeyset(std::string Key1, std::string Key2, std::string Key3)
{
tKeyset* keyset = new tKeyset();
keyset ->Key1 = "12345678";
keyset ->Key2 = "23456789";
keyset ->Key3 = "34567890";
//return Keyset; -eventually I would like to return this
return 0;
}
}
Here is my DLLWrap.h file:
#pragma once
#include "stdafx.h"
#include "Primary.h"
#include <stdexcept>
#include <string>
extern "C"{
#ifdef DLLWRAPDLL_EXPORT
#define DLLWRAP_API __declspec(dllexport)
#else
#define DLLWRAP_API __declspec(dllimport)
#endif
namespace MyFunc
{
class MyCall
{
public:
static DLLWRAP_API std::string DiversifyKeysetCall(std::string a,std::string b,std::string c);
};
}
}
The DLLWrap.cpp file:
// DLLWrap.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "PrimaryDll.h"
#include <stdexcept>
#include "DLLWrap.h"
#include <iostream>
#include <string>
using namespace std;
namespace MyFunc
{
std::string MyCall::DiversifyKeysetCall(std::string a,std::string b,std::string c)
{
/*cout << "Here is what is returned: " <<
firstDllLayer::tKeyset::DiversifyKeyset(a,b,c) << endl;
return 0;*/
cout << "Here is what is returned: " <<
firstDllLayer::tKeyset::DiversifyKeyset(a,b,c) << endl;
return 0;
}
}
And finally the C# Program.cs file:
// Marshal.cs
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{ public class DllHelper
{
[DllImport(#"C:\Users\user\Documents\Visual Studio 2010\Projects\KeyDll\Debug\DLLWrap.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?DiversifyKeysetCall#MyCall#MyFunc##SA?AV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##V34#00#Z")]
public static extern string DiversifyKeysetCall(string a, string b, string c);
}
static void Main()
{
try
{
DllHelper.DiversifyKeysetCall("1234","5678","0910");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
In my PrimaryDLL.cpp file, I would eventually like to return the object but because it is so confusing on how to reference the pointer and when i just leave the :
return keyset;
un commented I receieve the error that it cannot convert from object type to string type.
So please anyhelp would be greatly appreciated to why I am receiving the "Attempted to read or write protected memory. This is often an indication that other memory is corrupt" error.
Best Regards.
Its a bad Idea in general to create an object in c++ dll and hand it back to c#. The ownership of the memory becomes a problem. Strings are ok because they get Marshaled across by coping from c memory to the c# owned memory.
I suggest you simplify the whole thing by passing the three strings separately and building your keyset object already in c#.
Another option is to flatten you keyset object into a binary array of bytes. Then have a custom function when you get it back to unflatten it back into an object.
Here is what i have done before
[DllImport("Helper.dll", CharSet = CharSet.Auto)]
private static extern bool GetStuff(
[MarshalAs(UnmanagedType.LPStr)] StringBuilder inputString,
byte[] outputBuffer,
UInt32 outputSize,
ref UInt32 outputFinalSize);
public static void DoStuff(string inputString)
{
int buffSize = 4000;
byte[] buff = new byte[buffSize];
StringBuilder inputString = new StringBuilder();
inputString.Append(blobs);
UInt32 size = 0;
if (!GetStuff(inputString, buff, (uint)buffSize, ref size) || size == 0)
{
//ERROR
}
when it comes back i just do
StringBuilder outputString;
for (uint i = 0; i < outputFinalSize; i++)
{
outputString.Append((char)buff[i]);
}
outputString.toString();
}
c signatrue looks like this
extern "C" __declspec(dllexport) bool GetStuff(char* inputString, char* outputBuffer, UInt32 outputSize, UInt32& outputFinalSize);
Note that i use string builder to pass the string in as well, you may not need that...
As you can see i allocate everything on the c# side so i don't have to worry about memory management of the c++, everything in c++ should get deallocated when the function completes.
Your call should look somthing like
private static extern bool DiversifyKeysetCallAndRetrunFlatBuffer(
[MarshalAs(UnmanagedType.LPStr)] StringBuilder inputStringA,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder inputStringB,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder inputStringC,
byte[] outputBuffer,
UInt32 outputSize,
ref UInt32 outputFinalSize);
{
std::string str1(inputStringA);
std::string str2(inputStringB);
std::string str3(inputStringC);
KeySet key = DiversifyKeyset(str1, str2, str3);
outputFinalSize = key.SerializeToBuffer(outputBuffer, outputSize);
if (outputFinalSize == 0)
{
return false;
}
return true;
}
int KeySet::SerializeToBuffer(char* buffer, size_t bufferSize)
{
//We are going to fill the buffer like so "key1|key2|key3"
size_t totalSize = Key1.size() + Key2.size() + Key3.size() + 4;
if (bufferSize < totalSize)
{
return 0; // buffer too small
}
char* bufferCurr = buffer;
memcpy(bufferCurr, Key1.c_str(), Key1.size());
bufferCurr += Key1.size();
bufferCurr[0] = '|';
bufferCurr++;
memcpy(bufferCurr, Key2.c_str(), Key2.size());
bufferCurr += Key2.size();
bufferCurr[0] = '|';
bufferCurr++;
memcpy(bufferCurr, Key3.c_str(), Key3.size());
bufferCurr += Key3.size();
bufferCurr[0] = '\0';
return totalSize;
}
And finally on the c# side you would convert the buffer to a string and do a split by | to get all 3 keys, then create a c# KeySet Object that has the 3 strings.
std::string tKeyset::DiversifyKeyset(...) {
return 0;
}
This calls std::string(const char*) constructor, passing a NULL pointer. This is illegal.