Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.10.2015, 21:13   #1
JPCool
Пользователь
 
Регистрация: 06.09.2015
Сообщений: 31
Подмигивание Перехват API в 64 bit Процессах

Добрый день, хочу перехватить апи в 64 битном процессе. Методом замены таблиц импорта.

Delphi XE5

Есть такой код:

Код:
function ReplaceIATEntry64(const OldProc, NewProc: FARPROC): Boolean;
var
  ImportEntry: PImageImportDescriptor;
  Thunk: PImageThunkData64;
  Protect: DWORD;
  ImageBase: Cardinal;
  DOSHeader: PImageDosHeader;
  NTHeader: PImageNtHeaders64;
begin
  Result := False;
  if OldProc = nil then Exit;
  if NewProc = nil then Exit;
  ImageBase := GetModuleHandle(nil);

try
  DOSHeader:=PImageDosHeader(ImageBase);
  NTHeader:=PImageNtHeaders64(DWORD(DOSHeader)+DWORD(DOSHeader^._lfanew));
  ImportEntry:=PImageImportDescriptor(DWORD(ImageBase) + DWORD(NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));

  while ImportEntry^.Name <> 0 do
        begin

        Thunk := PImageThunkData64(DWORD(ImageBase) + DWORD(ImportEntry^.FirstThunk));
        while Pointer(Thunk^.Function_) <> nil do
              begin

              if Pointer(Thunk^.Function_) = OldProc then
                 begin
                 if VirtualProtect(@Thunk^.Function_, SizeOf(DWORD),PAGE_EXECUTE_READWRITE, Protect) then
                    begin
                    try
                     InterlockedExchangePointer(Pointer(Thunk^.Function_),NewProc);
                     Result := True;
                    finally
                     VirtualProtect(@Thunk^.Function_, SizeOf(DWORD), Protect, Protect);
                     FlushInstructionCache(GetCurrentProcess, @Thunk^.Function_, SizeOf(DWORD));
                    end;
                    end;
                 end else
                     Inc(PAnsiChar(Thunk), SizeOf(TImageThunkData64));
              end;

        ImportEntry := Pointer(Integer(ImportEntry) + SizeOf(TImageImportDescriptor));
        end;
except
 Result:=False;
end;
end;
Структуры:

Код:
Type
 PIMAGE_OPTIONAL_HEADER64 = ^IMAGE_OPTIONAL_HEADER64;
  {$EXTERNALSYM PIMAGE_OPTIONAL_HEADER64}
  _IMAGE_OPTIONAL_HEADER64 = record
    Magic: Word;
    MajorLinkerVersion: Byte;
    MinorLinkerVersion: Byte;
    SizeOfCode: DWORD;
    SizeOfInitializedData: DWORD;
    SizeOfUninitializedData: DWORD;
    AddressOfEntryPoint: DWORD;
    BaseOfCode: DWORD;
    ImageBase: Int64;
    SectionAlignment: DWORD;
    FileAlignment: DWORD;
    MajorOperatingSystemVersion: Word;
    MinorOperatingSystemVersion: Word;
    MajorImageVersion: Word;
    MinorImageVersion: Word;
    MajorSubsystemVersion: Word;
    MinorSubsystemVersion: Word;
    Win32VersionValue: DWORD;
    SizeOfImage: DWORD;
    SizeOfHeaders: DWORD;
    CheckSum: DWORD;
    Subsystem: Word;
    DllCharacteristics: Word;
    SizeOfStackReserve: Int64;
    SizeOfStackCommit: Int64;
    SizeOfHeapReserve: Int64;
    SizeOfHeapCommit: Int64;
    LoaderFlags: DWORD;
    NumberOfRvaAndSizes: DWORD;
    DataDirectory: array [0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1] of IMAGE_DATA_DIRECTORY;
  end;
  {$EXTERNALSYM _IMAGE_OPTIONAL_HEADER64}
  IMAGE_OPTIONAL_HEADER64 = _IMAGE_OPTIONAL_HEADER64;
  {$EXTERNALSYM IMAGE_OPTIONAL_HEADER64}
  TImageOptionalHeader64 = IMAGE_OPTIONAL_HEADER64;
  PImageOptionalHeader64 = PIMAGE_OPTIONAL_HEADER64;


