Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2006.01.08;
Скачать: [xml.tar.bz2];

Вниз

"Потеря хендла" в 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 вся ветка

Форум: "WinAPI";
Текущий архив: 2006.01.08;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.008 c
2-1134837845
Lokk
2005-12-17 19:44
2006.01.08
Помогите написать запрос


2-1135099118
Tiwaz
2005-12-20 20:18
2006.01.08
Фильтрация по двум базам


6-1127717027
Sam05
2005-09-26 10:43
2006.01.08
Ограничение получаемой информации через Сокеты


2-1135157933
Новенькая
2005-12-21 12:38
2006.01.08
опять treeview


4-1131038926
BURN
2005-11-03 20:28
2006.01.08
Смена Mac адреса





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский