#windows #delphi #winapi #dll #code-injection
#Windows #delphi #winapi #dll #внедрение кода
Вопрос:
Ну, это странно. Когда инжектор скомпилирован с более старой версией Delphi (я думаю, это был 2009 год, но я не могу быть уверен — я нашел приложение со своими старыми «игрушками»), оно работает безупречно как на Windows 7 (64-разрядная версия), так и на Windows 8 (64-разрядная версия).
Однако при компиляции с помощью XE5 тот же код работает на Win7, но не работает на Windows 8 — это вызывает нарушение доступа при выполнении, и я не могу найти для этого надлежащую причину.
Имейте в виду, что инжектор, целевой файл и dll являются 32-разрядными PE-файлами.
Мне нужно использовать новый компилятор, поскольку у меня больше нет старой версии Delphi, и предполагается, что этот фрагмент кода является частью более крупного приложения, которое использует некоторые из новых функций Delphi.
На заметку — необходимо внедрить dll, чтобы я мог регистрировать определенные вещи в целевом объекте. На данный момент все, что я внедряю, — это заглушка, которая просто показывает окно сообщения, поэтому это не может быть ошибкой DLL.
Это код, который я использую для внедрения DLL:
function InjectDLL(PID: Cardinal; sDll: String): Boolean;
var
hLib: Pointer;
hThread: THandle;
pMod: Pointer;
hOpen: NativeUInt;
dWritten: NativeUInt;
ThreadID: Cardinal;
begin
Result := False;
hOpen := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
if hOpen <> INVALID_HANDLE_VALUE then
begin
hLib := GetProcAddress(GetModuleHandle(PChar('KERNEL32.dll')), PWideChar('LoadLibraryW'));
pMod := VirtualAllocEx(hOpen, nil, (Length(sDll) 1) * SizeOf(char), MEM_COMMIT or MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if WriteProcessMemory(hOpen, pMod, @sDll[1], (Length(sDll)) * SizeOf(char), dWritten) then
Result := TRUE;
hThread := CreateRemoteThread(hOpen, nil, 0, hLib, pMod, 0, ThreadID);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hOpen);
CloseHandle(hThread);
end;
end;
Любые предложения будут оценены, я думаю, что я начинаю сходить с ума из-за этого…
Редактировать: Если вы хотите запустить тест самостоятельно, вот пример инжектора, dll и целевого объекта — все готово к компиляции: https://dl.dropboxusercontent.com/u/15031178/Stack Overflow/Test inject.rar
Комментарии:
1.
sDll
похоже, что это многобайтовая строка — вы копируете толькоLength(sDll) * SizeOf(char)
байты, и все же вы используетеLoadLibraryW
, которая ожидает строку Unicode.2. Я пробовал с помощью простых AnsiStrings, но проблема все еще сохраняется. Используя OllyDbg, я вижу, что sDll записывается в память правильно, кажется, что целевое приложение завершает работу после вызова CreateRemoteThread. Если я не использую версию, скомпилированную с более ранней версией Delphi, то есть, тогда, похоже, работает точно такой же код (я сохранил исходные тексты …) : f
3. Я думаю, вы упустили мою мысль — с ANSI / многобайтовой строкой вам следует использовать
LoadLibraryA
, а неLoadLibraryW
.4. @Jonathan, в XE5 (и 2009, если на то пошло),
string
являетсяUnicodeString
, поэтому использование этого кодаLoadLibraryW
уместно. Длина * SizeOf(Char) абсолютно правильная.5. Итак, давайте создадим sscce, чтобы мы могли повторить проблему. Я не буду делать больше, пока у нас не будет одного.