type
  PIMAGE_NT_HEADERS64 = ^IMAGE_NT_HEADERS64;
  {$EXTERNALSYM PIMAGE_NT_HEADERS64}
  _IMAGE_NT_HEADERS64 = record
    Signature: DWORD;
    FileHeader: IMAGE_FILE_HEADER;
    OptionalHeader: IMAGE_OPTIONAL_HEADER64;
  end;
  {$EXTERNALSYM _IMAGE_NT_HEADERS64}
  IMAGE_NT_HEADERS64 = _IMAGE_NT_HEADERS64;
  {$EXTERNALSYM IMAGE_NT_HEADERS64}
  TImageNtHeaders64 = IMAGE_NT_HEADERS64;
  PImageNtHeaders64 = PIMAGE_NT_HEADERS64;


type
  TIIDUnion = record
    case Integer of
      0: (Characteristics: DWORD);
      1: (OriginalFirstThunk: DWORD);
    end;

  PImageImportDescriptor = ^TImageImportDescriptor;
  TImageImportDescriptor = record
    Union: TIIDUnion;
    TimeDateStamp: DWORD;
    ForwarderChain: DWORD;
    Name: DWORD;
    FirstThunk: DWORD;
  end;


PIMAGE_THUNK_DATA64 = ^IMAGE_THUNK_DATA64;
  {$EXTERNALSYM PIMAGE_THUNK_DATA64}
  _IMAGE_THUNK_DATA64 = record
    case Integer of
      0: (ForwarderString: ULONGLONG);   // PBYTE
      1: (Function_: PDWORD);         // PDWORD
      2: (Ordinal: ULONGLONG);
      3: (AddressOfData: ULONGLONG);     // PIMAGE_IMPORT_BY_NAME
  end;
  {$EXTERNALSYM _IMAGE_THUNK_DATA64}
  IMAGE_THUNK_DATA64 = _IMAGE_THUNK_DATA64;
  {$EXTERNALSYM IMAGE_THUNK_DATA64}
  TImageThunkData64 = IMAGE_THUNK_DATA64;
  PImageThunkData64 = PIMAGE_THUNK_DATA64;


Const
  IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   = 13;

Последний раз редактировалось Stilet; 03.10.2015 в 21:31.
JPCool вне форума Ответить с цитированием
Старый 03.10.2015, 21:14   #2
JPCool
Пользователь
 
Регистрация: 06.09.2015
Сообщений: 31
Счастье

С Импортом все отлично,но вот если пытаюсь сделать замену адреса в таблице экспорта DLL примерно таким кодом:

Цитата:
function ReplaceEATEntry64(const DllName: WideString; OldProc, NewProc: FARPROC): Boolean;
var
ImageBase: Cardinal;
DOSHeader: PImageDosHeader;
NTHeader: PImageNtHeaders64;
ExportDirectory: PImageExportDirectory;
pFuntionAddr: PDWORD;
OrdinalCursor: PWORD;
Ordinal, Protect: DWORD;
FuntionAddr: FARPROC;
I: Integer;

begin
Result := False;
if OldProc = nil then Exit;
if NewProc = nil then Exit;
ImageBase := GetModuleHandle(PWideChar(DllName)) ;



DOSHeader := PImageDosHeader(ImageBase);
NTHeader:=PImageNtHeaders64(DWORD(D OSHeader)+DWORD(DOSHeader^._lfanew) );
ExportDirectory := PImageExportDirectory(DWORD(ImageBa se) +DWORD(NTHeader^.OptionalHeader.Dat aDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));

I := 1;

OrdinalCursor := Pointer(ImageBase + DWORD(ExportDirectory^.AddressOfNam eOrdinals));
while I < Integer(ExportDirectory^.NumberOfNa mes) do
begin

Ordinal := OrdinalCursor^;

FuntionAddr := Pointer(ImageBase + DWORD(ExportDirectory^.AddressOfFun ctions));
FuntionAddr := Pointer(ImageBase + PDWORD(DWORD(FuntionAddr) + Ordinal * 4)^);

if FuntionAddr = OldProc then
begin
pFuntionAddr := PDWORD(ImageBase + DWORD(ExportDirectory^.AddressOfFun ctions) + Ordinal * 4);
NewProc := Pointer(DWORD(NewProc) - ImageBase);
if VirtualProtect(pFuntionAddr, SizeOf(DWORD),
PAGE_EXECUTE_READWRITE, Protect) then
try
//InterlockedExchange(Integer(PImageT hunkData64(pFuntionAddr)^.Function_ ),Integer(NewProc));
Result := True;
finally
VirtualProtect(pFuntionAddr, SizeOf(DWORD), Protect, Protect);
FlushInstructionCache(GetCurrentPro cess, pFuntionAddr, SizeOf(DWORD));
end;
Break;
end;

Inc(I);
Inc(OrdinalCursor);
end;
end;
Получаю ACCESS_VIOLATION на

NTHeader:=PImageNtHeaders64(DWORD(D OSHeader)+DWORD(DOSHeader^._lfanew) );

или к любому обращению к заголовку DOSHeader по адресу DLL. тестировал на перехвате TranslateMessage из user32.dll

По какой причине у меня нет доступа к памяти длл (( в чем проблема куда копать что читать. подскажите помогите

Аналогичный код с 32 битными структурами работает на ура. И Импорт и Экспорт длл. в 32 битном процессе.

Последний раз редактировалось JPCool; 03.10.2015 в 21:32.
JPCool вне форума Ответить с цитированием
Старый 19.10.2015, 02:44   #3
JPCool
Пользователь
 
Регистрация: 06.09.2015
Сообщений: 31
По умолчанию

Переписал все на Read/WriteProcessMemory сейчас могу получать и писать данные. Поменял все с таблицей импорта как то так:

Цитата:
function ReplaceIATEntry64(const OldProc, NewProc: FARPROC): Boolean;
var
ImageBase,CurrProc:Int64;
WW:SIZE_T;

DOSHeader: _IMAGE_DOS_HEADER;
NTHeader : _IMAGE_NT_HEADERS64;
ImportEntry:TImageImportDescriptor;
Thunk:_IMAGE_THUNK_DATA64;

VirtMemAdrr,VirtMemAdrr2:Int64;
begin
Result := False;
try
if OldProc = nil then Exit;
if NewProc = nil then Exit;
ImageBase := GetModuleHandle(nil);

CurrProc:=GetCurrentProcess;

if ReadProcessmemory(CurrProc,Pointer( ImageBase),@DOSHeader,SizeOf(_IMAGE _DOS_HEADER),WW) then
begin
if ReadProcessmemory(CurrProc,Pointer( ImageBase+DWORD(DOSHeader._lfanew)) ,@NTHeader,SizeOf(_IMAGE_NT_HEADERS 64),WW) then
begin
VirtMemAdrr:=ImageBase+DWORD(NTHead er.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
if ReadProcessmemory(CurrProc,Pointer( VirtMemAdrr),@ImportEntry,SizeOf(TI mageImportDescriptor),WW) then
begin
while ImportEntry.Name <> 0 do
begin

VirtMemAdrr2:=DWORD(ImageBase)+DWOR D(ImportEntry.FirstThunk);
if ReadProcessmemory(CurrProc,Pointer( VirtMemAdrr2),@Thunk,SizeOf(_IMAGE_ THUNK_DATA64),WW) then
begin
while Thunk.Function_<> nil do
begin
if Thunk.Function_=OldProc then
begin
Thunk.Function_:=NewProc;
if WriteProcessMemory(CurrProc,Pointer (VirtMemAdrr2),@Thunk,SizeOf(_IMAGE _THUNK_DATA64),WW) then
Result:=True;
end;

VirtMemAdrr2:=VirtMemAdrr2+SizeOf(_ IMAGE_THUNK_DATA64);
if ReadProcessmemory(CurrProc,Pointer( VirtMemAdrr2),@Thunk,SizeOf(_IMAGE_ THUNK_DATA64),WW)=False then
Break;
end;
end;

VirtMemAdrr:=VirtMemAdrr+SizeOf(TIm ageImportDescriptor);
if ReadProcessmemory(CurrProc,Pointer( VirtMemAdrr),@ImportEntry,SizeOf(TI mageImportDescriptor),WW)=False then
Break;
end;
end;
end;
end;
except
end;

end;
А вот с таблицей экспорта в длл есть проблема расчета (точнее понимания расположения элементов в структуре) не помогу правильно расчитать адреса и сделать подмену накидал код примерно такой.

Цитата:
function ReplaceEATEntry64(const DllName: string; OldProc, NewProc: FARPROC): Boolean;
var
ImageBase,CurrProc,VirtMemAdrr,Virt MemAdrr2:Int64;

DOSHeader: _IMAGE_DOS_HEADER;
NTHeader : _IMAGE_NT_HEADERS64;
ExportDirectory: _IMAGE_EXPORT_DIRECTORY;


//DOSHeader: PImageDosHeader;
//NTHeader: PImageNtHeaders64;


pFuntionAddr: PDWORD;
OrdinalCursor: PWORD;
Ordinal, Protect: DWORD;
FuntionAddr: FARPROC;
I,Error: Integer;
DOSH:_IMAGE_DOS_HEADER;
WW:SIZE_T;
begin
Result := False;
if OldProc = nil then Exit;
if NewProc = nil then Exit;
ImageBase := GetModuleHandle(PChar(DllName));
CurrProc:=GetCurrentProcess;

if ReadProcessmemory(CurrProc,Pointer( ImageBase),@DOSHeader,SizeOf(_IMAGE _DOS_HEADER),WW) then
begin
if ReadProcessmemory(CurrProc,Pointer( ImageBase+DWORD(DOSHeader._lfanew)) ,@NTHeader,SizeOf(_IMAGE_NT_HEADERS 64),WW) then
begin
VirtMemAdrr:=ImageBase+NTHeader.Opt ionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
if ReadProcessmemory(CurrProc,Pointer( VirtMemAdrr),@ExportDirectory,SizeO f(_IMAGE_EXPORT_DIRECTORY),WW) then
begin
I:=1;
OrdinalCursor := Pointer(ImageBase + DWORD(ExportDirectory.AddressOfName Ordinals));
while I<Integer(ExportDirectory.NumberOfN ames) do
begin
Ordinal := OrdinalCursor^;
//--- Проблема с расчетом адреса ((( и правильной обработкой структур....
FuntionAddr := Pointer(ImageBase+DWORD(ExportDirec tory.AddressOfFunctions));
ReadProcessmemory(CurrProc,Pointer( DWORD(FuntionAddr)+Ordinal*4),@Funt ionAddr,SizeOf(FuntionAddr),WW);

if FuntionAddr = OldProc then
begin
//--- Write Address ....

Result:=True;
end;

Inc(I);
Inc(OrdinalCursor);
end;
end;
end;
end;
end;
Не понять как именно расположенны структуры. Помогите, можно и любой другой рабочий код для перехвата таблиц импорта экспорта для 64 битных систем.
JPCool вне форума Ответить с цитированием
Старый 25.04.2017, 17:52   #4
Zegunder
Новичок
Джуниор
 
Регистрация: 04.06.2016
Сообщений: 1
По умолчанию

@JPCool, Вам удалось справиться с этой проблемой?
Помогите пожалуйста с решением.
Zegunder вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Перехват 64-bit hiho Win Api 13 25.11.2015 18:56
Перехват Api egorzenit Win Api 16 22.10.2011 23:26
Перехват GL Api coNsept Общие вопросы C/C++ 6 19.06.2011 02:42
Перехват API BOBAH13 Win Api 12 10.05.2010 10:11
API перехват Irat Помощь студентам 13 11.02.2008 12:04