Delphi - hook\bypass\catch all the OutputDebugString from the system into my application with process id and name

StackOverflow https://stackoverflow.com/questions/11226669

Domanda

Based on this question I've created a small application which is catching all debug strings into my application. Code of the thread is shown below.

I want to get the process id and its name for each debug string I got. After I've made some research I got this article where it says: "The first 4 bytes (32-bit DWORD) is the process ID of the process that wrote the text using OutputDebugString.". I have tried to get the process by calling the functions below, but the result is null.

TempString := '';
CopyMemory(PChar(TempString), SharedMemory, sizeof(SharedMemory)); // - returns 0....
TempString := String(PAnsiChar(SharedMemory) + SizeOf(DWORD));

I do not know what it is wrong.

Also is it possible to get the name of the process which has sent the debug string?

Thread code:

interface

uses Classes,
     windows,
     Forms,
     StdCtrls,
     SysUtils;

type
  TDebugStringThread = class(TThread)
    private
      FMemo : TMemo;
    protected
      procedure Execute; override;
      procedure DoShowData;
      procedure DoShowErrors;
    public
     constructor Create(aMemo : TMemo);
  end;

implementation

var SharedMessage: string;
    ErrsMess      : String;

constructor TDebugStringThread.Create(aMemo: TMemo);
begin
  FMemo := aMemo;
  FreeOnTerminate := True;
  inherited Create(False);
end;

procedure TDebugStringThread.DoShowData;
begin
 FMemo.Lines.Add(SharedMessage);
end;

procedure TDebugStringThread.DoShowErrors;
begin
 FMemo.Lines.Add('Error ' + ErrsMess);
 ErrsMess := '';
end;

procedure TDebugStringThread.Execute;
var SharedMem: Pointer;
    SharedFile: THandle;
    WaitingResult: DWORD;
    DataReadyEvent: THandle;
    BufferReadyEvent: THandle;
    SecurityAttributes: SECURITY_ATTRIBUTES;
    SecurityDescriptor: SECURITY_DESCRIPTOR;
    SharedMemory : Pointer;
    TempString : String;
begin
  ErrsMess := '';

  SecurityAttributes.nLength := SizeOf(SECURITY_ATTRIBUTES);
  SecurityAttributes.bInheritHandle := True;
  SecurityAttributes.lpSecurityDescriptor := @SecurityDescriptor;

  if not InitializeSecurityDescriptor(@SecurityDescriptor,       SECURITY_DESCRIPTOR_REVISION) then
    Exit;

  if not SetSecurityDescriptorDacl(@SecurityDescriptor, True, nil, False) then
    Exit;

  BufferReadyEvent := CreateEvent(@SecurityAttributes, False, True, 'DBWIN_BUFFER_READY');

  if BufferReadyEvent = 0 then
    Exit;

  DataReadyEvent := CreateEvent(@SecurityAttributes, False, False, 'DBWIN_DATA_READY');

  if DataReadyEvent = 0 then
    Exit;

  SharedFile := CreateFileMapping(THandle(-1), @SecurityAttributes, PAGE_READWRITE, 0, 4096, 'Global\DBWIN_BUFFER');

  if SharedFile = 0 then
  begin
    ErrsMess := SysErrorMessage(GetLastError);
    Synchronize(DoShowErrors);
    Exit;
  end;

  SharedMem    := MapViewOfFile(SharedFile, FILE_MAP_READ,  0, 0, 512);
  SharedMemory := MapViewOfFile(SharedFile, SECTION_MAP_READ, 0, 0, 1024);

  if not Assigned(SharedMem) then
  begin
    ErrsMess := SysErrorMessage(GetLastError);
    Synchronize(DoShowErrors);
    Exit;
  end;

  if not Assigned(SharedMemory) then
  begin
    ErrsMess := SysErrorMessage(GetLastError);
    Synchronize(DoShowErrors);
  end;

  while (not Terminated) and (not Application.Terminated) do
    begin
      SetEvent(BufferReadyEvent);
      WaitingResult := WaitForSingleObject(DataReadyEvent, INFINITE);

      case WaitingResult of
        WAIT_TIMEOUT: Continue;
        WAIT_OBJECT_0:
          begin
          try
            TempString := '';
            //CopyMemory(PChar(TempString), SharedMemory, sizeof(SharedMemory)); // - returns 0....
            TempString := String(PAnsiChar(SharedMemory) + SizeOf(DWORD));
            SharedMessage := TempString + ' ' + String(PAnsiChar(SharedMem) + SizeOf(DWORD));
            Synchronize(DoShowData);
          finally
          end;
          end;

       WAIT_FAILED: Continue;
     end;
   end;

   UnmapViewOfFile(SharedMem);
   CloseHandle(SharedFile);
end;

end.

È stato utile?

Soluzione

To read the first four bytes as DWORD:

var
  ProcessID: DWORD;

  ...

  ProcessID := PDWORD(SharedMemory)^;

See here how to get the file name of the process.

Altri suggerimenti

If the first four bytes are really a DWord, then the first thing you need to do is stop trying to copy it into a string. Integers aren't strings, and storing one in the other doesn't transform it.

var
  ProcessID: DWord;

ProcessID := PDWord(SharedMemory)^;

If you're getting zero from that, then the first four bytes of the memory contain zero. If you're expecting something else, then either your expectations are wrong, or you're not reading from the right place.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top