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

Вниз

Подмена WinAPI функции в своём приложении.   Найти похожие ветки 

 
GuAV ©   (2004-08-14 00:50) [0]

Как подменить например LoadString ?


 
Cobalt ©   (2004-08-14 01:29) [1]

Use Debug DCU"s (в свойствах проекта, если не ошибаюсь), и изменение модуля Windows.


 
GuAV ©   (2004-08-14 01:49) [2]

Спасибо, но не то. В рантайме надо.


 
Cobalt ©   (2004-08-14 02:03) [3]

Дык, а чем рантайм-то отличается? Делай настроечку - Ещё одну функцию добавь - SetLoadStringProc с параметром адреса процедуры, её запоминаешь в переменной, и вызываешь в LoadString. И вся недолга.


 
TUser ©   (2004-08-14 03:18) [4]

Что-то уже второй вопрос подряд читаю про изменения стандартных модулей. И зачем людям это надо?


 
GuAV ©   (2004-08-14 05:17) [5]


> изменения стандартных модулей

Об этом речь не идёт


 
Ihor Osov'yak ©   (2004-08-14 05:32) [6]

есть несколько методов подмены (перехвата), в частности -
1. Модификация таблиц импорта
2. Модификация таблий экспорта
3. Подмена кода самой функции (как правило, jmp на свою процедуру)
4. "Подсовывание" фальшивой dll, если функция в dll

Каждый из способов имеет свои недостатки и свои преимущества, и не всегда в конкретном случае может быть приемлемый (например, 1 и 2, 4 - только для функций, живущих в длл, и вызываемых с других модулей).

Метод 1, кажется, описан в Рихтера, в том, который со "спецификой 64-битности". Также когда-то видел статью на www.rsdn.ru - обзор этих методов перехвата, c примерами кода.


 
GuAV ©   (2004-08-14 14:03) [7]


> 4. "Подсовывание" фальшивой dll, если функция в dll

Хм... мне не все функции нужны а одна... и в подмененную никто не полезет, ясли в памяти уже находится настоящая.

> 2. Модификация таблий экспорта

Нужно только для своей программы.

> 1. Модификация таблиц импорта

Это интересно. Буду благодарен за ссылку.

> 3. Подмена кода самой функции (как правило, jmp на свою
> процедуру)

Это тоже интересно, если делается для процедур из system.pas, а не библиотеки. Опять же, буду благодарен за ссылку.

Ладно, спасибо, пойду искать статьи...


 
GuAV ©   (2004-08-14 20:03) [8]

Получилось подменить LoadResString (это уже не апи. так что ветку обратно в основную ;-) )

type
 TInterceptRec = packed record
   JMP: Byte; // Set to $E9
   FCN: Pointer;
 end;

function NewLoadResString(ResStringRec: PResStringRec): string;
begin
 Result:="Nothing Special";
end;

procedure TfrmMain.Button1Click(Sender: TObject);
var Op: LongWord; I: TInterceptRec; Written: Cardinal;
begin
 I.JMP:=$E9;
 I.FCN:=Pointer(Integer(@NewLoadResString)
   - Integer(@LoadResString) - SizeOf(I));
 VirtualProtect(@LoadResString,SizeOf(I), PAGE_READWRITE, Op);
 WriteProcessMemory(GetCurrentProcess, @LoadResString,
                    @I, SizeOf(I), Written);
 VirtualProtect(@LoadResString, SizeOf(I), Op, nil);
end;


Это реализовано

> 3. Подмена кода самой функции (как правило, jmp на свою
> процедуру)

Спасибо, Ihor Osov"yak.

зы - помнится. Вы также про что-то подобное спрашивали :)


 
GuAV ©   (2004-08-14 20:12) [9]

Да, ещё нашел вот что:

Практика показала, что вместо обычного jmp лучше применять комбинацию

push xxxxxxxx
ret


http://rsdn.ru/article/baseserv/IntercetionAPI.xml


 
GuAV ©   (2004-08-14 20:44) [10]

Итак, вот что сейчас имеем.
type
 TInterceptRec = packed record
   JMP: Byte;
   FCN: Pointer;
   RET: Byte;
 end;

procedure Interceptor; assembler;
asm
 PUSH 0.DWORD
 RET
end;

function NewLoadResString(ResStringRec: PResStringRec): string;
begin
 Result:="Nothing Special";
end;

procedure Hook(Old, New: Pointer);
var I: TInterceptRec;
begin
 Move(Interceptor, I, SizeOf(I));
 I.FCN:=New;
 WriteProcessMemory(GetCurrentProcess, Old,
   @I, SizeOf(I), LongWord(nil^));
end;


Кстати, только что было AV - текст - Nothing Special... LOL!


 
Digitman ©   (2004-08-16 08:39) [11]


> Подмена WinAPI функции в своём приложении


то что здесь показано примером не имеет к сабжу никакого отношения


 
VMcL ©   (2004-08-16 15:59) [12]

>>GuAV ©  (14.08.04 20:03) [8]

Использование WriteProcessMemory() для текущего процесса вместо Move() - это удаление гланд через задний проход, ИМХО.


 
GuAV ©   (2004-08-18 16:17) [13]

Чезер MOVE у меня AV. Через MOVE я могу читать а не писать

К сабжу код отношение не имел, этот имеет:


procedure HookIt;
var
 P: Pointer; Addr: Pointer; LName: PChar;
 A: PIMAGE_THUNK_DATA32;
begin
 P:=Pointer(Hinstance);
 with IMAGE_DOS_HEADER(P^) do
 begin
   Assert(e_magic=$5A4D); // "MZ"
   Inc(Longint(P), e_lfanew + 4 + SizeOf(IMAGE_FILE_HEADER));
 end;
 with IMAGE_OPTIONAL_HEADER(P^) do
 begin
   Assert(Magic=$010B);
   P:=@DataDirectory[1]; // импорт
 end;
 P:=Pointer(Hinstance+IMAGE_DATA_DIRECTORY(P^).VirtualAddress);
 Addr:=GetProcAddress(GetModuleHandle("user32.dll"), "LoadStringA");

 repeat
   with IMAGE_IMPORT_DESCRIPTOR(P^) do
   begin
     LName:=PChar(Hinstance+Name);
     if SameText(LName,"user32.dll") then
     begin
       A:=Pointer(Hinstance+FirstThunk);
       while A^.AddressOfData <>0 do
       begin
         // Что тут писать ?
         Inc(Longint(A), SizeOf(A^));
       end;
     end;
   end;
   Inc(Longint(P), SizeOf(IMAGE_IMPORT_DESCRIPTOR));
 until IMAGE_IMPORT_DESCRIPTOR(P^).Name=0;

end;  


Как узнать какой case ???

 _IMAGE_THUNK_DATA32 = record
   case Integer of
     0: (ForwarderString: DWORD);   // PBYTE
     1: (Function_: DWORD);         // PDWORD
     2: (Ordinal: DWORD);
     3: (AddressOfData: DWORD);     // PIMAGE_IMPORT_BY_NAME
 end;

Или опять через тот проход ? :(


 
VMcL ©   (2004-08-18 16:50) [14]

>>GuAV ©  (18.08.04 16:17) [13]

>Чезер MOVE у меня AV. Через MOVE я могу читать а не писать

В [8] использовался VirtualProtect, поэтому там использовать WriteProcessMemory - изврат. Если же без VirtualProtect, то даже наоборот - удобнее.


 
Digitman ©   (2004-08-18 17:15) [15]


> GuAV ©   (18.08.04 16:17) [13]


легко отделаться хочешь ) .. не через "тот проход" ...

ключевой момент может выглядеть не проще чем вот так :

function SetProcAddress(hModule: THandle; lpProcName: PChar; pProcAddr: Pointer): Boolean;
var
 Peb: PPeb;
 hProcess, hImporter: THandle;
 pOptHdr: PImageOptionalHeader;
 pImpDir: PImageImportDescriptor;
 pExpDir: PImageExportDirectory;
 pIATEntry: PImageThunkData;
 pOldProcAddr: Pointer;
 pdwNamePtr, pdwEntryPoint: PDWord;
 pName: PChar;
 pwOrdinalPtr: PWord;
 i, nOrdinal, dwNewProcAddrRVA, dwProtect: DWord;
 pLdrData : PPEB_LDR_DATA;
 pLoadOrderList : PPLIST_ENTRY;
 pInLoadModuleEntry: PModuleEntry;
 pModuleNfo: PModuleInfo;
 pImpModuleNfo: PModuleInfo;
 sModuleName: String;
 dwDirSize: DWord;
begin
 Result := False;
 if (hModule = 0) or (lpProcName = nil) then Exit;
 peb := GetCurrentPEB;
 LockLoader(Peb);
 try
   pModuleNfo := FindModuleInfo(hModule);
   if not Assigned(pModuleNfo) then Exit;
   sModuleName := WideCharToString(pModuleNfo^.BaseDllName.Buffer);
   pOptHdr := PImageOptionalHeader(hModule + PImageDosHeader(hModule)._lfanew + SIZE_OF_NT_SIGNATURE + IMAGE_SIZEOF_FILE_HEADER);
   dwDirSize := pOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
   if (pOptHdr^.NumberOfRvaAndSizes < 16) or (dwDirSize = 0) then Exit;
   pExpDir := PImageExportDirectory(hModule + pOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
   pdwEntryPoint := nil;
   pwOrdinalPtr := PWord(hModule +  DWord(pExpDir^.AddressOfNameOrdinals));
  if HiWord(DWord(lpProcName)) = 0 then
     begin
       nOrdinal :=  LoWord(DWord(lpProcName)) - pExpDir^.Base;
       if (nOrdinal < pExpDir^.NumberOfFunctions) then
         pdwEntryPoint := PDWord(hModule + DWord(pExpDir^.AddressOfFunctions) + nOrdinal * SizeOf(PDWord));
     end
   else
     begin
       pdwNamePtr := PDWord(hModule + DWord(pExpDir^.AddressOfNames));
       for i := 0 to pExpDir^.NumberOfNames - 1 do
         begin
        pName := PChar(PDWord(hModule  + PDword(pdwNamePtr)^));
        if lstrcmp(pName,lpProcName) = 0 then
             begin
           nOrdinal := pwOrdinalPtr^;
               pdwEntryPoint := PDWord(hModule + DWord(pExpDir^.AddressOfFunctions) + nOrdinal * SizeOf(PDWord));
               Inc(nOrdinal, pExpDir^.Base);
           Break;
          end
           else
             begin
               Inc(pdwNamePtr);
            Inc(pwOrdinalPtr);
             end
         end;
     end;
   if not Assigned(pdwEntryPoint) then Exit;
   pOldProcAddr := Pointer(hModule + pdwEntryPoint^);
   if pOldProcAddr = pProcAddr then
     Result := True
   else
     try
       dwNewProcAddrRVA := DWord(pProcAddr) - hModule;
       hProcess := OpenProcess(PROCESS_VM_OPERATION, False, GetCurrentProcessId);
       Win32Check(hProcess <> 0);
       try
         Win32Check(VirtualProtectEx(hProcess, pExpDir, dwDirSize, PAGE_WRITECOPY, dwProtect));
         try
           pdwEntryPoint^ := dwNewProcAddrRVA;
         finally
           VirtualProtectEx(hProcess, pExpDir, dwDirSize, dwProtect, dwProtect);
         end;
         pName := PChar(sModuleName);
         pLdrData := Peb^.LdrData;
         pLoadOrderList := @pLdrData.InLoadOrderModuleList;
         pInLoadModuleEntry := PModuleEntry(pLoadOrderList^);
         while PPListEntry(pInLoadModuleEntry) <> pLoadOrderList do
           begin
             pImpModuleNfo := @pInLoadModuleEntry.ModuleInfoData;
             if pImpModuleNfo <> pModuleNfo then
               begin
                 hImporter := THandle(pImpModuleNfo^.DllBase);
                 pOptHdr := PImageOptionalHeader(hImporter + PImageDosHeader(hImporter)._lfanew + SIZE_OF_NT_SIGNATURE + IMAGE_SIZEOF_FILE_HEADER);
                 if pOptHdr^.NumberOfRvaAndSizes = 16 then
                   begin
                     dwDirSize := pOptHdr^.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
                     if dwDirSize > 0 then
                       begin
                         pImpDir := PImageImportDescriptor(hImporter + pOptHdr^.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
                         while Assigned(PChar(pImpDir^.RVAImportModuleName)) do
                           begin
                             if lstrcmpi(PChar(hImporter + pImpDir^.RVAImportModuleName), pName) = 0 then
                               begin
                                 pIATEntry := PImageThunkData(hImporter + DWord(pImpDir^.RVAImportAddressTable));
                                 while Assigned(pIATEntry^.Func) do
                                   begin
                                     if pIATEntry^.Func = pOldProcAddr then
                                       begin
                                         Win32Check(VirtualProtectEx(hProcess, pIATEntry, SizeOf(pIATEntry), PAGE_WRITECOPY, dwProtect));
                                         try
                                           pIATEntry^.Func := pProcAddr;
                                         finally
                                           VirtualProtectEx(hProcess, pIATEntry, SizeOf(pIATEntry), dwProtect, dwProtect);
                                         end;
                                         Break;
                                       end;
                                     Inc(pIATEntry);
                                   end;
                               end;
                             Inc(pImpDir);
                           end;
                       end;
                   end;
               end;
             pInLoadModuleEntry := PModuleEntry(pInLoadModuleEntry.InLoadOrderLinks.Flink);
           end;
       finally
         CloseHandle(hProcess);
       end;
       Result := True;
     except
     end;
 finally
   UnLockLoader(Peb);
 end;
end;

а вокруг него - обвязка из определений ОГРОМНОЙ КУЧИ типов ... попробу испугаться ?


 
jack128 ©   (2004-08-18 17:23) [16]


> CloseHandle(hProcess);
>        end;
>        Result := True;
>      except
>      end;

>  finally
>    UnLockLoader(Peb);
>  end;
> end;

Какой кашмар!!!! ;-)



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

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

Наверх




Память: 0.53 MB
Время: 0.042 c
1-1094505200
массив
2004-09-07 01:13
2004.09.26
Как объяснить следующий код ?


14-1094208586
peypivo
2004-09-03 14:49
2004.09.26
Не работают сайты с новостями?


14-1094330033
Piter
2004-09-05 00:33
2004.09.26
Где скачать SynEdit?


1-1094637857
jonik
2004-09-08 14:04
2004.09.26
Форма с Настройками программы


4-1092602199
DeadMeat
2004-08-16 00:36
2004.09.26
Буфер или не буфер...