ОК, я уже видел код, в котором автор записывает случайные данные в точку входа введенной dll. был код для отладки целевого процесса и DLL был введен в эту цель. Выгрузка была сделана в событии load_dll_debug_event .
Тогда такой подход записи случайных данных в точку входа введенного модуля или в ваш базовый адрес кажется решением, более приемлемым для моего вопроса, это может привести к выгрузке dll без сбоя процесса.
И работает, но при этом используется функция CreateProcess()
для отладки цели (жертва процесса).
Я ищу альтернативу, чтобы выполнить ту же задачу без необходимости в 2 исполняемых файлах, но если ее не существует, то считаю это окончательным решением до этого момента.
program SpecialLauncher;
// MinDbg的Delphi版本源代码
// http://m.newsmth.net/article/Delphi/777
//program EventTester;
//{$APPTYPE CONSOLE}
{uses
Windows, SysUtils;
begin
try
raise Exception.Create('This is a test');
except
On E: Exception do
OutputDebugString(PChar(E.Message));
end;
end.}
{$APPTYPE CONSOLE}
{$WARN SYMBOL_PLATFORM OFF}
uses
Windows,
Psapi,
SysUtils;
type
NTStatus = cardinal;
PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;
IO_STATUS_BLOCK = packed record
Status: NTStatus;
Information: dword;
end;
PFILE_NAME_INFORMATION = ^FILE_NAME_INFORMATION;
FILE_NAME_INFORMATION = packed record
FileNameLength: ULONG;
FileName: array [0 .. MAX_PATH - 1] of WideChar;
end;
function NtQueryInformationFile(FileHandle: THandle;
IoStatusBlock: PIO_STATUS_BLOCK; FileInformation: pointer; Length: dword;
FileInformationClass: dword): NTStatus; stdcall; external 'ntdll.dll';
const
Values : Array[0..4] of byte = ($C2,$00,$00,$90,$90);
var
bSeenInitialBP: Boolean;
hProcess: THandle;
function GetFileNameFromHandle(const hFile: THandle): string;
var
IO_STATUSBLOCK: IO_STATUS_BLOCK;
FileNameInfo: FILE_NAME_INFORMATION;
szFile: String;
begin
FillChar(FileNameInfo.FileName, SizeOf(FileNameInfo.FileName), 0);
NtQueryInformationFile(hFile, @IO_STATUSBLOCK, @FileNameInfo, 500, 9);
szFile := WideCharToString(FileNameInfo.FileName);
Result := ExtractFileName(szFile);
end;
{function GetFileNameFromHandle(hFile: cardinal): String;
var
hFileMap: cardinal;
pMem: pointer;
FilePath: array [0 .. MAX_PATH - 1] of Char;
sFilePath: String;
sFileName: String;
begin
Result := '';
try
hFileMap := CreateFileMapping(hFile, NIL, PAGE_READONLY, 0, 0, NIL);
if hFileMap <> 0 then
begin
pMem := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if pMem <> NIL then
begin
if GetMappedFileName(GetCurrentProcess(), pMem, @FilePath,
SizeOf(FilePath)) <> 0 then
begin
sFilePath := StrPas(FilePath);
sFileName := ExtractFileName(sFilePath);
Result := sFilePath;
end
else
Exit;
end
else
Exit;
end
else
Exit;
finally
UnMapViewOfFile(pMem);
CloseHandle(hFileMap);
end;
end;}
function GetDllEntryPoint(hFile: DWORD; hModule: pointer): pointer;
var
hMapFile, dwFSizeLow, dwFSizeHight: DWORD;
pMemory, DllEntryPoint: pointer;
idh: PImageDosHeader;
inh: PImageNtHeaders;
begin
DllEntryPoint := nil;
pMemory := nil;
dwFSizeHight := 0;
dwFSizeLow := GetFileSize(hFile, @dwFSizeHight);
if ((hFile > 0) and (dwFSizeLow > 0)) then
begin
Writeln('');
writeln(Format('Dll size: %d', [dwFSizeLow]));
hMapFile := CreateFileMapping(hFile, nil, PAGE_READONLY, dwFSizeHight, dwFSizeLow, nil);
Writeln(Format('Error: 0x%.08x', [GetLastError]));
pMemory := MapViewOfFile(hMapFile, FILE_MAP_READ,
0, 0, 0);
if (Assigned(pMemory)) then
begin
idh := pointer(pMemory);
inh := pointer(DWORD(idh) + idh^._lfanew);
DllEntryPoint := PBYTE(hModule) + inh^.OptionalHeader.AddressOfEntryPoint;
end;
UnmapViewOfFile(pMemory);
CloseHandle(hMapFile);
// CloseHandle(hFile);
end;
Result := DllEntryPoint;
end;
procedure WriteBytes(hProcess: THandle; Address: Pointer; const Buffer: array of Byte);
var
Read: THandle;
oldprot, tmp: DWORD;
begin
if (VirtualProtectEx(hProcess, Address, Length(Buffer), PAGE_EXECUTE_READWRITE, @oldprot)) then
Writeln('1 - VirtualProtectEx() successfully!');
if (WriteProcessMemory(hProcess, Address, @Buffer, Length(Buffer), Read)) then
Writeln('2 - WriteProcessMemory() successfully!');
if (VirtualProtectEx(hProcess, Address, Length(Buffer), oldprot, @tmp)) then
Writeln('3 - VirtualProtectEx() successfully!');
Writeln('');
end;
procedure Help;
begin
WriteLn(ExtractFileName(ParamStr(0)) + ' <program to debug> ');
end;
type
TDebugEventHandler = function(const de: TDebugEvent): DWORD;
const
DebugEventNames: array [EXCEPTION_DEBUG_EVENT .. RIP_EVENT]
of string = ('EXCEPTION_DEBUG_EVENT', 'CREATE_THREAD_DEBUG_EVENT',
'CREATE_PROCESS_DEBUG_EVENT', 'EXIT_THREAD_DEBUG_EVENT',
'EXIT_PROCESS_DEBUG_EVENT', 'LOAD_DLL_DEBUG_EVENT',
'UNLOAD_DLL_DEBUG_EVENT', 'OUTPUT_DEBUG_STRING_EVENT', 'RIP_EVENT');
function DefaultDebugEventHandler(const de: TDebugEvent): DWORD;
begin
WriteLn('========================================');
WriteLn(Format('Debug Event [%d] : %s', [de.dwDebugEventCode,
DebugEventNames[de.dwDebugEventCode]]));
Result := DBG_CONTINUE;
end;
function ExceptionHandler(const de: TDebugEvent): DWORD;
procedure ShowExceptionRecord(const per: PExceptionRecord);
var
I: Integer;
begin
if Assigned(per) and not IsBadReadPtr(per, SizeOf(TExceptionRecord))
then with per^ do
begin
WriteLn;
WriteLn(Format(' ExceptionCode : 0x%.08x', [ExceptionCode]));
WriteLn(Format(' ExceptionFlags : 0x%.08x', [ExceptionFlags]));
WriteLn(Format(' ExceptionRecord : 0x%p', [ExceptionRecord]));
WriteLn(Format(' ExceptionAddress : 0x%p', [ExceptionAddress]));
WriteLn(Format(' NumberParameters : 0x%.08x',
[NumberParameters]));
if NumberParameters > 0 then
for I := 0 to NumberParameters - 1 do
WriteLn(Format(' ExceptionInformation[%d] : 0x%.08x',
[I, ExceptionInformation[I]]));
ShowExceptionRecord(ExceptionRecord);
end;
end;
begin
if not bSeenInitialBP then
begin
bSeenInitialBP := True;
Result := DBG_CONTINUE;
end
else
begin
DefaultDebugEventHandler(de);
with de.Exception do
begin
WriteLn(Format(' dwFirstChance : 0x%.08x', [dwFirstChance]));
ShowExceptionRecord(@ExceptionRecord);
end;
Result := DBG_EXCEPTION_NOT_HANDLED
end;
end;
function CreateProcessHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
hProcess := de.CreateProcessInfo.hProcess;
with de.CreateProcessInfo do
begin
WriteLn(Format(' hFile : 0x%.08x', [hFile]));
WriteLn(Format(' hProcess : 0x%.08x', [hProcess]));
WriteLn(Format(' hThread : 0x%.08x', [hThread]));
WriteLn(Format(' lpBaseOfImage : 0x%p', [lpBaseOfImage]));
WriteLn(Format(' dwDebugInfoFileOffset : 0x%.08x',[dwDebugInfoFileOffset]));
WriteLn(Format(' nDebugInfoSize : 0x%.08x', [nDebugInfoSize]));
WriteLn(Format(' lpThreadLocalBase : 0x%p', [lpThreadLocalBase]));
WriteLn(Format(' lpStartAddress : 0x%p', [lpStartAddress]));
WriteLn(Format(' lpImageName : 0x%p', [lpImageName]));
WriteLn(Format(' ImageName : %s', [GetFileNameFromHandle(hFile)]));
WriteLn(Format(' fUnicode : 0x%.08x', [fUnicode]));
end;
end;
function ExitProcessHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.ExitProcess do
WriteLn(Format(' dwExitCode : 0x%.08x', [dwExitCode]));
end;
function CreateThreadHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.CreateThread do
begin
WriteLn(Format(' hThread : 0x%.08x', [hThread]));
WriteLn(Format(' lpThreadLocalBase : 0x%p', [lpThreadLocalBase]));
WriteLn(Format(' lpStartAddress : 0x%p', [lpStartAddress]));
end;
end;
function ExitThreadHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.ExitThread do
WriteLn(Format(' dwExitCode : 0x%.08x', [dwExitCode]));
end;
function LoadDllHandler(const de: TDebugEvent): DWORD;
var
DllEntryPtr: Pointer;
DllName: string;
begin
Result := DefaultDebugEventHandler(de);
with de.LoadDll do
begin
WriteLn(Format(' hFile : 0x%.08x', [hFile]));
DllName := GetFileNameFromHandle(hFile);
WriteLn(Format(' lpBaseOfDll : 0x%p', [lpBaseOfDll]));
WriteLn(Format(' dwDebugInfoFileOffset : 0x%.08x', [dwDebugInfoFileOffset]));
WriteLn(Format(' nDebugInfoSize : 0x%.08x', [nDebugInfoSize]));
WriteLn(Format(' lpImageName : 0x%p', [lpImageName]));
WriteLn(Format(' ImageName : %s', [DllName]));
WriteLn(Format(' fUnicode : 0x%.08x', [fUnicode]));
//////////////////////////////////////////////////////////////////////////
if ( Pos('dll01.dll', DllName) > 0) or
( Pos('dll02.dll', DllName) > 0) or
( Pos('dll03.dll', DllName) > 0) or
( Pos('dll04.dll', DllName) > 0) then
begin
DllEntryPtr := GetDllEntryPoint(hFile, lpBaseOfDll);
if DllEntryPtr <> nil then
WriteBytes(hProcess, DllEntryPtr, Values)
else
Writeln('GetDllEntryPoint() failed.');
end;
/////////////////////////////////////////////////////////////////////////
end;
end;
function UnloadDllHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.UnloadDll do
WriteLn(Format(' lpBaseOfDll : 0x%p', [lpBaseOfDll]));
end;
function DebugStringHandler(const de: TDebugEvent): DWORD;
var
Buf: array [1 .. 1024] of Byte;
dwRead: DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.DebugString do
begin
WriteLn(Format(' lpDebugStringData : 0x%.08x', [DWORD(lpDebugStringData)]));
WriteLn(Format(' nDebugStringLength : 0x%.08x', [nDebugStringLength]));
WriteLn(Format(' fUnicode : 0x%.08x', [fUnicode]));
if nDebugStringLength < SizeOf(Buf) then
begin
FillChar(Buf, SizeOf(Buf), 0);
ReadProcessMemory(hProcess, lpDebugStringData, @Buf, SIZE_T(nDebugStringLength), SIZE_T(dwRead));
Write(' DebugString : ');
if fUnicode <> 0 then
WriteLn(WideString(PWideChar(@Buf)))
else
WriteLn(string(PChar(@Buf)));
end;
end;
end;
function RipHandler(const de: TDebugEvent): DWORD;
begin
Result := DefaultDebugEventHandler(de);
with de.RipInfo do
begin
WriteLn(Format(' dwError : 0x%.08x', [dwError]));
WriteLn(Format(' dwType : 0x%.08x', [dwType]));
end;
end;
const
DebugEventHandlers: array [EXCEPTION_DEBUG_EVENT .. RIP_EVENT]
of TDebugEventHandler = (ExceptionHandler, CreateThreadHandler,
CreateProcessHandler, ExitThreadHandler, ExitProcessHandler, LoadDllHandler,
UnloadDllHandler, DebugStringHandler, RipHandler);
procedure Init;
var
si: TStartupInfo;
pi: TProcessInformation;
begin
bSeenInitialBP := False;
hProcess := INVALID_HANDLE_VALUE;
FillChar(si, SizeOf(TStartupInfo), 0);
FillChar(pi, SizeOf(TProcessInformation), 0);
si.cb := SizeOf(TStartupInfo);
Win32Check(CreateProcess({nil}'c:\windows\system32\notepad.exe', {PChar(ParamStr(1)}nil{)}, nil, nil, False,
CREATE_NEW_CONSOLE or DEBUG_ONLY_THIS_PROCESS, nil, nil, si, pi));
end;
procedure Run;
var
de: TDebugEvent;
bContinue: Boolean;
dwContinueStatus: DWORD;
begin
bContinue := True;
while bContinue do
begin
bContinue := WaitForDebugEvent(de, INFINITE);
dwContinueStatus := DebugEventHandlers[de.dwDebugEventCode](de);
if EXIT_PROCESS_DEBUG_EVENT = de.dwDebugEventCode then
bContinue := False;
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
end;
end;
procedure Done;
begin
end;
begin
{ if ParamCount = 0 then
begin
Help;
Exit;
end; }
Init;
Run;
Done;
end.