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

Вниз

Перехват функций Dll   Найти похожие ветки 

 
DinoRay   (2005-08-10 22:11) [0]

Есть dll. Нужно перехватывать вызовы функций этой длл всеми приложениями использующими ее.
Я так думаю алгоритм такой.
1. Перехватить createprocess
2. Проверить загружена эта длл
3. Если загружена внедриться в процесс
4. Переписать вызовы функций на себя.

Отсюда вопрос есть где на Делфях пример?
Эксперементировал с MessageBox работает нормально а вот с не виндовой длл не хочет


 
NikotiN ©   (2005-08-10 23:15) [1]

если смог перехватить MessageBox, то перехвати createprocess или loadlibrary.


 
Alexander Panov ©   (2005-08-11 01:08) [2]

Подменить библиотеку своей.


 
Digitman ©   (2005-08-11 08:17) [3]

в частном случае (для приложений, обращающихся в ходе работы к оконному механизму Windows) достаточно установить глоб.хук на создание окна - как только то или иное приложение вызовет CreateWindow[Ex], в АП его процесса система автоматически внедрит образ экз-ра хук-библиотеки.

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

и в том и ином случае внедренная тем или иным образом библиотека в ходе иниц-ции как раз и выполняет перехват нужных элементов IAT и EAT


 
KyberTECH   (2005-08-19 15:56) [4]

Ктото подскажет мне как можно в определённой DLL узнать какая функция выполняется в данный момент.

Ответ прошу на kybertech@mail.ru


 
Digitman ©   (2005-08-19 16:09) [5]


> какая функция выполняется в данный момент


какая вызвана, та и выполняется


 
Игорь Шевченко ©   (2005-08-19 16:12) [6]


> Ответ прошу на kybertech@mail.ru


Это неуважение к отвечающим


 
alpet ©   (2005-08-19 16:39) [7]

Игорь Шевченко ©   (19.08.05 16:12) [6]
Видать спаму ему мало.


 
alpet ©   (2005-08-19 16:48) [8]

Копать нужно в строну SuspendThread, GetThreadContext, ReadProcessMemory + получить список всех функций в DLL.


 
Игорь Шевченко ©   (2005-08-19 16:56) [9]

alpet ©   (19.08.05 16:48) [8]

Зацем ? Не проще взять DLL с диска и проанализировать ?


 
alpet ©   (2005-08-19 17:02) [10]

Игорь Шевченко ©   (19.08.05 16:56) [9]

Как с диска? В текущий момент в DLL Функция может выполнятся любая, и идентифицировать ее можно разве что по EIP. Что значит придется считывать контест, стек (от esp и выше, для его послед. развертки до вызова экспортируемой функции).  Это только по сабжу [4].


 
Defunct ©   (2005-08-20 04:25) [11]

alpet ©   (19.08.05 17:02) [10]

> и идентифицировать ее можно разве что по EIP

как ты себе представляешь такую идентификацию?

проверить какие функции сейчас выполняются можно в том случае, если поставить инкремент счетчика вызовов на входе в функцию и декремент на выходе.

