Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.08;
Скачать: CL | DM;

Вниз

"Потеря хендла" в RegSetValue после RegCreateKey   Найти похожие ветки 

 
The One ©   (2005-11-04 20:42) [0]

Здраствуйте уважаемые.
Опишу проблемму. Пытаюсь ловить 2 АПИ-функции вызываемые из некоторого процесса. Это RegCreateKeyEx и RegSetValueEx, вместо них я выполняю соответственно NewRegCreateKeyEx и NewRegSetValueEx. В этих функциях я проделываю следующее:
1) Извлекаю и сохраняю некоторые входные параметры.
2) Снимаю перехват
3) Вызываю оригинальные АПИ-функции (теперь они уже не будут перехваченны и сделают свою работу)
4) Снова устанавливаю перехват

Собственно, весь процесс вылетает, возникает исключение ERegistryException с сообщением "failed to set data for "здесь имя некоторого параметра"".
Выполняя отладку вижу, что в функцию NewRegSetValueEx параметр несущий в себе хендл открытого ключа приходит зануленным, отсюда и result=6, т.е. ERROR_INVALID_HANDLE = 6;
При этом замеченно - если не ловить RegCreateKeyEx, но ловить лишь RegSetValueEx, то вторая функция успешно завершается, параметру присваивается значение (хендл в функции RegSetValueEx приходит нормальный). Если же не ловить функцию RegSetValueEx, но ловить

RegCreateKey, то результат также положительный. Т.е. функции перехватчики отрабатывают на все 100% только по отдельности, вместе же мы имеем "потерю" хендла где-то "на пути от первой функции ко второй".

Хотелось бы услышать ваше мнение, по поводу описанной проблеммы. Как можно выпутаться?

ЗЫ: Сорри за косноязычие.
ЗЫЫ: Ежели нужно я выложу листинг.


 
gdaujk ©   (2005-11-05 03:36) [1]

Вызываю оригинальные АПИ-функции

А не может ли быть сл. ситуации: после того, как твоя функция NewRegCreateKeyEx, в которой ты вызвал оригинал, вернёт управление "некоторому процессу", он снова выполнит оригинал, т. е. оригинал выполнится два раза подряд?  

PS: Не совсем понятен механизм "ловли". Выложи листинг.


 
The One ©   (2005-11-05 09:44) [2]

Ниже приведенную библиотеку я внедряю в адресное пространство некоторого процесса. В этом процессе я посредством TRegistry создаю ключ в реестре и записываю туда парамет + значение, т.е. процесс создан чисто как тест работы dll и без этой dll прекрасно справляется со своей задачей. Запуском процесса-тестера и внедрением туда библиотеки занимается третье приложение, там также исключенны ошибки.
Код dll:
library RegApiHk;
uses
 TLHelp32,
 windows,
 Dialogs,
 shellAPI;

type
far_jmp = packed record
  PuhsOp: byte;
  PushArg: pointer;
  RetOp: byte;
 end;

OldCode = packed record
 One: dword;
 two: word;
end;

var
AdrRegCreateKeyEx, AdrRegSetValEx: pointer;
OldRegCrK, OldRegSetVE: OldCode;
JmpRegCrK, JmpRegSetVE: far_jmp;
CurrProc,Writen,bw:cardinal;

Function OpenThread(dwDesiredAccess: dword; bInheritHandle: bool; dwThreadId: dword):dword;
                   stdcall; external "kernel32.dll";

Procedure StopThreads;
var
h, CurrTh, ThrHandle, CurrPr: dword;
Thread: TThreadEntry32;
begin
CurrTh := GetCurrentThreadId;
CurrPr := GetCurrentProcessId;
h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if h <> INVALID_HANDLE_VALUE then
  begin
   Thread.dwSize := SizeOf(TThreadEntry32);
   if Thread32First(h, Thread) then
   repeat
    if (Thread.th32ThreadID <> CurrTh) and (Thread.th32OwnerProcessID = CurrPr) then
     begin
      ThrHandle := OpenThread(0, false, Thread.th32ThreadID);
      if ThrHandle>0 then
        begin
         SuspendThread(ThrHandle);
         CloseHandle(ThrHandle);
        end;
      end;
   until not Thread32Next(h, Thread);
  CloseHandle(h);
  end;
end;

Procedure RunThreads;
var
h, CurrTh, ThrHandle, CurrPr: dword;
Thread: TThreadEntry32;
begin
CurrTh := GetCurrentThreadId;
CurrPr := GetCurrentProcessId;
h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if h <> INVALID_HANDLE_VALUE then
  begin
   Thread.dwSize := SizeOf(TThreadEntry32);
   if Thread32First(h, Thread) then
   repeat
    if (Thread.th32ThreadID <> CurrTh) and (Thread.th32OwnerProcessID = CurrPr) then
     begin
      ThrHandle := OpenThread(0, false, Thread.th32ThreadID);
      if ThrHandle>0 then
        begin
         ResumeThread(ThrHandle);
         CloseHandle(ThrHandle);
        end;
      end;
   until not Thread32Next(h, Thread);
  CloseHandle(h);
  end;
end;

function NewRegSetValueEx(
  hKey: HKEY; // handle of key to set value for
   lpValueName: PAnsiChar; // address of value to set
  Reserved: Cardinal; // reserved
  dwType: Cardinal; // flag for value type
   lpData: Pointer; // address of value data
   cbData:Cardinal   // size of value data
  ):integer;stdcall;
begin
 //снятие перехвата
WriteProcessMemory(CurrProc, AdrRegSetValEx, @OldRegSetVE, SizeOf(OldCode), Writen);
//вызов функции
result := RegSetValueEx(hKey {параметр равено 0}, lpValueName, Reserved, dwType,lpData,cbData);
//result равен 6
//установка перехвата
WriteProcessMemory(CurrProc, AdrRegSetValEx, @JmpRegSetVE, SizeOf(far_jmp), Writen);
showmessage("Функция RegSetValueEx перехваченна. Имя параметра: " + lpValueName + ", значение параметра: " + string(lpData) +"." );
end;

function NewRegCreateKeyEx(
hKey: HKEY; // handle of an open key
  lpSubKey: PAnsiChar; // address of subkey name
  Reserved: Cardinal; // reserved
  lpClass: PAnsiChar; // address of class string
  dwOptions: Cardinal; // special options flag
  samDesired: Cardinal; // desired security access
  lpSecurityAttributes: PSECURITYATTRIBUTES; // address of key security structure
  phkResult: HKEY; // address of buffer for opened handle
  lpdwDisposition: PDWORD   // address of disposition value buffer
  ):integer;stdcall;
