Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Перехват сохранения в файл

10K
23 марта 2012 года
In0stRAnez
66 / / 16.02.2008
Привет всем! Помогите пожалуйста! Такой вопрос:
необходимо перехватить запись в файл.
пример, на рабочем столе есть текстовый файлик с текстом, после чего я его изменяю добавляя в него текст, и нажимаю сохранить..
как сделать перехват сохранения чтобы он сохранился не в старый уже существующий файлик а в новый файлик в другом месте?
заранее спасибо, обгуглился по горло ничего не нашёл, прошу вашей помощи товарищи!
316
24 марта 2012 года
Alm3n
889 / / 29.05.2009
Клац2
Клац1
10K
24 марта 2012 года
In0stRAnez
66 / / 16.02.2008
а что нибудь конкретнееможно в студию?
316
24 марта 2012 года
Alm3n
889 / / 29.05.2009
А что в моих ссылка было не конкретно?
Либо пишешь драйвер, либо dll, которая будет сплайсить вход в функцию WriteFile. Конкретней некуда.
Или ты думаешь, что это все в одну функцию делается и тут можно дать тебе код?
7.2K
25 марта 2012 года
polaroid
94 / / 05.07.2008
Наверное стоит уточнить, что т.н. сплайсинг (по-английски inline hooking) техника весьма специфическая, поэтому если есть такая возможность, нужно всё-таки ставить хук в таблице импорта. Но это тоже весьма неоднозначно.
Вкратце, Вам нужно перехватить системную функцию WriteFileEx, причем перехватывать её надо не где-то там, а конкретно внутри процесса, который будет сохранять нужный Вам файл.
Такого можно добиться установив хук SetWindowsHookEx (погуглите). После этого Ваша dll будет находится почти во всех процессах, у которых есть интерфейс (GUI).
Еще посоветую Вам, чтобы не дербанить много материала по перехватам и прочей фигне, просто скачать библиотеку Microsoft Detours. Была там бесплатная для некоммерческого использования версия. Один минус - урезанный функционал (не сможете перехватывать в 64 разрядном процессе).
316
25 марта 2012 года
Alm3n
889 / / 29.05.2009
Лучше обе - и WriteFileEx, и WriteFile. Если не ошибаюсь, то это всё-таки разные функции с разными точкам входа.
465
12 апреля 2012 года
QWERYTY
595 / / 25.03.2012
Помогу не словом, а делом:

Код:
// ФУНКЦИЯ ЗАГРУЖАЕТ ДЛЛ В УКАЗАННЫЙ ПРОЦЕСС
function InjectDLL(PId: CARDINAL; DllPath: WideString): BOOL; stdcall;
var
RemotePMem, StartAddress: POINTER;
LibPathLen, HProcess, RealWrite, MyTId, HThread: CARDINAL;
WriteProcess: BOOL;
begin
  Result := FALSE;
  LibPathLen := Length(DllPath)*2; // Вот тут осторожнее, у меня такой изврат пошёл из за юникода. Length подсчитывает количиство символов но не учитывает что они юникодовские(на этом месте я встрял на долго пока меня не осинило).
  HProcess := OpenProcess(PROCESS_ALL_ACCESS, TRUE, PId);
  if HProcess = 0 then
  begin
    ShowMessage('Не удалось получить доступ к процессу.');
    Result := FALSE;
    Exit;
    end
  else
  RemotePMem := VirtualAllocEx(HProcess, NIL, LibPathLen, MEM_COMMIT, PAGE_READWRITE);
  if not Assigned(RemotePMem) then
  begin
    ShowMessage('Ошибка выделения памяти в процессе "жертве".');
    Result := FALSE;
    CloseHandle(HProcess);
    Exit;
    end
  else
  StartAddress := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryW'); // Вот я получаю юникод версию, т.к. сконвертить путь к длл юникод в анси так и не смог(там какая то чудовищная функция на понимание которой мне показалось уйдет пол жизни  ( а аптечек нету, и до фантана пополняющего жизнь не добежать   :-)  )).
  if not Assigned(StartAddress) then
  begin
    ShowMessage('Ошибка в получении адреса функции "LoadLibraryW".');
    Result := FALSE;
    CloseHandle(HProcess);
    Exit;
    end
  else
  WriteProcess := WriteProcessMemory(HProcess, RemotePMem, PWideChar(DllPath), LibPathLen, RealWrite);
  if WriteProcess = FALSE then
  begin
    ShowMessage('Ошибка записи в память процесса.');
    Result := FALSE;
    CloseHandle(HProcess);
    Exit;
    end
  else
  HThread := CreateRemoteThread(HProcess, NIL, 0, StartAddress, RemotePMem, 0, MyTId);
  if HThread = 0 then
  begin
    ShowMessage('Ошибка в создании удалённого потока.');
    Result := FALSE;
    CloseHandle(HProcess);
    Exit;
    end
  else
  CloseHandle(HProcess);
  Result := TRUE;
