Форум: "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