var header:string;
begin
//определяем root-ключ по хендлу
case hKey of
HKEY_CLASSES_ROOT:header:="HKEY_CLASSES_ROOT";
HKEY_CURRENT_USER:header:="HKEY_CURRENT_USER";
HKEY_LOCAL_MACHINE:header:="HKEY_LOCAL_MACHINE";
HKEY_USERS:header:="HKEY_USERS";
end;
showmessage("Функция RegCreateKeyEx перехваченна. Имя ключа: "+ header + "\" + lpsubkey);
//снятие перехвата
WriteProcessMemory(CurrProc, AdrRegCreateKeyEx, @OldRegCrK, SizeOf(OldCode), Writen);
//вызов функции
result := RegCreateKeyEx(hKey, lpSubKey,Reserved,lpClass, dwOptions,samDesired,lpSecurityAttributes,phkResult,lpdwDisposition);
//result равен 0, т.е. ключ успешно создается
//установка перехвата
WriteProcessMemory(CurrProc, AdrRegCreateKeyEx, @JmpRegCrK, SizeOf(far_jmp), Writen);
end;

Procedure SetHook;
begin
CurrProc := GetCurrentProcess;
//получение адреса процедур
AdrRegCreateKeyEx := GetProcAddress(GetModuleHandle("advapi32.dll"), "RegCreateKeyExA");
AdrRegSetValEx := GetProcAddress(GetModuleHandle("advapi32.dll"), "RegSetValueExA");
//инициализация структуры перехвата
JmpRegCrK.PuhsOp  := $68;
JmpRegCrK.PushArg := @NewRegCreateKeyEx;
JmpRegCrK.RetOp   := $C3;

JmpRegSetVE.PuhsOp  := $68;
JmpRegSetVE.PushArg := @NewRegSetValueEx;
JmpRegSetVE.RetOp   := $C3;
//сохраняем старое начало функциий
ReadProcessMemory(CurrProc, AdrRegCreateKeyEx, @OldRegCrK, SizeOf(OldCode), bw);
ReadProcessMemory(CurrProc, AdrRegSetValEx, @OldRegSetVE, SizeOf(OldCode),bw);
//записываем новое начало
WriteProcessMemory(CurrProc, AdrRegCreateKeyEx, @JmpRegCrK, SizeOf(far_jmp), Writen);
WriteProcessMemory(CurrProc, AdrRegSetValEx, @JmpRegSetVE, SizeOf(far_jmp), Writen);
end;

begin
//останавливаем побочные нити
StopThreads;
//устанавливаем перехват
SetHook;
//запускаем нити
RunThreads;
end.


 
The One ©   (2005-11-05 09:52) [3]

Метод перехвата состоит в следующем: определяется адрес перехватываемой функции, и первые 6 байт её начала заменяются на длинный jmp переход по адресу обработчика перехвата.
Если необходимо вызывать перехватываемую функцию, то перед заменой необходимо сохранить её начальные байты и перед вызовом восстанавливать их.
Вот ссылка на статью http://www.wasm.ru/article.php?article=apihook_1


 
gdaujk ©   (2005-11-05 12:13) [4]

Всё дело, похоже, в параметрах функции

function NewRegCreateKeyEx(
 hKey: HKEY; // handle of an open key
 lpSubKey: PAnsiChar; // address of subkey name
 Reserved: Cardinal; // reserved
 lpClass: PAnsiChar; // address of class string
 dwOptions: Cardinal; // special options flag
 samDesired: Cardinal; // desired security access
 lpSecurityAttributes: PSECURITYATTRIBUTES; // address of key security structure
 var phkResult: HKEY; // address of buffer for opened handle
 lpdwDisposition: PDWORD   // address of disposition value buffer
 ):integer;stdcall;


Обращаю особое внимание на слово var в выделенной строке.


 
The One ©   (2005-11-05 14:11) [5]

Да вы абсолютно правы. Теперь все работает. Спасибо. Но нельзя ли пояснить, в чем разница с Var и без?


 
gdaujk ©   (2005-11-05 14:47) [6]

Позволю себе процитировать книгу Стива Тейксейра и Ксавье Пачеко "Delphi 5. Руководство разработчика":

Передача параметров по значению

...Если параметр передаётся по значению, создаётся локальная копия данной переменной, которая и представляется для обработки в процедуру или функцию. Рассмотрим следующий пример:

procedure Foo(S: string);

При вызове указанной процедуры будет создана копия передаваемой ей в качестве параметра строки S, с которой и будет работать процедура Foo...

Передача параметров по ссылке

... Передача параметров по ссылке означает, что функция или процедура сможет изменить полученные значения параметров...

procedure ChangeMe(var X: Longint);
begin
   X := 2;
end;


Вместо создания копии переменной X, ключевое слово var требует передачи адреса самой переменной X, что позволяет процедуру непосредственно изменять её значения.

Параметры-константы

...Ключевое слово const не только защищает параметр от изменения, но и позволяет компилятору сгенерировать более оптимальный код передачи строк и записей.



Страницы: 1 вся ветка

Текущий архив: 2006.01.08;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.013 c
1-1133632452
ST
2005-12-03 20:54
2006.01.08
Упрямый OleContainer


2-1134919368
newhite
2005-12-18 18:22
2006.01.08
Бешеный курсор


10-1111046230
LgcPiton
2005-03-17 10:57
2006.01.08
Как узнать заущено ли приложение


14-1133450740
Kerk
2005-12-01 18:25
2006.01.08
Приглашение в orkut


3-1131906942
Layner
2005-11-13 21:35
2006.01.08
Помогите узнать в ADOQuery - Mode (состояние)