Внедрение DLL приводит к сбою целевого объекта в зависимости от используемого компилятора и системы

#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, чтобы мы могли повторить проблему. Я не буду делать больше, пока у нас не будет одного.