Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.08.2010, 05:50   #1
Alex217Vish
Пользователь
 
Регистрация: 07.02.2009
Сообщений: 31
Вопрос Хук CreateFile x64

Есть код на ObjectPascal (Delphi) компилируемый в FPC (из-под Lazarus'a) в dll x64. После запуска тестовой проги все процессы просто завершаются с ошибкой в kernel32 (там CreateFileW находится).
Вот код dll:
Код:
library HookDriveCore;

uses
  Windows;

{$mode delphi}

type
  CreateFileWHookRecord = packed record
    PushOperation: byte;
    Argument: Pointer;
    ReturnOperation: byte;
  end;

  PObjectAttributes = ^TObjectAttributes;
  TObjectAttributes = packed record
    Length: DWORD;
    RootDirectory: THandle;
    ObjectName: PChar;
    Attributes: DWORD;
    SecurityDescriptor: Pointer;
    SecurityQualityOfService: Pointer;
  end;

var
  hGlobalHook: cardinal;
  CreateFileWBackup, CreateFileWHook: CreateFileWHookRecord;
  CreateFileW: function(lpFileName:LPCWSTR;
 dwDesiredAccess:DWORD;
 dwShareMode:DWORD;
 lpSecurityAttributes:LPSECURITY_ATTRIBUTES;
 dwCreationDisposition:DWORD;
 dwFlagsAndAttributes:DWORD;
 hTemplateFile:HANDLE):HANDLE; stdcall;

const MutexName: LPSTR = 'Elysium_HookDrive_Mutex';

function HookCreateFileW(lpFileName:LPCWSTR;
 dwDesiredAccess:DWORD;
 dwShareMode:DWORD;
 lpSecurityAttributes:LPSECURITY_ATTRIBUTES;
 dwCreationDisposition:DWORD;
 dwFlagsAndAttributes:DWORD;
 hTemplateFile:HANDLE):HANDLE; stdcall;
var
  WrittedBytes: dWord;
begin
  MessageBox(0, 'A', '', 0); // Проверка хука
  WriteProcessMemory(INVALID_HANDLE_VALUE,
   @CreateFileW,
   @CreateFileWBackup,
   sizeof(CreateFileWHookRecord),
   WrittedBytes);
  Result := CreateFileW(lpFileName,
   dwDesiredAccess,
   dwShareMode,
   lpSecurityAttributes,
   dwCreationDisposition,
   dwFlagsAndAttributes,
   hTemplateFile);
  WriteProcessMemory(INVALID_HANDLE_VALUE,
   @CreateFileW,
   @CreateFileWHook,
   sizeof(CreateFileWHookRecord),
   WrittedBytes);
end;

procedure SetHook();
var
  hkernel32: dWord;
  WrittedBytes: dWord;
  OldProtect: dWord;
begin
  hkernel32 := GetModuleHandle('kernel32.dll');
  CreateFileW := GetProcAddress(hkernel32, 'CreateFileW');
  ReadProcessMemory(INVALID_HANDLE_VALUE,
   @CreateFileW,
   @CreateFileWBackup,
   sizeof(CreateFileWHookRecord),
   WrittedBytes);
  with CreateFileWHook do
  begin
    PushOperation := $68;
    Argument := @HookCreateFileW;
    ReturnOperation := $C3;
  end;
  VirtualProtectEx(INVALID_HANDLE_VALUE,
   @CreateFileW,
   sizeof(CreateFileWHookRecord),
   PAGE_EXECUTE_READWRITE,
   @OldProtect);
  WriteProcessMemory(INVALID_HANDLE_VALUE,
   @CreateFileW,
   @CreateFileWHook,
   sizeof(CreateFileWHookRecord),
   WrittedBytes);
end;

procedure UnHook();
var
  WrittedBytes: dWord;
begin
  WriteProcessMemory(INVALID_HANDLE_VALUE,
   @CreateFileW,
   @CreateFileWBackup,
   sizeof(CreateFileWHookRecord),
   WrittedBytes);
end;

function MessageProc(code: integer; wParam: word; lParam: longint): longint; stdcall;
begin
  Result := CallNextHookEx(0, code, wParam, lParam);
end;

procedure SetGlobalHookProc();
begin
  hGlobalHook := SetWindowsHookEx(WH_GETMESSAGE, @MessageProc, HInstance, 0);
  Sleep(Infinite);
end;

procedure SetGlobalHook();
var
  hMutex: dWord;
  ThreadId: dWord;
begin
  hMutex := CreateMutex(nil, false, MutexName);
  if GetLastError = 0 then
    CreateThread(nil, 0, @SetGlobalHookProc, nil, 0, ThreadId)
  else
    CloseHandle(hMutex);
end;

procedure GlobalUnHook();
begin
  if hGlobalHook <> 0 then
    UnHookWindowsHookEx(hGlobalHook);
end;

function DllProcessAttach(dwReason: longint): longbool;
begin
  SetGlobalHook();
  SetHook();
  Result := True;
end;

procedure DllProcessDetach(dwReason: longint);
begin
  GlobalUnHook();
  UnHook();
end;

{$IFDEF WINDOWS}{$R HookDriveCore.rc}{$ENDIF}

begin
  DllProcessAttach(DLL_PROCESS_ATTACH);
  DLL_Process_Detach_Hook := @DllProcessDetach;
end.
И код программы:
Код:
program HookDriveCoreTest;

uses Windows;

begin
  LoadLibrary('HookDriveCore.dll');
  Sleep(Infinite);
end.
Собственно, найдите ошибку

Последний раз редактировалось Alex217Vish; 24.08.2010 в 05:53.
Alex217Vish вне форума Ответить с цитированием
Старый 24.08.2010, 08:50   #2
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

вся проблема здесь
Код:
 CreateFileWHookRecord = packed record
    PushOperation: byte;
    Argument: Pointer;
    ReturnOperation: byte;
  end;
и здесь
Код:
  with CreateFileWHook do
  begin
    PushOperation := $68;
    Argument := @HookCreateFileW;
    ReturnOperation := $C3;
  end;
прыжок реализуется с помощью PUSH ADDR/RET. Опкод в 32 битном режиме PUSH imm32 выглядит так $68 imm32. В 32 битном режиме всё отлично работает. Но нельзя использовать одни и те же опкоды инструкций в защищённом и 64-битном режиме.
в 64 битном режиме адреса 64 битные, соответственно прыгать на по 64 битному адресу. Но возникает одна важная проблема инструкции PUSH imm64 просто не существует. Поэтому надо думать над другими вариантами. Например, JMP rel32, опкод у этой инструкции такой же как и в защищённом режиме и работает она так же как и в защищённом режиме.
rpy3uH вне форума Ответить с цитированием
Старый 24.08.2010, 17:27   #3
Alex217Vish
Пользователь
 
Регистрация: 07.02.2009
Сообщений: 31
По умолчанию

Ну я догадывался что тут ассемблер примешан. Код позаимствован из adwarebox ms-rem'а. Но у меня собственно вопрос только один: как заставить код работать?) Т.е. проще говоря что на что тут надо поменять?)

Нашёл в забугорном инете константы $EB и $09. Вот такой код:
Код:
  with CreateFileWHook do
  begin
    PushOperation := $EB;//$68;
    Argument := @HookCreateFileW;
    ReturnOperation := $09;//$C3;
  end;
пишет что ошибка дескриптора

Последний раз редактировалось rpy3uH; 26.08.2010 в 15:27.
Alex217Vish вне форума Ответить с цитированием
Старый 26.08.2010, 15:26   #4
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

трудно конечно, ставить хук на функцию не зная ассемблера.
во-первых, $EB это опкод JMP rel8, а тебе надо JMP rel32, её опкод $E9,
во-вторых, адрес для $E9 вычисляется по определённым правилам здесь написано
в-третьих, ReturnOperation не нужен вовсе!

Последний раз редактировалось rpy3uH; 26.08.2010 в 15:34.
rpy3uH вне форума Ответить с цитированием
Старый 29.08.2010, 05:08   #5
Alex217Vish
Пользователь
 
Регистрация: 07.02.2009
Сообщений: 31
По умолчанию

Спасибо за пинок, полетел в направлении вот такого кода:
Код:
  with CreateFileWHook do
  begin
    Jmp := $E9;
    JmpOffset := 0 - ((Integer(CreateFileWAddress) + 5) - Integer(@HookCreateFileW));
  end;
Довольно успешно полетел =)
Alex217Vish вне форума Ответить с цитированием
Старый 29.08.2010, 21:41   #6
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

