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

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

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.

有帮助吗?

解决方案

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.

其他提示

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top