> Что значит придется считывать контест, стек (от esp и выше, для его послед. развертки до вызова экспортируемой функции

и что это даст?
Пример который развеивает подобного рода идеи:

function zzzz;
asm
 sub esp, 3
  ...
  ...      ; <-- в этом месте развертка стека кроме гемороя ничего больше не даст        
  ...
 add esp, 3
end;


 
n0name   (2005-08-20 08:51) [12]

>>Defunct ©   (20.08.05 04:25) [11]
Считать EIP и посмотреть в таблице экспорта к какой функции относиться этот адрес. Но возможно то, что EIP указывает на общую функцию которая вызывается не из одной экспортируемой, а их нескольких.


 
iskatel ©   (2005-08-20 11:04) [13]

Перехват API-функций в Windows NT/2000/XP

Автор: Тихомиров В.А.
Зав.кафедрой математического обеспечения и применения ЭВМ
Комсомольского-на-Амуре государственного технического университета
К.т.н., доцент, практикующий программист
kmopevm@knastu.ru
Что такое «перехват API-функций»

Метод 1. Перехват API непосредственной записью в код системной функции.
Метод 2. Перехват API через таблицу импорта.

Внедрение кода в чужой процесс в Windows NT

Внедрение 1
Внедрение 2

Как отлаживать такие выкрутасы

Отладка кода загрузчика
Отладка функций, выполняющихся при старте DLL
Отладка функций – двойников, получающих управление при вызове перехваченных API функций

Тестирование

Заключение

Системные программисты, работавшие под MS DOS, прекрасно помнят технологию перехвата системных прерываний, позволявшую брать под контроль практически все процессы, проходившие в любимой операционной системе.

С переходом на Windows использование системных ресурсов программистами в большом объеме стало осуществляться через функции API, и у многих «сиспрогов» стал возникать вопрос: «существуют ли в Windows технологии перехватов этих системных функций?» Особый интерес это вызывает применительно к высокозащищенным ОС, выполненным на ядре NT. Данная статья подробнейшим образом, с действующими примерами покажет практическую реализацию такой технологии (предполагается, что читатель знаком с принципами системного программирования в Windows и умеет применять в своей работе Visual C++).

Что такое «перехват API-функций»
Перехват системной функции API заключается в изменении некоторого адреса в памяти процесса или некоторого кода в теле функции таким образом, чтобы при вызове этой самой API-функции управление передавалось не ей, а вашей функции, подменяющей системную. Эта функция, работая вместо системной, выполняет какие-то запланированные вами действия, и затем, в зависимости от вашего желания, либо вызывает оригинальную функцию, либо не вызывает ее вообще. Перехват функций является очень полезным средством в том случае, если вы хотите отследить, изменить или заблокировать некоторые конкретные действия приложения.

Перехват функций чужого процесса удобнее всего осуществлять внедрением собственной DLL с функцией-двойником в адресное пространство того процесса, контроль над функциями API которого вы хотите установить. При написании двойников функций следует особое внимание обратить на соглашения о вызовах функций __cdecl и __stdcall. В __cdecl функциях подразумевается, что параметры кладутся в стек справа налево, и вызывающая функция очищает стек от аргументов. В __stdcall функциях подразумевается, что параметры кладутся в стек справа налево, но стек от аргументов очищает вызываемая функция. Кроме того, следует учитывать, что в Windows API многие функции встречается в 2-х экземплярах: ANSI и UNICODE. Первые обозначаются суффиксом A: например MessageBoxA, вторые – суффиксом W – например MessageBoxW.

Рассмотрим два метода перехвата API функций:

Непосредственная запись в код функции.
Подмена адреса функции в таблице импорта.
Метод 1. Перехват API непосредственной записью в код системной функции.
Прием заключается в том, чтобы в начало перехватываемой функции записать команду jmp ваша_функция_двойник или эквивалентную ей. Затираемые байты желательно где-нибудь сохранить. После вызова исправленной функции приложением управление будет передано вашей функции. Она должна корректно обработать стек, то есть извлечь переданные ей параметры и произвести необходимые вам действия. Затем, если вы собираетесь вызывать оригинальную функцию, необходимо восстановить затертые байты в начале оригинальной функции. Вызвать ее, передав ей все необходимые параметры. После возврата из оригинальной функции, необходимо снова в начало кода функции записать команду перехода на вашу функцию. Вернуть управление вызвавшей программе.

Достоинство данного метода состоит в том, что он позволяет перехватывать любые функции, а не только те, которые указаны в таблице импорта.

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

Разберем пример программы (в виде DLL-файла), перехватывающей функцию MessageBoxA методом 1.

Для работы нам потребуются следующие заголовочные файлы:

#include "stdafx.h"
#include "intercpt.h"



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

push xxxxxxxx
ret



где хххххххх – это адрес функции-двойника. В результате структура, которая будет хранить нужный код перехода, выглядит так:

struct jmp_far
{
 BYTE instr_push;  //здесь будет код инструкции push
 DWORD arg;         //аргумент push
 BYTE  instr_ret;    //здесь будет код инструкции ret
};



Зададим нужные переменные:

BYTE old[6]; //область для хранения 6-ти затираемых байт начала функции
DWORD adr_MessageBoxA //будущий адрес оригинальной функции
DWORD written; //вспомогательная переменная
jmp_far jump; //здесь будет машинный код инструкции перехода



Главная функция DLL будет выглядеть следующим образом:

BOOL APIENTRY DllMain( HANDLE hModule,  DWORD  ul_reason_for_call,
                      LPVOID lpReserved )
{
// Если система подключает DLL к какому-либо процессу,
// она сначала вызовет главную функцию DLL с параметром
// DLL_PROCESS_ATTACH, на что мы сразу вызовем нашу функцию
// InterceptFunctions, которая произведет подмену стандартной API функции
// MessageBoxA нашей функцией Intercept_MessageBoxA (см. ниже)

 if(ul_reason_for_call = = DLL_PROCESS_ATTACH )
 {
   InterceptFunctions();
 }
 return TRUE;
}



Функция, которую мы только что вызвали и которая выполняет основную хитрость, перехват API перезаписью начальных байт стандартной функции, выглядит следующим образом:

void InterceptFunctions(void)
{
 DWORD op;
 //сначала получим абсолютный адрес функции для перехвата
 adr_MessageBoxA = (DWORD)GetProcAddress(GetModuleHandle("user32.dll"),
                   "MessageBoxA");
 if(adr_MessageBoxA == 0)
 {
   MessageBox(NULL, "Can`t get adr_MessageBoxA, "Error!", 0);
   return;
 }

 // Зададим машинный код инструкции перехода, который затем впишем
 // в начало полученного адреса:
 jump.instr_push = 0x68;
 jump.arg = (DWORD)&Intercept_MessageBoxA;
 jump.instr_ret = 0xC3;

 //Прочитаем и сохраним первые оригинальные 6 байт стандартной API функции
 ReadProcessMemory(GetCurrentProcess(),(void*) adr_MessageBoxA,
                   (void*)&old, 6, &written);

//Запишем команду перехода на нашу функцию поверх этих 6-ти байт
WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA,
    (void*)&jump, sizeof(jmp_far), &written);
}


 
iskatel ©   (2005-08-20 11:08) [14]

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

//данное определение аналогично __srtdcall
BOOL WINAPI Intercept_MessageBoxA(HWND hwnd, char *text, char *hdr, UINT utype)
{
 //Сначала восстанавливаем 6 первых байт функции. Это не обязательное
 // действие, просто мы решили подшутить над пользователем, и все
 // сообщения функции MessageBoxA переделать на свои, поэтому нам придется
 // вызвать оригинальную функцию, а для этого следует восстановить ее адрес:
 WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA,
                    (void*)&old, 6, &written);

 //Здесь вы можете порезвиться от души и выполнить любые, пришедшие вам
 // в голову действия. Мы просто заменили сообщение функции на свое:
 char *str = "Hi From MessageBOX!!!!";

 //Вызываем оригинальную функцию через указатель
 ((BOOL (__stdcall*)(HWND, char*, char*, UINT))adr_MessageBoxA)(hwnd,
            str, hdr, utype);

 //Снова заменяем  6 байт функции на команду перехода на нашу функцию
 WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA,
                    (void*)&jump, 6,&written);
 return TRUE;
}



Если откомпилировать этот код как DLL, то получим файл, который в дальнейшем (см.ниже) следует внедрить в процесс, в котором мы хотим перехватить API MessageBoxA.

Метод 2. Перехват API через таблицу импорта.
Прием заключается в замене адреса функции в таблице импорта на адрес функции-двойника. Для понимания данного метода потребуется знание формата PE исполняемых файлов Windows. Как известно, большинство приложений вызывает функции из dll через таблицу импорта, представляющую собой после загрузки exe файла в память списки адресов функций, импортируемых из различных Dll. Откомпилированный вызов функции через таблицу импорта выглядит следующим образом:

Call dword ptr[address_of_function]



или что-то наподобие. Здесь address_of_function – адрес в таблице импорта, по которому находится адрес вызываемой функции. (Тем, кто не знаком со структурой PE заголовка EXE файла, рекомендуем заглянуть в Интернет за соответствующей информацией.)

При перехвате API через таблицу импорта надо:

найти в таблице импорта элемент IMAGE_IMPORT_DESCRIPTOR, соответствующий той DLL, из которой импортирована функция;
узнать адрес перехватываемой функции при помощи GetProcAddress;
перебирая элементы массива, на который указывает поле FirstThunk, найти адрес перехватываемой функции;
запомнить этот адрес где-нибудь и записать на его место адрес функции-двойника.
Теперь при вызове подмененной функции вначале будет вызываться функция-двойник. После этого она может вызвать (или не вызывать) оригинальную функцию.

Достоинство данного метода в том, что он будет корректно работать в многопоточном приложении, когда несколько потоков одновременно вызывают подмененную функцию. Так же данный метод будет работать в ОС WINDOWS 9.x.

Недостаток – не все функции вызываются через таблицу импорта.

Ниже приведен пример программы, аналогичной приведенной выше, но использующей второй метод перехвата функции:

DWORD adr_MessageBoxA;

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call,
                     LPVOID lpReserved)
{
 if(ul_reason_for_call == DLL_PROCESS_ATTACH)
   InterceptFunctions();
 return TRUE;
}

// Эта функция ищет в таблице импорта - .idata нужный адрес и меняет на
// адрес процедуры-двойника
void InterceptFunctions(void)
{
 // Начало отображения в памяти процесса
 BYTE *pimage = (BYTE*)GetModuleHandle(NULL);
 BYTE *pidata;
 // Стандартные структуры описания PE заголовка
 IMAGE_DOS_HEADER *idh;
 IMAGE_OPTIONAL_HEADER *ioh;
 IMAGE_SECTION_HEADER *ish;
 IMAGE_IMPORT_DESCRIPTOR *iid;
 DWORD *isd;  //image_thunk_data dword

 // Получаем указатели на стандартные структуры данных PE заголовка
 idh = (IMAGE_DOS_HEADER*)pimage;
 ioh = (IMAGE_OPTIONAL_HEADER*)(pimage + idh->e_lfanew
                                + 4 + sizeof(IMAGE_FILE_HEADER));
 ish = (IMAGE_SECTION_HEADER*)((BYTE*)ioh + sizeof(IMAGE_OPTIONAL_HEADER));
 //если не обнаружен магический код, то у этой программы нет PE заголовка
 if (idh->e_magic != 0x5A4D)
 {
   MessageBox(NULL, "Not exe hdr", "Error!", 0);
   return;
 }

 //ищем секцию .idata
 for(int i=0; i<16; i++)
   if(strcmp((char*)((ish+ i)->Name) , ".idata") == 0) break;
 if(i==16)
 {
   MessageBox(NULL, "Unable to find .idata section", "Error!", 0);
   return;
 }

 // Получаем адрес секции .idata(первого элемента IMAGE_IMPORT_DESCRIPTOR)
 iid = (IMAGE_IMPORT_DESCRIPTOR*)(pimage + (ish +i)->VirtualAddress );
 
 // Получаем абсолютный адрес функции для перехвата
 adr_MessageBoxA = (DWORD)GetProcAddress(
                       GetModuleHandle("user32.dll"), "MessageBoxA");
 if(adr_MessageBoxA == 0)
 {
   MessageBox(NULL, "Can`t get addr_MessageBoxA", "Error!", 0);
   return;
 }

 // В таблице импорта ищем соответствующий элемент для
 // библиотеки user32.dll
 while(iid->Name)  //до тех пор пока поле структуры не содержит 0
 {
   if(strcmp((char*)(pimage + iid->Name), "USER32.dll") ==0 ) break;
   iid++;
 }

 // Ищем в IMAGE_THUNK_DATA нужный адрес
 isd = (DWORD*)(pimage + iid->FirstThunk);
 while(*isd!=adr_MessageBoxA && *isd!=0)  isd++;
 if(*isd == 0)
 {
   MessageBox(NULL, "adr_MessageBoxA not found in .idata", "Error!", 0);
   return;
 }
 
 // Заменяем адрес на свою функцию
 
 DWORD buf =  (DWORD)&Intercept_MessageBoxA;
 DWORD op;
 
 // Обычно страницы в этой области недоступны для записи
 // поэтому принудительно разрешаем запись
 VirtualProtect((void*)(isd),4,PAGE_READWRITE, &op);
 
 // Пишем новый адрес
 WriteProcessMemory(GetCurrentProcess(), (void*)(isd),
                   (void*)&buf,4,&written);
 //восстанавливаем первоначальную защиту области по записи
 VirtualProtect((void*)(isd),4,op, &op);
 //если записать не удалось – увы, все пошло прахом…
 if(written!=4)
 {
   MessageBox(NULL, "Unable rewrite address", "Error!", 0);
   return;
 }
}


 
iskatel ©   (2005-08-20 11:08) [15]

А вот так выглядит подстановочная функция:

BOOL WINAPI Intercept_MessageBoxA(HWND hwnd, char *text,
                                 char *hdr, UINT utype)
{
 //здесь вы выполняете любые свои действия
 char *str = "Hi From MessageBOX!!!!";
 // вызываем оригинальную функцию через указатель
 ((BOOL (__stdcall*)(HWND, char*, char*, UINT))adr_MessageBoxA)(hwnd,
           str, hdr, utype);
 return TRUE;
}



Внедрение кода в чужой процесс в Windows NT
Теперь осталось показать, как вышеописанные DLL можно внедрить в процесс, избранный в качестве жертвы эксперимента. (Нелишне напомнить, что для нашего примера процесс-жертва должен иметь окна со стандартными сообщениями MessageBox ).

Внедрить код – значит, записать некоторую программу в чужой процесс и исполнить ее от имени этого процесса. Таким образом, внедренный код становится частью процесса и получает доступ ко всем ресурсам, которыми обладает процесс. В отличие от DOS, семейство ОС Windows (на ядре NT) – операционные системы с разделяемой памятью, т.е каждое приложение выполняется в своем адресном пространстве, не пересекающемся с другими, и не имеет непосредственного доступа к памяти чужого приложения. Таким образом, внедрение кода является нетривиальной задачей. Существует несколько способов внедрить свой код:

1. «Вручную».

2. При помощи хуков.