следует быть внимательным, так как в x64 адреса стали 64 битными и следовательно если разница между адресами более чем 2 ГБ такой код работать не будет
rpy3uH вне форума Ответить с цитированием
Старый 21.09.2010, 00:59   #7
Alex217Vish
Пользователь
 
Регистрация: 07.02.2009
Сообщений: 31
Восклицание

мм... тогда закономерный вопрос: как сделать чтобы работало?)
компилятор используется fpc x86 + x64 cross compile
Alex217Vish вне форума Ответить с цитированием
Старый 21.09.2010, 12:03   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Сообщение от rpy3uH Посмотреть сообщение
следует быть внимательным, так как в x64 адреса стали 64 битными и следовательно если разница между адресами более чем 2 ГБ такой код работать не будет
А Integer в FPC не 64-х битный, что-ли?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 22.09.2010, 12:50   #9
rpy3uH
добрый няша
Старожил
 
Аватар для rpy3uH
 
Регистрация: 29.10.2006
Сообщений: 4,804
По умолчанию

Цитата:
Сообщение от Alex217Vish Посмотреть сообщение
мм... тогда закономерный вопрос: как сделать чтобы работало?)
компилятор используется fpc x86 + x64 cross compile
не знаю. думать надо.
вся проблема в том что в x64 инструкции JMP rel64 и это главная проблема.
есть JMP r/m64 т.е. адрес должен находиться в регистре или в ячейке памяти.
т.е. надо что-то в духе
Код:
mov eax, абсолютный адрес (64 бита)
jmp eax
но возникает проблема так как портится регистр EAX, впрочем регистр EAX самый приемлемый вариант так как его содержимое в начале выполнения функции в 99,99% случаев не важно.

Последний раз редактировалось rpy3uH; 22.09.2010 в 12:53.
rpy3uH вне форума Ответить с цитированием
Старый 22.10.2010, 22:12   #10
Alex217Vish
Пользователь
 
Регистрация: 07.02.2009
Сообщений: 31
По умолчанию

А можно код на каком-нибудь из высокоуровневых языков?)
Alex217Vish вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
CreateFile прочитать бут-сектор RoS Win Api 6 06.07.2010 09:36
Перехват CreateFile qwerc1 Win Api 6 29.06.2010 22:01
CreateFile, Delphi. edmynt Помощь студентам 0 01.06.2010 18:23
Создание Pipe на C# (CreateFile) WinApi Помощь студентам 0 23.12.2009 08:07
После CreateFile не срабатывает DeleteFile Arkuz Общие вопросы Delphi 7 13.03.2009 00:04