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