Delphi - перехватить \bypass\ перехватить всю OutputDebugString из системы в моем приложении с идентификатором и именем процесса
Основываясь на этом вопросе, я создал небольшое приложение, которое перехватывает все строки отладки в моем приложении. Код темы показан ниже.
Я хочу получить идентификатор процесса и его имя для каждой строки отладки, которую я получил. После того, как я провел некоторое исследование, я получил эту статью, в которой говорится: "Первые 4 байта (32-битный DWORD) - это идентификатор процесса, который написал текст, используя OutputDebugString.". Я пытался получить процесс, вызывая функции ниже, но результат нулевой.
TempString := '';
CopyMemory(PChar(TempString), SharedMemory, sizeof(SharedMemory)); // - returns 0....
TempString := String(PAnsiChar(SharedMemory) + SizeOf(DWORD));
Я не знаю, что это не так.
Также возможно ли получить имя процесса, который отправил строку отладки?
Код темы:
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;
конец.
2 ответа
Чтобы прочитать первые четыре байта как DWORD
:
var
ProcessID: DWORD;
...
ProcessID := PDWORD(SharedMemory)^;
Смотрите здесь, как получить имя файла процесса.
Если первые четыре байта действительно являются DWord, то первое, что вам нужно сделать, это перестать пытаться скопировать его в строку. Целые числа не являются строками, и сохранение одного в другом не преобразует его.
var
ProcessID: DWord;
ProcessID := PDWord(SharedMemory)^;
Если вы получаете ноль от этого, то первые четыре байта памяти содержат ноль. Если вы ожидаете чего-то другого, то либо ваши ожидания неверны, либо вы не читаете из правильного места.