Внедрение 1
Рассмотрим наиболее эффективный, на наш взгляд, способ внедрения – первый. Он заключается в записи короткого участка машинного кода в память процесса, который должен присоединить DLL к этому процессу, запустить ее код, после чего Dll сможет выполнять любые действия от имени данного процесса. В принципе можно и не присоединять DLL, а реализовать нужные действия во внедряемом машинном коде, но это будет слишком трудоемкой задачей, поскольку все смещения для данных потеряют смысл, и вы не сможете корректно обратиться к ним, не настроив соответствующим образом смещения (морока :( ).

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

PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION.

ПРЕДУПРЕЖДЕНИЕ

При реализации данного метода необходимо указать компилятору выравнивать структуры ПОБАЙТОВО. Иначе структура с машинным кодом будет содержать совершенно не тот код, что был запланирован.


Общая схема внедрения:

Открыть процесс (OpenProcess).
Выделить в нем память (VirtualAllocEx – доступно только для WinNT).
Записать внедряемый код в эту память (WriteProcessMemory).
Исполнить его(CreateRemoteThread).
Внедряемый машинный код должен (по нашему сценарию) произвести такие действия:

call LoadLibrary – вызвать функцию LoadLibrary из kernel32.dll для загрузки присоединяемой библиотеки (одной из разбиравшихся выше).
Call ExitThread – вызвать функцию ExitThread из kernel32.dll для корректного завершения данного потока.
В WinNT стартовый адрес отображения системных DLL (user32, kernel32 и т. д.) один и тот же для всех приложений. Это означает, что адрес некоторой функции из системной DLL в одном приложении будет актуален и в другом приложении. То есть точки входа функций системных DLL всегда одни и те же.

Ниже приведен пример процедуры, внедряющей dll с заданным именем в процесс с заданным PID (идентификатором процесса) (их можно наблюдать в закладке «процессы» диспетчера задач или получить с помощью стандартных API-функций).

//структура описывает поля, в которых содержится код внедрения
struct INJECTORCODE
{
 BYTE  instr_push_loadlibrary_arg; //инструкция push
 DWORD loadlibrary_arg;            //аргумент push  

 WORD  instr_call_loadlibrary;     //инструкция call []  
 DWORD adr_from_call_loadlibrary;

 BYTE  instr_push_exitthread_arg;
 DWORD exitthread_arg;

 WORD  instr_call_exitthread;
 DWORD adr_from_call_exitthread;

 DWORD addr_loadlibrary;
 DWORD addr_exitthread;     //адрес функции ExitTHread
 BYTE  libraryname[100];    //имя и путь к загружаемой библиотеке  
};

BOOL InjectDll(DWORD pid, char *lpszDllName)
{
 HANDLE hProcess;
 BYTE *p_code;
 INJECTORCODE cmds;
 DWORD wr, id;

 //открыть процесс с нужным доступом
 hProess=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|
 PROCESS_VM_OPERATION, FALSE, pid);
 if(hProcess == NULL)
 {
   MessageBoxA(NULL, "You have not enough rights to attach dlls",
              "Error!", 0);
   return FALSE;
 }
 
 //зарезервировать память в процессе
   p_code = (BYTE*)VirtualAllocEx(hProcess, 0, sizeof(INJECTORCODE),
                                  MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   if(p_code==NULL)
   {
     MessageBox(NULL, "Unable to alloc memory in remote process",
                      "Error!", 0);
     return FALSE;
   }


 
iskatel ©   (2005-08-20 11:08) [16]

//инициализировать  машинный код
 cmds.instr_push_loadlibrary_arg = 0x68; //машинный код инструкции push
 cmds.loadlibrary_arg = (DWORD)((BYTE*)p_code
          + offsetof(INJECTORCODE, libraryname));
 
 cmds.instr_call_loadlibrary = 0x15ff; //машинный код инструкции call
 cmds.adr_from_call_loadlibrary =
 (DWORD)(p_code + offsetof(INJECTORCODE, addr_loadlibrary));
 
 cmds.instr_push_exitthread_arg  = 0x68;
 cmds.exitthread_arg = 0;
 
 cmds.instr_call_exitthread = 0x15ff;
 cmds.adr_from_call_exitthread =
 (DWORD)(p_code + offsetof(INJECTORCODE, addr_exitthread));
 
 cmds.addr_loadlibrary =
 (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
 
 cmds.addr_exitthread  =
 (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitThread");
 
 if(strlen(lpszDllName)>99)
 {
    MessageBox(NULL, "Dll Name too long", "Error!", 0);
    return FALSE;
 }
 strcpy((char*)cmds.libraryname, lpszDllName );
 
 /*После инициализации cmds в мнемонике ассемблера выглядит следующим
   образом:
     push  adr_library_name               ;аргумент ф-ции loadlibrary
     call dword ptr [loadlibrary_adr]     ; вызвать LoadLibrary
     push exit_thread_arg                 ;аргумент для ExitThread
     call dword ptr [exit_thread_adr]     ;вызвать ExitThread    
 */
 
 //записать машинный код по зарезервированному адресу
 WriteProcessMemory(hProcess, p_code, &cmds, sizeof(cmds), &wr);
 
 //выполнить машинный код
 HANDLE z = CreateRemoteThread(hProcess, NULL, 0,
              (unsigned long (__stdcall *)(void *))p_code, 0, 0, &id);

 //ожидать завершения удаленного потока
 WaitForSingleObject(z, INFINITE);
 //освободить память
 VirtualFreeEx(hProcess, (void*)p_code, sizeof(cmds), MEM_RELEASE);

 return TRUE;
}


 
iskatel ©   (2005-08-20 11:09) [17]

Внедрение 2
Второй способ внедрения исполняемого кода (через хуки) наиболее прост в использовании. Он основан на технологии хуков, а именно: если установить хук на поток чужого процесса, то, как только поток получит сообщение, соответствующее заданному типу хука, система автоматически подключит DLL c хуком к данному процессу. Недостатком данного способа в том, что нельзя внедрить DLL в процесс, не имеющий очереди сообщений. Данная DLL будет присоединена к чужому процессу лишь до тех пор, пока запущена программа, установившая хук. Как только вы завершите эту программу, dll автоматически будет отключена. Первый способ лишен таких недостатков.

С другой стороны, первый способ будет работать лишь в WinNT, по причине использования функции VirtualAllocEx, которая резервирует память в заданном (отличном от того, в котором происходит вызов этой функции) процессе. Теоретически, данную проблему можно обойти, если писать код в некоторую часть отображения exe-файла чужого процесса, например в заголовок DOS, который после загрузки не используется. Но ОС не всегда позволяет писать в эту область памяти, даже если попытаться изменить разрешения при помощи VirtualProtextEx.

Есть еще и третий способ внедрения, но он наиболее опасен, так как может привести к краху системы. При помощи данного метода ОС сама внедряет указанную dll во все без исключения процессы операционной системы, даже защищенные. Для реализации необходимо прописать в реестре по пути Hkey_local_machine\software\microsoft\windowsnt\currentversion\windows в ключе AppInit_DLLs полный путь к своей dll.


 
iskatel ©   (2005-08-20 11:10) [18]

извини, что на сях, но это не мой пример, там в начале указан автор))
я пробовал - все работает ))
удачи!


 
alpet ©   (2005-08-20 12:15) [19]

Defunct ©   (20.08.05 04:25) [11]

EIP и ESP. Если некоторая функция из импортированного списка вызывается, и выполнение внутрии ее зацикливается - определить можно по EIP, если она вызывает какую-либо функцию, можно поискать в стеке адрес возврата в нее. Способ работать не будет - если функция передает управление с помощью jmp за свои пределы.


 
KyberTECH   (2005-08-26 03:39) [20]

Спасибо всем ! Кто хоть что-то написал !
А то, что кто-то там заикнулся за НЕУВАЖЕНИЕ, тебе тоже спасибо ! Буду знать ! Просто я не так часто задаю вопросы, восновном пытаюсь сам разбираться !

Вобщем всем спасибо !

Ребята, кто-то из вас работал с CashFiesta ???



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

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

Наверх




Память: 0.58 MB
Время: 0.041 c
14-1128920739
ilya39
2005-10-10 09:05
2005.10.30
Visual Studio Beta 2


1-1128354172
Alex_1234
2005-10-03 19:42
2005.10.30
Подскажите алгоритм реализацию "плагинной" программы...


14-1128266771
Некто
2005-10-02 19:26
2005.10.30
Тётьки с брашурами


14-1128668966
syte_ser78
2005-10-07 11:09
2005.10.30
ищу книгу


1-1128521993
Aleksey
2005-10-05 18:19
2005.10.30
Image.Canvas и LineTo