end;  
Если у тебя с анси всё норм тогда получай адреса анси версий и без всяких умножений на 2
Ну пол дела я тебе сделал, дальше пиши саму длл в которой ты будешь подменять какую то функцию по твоему выбору в какой то длл на свою из своей длл. InjectDll принимает полный путь начиная с диска.
465
12 апреля 2012 года
QWERYTY
595 / / 25.03.2012
Тебе повезло у меня сегодня настроение хорошее, надеюсь у тебя тоже поднимется после того как увидишь коды ниже.

В своей длл которую будеш внедрятить добавь вот такие функции :
Код:
Во первых объяви вот это:

type
///////////////////////////////////////////////////////////////////
  PFunctionRestoreData = ^TFunctionRestoreData;
  TFunctionRestoreData = packed record
                         Address: POINTER;
                         Val1: BYTE;
                         Val2: DWORD;
///////////////////////////////////////////////////////////////////
end;


 // ФУНКЦИЯ ПЕРЕПИСЫВАЕТ ПЕРВЫЕ 5 БАЙТ У ПЕРЕХВАТЫВАЕМОЙ ФУНКЦИИ
 // ЗАПИСЫВАЯ АДРЕС ФУНКЦИИ ОБРАБОТЧИКА
function RewriteFuncCode(CurFuncAddress, NewFuncAddress: POINTER; FuncRestoreData: PFunctionRestoreData): BOOL; stdcall;
var
OldProtect, JMPValue: CARDINAL;
begin
  Result := FALSE;
  if not VirtualProtect(CurFuncAddress, 5, PAGE_EXECUTE_READWRITE, OldProtect) then Exit;
  JMPValue := CARDINAL(NewFuncAddress) - CARDINAL(CurFuncAddress) - 5;
  FuncRestoreData^.Val1 := BYTE(CurFuncAddress^);
  FuncRestoreData^.Val2 := CARDINAL(Pointer(DWORD(CurFuncAddress) + 1)^);
  FuncRestoreData^.Address := CurFuncAddress;
  BYTE(CurFuncAddress^) := $E9;
  CARDINAL(Pointer(DWORD(CurFuncAddress)+1)^) := JMPValue;
  Result := VirtualProtect(CurFuncAddress, 5, OldProtect, OldProtect);
end;


 // ФУНКЦИЯ ВОССТАНАВЛИВАЕТ(ЗАПИСЫВАЕТ ИЗНАЧАЛЬНЫЕ)
 // ПЕРВЫЕ 5 БАЙТ У ПЕРЕХВАЧЕННОЙ ФУНКЦИИ
function RestoreFuncCode(FuncRestoreData: PFunctionRestoreData): BOOL; stdcall;
var
ProcAddress: POINTER;
OldProtect, JMPValue: CARDINAL;
begin
  Result:=False;
  ProcAddress := FuncRestoreData^.Address;
  if not VirtualProtect(ProcAddress, 5, PAGE_EXECUTE_READWRITE, OldProtect) then Exit;
  Byte(ProcAddress^) := FuncRestoreData^.Val1;
  CARDINAL(POINTER(CARDINAL(ProcAddress) + 1)^) := FuncRestoreData^.Val2;
  Result := VirtualProtect(ProcAddress, 5, OldProtect, OldProtect);
end;



 // ФУНКЦИЯ УСТАНАВЛИВАЕТ ПЕРЕХВАТ ВЫЗОВОВ API ФУНКЦИЙ
function SetFuncHook(ModuleHandle: CARDINAL; FuncName: PWideChar; NewFuncAddress: POINTER; FuncRestoreData: PFunctionRestoreData): BOOL; stdcall;
var
FuncAddress: POINTER;
begin
  FuncAddress := GetProcAddress(ModuleHandle, FuncName);
  Result := RewriteFuncCode(FuncAddress, NewFuncAddress, FuncRestoreData);
  //RestoreFuncCode(FuncRestoreData);
end;
Также ты должен написать функцию в замен перехватываемой которая будет принимать и возвращить данные в таком же количестве и таких же типов как перехватываемая функция.
Вот тебе пример как я перехватывал разрушение окна:

Код:
Это всё там же в длл если кто не понял

 // ФУНКЦИЯ ВЫЗЫВАЕМАЯ В ОТВЕТ НА ВЫЗОВ СТАНДАРТНОЙ DestroyWindow
 // ПРИ ЗАКРЫТИИ ОКНА
function MyDestroyWindow(Handle: HWND): BOOL; stdcall; export;
var
DestroyWindowState: BOOL;
begin
  RestoreFuncCode(Addr(DestroyWindowRestoreData));
  // тут выполняем нужные нам действия
  // перед убийством окна, я например проверял хендл переданный в функцию
  // с имеющимся у меня и если они совпадают то я вообще больше не ставил хук
  DestroyWindowState := DestroyWindow(Handle); // Обрати внимание, мы вызываем стандартную т.к её только что восстановили(она теперь как родненькая).
  if Handle = ParentHandle then Exit;  // Тут я уже не следил что будет возвращать функция т.к это уже был конец работы приложения.
  SetFuncHook(User32Handle, 'DestroyWindow', MyDestroyWindowAddr, Addr(DestroyWindowRestoreData));
  Result := DestroyWindowState;
end;

Хук должен быть установлен при загрузке длл, для чего мы пишем в самом низу длл:

begin
// получаем тут все пути, пиды, хендлы которые нам понадобятся и ставим перехват
SetFuncHook(User32Handle, 'DestroyWindow', MyDestroyWindowAddr, Addr(DestroyWindowRestoreData));

end.
добавь переменные типа TFunctionRestoreData для каждой перехватываемой тобой функции.
Вот тебе и вторая половина дела, я недавно с этим занимался и с нуля конечно же тяжкое бремя.
465
12 апреля 2012 года
QWERYTY
595 / / 25.03.2012
Наверное если недавно кодишь покажется убийством мозга, но поверь это один из самых простых вариантов.
Там тебе советовали с драйвером повозиться, как я понимаю нужно писать драйвер виртуального устройства но в твоём случае не считаю это хорошей идеей, тут будет достаточно обычного локального перехвата.

И ещё, чтоб понять какую именно функцию перехватывать тебе нужно использовать API Monitor, установиш хук в нём на тот процесс который занимается сохранением файла, и не забудь в фильтре убрать выделение со всех функций кроме предпологаемых к перехвату иначе там может появляться тысяча записей о перехватах в которых потом сложно разобраться.
Так ты увидиш какую именно вызывает твоя прога, она же не может при сохранении и ту и ту вызывать?

Знаете кого-то, кто может ответить? Поделитесь с ним ссылкой.

Ваш ответ

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог