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

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

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 26.12.2011, 00:56   #1
nls
Пользователь
 
Регистрация: 25.12.2011
Сообщений: 20
По умолчанию Проблема с инжектом.

Дело в том, что всю сознательную жизнь писал на С/WinAPI. Не знаю какой чёрт дернул браться писать на Delphi, но тем не менее этот проект лично для меня и отдельной части людей очень важен, поэтому я очень прошу вашей помощи.

В общем, суть такая:
Программа в цикле ждет создание процесса notepad.exe, и, как только процесс с этим именем создается, проводит инжект библиотеки в этот процесс и завершает свою работу.

Как я это сделал:
В событиях главной формы, в обработчике сообщения FormCreate(), создаю свой поток. В функции потока - бесконечный цикл, проверяющий каждые пол секунды существование процесса с нужным именем, путем проверки идентификатора на 0.

Вот код функции потока:
Код:
procedure AutoInject;
var
   pID: cardinal;
begin
    while True do
    begin
        pID := GetProcessID('notepad.exe');

        if pID <> 0 then
            begin
            InjectDll(pID, 'C:\1.dll');
            Sleep(5000);
            ExitProcess(0)
            end
            else
        Sleep(500);
    end
end;
Вообще, весь код инжекта взят полностью из этой статьи:
http://www.progamercity.net/delphi/1...injection.html.

А теперь суть проблемы:

Сам инжект отлично работает, и все было бы хорошо, если бы при запуске программы в режиме отладки иногда не вываливались сообщения об ошибках. Вот некоторые из них:
http://s017.radikal.ru/i404/1112/ab/7e7780617b0a.bmp
http://s017.radikal.ru/i425/1112/0d/dfc79e15fd7c.bmp
http://s017.radikal.ru/i417/1112/cd/38056824a8fb.bmp
http://s19.radikal.ru/i192/1112/4c/7a4e1a94b38b.bmp
http://s52.radikal.ru/i137/1112/16/45b51ce3bbfb.bmp

Я вообще не понимаю логики этих сообщений, т.к. сообщения каждый раз разного содержания, и понять в чем причина их возникновения для меня нереально. Опытным путем было установлено, что проблема в строчке, где получается идентификатор процесса (pID := GetProcessID('notepad.exe')). Пробовал найти похожие функции такого же назначения, результат тот же самый. Так же попробовал создать новый чистый проект с одной формой, и точно таким же способом провести инжект библиотеки. Самое интересное что в этом случае работает все идеально и без ошибок. Видимо проблема в коде проекта, но честно говоря нет ни опыта, ни знаний как искать и исправлять подобного рода ошибки.

В чем вообще может быть причина таких ошибок? В какую сторону смотреть?
nls вне форума Ответить с цитированием
Старый 26.12.2011, 01:11   #2
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

я бы сказал, что проблема в ExitProcess(). Не думаю, что это лучший способ завешить вцл приложение. Почему бы просто не выйти из потока, послав предварительно главной форме WM_CLOSE?
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 26.12.2011, 01:35   #3
nls
Пользователь
 
Регистрация: 25.12.2011
Сообщений: 20
По умолчанию

Цитата:
Сообщение от veniside Посмотреть сообщение
я бы сказал, что проблема в ExitProcess(). Не думаю, что это лучший способ завешить вцл приложение. Почему бы просто не выйти из потока, послав предварительно главной форме WM_CLOSE?
Спасибо что откликнулись. Я на самом деле не знаю, как в Delphi отправлять виндовые сообщения форме. Попробовал через MainForm.Close. Ошибки те же самые. К тому же необязательно завершать целевую программу, закомментировал вызов ExitProcess() и через break вышел из цикла - все та же проблема.
nls вне форума Ответить с цитированием
Старый 26.12.2011, 01:44   #4
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

> как в Delphi отправлять виндовые сообщения форме

как и везде:

Код:
PostMessage(Form1.Handle, ....);
> закомментировал вызов ExitProcess()

хм, тогда проблема в InjectDll(), больше там глючить вроде нечему. Ну или вы где-то из потока цепляете вызовы к вцл, в этом случае могут рандомные ошибки выскакивать. Откуда вызывается AutoInject()?
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 26.12.2011, 01:59   #5
nls
Пользователь
 
Регистрация: 25.12.2011
Сообщений: 20
По умолчанию

Цитата:
Сообщение от veniside Посмотреть сообщение
хм, тогда проблема в InjectDll(), больше там глючить вроде нечему.
Но ведь в новом проекте все отлично работает.

Цитата:
Сообщение от veniside Посмотреть сообщение
Ну или вы где-то из потока цепляете вызовы к вцл, в этом случае могут рандомные ошибки выскакивать.
Действительно рэндомные ошибки. Без понятия где и что там цепляю. Функцию AutoInject я привел полностью.

Цитата:
Сообщение от veniside Посмотреть сообщение
Откуда вызывается AutoInject()?
Если я правильно понял вопрос, то поток создаю вот этой функцией:
HThread:=CreateThread (nil, 0, @ AutoInject, nil, 0, ThreadID);
Функция вызывается в конце обработчика OnCreate() главной формы.
nls вне форума Ответить с цитированием
Старый 26.12.2011, 02:13   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Если я правильно понял вопрос, то поток создаю вот этой функцией:
а теперь посмотрите какой должна быть функция для CreateThread.
так что не удивительно.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 26.12.2011, 02:19   #7
nls
Пользователь
 
Регистрация: 25.12.2011
Сообщений: 20
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
а теперь посмотрите какой должна быть функция для CreateThread.
так что не удивительно.
Я совсем не опытен в Delphi.

Иф-ю про потоки брал вот отсюда:
http://*************/readarticle.php?article_id=1998.

Пепел Феникса, наведите, пожалуйста, на путь истинный. Где и что я должен подправить?

ADD:
Вообще нет принципиальной разницы. Сейчас попробовал создать поток через компонент TThread, и так же обломался. Зато в новом проекте с одной пустой формой всё отлично. Неужели всё по новой переписывать?

Последний раз редактировалось nls; 26.12.2011 в 02:46.
nls вне форума Ответить с цитированием
Старый 26.12.2011, 03:18   #8
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Так Дельфи тут не при чём, прототип ThreadProc везде одинаковый:

Код:
DWORD WINAPI ThreadProc(
  __in  LPVOID lpParameter
);
На Дельфи это выглядит примерно так:

Код:
function ThreadProc(
   lpParameter: LPVOID
): DWORD; stdcall;
> Функция вызывается в конце обработчика OnCreate() главной формы.

это не слишком удачное место, имхо. Судя по обилию ошибок EReadError, остальные формы ещё даже не успевают загрузиться. Я бы перенёс это в OnShow() (с проверкой того, что вызов проходит первый раз, т.к. OnShow() может быть вызвано несколько раз).

> в новом проекте с одной пустой формой всё отлично

есть лёгкое подозрение, что это у вас не единственный поток.
Или же используются какие-то странные компоненты.

Я бы сделал так: комментировал бы код в старом проекте, вплоть до того, пока он не станет похож на пустой проект с одной формой. По-идее в этот момент он не будет глючить, после чего начинаем открывать код обратно, пока не пойдут старые ошибки.

Или же навешивать на пустой проект все те формы и компоненты, которые есть в исходном, пока не начнутся схожие проблемы. Одну и ту же форму можно подключать к нескольким проектам, так что особых сложностей быть не должно.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 26.12.2011, 07:49   #9
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Вот на этом скрине можно было нажать на кнопочку Break и отладчик ткнёт на строку с ошибкой.

А окно Call Stack (View/Debug Windows/Call Stack) при этом показало бы, как мы туда попали.

Это либо повреждение файлов, либо проблемы с отсутствием синхронизации потоков. Из вторичных потоков к VCL (формам и компонентам) обращаться нельзя.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 26.12.2011, 07:52   #10
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
CreateThread
Эээ... ещё товарищ Рихтер за такое по рукам давал. Нужно либо использовать функции языка (BeginThread), либо самому делать то, то делают языковые обёртки (IsMultiThreaded).
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с рамами/Проблема с ЖД DRAGGER Компьютерное железо 6 04.01.2009 23:37