mutex owner

delphi package - easy access to kernel objects etc.

mutex owner

Postby digitaldoom » Mon Oct 06, 2008 1:35 pm

Is it possible to find the process owner of a given mutex? If so, how? Thanks!
digitaldoom
 
Posts: 10
Joined: Fri Aug 18, 2006 2:36 am

Postby madshi » Wed Oct 08, 2008 8:58 pm

Maybe it's possible with some internal native API. Or maybe by making use of the undocumented mutex structure (which may change between different OSs). But to be honest, I'm not sure...
madshi
Site Admin
 
Posts: 9414
Joined: Sun Mar 21, 2004 5:25 pm

Postby digitaldoom » Wed Oct 08, 2008 10:56 pm

I know it *can* be done as somehow ProcessExplorer lists the mutex of a given process. I just want to do the reverse of that. Having said that when I use madkernel to get at the information it always returns my process as the owner.

When I try to get the handle manually it always says ACCESS DENIED even though I have Admin access and Debug privs.

If I figure it out I'll let you know if you are interested :)
digitaldoom
 
Posts: 10
Joined: Fri Aug 18, 2006 2:36 am

Postby madshi » Thu Oct 09, 2008 6:44 am

Hmmmm... How do you define "owner"? ProcessExplorer lists the kernel handles which a specific process has opened (and not closed yet). madKernel does the same thing. However, this information does NOT tell you which process currently "owns" the mutex in that sense that it called WaitForSingleObject on the mutex and succeeded to get access. You know, multiple processes can share the same mutex. But only one of them can "own" it at the same time, although all of them can have a handle open to the same mutex at the same time...
madshi
Site Admin
 
Posts: 9414
Joined: Sun Mar 21, 2004 5:25 pm

Postby digitaldoom » Thu Oct 09, 2008 2:27 pm

Ideally I would like to list all processes that have a handle to the mutex but just the original .exe that created it would be fine.
digitaldoom
 
Posts: 10
Joined: Fri Aug 18, 2006 2:36 am

Postby madshi » Thu Oct 09, 2008 4:09 pm

Well, listing all processes that have a handle to the mutex is no big problem with madKernel. Just use "Handles(true)" which will return a list of all handles system wide. Be aware, though, that some OSs don't like it much if you try to look at handles of some of their system processes. So you may want to enumerate through processes instead and then enumerate through the handles of each process.
madshi
Site Admin
 
Posts: 9414
Joined: Sun Mar 21, 2004 5:25 pm

Postby digitaldoom » Fri Oct 10, 2008 1:01 am

here is the code I am using to get the mutex list:

Code: Select all
procedure ttest.getmutexlist;
var dirhandle: thandle;
    oadir: jwawindows.pobject_attributes;
    status: ntstatus;
    wdir: unicode_string;
    mut: unicode_string;
    name: array[0..17] of widechar;
    mutant: array[0..6] of widechar;
    ctx: ULONG;
    p: PDIRECTORY_BASIC_INFORMATION;
    i: Integer;
    mtx: imutex;
begin
  mutex.Clear;
  if (getwindowsversion < jclsysinfo.wvWinNT31) then
    exit;
  ctx:=0;
  name[0]:='\'; name[1]:='B'; name[2]:='a'; name[3]:='s'; name[4]:='e'; name[5]:='N'; name[6]:='a'; name[7]:='m';
  name[8]:='e'; name[9]:='d'; name[10]:='O'; name[11]:='b'; name[12]:='j'; name[13]:='e'; name[14]:='c'; name[15]:='t';
  name[16]:='s'; name[17]:=#0;
  mutant[0]:='M'; mutant[1]:='u'; mutant[2]:='t'; mutant[3]:='a'; mutant[4]:='n'; mutant[5]:='t'; mutant[6]:=#0;

  jwanative.RtlCreateUnicodeString(@wdir, @name);
  jwanative.RtlCreateUnicodeString(@mut, @mutant);

  new(oadir);
  oadir^.Length:=sizeof(object_attributes);
  oadir^.RootDirectory:=0;
  oadir^.ObjectName:=@wdir;
  oadir^.Attributes:=OBJ_PERMANENT;
  oadir^.SecurityDescriptor:=nil;
  oadir^.SecurityQualityOfService:=nil;
  status:=ZwOpenDirectoryObject(@dirhandle, DIRECTORY_QUERY or DIRECTORY_TRAVERSE, oadir);
  p:=nil;

  try
    getmem(p, 1024);
    while (status = STATUS_SUCCESS) do
      begin
        status:=ZwQueryDirectoryObject(dirhandle, p, 300, true, false, @ctx, nil);
        if (status = STATUS_SUCCESS) then
          if (p^.ObjectTypeName.Buffer[0] = mut.Buffer[0]) then
            begin
              mtx:=madkernel.OpenMutex(p^.ObjectName.Buffer);
              mutex.Add(mtx.Handle.OwnerProcess.ExeFile+#32+p^.ObjectName.Buffer);
              mutexlistcb.Items.add(mtx.Handle.OwnerProcess.ExeFile+#32+p^.ObjectName.Buffer);
            end;
      end;
  finally
    ZwClose(dirhandle);
    dispose(oadir);
    freemem(p);
  end;


In there I have:

Code: Select all
mtx:=madkernel.OpenMutex(p^.ObjectName.Buffer);
              mutex.Add(mtx.Handle.OwnerProcess.ExeFile+#32+p^.ObjectName.Buffer);
              mutexlistcb.Items.add(mtx.Handle.OwnerProcess.ExeFile+#32+p^.ObjectName.Buffer);


the output is:
Code: Select all
Mutex
-----
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe ZonesCacheCounterMutex
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe SHIMLIB_LOG_MUTEX
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe ZonesLockedCacheCounterMutex
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe CTF.LBES.MutexDefaultS-1-5-21-1177238915-573735546-839522115-1003
 0CADFD67AF62496dB34264F000F5624A
 PSched_Perf_Library_Lock_PID_c4
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe WPA_RT_MUTEX
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe c:!documents and settings!daniel!cookies!
 aspnet_state_Perf_Library_Lock_PID_c4
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe WPA_PR_MUTEX
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe {45DB34C3-955C-11D3-ABEF-444553540000} Hook
 PnP_Init_Mutex
 ASP.NET_Perf_Library_Lock_PID_c4
 MSDTC_Perf_Library_Lock_PID_c4
 PerfDisk_Perf_Library_Lock_PID_c4
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe SRDataStore
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe madToolsMsgHandlerMutex$ddc$57009194
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe MidiMapper_modLongMessage_RefCnt
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe MidiMapper_Configure
 ASP.NET_1.1.4322_Perf_Library_Lock_PID_c4
 PerfProc_Perf_Library_Lock_PID_c4
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe MSCTF.Shared.MUTEX.MNN
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe MSCTF.Shared.MUTEX.APG
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe userenv: machine policy mutex
C:\Documents and Settings\daniel\My Documents\Borland Studio Projects\test5.5\test.exe userenv: user policy mutex
 ShimCacheMutex


I don't think my process "owns" all these mutex'
digitaldoom
 
Posts: 10
Joined: Fri Aug 18, 2006 2:36 am

Postby madshi » Fri Oct 10, 2008 8:14 am

Well, obviously you are opening all the mutexes listed in BaseNamedObjects. In the moment when you open them your process gets a handle to them. I still don't know if that is what you define as "own".
madshi
Site Admin
 
Posts: 9414
Joined: Sun Mar 21, 2004 5:25 pm

Postby digitaldoom » Fri Oct 10, 2008 12:30 pm

I want to map the mutex to the original creator of the mutex.
digitaldoom
 
Posts: 10
Joined: Fri Aug 18, 2006 2:36 am

Postby madshi » Fri Oct 10, 2008 1:36 pm

Well, in that case I have to refer you to my first post in this thread.
madshi
Site Admin
 
Posts: 9414
Joined: Sun Mar 21, 2004 5:25 pm

Postby Nico Bendlin » Mon Nov 17, 2008 5:18 pm

Maybe this code snippet contains what you want:
Code: Select all
{$ALIGN ON}
{$MINENUMSIZE 4}

type
  TNtStatus = LongInt;
  TClientId = record
    UniqueProcess: Pointer;
    UniqueThread : Pointer;
  end;
  TMutantInformationClass = (
    MutantBasicInformation,  // 0
    MutantOwnerInformation   // 1
  );
  TMutantBasicInformation = record
    CurrentCount  : LongInt;
    OwnedByCaller : Boolean;
    AbandonedState: Boolean;
  end;
  TMutantOwnerInformation = record
    ClientId: TClientId;
  end;

function NtQueryMutant(MutantHandle: THandle;
  MutantInformationClass: TMutantInformationClass; out MutantInformation;
  MutantInformationLength: ULONG; ReturnLength: PULONG): TNtStatus; stdcall;
  external 'ntdll';

var
  Mutex: THandle;
  Basic: TMutantBasicInformation;
  Owner: TMutantOwnerInformation;
  Bytes: ULONG;
begin
  Mutex := OpenMutex(MUTANT_QUERY_STATE, False, 'MutantTest');
  if Mutex <> 0 then
  try
    FillChar(Basic, SizeOf(Basic), 0);
    Bytes := 0;
    ShowMessage('MutantBasicInformation: $' + IntToHex(NtQueryMutant(Mutex,
      MutantBasicInformation, Basic, SizeOf(Basic), @Bytes), 8) +
      #13#10'Basic.CurrentCount: ' + IntToStr(Basic.CurrentCount) +
      #13#10'Basic.OwnedByCaller: ' + BoolToStr(Basic.OwnedByCaller, True) +
      #13#10'Basic.AbandonedState: ' + BoolToStr(Basic.AbandonedState, True) +
      #13#10'Bytes: ' + IntToStr(Bytes));
    FillChar(Owner, SizeOf(Owner), 0);
    Bytes := 0;
    ShowMessage('MutantOwnerInformation: $' + IntToHex(NtQueryMutant(Mutex,
      MutantOwnerInformation, Owner, SizeOf(Owner), @Bytes), 8) +
      #13#10'Owner.ClientId.UniqueProcess: $' +
      IntToHex(NativeUInt(Owner.ClientId.UniqueProcess), SizeOf(Pointer) * 2) +
      #13#10'Owner.ClientId.UniqueThread: $' +
      IntToHex(NativeUInt(Owner.ClientId.UniqueThread), SizeOf(Pointer) * 2) +
      #13#10'Bytes: ' + IntToStr(Bytes));
  finally
    CloseHandle(Mutex);
  end;
end.
Well, I don’t know the Windows version that introduced MutantOwnerInformation.

Note that the "owner" of the Mutex is the thread that called CreateMutex(..., True, ...) or a wait function and not (yet) called ReleaseMutex(...) to release the ownership. Read the Remarks section of ReleaseMutex in MSDN.
Nico Bendlin
 
Posts: 46
Joined: Fri Apr 28, 2006 1:17 pm


Return to madKernel

Who is online

Users browsing this forum: No registered users and 1 guest