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

Вниз

Тонкости перехвата API   Найти похожие ветки 

 
Dmitry S ©   (2008-04-28 22:59) [0]

Конструктивно:

Перехватываю функцию CreateFileW путем записи нескольких первых байт. (точнее 10):
$68, $A1, $A2, $A3, $A4 // push A1A2A3A4h
$68, [@MyCreateFileW] // push ...
$C3 // ret

После чего, как я думал, мне необходимо в описание MyCreateFileW добавить еще один параметр (первый) резмером Integer, где и будет храниться переданное мной число A1A2A3A4h.
Однако параметр полченный в функцию "левый", а число A1A2A3A4h продолжает храниться в стеке. Почему так? Ведь я добавил еще один параметр, он ведь должен браться из стека?


 
Тыщ ©   (2008-04-28 23:04) [1]

Какое соглашение вызова у функции MyCreateFileW?


 
Dmitry S ©   (2008-04-28 23:04) [2]

stdcall


 
Dmitry S ©   (2008-04-28 23:11) [3]

А еще вопрос по теме.
Как сделать call по абслютному адресу? Т.е. в машинных инстукциях как?
E8 xx xx xx xx - это я так понимаю относительный. А как абсолютный?


 
Тыщ ©   (2008-04-28 23:15) [4]

Dmitry S ©   (28.04.08 23:11) [3]

call по абслютному адресу сделать нельзя, потому так как он изменит сегментный регистр cs, а это запрещено в Windows.
Да и не нужно, в общем-то.


 
Dmitry S ©   (2008-04-28 23:19) [5]

А как тогда быть??


 
Тыщ ©   (2008-04-28 23:19) [6]

mov eax, some_absolute_address
call eax


 
Dmitry S ©   (2008-04-28 23:23) [7]

окей.
А можно это в кодах команд?


 
Тыщ ©   (2008-04-28 23:25) [8]

B8 78563412 // mov eax, 12345678h
FFD0 // call eax


 
Dmitry S ©   (2008-04-28 23:43) [9]

Не понимаю вот чего:

Делаю простой вызов своей
MyCreateFileW

В итоге в окне асемблера наблюдаю:
делается куча push, потом call
а в теле функци pop-ов нет, значения переменных беруться из памяти. как так?


 
Anatoly Podgoretsky ©   (2008-04-28 23:52) [10]

> Dmitry S  (28.04.2008 23:43:09)  [9]

Есть такое понятие, как фрейм стека, вот отностительно его и берутся.
Сходи ко мне на сайт и возьми две статьи по basm

http://www.podgoretsky.com/Redir.aspx?id=142&DownloadFile=~/ftp/Docs/Delphi/Podgoretsky/basmru.zip
http://www.podgoretsky.com/Redir.aspx?id=129&DownloadFile=~/ftp/Docs/Delphi/Podgoretsky/BasmForBeginners-ru.doc

Поскольку ты занимаешься АСМ то информация будет интересна.


 
Dmitry S ©   (2008-04-29 00:11) [11]

Кажеться я понял в чем дело.
Объясните пожалуйста следующее.
Мне нужно вставить некое значение в стек ПЕРЕД текущим. Так правильно:
pop eax;
push $xxxxxxx;
push eax;
?


 
Dmitry S ©   (2008-04-29 00:21) [12]

Все!!! Я понял!! И исправил.

Дело в том, что я "добавлял" этот самый параметр ПОСЛЕ выполнения call. А последняя использует стек, видимо для хранения точки возврата. Поэтому мой параметр и адрес точки возврата, какбы поменялись местами.Вставил код из 11, все заработало =) уфф=)


 
Dmitry S ©   (2008-04-29 00:40) [13]

В итоге получился такой код:

pop eax  // 58
push $xxxxxxxx // 68xxxxxxxx
push eax  // 50
push $yyyyyyyy // 68yyyyyyyy
ret  // c3

Этот код я вставляю в начало перехватываемой функции.
Тут $xxxxxxxx - адрес какого либо параметра
$yyyyyyyy - мой функция, которая должна выполнить оригинальную...
Блин, совсем как с SetIntVec в паскале =)


 
KSergey ©   (2008-04-29 09:55) [14]

