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

Вниз

Подмена 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 вся ветка

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

Наверх




Память: 0.52 MB
Время: 0.037 c
4-1092568796
Dimka-gl
2004-08-15 15:19
2004.09.26
Про подмену процедуры окна или "SelectDirectory" с checkbox


1-1094667825
Jus
2004-09-08 22:23
2004.09.26
Если я захочу сделать ещё один дом Dom2:TObj то как поступить? По


3-1093498750
Artem123
2004-08-26 09:39
2004.09.26
Как динамически добавить в ClientDataSet поле SmallInt чтобы....


1-1095087410
M-Alex
2004-09-13 18:56
2004.09.26
Математические операции


1-1094750155
Ajax
2004-09-09 21:15
2004.09.26
Изменение значения локальных переменных извне





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский