Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Assembler&Delphi!!!!!


Страницы:   1 2 3

4ert ©   (2006-12-27 02:01:00) 

И вновь здравствуйте!!! Хотелось бы узнать(теперь серьзно(вчера тупил)), немного об использовании assembler в delphi. Коротко о задаче. Пишу прогу, пожалуй опишу её предназначение(дабы гнусным вирусописателем не называли). Я по природе человек любопытный и меня всегда интересовал вопрос как же конкретно работает то, или иное приложение. И вот в последнии дни пришла в голову мысль написать софтину призванную помогать мне в этом. Как рашил реализовать: есть dll с функциями перехвата(путем подмены адреса APi функции), её мы подгружаем в указанный процесс), она меняет адреса всех нужных нам APi функций на адреса наших обработчиков, обработчики работают по одному принципу: получают всю возможную инфу о параметрах перехватываемой функции и отсылает главному приложению, та в свою очередь выводит всю информацию в Memo и ждет новых сообщений...
В принципе все просто(благо примеров в инете море!!!!), но вот возникла вовсе неожиданная прблема примеров в нете  много, но все, как правило, иллистрирует перехват одной конкретной функции, а у меня же их по плану ну штук сто наверно будет.С утановкой перехвата всё ништяк, с получением инфы тож, а проблема с реальным выполнением функции, то есть чтобы дать зараженному процессу все-таки выполнить то, что он хочет. В каждом перехватчике я возращаю память в исходное состояиние(до установки перехвата) и похорошему необходимо бы выполнить перехваченную функцию API, а затем установить перехватчик снова... Вот такие идеи. Сложность в том что никак не могу понять как реализовать запуск нужной функции API, причем функция запуска хотелос, чтобы была одна...Ибо обработчик для каждой API я то напишу(благо есть windows.pas), а вот писать ещё сто функций запуска для каждой API это уж слишком.....
Структура перехватчика:


function perexvat(<параметры>): integer; stdcall;
begin
<получаем параметры>
<отсылаем сообщение с параметрами>
<восстонавливаем память в исходное состояние>
<запускаем функцию CallApi>
<устанавливаем перехватчик>
end;


Мотив обращения к вам - вопрос реализации функции CallApi. Этот глобальный вопрос делится на два субвопроса:

1)как реализовать запуск функции зная её адрес(ну и естественно передать ей необходимые параметры)?

2)Как сделать чтобы функция была универсальна, т.е. была в состоянии запустить любую функцию API с любым количеством параметров и их типов?

По поводу первого вопроса я целый день рылся в инете(не без вашего пинка) и в собственных архивах. Я так понимаю едиственный верный вариант реализации CallApi это assembler, параметры передавать через стек(ведь мы даже не знаем сколько их может быть максимально!), а на вход функция должна принимать, я думаю(я знаком с assembler один день!!! А с Delphi всего четыри месяца!) массив параметров затем запускать цикл который будет делать нечто наподобии:


push parametrs[i]


пока не кончится массив, а затем делать собственно:


call addr


Вопрос к вам уважаемые Мастера: как вы думаете алгоритм(теоритически) продуман нормально? аль косячки имеются?
-------------------------------------------
Теперь о практике, забудем немного о необходимости универсальности функции, ибо не получается даже елементарное: Решил сделать тест, получится ли у меня запустить с помощью assembler API функцию MessageBoxA:
Делал так:


function asem(hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall;
asm
push hWnd
push lpText
push lpCaption
push uType
call addr
end;


где


addr:=@MessageBoxA;


При запуске функции появляется таки messagebox но глючит, скажу я вам, его вовсе не подетски, то вместо MB_OK(а именно эта константа передаетсяв качестве uType) появляется три кнопки с надписями "повторить" "отменить" "продолжить" то текст выравне слева, то справа, то присутствует 3D эффект то нет... Короче лажа какая-то!!!! Я подозреваю, что происходит это из-за того, что я не очищаю стек, но как же быть? Ведь если я его очищаю методом который описан у всех авторов(вставляю сразу после "call"):


add        sp,8


(Насчет восмерки не уверен), то замечательный компилятор не менее замечательного Delphi 7 enterprise выдаёт ошибку примерно следующего содержания:


Project test.exe raised exception EAccessViolation with message 'Access violation at address 0012F7C8.
Write of address 0342B299'.


Как же быть? Или поповоду очистки стека я ошибаюсь?
------------------------------------------------------
Также очень бы хотелось Уважаемые Мастера услышать ваше мнение поповоде 1) и 2), а также вцелом алгоритма......

Заранее ОГРОМНЕЙШЕЕ СПАИБО!!!!!!
(надеюсь не задолбались читаь?)


Игорь Шевченко   (2006-12-27 15:45:00) [21]


> Далее уясни, что перехват методом модификации EAT/IAT в
> АП процесса-жертвы в подавляющем большинстве случаев проще
> и эффективней, чем перехват методом модификации секции кода.
>


Не всегда. Если перехватываемая функция вызывается изнутри той же самой DLL, то при модификации таблиц импорта этот вызов будет неперехвачен, а при модификации кода перехвачен.


> делать "универсальный" перехват (любая API-ф-ция из любого
> модуля с любым соглашением и произвольными наперед неизвестными
> параметрами) попросту лишен смысла


Это точно.


Сергей М.   (2006-12-27 15:40:00) [22]


> 4ert   (27.12.06 15:02) [17]


Для начала пойми, что делать "универсальный" перехват (любая API-ф-ция из любого модуля с любым соглашением и произвольными наперед неизвестными параметрами) попросту лишен смысла.

Далее уясни, что перехват методом модификации EAT/IAT в АП процесса-жертвы в подавляющем большинстве случаев проще и эффективней, чем перехват методом модификации секции кода.

Следом вникни, что ассемблер в общем случае тут нафиг не нужен - все задуманное с успехом делается прямо в Паскаль-коде.


Elen   (2006-12-27 15:38:00) [23]


> Игорь Шевченко

Так прошу прощения. Не в регистрах а в стеке записываются указатели на параметры перед вызовом. (Давно Olly не открываю)


Игорь Шевченко   (2006-12-27 15:31:00) [24]


> Там он очень хорошо показывает какие параметры в какие регистры
> запихнуть надо для MessageBoxA.


Читай матчасть, чудо. Для MessageBox ни один параметр не "запихивается" в регистры.


Elen   (2006-12-27 15:20:00) [25]


> pusha - сохранение всех регистров процессора(правда где?
> )

Если не ошибаюсь - В стеке.


> ток тяжело для восприятия: как же можно сохранить, хрен
> знает сколько переменных в ограниченное число регистров(ведь
> данные могут быть не только типа word и DWord но и, скажем,
>  TSocket - структура совсе-е-м не маленькая а помимо неё
> еще три параметра(функция connect)

А в регистрах не вся эта инфа сохраняется а только указатели на память с этими данными, вот их и PUSHают и потом POPают.


> 1) Как же кокретно сохранить это состояние регистров?? (если
> кому не тяжело, мне бы очень помог для понимания примерчик
> запуска скажем messgeboxA с сохраненными регистрами( например
> есть функция идентичная messagebox в ней сохраняются параметры
> передаваемые ей, а потом непосредственно запускается MessgeBoxA
> с параметрами передаваемыми в индентичную функцию)?


Если так уж любопытно то это можно увидеть в отладчике OllyDebuger или иже с ним. Там он очень хорошо показывает какие параметры в какие регистры запихнуть надо для MessageBoxA. А в прочем Делфийский отладчик тоже покажет и объяснит. Делаq прогу и запускай пошагово в дебугере - все  и увидиш. ;)


evvcom   (2006-12-27 15:13:00) [26]

> [17] 4ert   (27.12.06 15:02)
> pusha - сохранение всех регистров процессора(правда где?
> ),

команды push и pop работают со стеком

> в регистрах процессора и содержаться все параметры

зависит от соглашения вызовов, обычно в том же стеке, в Дельфи принято по умолчанию соглашение до 3-х параметров в eax, edx, ecx, остальные в стеке.

> данные могут быть не только типа word и DWord но и, скажем,
> TSocket - структура совсе-е-м не маленькая

А здесь передается не сама структура, а только указатель на нее, т.е. те же 4 байта.

> Как понимает гда какой?

RTFM. Соглашения о вызовах. Calling conventions.

> к моменту передачи управления содеражания регистров не изменится
> разве?

управления куда? Если вызываемой процедуре, то для нее важны только параметры, а если назад в вызывающую, то на то и делается pusha/popa


4ert   (2006-12-27 15:02:00) [27]

Да тут скорее не в самой задачи, просто программист я почти никакой, вот и захотел опыта понабраться, цель по-моему вполне достойная, во всяком случае не голимый hello world! К тому же давно уже мечтал хоть почуть в асме подразобраться.............. Задача объемная затрагивает работу с памятью, работа с WinApi, Общение приложений и мн. др. , так, что мне кажется, вовсе неплохой курс.....
Уважаемый ors_archangel я так понимаю предложенный тобой код надо внедрять в процедуру обработчика......... Если я правильно понял, то работает он так(сорри за тупорыльство): pusha - сохранение всех регистров процессора(правда где?), в регистрах процессора и содержаться все параметры(ток тяжело для восприятия: как же можно сохранить, хрен знает сколько переменных в ограниченное число регистров(ведь данные могут быть не только типа word и DWord но и, скажем, TSocket - структура совсе-е-м не маленькая а помимо неё еще три параметра(функция connect)), потом запускаем функцию обработчик, аналогичную(в плане параметров) перехватываемой, которая читает из того места(из какого?) нужные и сохраненные нами параметры(как именно читает? Как понимает гда какой?), ну и обрабатывает их как-нить, передает управление приведенному тобой коду..... вопрос к моменту передачи управления содеражания регистров не изменится разве? их не нужно заново сохранять ?............ Твой код переписывает память(ну или можно вызвать сторонюю процедуру, написанную на pascal(как-то легче мной воспринимается)), и запускает оригинальную функцию с теми же параметрами, с которыми запускал функцию обработчика(возможно ток тогда, когда состояние регистров к моменту запуска оригинала было идентичным состоянию к моменту запуска функции обработчика(нашей)), два для меня "мутных" моменты(не могу понять):
1) Как же кокретно сохранить это состояние регистров?? (если кому не тяжело, мне бы очень помог для понимания примерчик запуска скажем messgeboxA с сохраненными регистрами( например есть функция идентичная messagebox в ней сохраняются параметры передаваемые ей, а потом непосредственно запускается MessgeBoxA с параметрами передаваемыми в индентичную функцию)?
2)Как же заставить функцию API считывать параметры именно с тех регистров какие мы сохраняли?(или этот набор стандартен для всех API? Тогда возникает вопрос: как же черт возьми функции MessageBoxA и connect могут считывать параметры из одних и тех же регистров, ведь число параметров разное, да их тип тож?(в Connect даже целые структуры!))
Заранее спасибо!!!!
(Еще раз сорри за тупорыльство, assembler язык наверно не сложно, но тяжело поддающийся пониманию(я в плане кода))


Сергей М.   (2006-12-27 08:33:00) [28]


> пришла в голову мысль написать софтину призванную помогать
> мне в этом


Кулибин)

Существующие отладчики-то чем не угодили ?


ors_archangel   (2006-12-27 08:31:00) [29]

Так, быстро сдавать сессию!!!

Я думаю, алгоритм, как в [6] вполне справляется с задачей вызова функции с любыми параметрами, как я уже писал, код довольно небольшой:

asm
 pusha
 наш обработчик-перехватчик вызова
 потом на асме нужно сделать процедуру прыжка (у тебя она там есть JMpCrProc, если не ошибаюсь.. мне идти уже пора) в памяти и прыгнуть на неё,
 процедура должна содержать код:  
    прочитать куда-нибудь область памяти начала ловушки (сохранить код ловушки)
    popa
    mov temp_var,esi
    pop esi
    call addr // здесь addr - оригинальный адрес
    push esi
    pusha
    записать обратно область памяти начала ловушки (восстановить)
    popa
    mov esi,temp_var
    ret
end


ну вот типа такого и я пошёл


4ert   (2006-12-27 07:51:00) [30]

SetHok работает  так:
определяется адрес перехватываемой функции, и первые 5 байт её начала заменяются на длинный jmp переход по адресу обработчика перехвата.
Переписывать таблицу импорта я не хочу, ибо dll свою внедряю "на ходу" процесса, а хрен его знает, может он где-то уже сохранил адрес нужной ему функции, и будет обращаться к ней минуя таблицу импорта, а значит и наш обработчик..... Бесполезно тогда все. Прога где-то работать будет, а где-то нет.........
........А чё адреса нельзя выяснять походу выполнения цикла


AdrCreateProcessA := GetProcAddress(GetModuleHandle('user32.dll'), apis[n]);


Дело в том, что я хочу ставить ловушки на конкретные функции, которые ручками занесу в массив apis, для того, чтобы сделать красивую расшифровку действий процесса, например: "Шлем данные такие-то через сокет такой-то по адресу такому-то на порт такой-то". Далее перепишу SetHook, следующим образом:


function SetHook(libname,apif: PAnsiChar; adr: pointer): TApis;
var
HKernel32, HUser32: dword;
begin
CurrProc := GetCurrentProcess;
AdrCreateProcessA := GetProcAddress(GetModuleHandle(libname),  apif);
JmpCrProcA.PuhsOp  := $68;
JmpCrProcA.PushArg := adr;    //указатель на функцию обработчика(сюда собственно и скачем)
JmpCrProcA.RetOp   := $C3;
ReadProcessMemory(CurrProc, AdrCreateProcessA, @OldCrp, SizeOf(OldCode), bw);
WriteProcessMemory(CurrProc, AdrCreateProcessA, @JmpCrProcA, SizeOf(far_jmp), Writen);
result.addr:=AdrCreateProcessA;//адрес перехватываемой функции
result.Code:=oldcrp;                //первые пять байт до того пока мы их не        
end;                                        изменили


Где :


type
OldCode = packed record
 One: dword;
 two: word;
end;

TApis=packed record
  libname: PAnsiChar; //имя windows библиотеки
  FuncApi: PAnsiChar;//имя импортируемой функции(она же перехватываемая)
  FuncHook: pointer; //указатель на процедуру обработки
  addr: pointer;//адрес импортируемой функции
  code: oldcode;//старые первые пять байт
end;
var
OldCrp: OldCode;
APis: array of TApis;


процедура которая будет ставить hook:


procedure start(i,n: integer);//i-начиная с какого элемента массива apis ставить hook, n-по какой элемент.
var
tmp: TApis;
begin
while i<n do
  begin
    tmp:=SetHook(Apis[i].libname,Apis[i].FuncApi,Apis[i].FuncHook);
    Apis[i].addr:=tmp.addr;
    Apis[i].code:=tmp.code;
    i:=i+1;
  end;
end;


  Правда не компилил, но в принципе должно работать первые три параметра в каждом элементе массива Apis придется писать вручную.
Вызывать оч. просто, если хотим выставить все ловушки, то i у нас равно нулю, а n числу элементов массива. А дальше каждая процедура обработки после отправки сообщения, перезаписи памяти и запуска реальной функции будет находить себя в массиве Apis и, соответственно присваивать переменной i свой порядковый номер в массиве, а n:=i+1. Таким образом ввсё должно быть на мази.
  Обработчики находится будут в нашей dll, которая будет находится в памяти чужого процесса(все это уже реализовано).
 А процесс зараженный.... ну... типа как бы внедрение чужеродного организма в тело(инъекция) заражает, так и выходит наша dll чужеродный организм(инфекция :) ) , а процесс тело..... Я ж сказал, что не вирус...
В смысле на чем писал?

До логов еще рано :) .......

Так вот вернемся к вопросу о функции CallApi....
Уважаемые мастера, хотелось бы еще раз напомнить, что assembler я знаю всего один день!!!!
Короче что нужно(если это вооще возможно):
Итак нет абсолютно никаких проблем вызвать функцию API есть одна серьезная проблема, как не зная, не количество параметров передаваемой функции не их тип дать этой гадкой функции то, что ей нужно для работы?
Не возможно!!! -- кажется на первый взгляд, но есть маленькая зацепка, наш обработчик(из которого эта CallApi и запускается) принимает те же самые параметры, которые необходимы для работы реальной функции API....
Может есть какие соображения по этому поводу?
Как человек абсолютно не знающий assembler могу предположить схему работы всего этого механизма: наш обработчик, приняв параметры, сохраняет их в каком-то определенном(в каком?) виде в памяти передавая указатель на эту область функции API, а также адресс функции которую нужно выполнить с этими параметрами, CallApi получает как-то(как?) эти параметры и запускает сними нужную функцию..... Эт я так думаю....
Может кто-нить подскажет конкретно как реализовать?
(Извините за обилие слов, просто проблема настолько меня заинтересовала, что я аж сессию перестал сдавать..)


ors_archangel   (2006-12-27 05:12:00) [31]

Короче, как переписывать импорт-адреса кода у тебя нет? У меня есть, но он корявый (не всегда работает), так что придётся тебе искать самому, мне просто в лом, честно :( Даже здесь на сайте где-то помойму видел. Ещё лог нужно будет как-то непотекстовому организовать, иначе он тебе весь диск, извини, засрёт (такой большой, да, однако), поэтому, например, надо все функции проидексировать и писать вместо имён индексы, причём в бинаре, текст - прочь! Правда просмотрщик логов нужен тогда, вот такая засада, вот так всегда: за всё хорошее приходится платить :)


ors_archangel   (2006-12-27 05:11:00) [32]

Короче, как переписывать импорт-адреса кода у тебя нет? У меня есть, но он корявый (не всегда работает), так что придётся тебе искать самому, мне просто в лом, честно :( Даже здесь на сайте где-то помойму видел. Ещё лог нужно будет как-то непотекстовому организовать, иначе он тебе весь диск, извини, засрёт (такой большой, да, однако), поэтому, например, надо все функции проидексировать и писать вместо имён индексы, причём в бинаре, текст - прочь! Правда просмотрщик логов нужен тогда, вот такая засада, вот так всегда: за всё хорошее приходится платить :)


ors_archangel   (2006-12-27 05:06:00) [33]

Думаю, всё довольно быстро будет, если SetHook получит уже подготовленные данные, то чё он будет делать даже не знаю, переписывать, наверно, адреса в импорте процесса? Вобщем так предлагаю: сначала нужно узнать все адреса/имена импортируемых процессом функций, затем нужно выделить себе в целевом процессе место под ловушки (VirtualAllocEx идеально подойдёт), наклепать их для всех функций, потом проблема будет, где обработчик хранить - в чужом аль в своём процессе, если в чужом, то к нему этому процессу легко добраться будет, а если ж мы во свояси хотим, то между процессами, значит, какую-то коммуникацию придётся налаживать, что под Виндой не очень рентабельно может получиться. Вот… дальше переписываем адреса в импорт-таблице, чтобы наши ловушки ловили!!!

А почему "заражённый" процесс? Мы, чё, вирусы пишем-с? Ну да по фигу уже, что писать в такую рань!

Что же думаешь? А ты на чём писал? (так, интересно)


ors_archangel   (2006-12-27 05:00:00) [34]

Ну, во-первых, про Read/WritePM я загнул конечно, меня уж подклинило, видно :(
Но, как же ты тестишь-то, кода-то нет? (всего)


4ert   (2006-12-27 03:58:00) [35]

Блин, чё я косячу постоянно?..... естественно в цикле увеличиваем n на единицу(вообще если так, то наверно надо трехмерный массив пердавать, где будет функция API,  имя библиотеки, и указатель на функцию обработчик)


4ert   (2006-12-27 03:55:00) [36]

Блин, спасибо!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!
Такого helpa нигде не найдешь!!!!
Прям сщас тестить начинаю!!!!!!!!
Да небольшой вопрос еще(в принципе мож и сам догоню, но от Мастеров как то надежней):
Как при старте моей dll поставить такую ловушку на все скажем функции имена которых лежат в массиве, скажем apis?

Как считаете, если сделать SetHook функцией возращающей AdrCreateProcessA  и вызывать её, ну, скажем, если у нас будет 100 функций, то так(просто, что сразу в голову пришло):


n:=0;
while n<100 do
begin
addrs[n]:=SetHooK(apis[n]);
end;


Как считаете прокатит?
Еще беспокоит вопрос чё с зараженным процессом будет? Вынесет нагрузку? :)


ors_archangel   (2006-12-27 03:26:00) [37]

Да..... (по поводу [5])
Понимаш, здесь мы пишем int 3 (аппаратное прерывание) прям в код dll, откуда вызов должен быть, мне больше по душе вариант, когда мы для каждой функции создаем wrapper, тогда просто он вызывается, делает что там положено (что-то левое вызывает), потом сразу управление, например, MessageBox передаёт.
Вариант с Read/WriteProcessMemory конечно требует восстановления постоянно, но вообще, эти функции тебе не нужны, потому что ты ведь первый параметр указываешь CurrProc - current process - текущий процесс, т.е. все операции происходят в памяти твоегопроцесса, значит много лучше писать непосредсвенно - mov, movs - в таком духе, быстрее будет уж точно.
Если подробней о коде [3]

  pusha; // сохраняем все регистры процессора
  mov eax,beforeParam // передаём параметр - идентификатор перехваченной функции, видимо, здесь нужно ещё будет как-то параметры передать, ну а в принципи сам обработчким может немного стека взять, но вообще, не знаю, что ты потом с этим всем будешь делать?
  call before // вызываем какой-то обработчик перед вызовом перехваченной функции
  popa; // восстанавливаем все регистры после обработчка
  mov save_edi,edi // запоминаем регистр edi - мы щас его менять будем
  mov save_esi,esi // запоминаем регистр esi - мы щас его менять будем
  pop esi // сохраняем оригинальный адрес возврата
  mov edi,addr // адрес оригинальной функции
  call edi // вызов, собственно, перехваченной функции
  push esi // восстанавливаем оригинальный адрес возврата
  mov edi,save_edi // восстанавливаем регистры, которые юзали выше
  mov esi,save_esi
 // ну дальше, если нужен пост-обработчик, например, узнать, что функция вернула
  pusha
  mov eax,afterParam
  call after
  popa
  ret