> Dmitry S ©   (29.04.08 00:21) [12]
> ПОСЛЕ выполнения call.
> А последняя использует стек, видимо для хранения точки возврата.

А может книжки-то почитать, а?
Ну зачем постигать компьютер методом проб и ошибок? Это ж жизни не хватит!


 
Rouse_ ©   (2008-04-29 10:18) [15]

Что-то ты сурово как-то сплайсинг делаешь... Вот тебе навскидку примерчик от руки написанный... Должен работать по идее

type
 TSpliceRec = packed record
   JMP_OpCode: Byte;
   ProcAddr: Pointer;
   RET_OpCode: Byte;
 end;

var
 FuncAddr: Pointer;
 OldSpliceData, NewSpliceData: TSpliceRec;

function SpliceEntry(const FuncAddr: Pointer;
 const NewData: TSpliceRec): Boolean;
var
 Dumme: DWORD;
begin
 Result := WriteProcessMemory(GetCurrentProcess, FuncAddr, @NewData,
   SizeOf(TSpliceRec), Dumme);
 if Result then
   Result := Dumme = SizeOf(TSpliceRec);
end;

type
 TCreateFileA = function(lpFileName: PAnsiChar;
   dwDesiredAccess, dwShareMode: DWORD;
   lpSecurityAttributes: PSecurityAttributes;
   dwCreationDisposition, dwFlagsAndAttributes: DWORD;
   hTemplateFile: THandle): THandle; stdcall;

function InterceptedCreateFileA(lpFileName: PAnsiChar;
 dwDesiredAccess, dwShareMode: DWORD;
 lpSecurityAttributes: PSecurityAttributes;
 dwCreationDisposition, dwFlagsAndAttributes: DWORD;
 hTemplateFile: THandle): THandle; stdcall;
begin
 SpliceEntry(FuncAddr, OldSpliceData);
 dwDesiredAccess := GENERIC_READ;
 dwShareMode := FILE_SHARE_READ or FILE_SHARE_WRITE;
 dwCreationDisposition := OPEN_EXISTING;
 Result := TCreateFileA(FuncAddr)(lpFileName, dwDesiredAccess,
   dwShareMode, lpSecurityAttributes, dwCreationDisposition,
   dwFlagsAndAttributes, hTemplateFile);
 SpliceEntry(FuncAddr, NewSpliceData);
end;


пример вызова:

 NewSpliceData.JMP_OpCode := $68;
 NewSpliceData.ProcAddr := @InterceptedCreateFileA;
 NewSpliceData.RET_OpCode := $C3;
 FuncAddr := GetProcAddress(GetModuleHandle(kernel32), "CreateFileA");
     ReadProcessMemory(GetCurrentProcess,
     FuncAddr,
     @OldSpliceData, SizeOf(TSpliceRec), Dumme);

 SpliceEntry(FuncAddr, NewSpliceData);
 try
   M := TFileStream.Create(Path, fmOpenRead);
   try
     M.Position := LogRecord[Index].Rec.DataOffset;
     Stream.CopyFrom(M, LogRecord[Index].Rec.DataSize);
     Result := True;
   finally
     M.Free;
   end;
 finally
   SpliceEntry(FuncAddr, OldSpliceData);
 end;


 
Дмитрий С   (2008-04-29 10:26) [16]


> Rouse_ ©   (29.04.08 10:18) [15]

Я делаю тоже самое, только передаю в InterceptedCreateFileA дополнительный параметр. Типа LPVOID lpParameter у CreateThread.


 
Дмитрий С   (2008-04-29 10:28) [17]

Вечером скину код, что получилось. Он дома.

ЗЫ. Не удается с тобой наладить связь. =(


 
Дмитрий С   (2008-04-29 10:29) [18]


> А может книжки-то почитать, а?
> Ну зачем постигать компьютер методом проб и ошибок? Это
> ж жизни не хватит!

Так ведь это просто! Мне АСМ в принципе не нужен. Для таких нехитрых задач достаточно тех знаний что есть:) Конечно возникают вопросы. Но они у всех возникают


 
Дмитрий С   (2008-04-29 10:35) [19]


> Поскольку ты занимаешься АСМ то информация будет интересна.
>
>

благодарю! :)


 
Rouse_ ©   (2008-04-29 10:38) [20]


> ЗЫ. Не удается с тобой наладить связь. =(

Дай свою асю сам свяжусь, у меня антиспам стоит, он почемуто только с QIP пропускает клиентов :)


 
Дмитрий С   (2008-04-29 10:40) [21]

Удалено модератором


 
Сергей М. ©   (2008-04-29 15:53) [22]


> Dmitry S ©   (28.04.08 22:59)


А нафих тебе сплайсинг сдался ?
Чем не устроил перехват методом модификации EAT+IAT ?


 
Дмитрий С   (2008-04-29 16:06) [23]

О вкусах не спорят


 
Сергей М. ©   (2008-04-29 17:08) [24]


> О вкусах не спорят


Не спорят, да)

А вот о блажи можно и поспорить.


 
Rouse_ ©   (2008-04-29 17:18) [25]

Через EAT+IAT доп.параметр не перекинешь, хотя я так и не понял зачем он тут сдался :)


 
Сергей М,   (2008-04-29 19:47) [26]


> зачем он тут сдался


Как зачем ? Блажь !) Самая что ни на есть настоящая).. Надежно прикрытая "вкусами, о которых не спорят")


 
Тыщ ©   (2008-04-29 22:47) [27]

Anatoly Podgoretsky ©   (28.04.08 23:52) [10]

> basmru.zip

Почитал. Что-то опечаток многовато, и некоторые неточности имеются.


 
Dmitry S ©   (2008-04-29 23:20) [28]

unit InterceptAPI;

interface
uses Windows;

type
 TInterceptProc = packed record
   instr_pop1: byte;               // pop eax;
   instr_push1: byte;              // push InterceptStruct;
   InterceptStruct: Pointer;
   instr_push2: byte;              // push eax;
   instr_push3: byte;              // push address;
   address: Pointer;
   instr_ret: byte;                // ret;
 end;

 PInterceptStruct = ^TInterceptStruct;

 TInterceptStruct = record
   OriginalFunction: Pointer;
   NewFunction: Pointer;

   Lock:RTL_CRITICAL_SECTION;

   NewFunctionCode: TInterceptProc;
   OldFunctionCode: TInterceptProc; // тип используется лишь для сорaзмерности
 end;

{ InterceptFunction устанавливает перехват функции по адресу OriginalFunction
функцией по адресу NewFunction. Под структуру InterceptStruct выделять память не нужно -
выделяется автоматически.
Важно!
Функции OriginalFunction и NewFunction должны быть stdcall.
Причем NewFunction имеет не только те же параметры, что и OriginalFunction, но
и дополнительный первый параметр: InterceptStruct: PInterceptStruct.
Например оригинальная функция:
 function MessageBoxW(hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;
тогда новая функция должна иметь вил:
 function InterMessageBoxW(InterceptStruct: PInterceptStruct; hWnd: HWND; lpText, lpCaption: PWideChar; uType: UINT): Integer; stdcall;

Данный параметр используется для вызовов LockFunction и UnLockFunction.
}
procedure InterceptFunction(var InterceptStruct: PInterceptStruct; const OriginalFunction, NewFunction: Pointer); stdcall;

{
 UnInterceptFunction восстанавливает оригинальную функцию и освобождает память
 стурктуры InterceptStruct.
}
procedure UnInterceptFunction(var InterceptStruct: PInterceptStruct); stdcall;

{
 LockFunction временно восстанавливает функцию.
}
procedure LockFunction(InterceptStruct: PInterceptStruct); stdcall;

{
 UnLockFunction снова перехватывает функцию
}
procedure UnLockFunction(InterceptStruct: PInterceptStruct); stdcall;

implementation

procedure InterceptFunction(var InterceptStruct: PInterceptStruct; const OriginalFunction, NewFunction: Pointer); stdcall;
var
 CurrentProcess: THandle;
 C: DWord;
 I: Integer;
 P:Pointer;
begin
 GetMem(InterceptStruct, SizeOf(TInterceptStruct));

 InterceptStruct^.OriginalFunction := OriginalFunction;
 InterceptStruct^.NewFunction := NewFunction;

 InitializeCriticalSection(InterceptStruct^.Lock);

 InterceptStruct^.NewFunctionCode.instr_pop1 := $58; // pop eax
 InterceptStruct^.NewFunctionCode.instr_push1 := $68; // push
 InterceptStruct^.NewFunctionCode.InterceptStruct := InterceptStruct;

 InterceptStruct^.NewFunctionCode.instr_push2 := $50; // push eax

 InterceptStruct^.NewFunctionCode.instr_push3 := $68; // push
 InterceptStruct^.NewFunctionCode.address := NewFunction;
 InterceptStruct^.NewFunctionCode.instr_ret := $C3; // ret

 CurrentProcess := GetCurrentProcess;
 ReadProcessMemory(CurrentProcess, OriginalFunction, @InterceptStruct^.OldFunctionCode, SizeOf(TInterceptProc), C);
 WriteProcessMemory(CurrentProcess, OriginalFunction, @InterceptStruct^.NewFunctionCode, SizeOf(TInterceptProc), C);
end;

procedure UnInterceptFunction(var InterceptStruct: PInterceptStruct); stdcall;
var
 C: DWord;
begin
 WriteProcessMemory(GetCurrentProcess, InterceptStruct^.OriginalFunction, @InterceptStruct^.OldFunctionCode, SizeOf(TInterceptProc), C);
 DeleteCriticalSection(InterceptStruct^.Lock);
 FreeMem(InterceptStruct);
end;

procedure LockFunction(InterceptStruct: PInterceptStruct); stdcall;
var
 C: DWord;
begin
 EnterCriticalSection(InterceptStruct^.Lock);
 WriteProcessMemory(GetCurrentProcess, InterceptStruct^.OriginalFunction, @InterceptStruct^.OldFunctionCode, SizeOf(TInterceptProc), C);
end;

procedure UnLockFunction(InterceptStruct: PInterceptStruct); stdcall;
var
 C: DWord;
begin
 WriteProcessMemory(GetCurrentProcess, InterceptStruct^.OriginalFunction, @InterceptStruct^.NewFunctionCode, SizeOf(TInterceptProc), C);
 LeaveCriticalSection(InterceptStruct^.Lock);
end;

end.


Вот код который я создал.
Тут у меня самого замечание.
EnterCriticalSection и LeaveCriticalSection стоят непоназначению.
Как бы сделать, чтобы когда я восстановил функцию, то все ее вызовы из других потоков блокировались EnterCriticalSection. И эта блокировка снималась тогда, когда я восстанавливал функцию?


 
Dmitry S ©   (2008-04-29 23:23) [29]

Неужели придеться действительно через таблицу импорта делать.


 
Сергей М. ©   (2008-04-30 09:02) [30]


> Неужели придеться действительно через таблицу импорта делать.
>
>


И не только "через" нее.
Потребуется еще и модификация таблицы экспорта.

Но этот способ ничуть не хуже сплайсинга и при прочих равных условиях имеет очевидное преимущество в простоте реализации и использования.


 
Дмитрий С   (2008-04-30 10:11) [31]

*ушел делать rtfm* =)


 
Дмитрий С   (2008-05-02 20:26) [32]


> Потребуется еще и модификация таблицы экспорта.

А это зачем?

Я нашел пример в сети. Понял, что с помощью подмены таблицы импорта можно "перекрыть" функции только в своем модуле.
Т.е. если функция вызывается из другого модуля (из какой либо подключенной dll), то вызывается оригинальная функция, а не перекрытая.

Получается, что нужно заранее загружать нужную библиотеку и выполнять перекрытие уже в ней?


 
Rouse_ ©   (2008-05-03 15:20) [33]


> Получается, что нужно заранее загружать нужную библиотеку
> и выполнять перекрытие уже в ней?

Это ко всем случаям относится, если хочешь делать глобально, а не только в своем адресном пространстве...


 
Дмитрий С   (2008-05-04 10:11) [34]


> Это ко всем случаям относится, если хочешь делать глобально,
>  а не только в своем адресном пространстве...

Как же так? Вышеприведенный способ (с помощью сплайсов) не требовал этого. Тем более во время отладки я не раз прерывал программу после перезаписи нескольких байт — и ничего, система жила. И при этом у подгруженной библиотеки функции автоматически были перекрыты.


 
Rouse_ ©   (2008-05-04 10:24) [35]


> Как же так? Вышеприведенный способ (с помощью сплайсов)
> не требовал этого.

Что значит не требовал? Т.е. ты хочешь сказать, что в своем адресном пространстве ты сделал сплайсинг входной точки функции и это изменение автоматически спроецировалось на всю систему?


 
Дмитрий С   (2008-05-04 10:44) [36]


> Что значит не требовал? Т.е. ты хочешь сказать, что в своем
> адресном пространстве ты сделал сплайсинг входной точки
> функции и это изменение автоматически спроецировалось на
> всю систему?

Нет. Только на мой процесс. На все подключенные позже библиотеки (к моему процессу) перехват также распространялся.

А вот способ изменения IAT не распространяется на библиотеки вообще. Т.е. каждую библиотеку нужно хакать индивидуально.


 
Rouse_ ©   (2008-05-04 12:12) [37]


> А вот способ изменения IAT не распространяется на библиотеки
> вообще

Естественно, IAT ты же поправил у своего приложения, а не у библиотеки, тем более это актуально только для статической линковки функций, для динамической применяют правку EAT у библиотеки, хранящей функцию, и это будет справедливо для всех вызовов даной функции из любых модулей, загруженных в твое ВАП (опять же с учетом динамики, а не статики) :)


 
Дмитрий С   (2008-05-04 12:40) [38]

Вот оно что. Ясно.
Если вернуться к той же CreateFileW. Изменения в EAT придеться делать для Kernel32, а как это скажется на работу других процессов.
Честно говоря я не знаю точно сколько копий kernel32 храниться в памяти: одна на всех или по одной на каждый процесс.

ЗЫ. помоему для моей задачи я скоро начну изучать тему "как написать драйвер файловой системы" или типа того=)


 
Rouse_ ©   (2008-05-04 12:53) [39]


> Изменения в EAT придеться делать для Kernel32, а как это
> скажется на работу других процессов.

Никак не скажется, они об этом даже не узнают ибо:

> я не знаю точно сколько копий kernel32 храниться в памяти:
>  одна на всех или по одной на каждый процесс

образ маппится в ВАП твого процесса

> как написать драйвер файловой системы

а это уже из серии "из пушки по воробьям"...


 
oxffff ©   (2008-05-04 14:54) [40]


> Rouse_ ©   (04.05.08 12:53) [39]
>
> > Изменения в EAT придеться делать для Kernel32, а как это
>
> > скажется на работу других процессов.
>
> Никак не скажется, они об этом даже не узнают ибо:
>
> > я не знаю точно сколько копий kernel32 храниться в памяти:
>
> >  одна на всех или по одной на каждый процесс
>
> образ маппится в ВАП твого процесса
>
> > как написать драйвер файловой системы
>
> а это уже из серии "из пушки по воробьям"...


Ничего не мешает мапить разные ВАП на одно ФП.
А именно мапить кодовые сегменты PE образа.



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

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

Наверх




Память: 0.58 MB
Время: 0.014 c
2-1211321993
deras
2008-05-21 02:19
2008.06.15
Как в Edit сделать так, чтоб текст при вводе помещался справа?


2-1211278899
Сергей
2008-05-20 14:21
2008.06.15
Не подключается объект Screen.


15-1209748940
dr_creigan
2008-05-02 21:22
2008.06.15
Необычный вопрос =)


15-1209883938
Slider007
2008-05-04 10:52
2008.06.15
С днем рождения ! 4 мая 2008 воскресенье


2-1211216757
Stepper
2008-05-19 21:05
2008.06.15
В какую библиотек входят следующие Компоненты?