ors_archangel   (2006-12-27 03:13:00) [38]

Чтобы функция была универсальная тебе нужно сохранить все регистры (pusha), вызвать свой обработчик, потом вернуть все регистры на место (popa), потом сделать pop esi; call addr; push esi - это вызовет нужную функцию с теми параметрами, которые ей передали, нам не надо делать push p1; push p2 - потому что это уже было сделано calleroм этой функции (если ей вообще нужны параметры), pop esi-push esi нужно, так как call, который был сделан на оригинальную функцию сунул (как ему и положено) адрес возврата (4 байта) в стек, т.о. если мы сразу сделаем call addr, то этот call тоже сунет адрес возврата, и мы получим два адреса возврата в стеке, где должен был быть один - предпоследний здесь лишний, т.к. файтически будет занимать место одного из параметров, поэтому мы его предварительно извлекаем из стека (pop esi), а после вызова обратно кладём - push esi, тогда наш ret (который скрывается у тебя под end), передаст управление в нужную точку, понимаешь? Вопросы, дополнения, аплодисменты? Если прогу доделаешь, то интересно будет глянуть, не каждый день получаешь гигабайтовый лог, чего там какая-то прога вызывет!


4ert   (2006-12-27 03:04:00) [39]

Сорри вновь.... Не заметил второе сообшение :(.... сплю уже. Идея неплохая наверное, "наверное" потому, что я ж один день об assembler знаю, и как уважающий себя чайник вовсе не втыкаю как приведенный код работает, если вас не затруднит не могли бы вы хоть немного поподробней о коде....
А востанавливать обработчик надо затем, что .... короче вот код своял на перехват MessageBoxA:


function HMessageBox(hWnd: HWND; lpText, lpCaption: PChar; uType: UINT): Integer; stdcall;
var
  dat: TCopyDataStruct;
  str,tmp: string;
begin
   with dat do
  begin
    dwData := 0;
    tmp:=lptext;
    cbData := StrLen(Pchar(tmp))+1;
    lpData :=PChar(tmp);
  end;
 sendmessage(findwindow(nil,'HPION'),WM_M,666,longint(@dat));
WriteProcessMemory(CurrProc, AdrCreateProcessA, @OldCrp, SizeOf(far_jmp), Writen);
asm                             //Вот в этом месте вместо assemblera хотелось        
push 0                         //вставить запуск мифической универсальной
push lpText                  //функции запуска API.
push lpCaption
push MB_OK
call AdrCreateProcessA
call hookaddr
end;
end;


hookaddr - указатель на функцию установки ловушки.
А вот собственно ее код:


Procedure SetHook;
var
HKernel32, HUser32: dword;
begin
CurrProc := GetCurrentProcess;
AdrCreateProcessA := GetProcAddress(GetModuleHandle('user32.dll'),  'MessageBoxA');
JmpCrProcA.PuhsOp  := $68;
JmpCrProcA.PushArg := @hMessageBox;
JmpCrProcA.RetOp   := $C3;
ReadProcessMemory(CurrProc, AdrCreateProcessA, @OldCrp, SizeOf(OldCode), bw);
WriteProcessMemory(CurrProc, AdrCreateProcessA, @JmpCrProcA, SizeOf(far_jmp), Writen);
end;


Помоему это короче будет, чем объяснять зачем...


4ert   (2006-12-27 02:54:00) [40]

Не, все я правильно сделал :) уже разобрался! ..... Просто переменная hwnd у меня была равна handl'у формы, а это как пишут многие(и как я убедился только что), оказывается в корне неверно первый параметр должен равнятся всегда нулю, как только сказанное выше было сделанно, все стало на свои места .... Спасибо, что потревожили из-за меня - чайника справку наверно уже спящего Delphi....

А можете дать совет по поводу организации "универсальности" этой функции(callapi) в моей dll? А то чего-то на ум ничего не идет..... да и приблизительных примеров вообще не видел...


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо