Перейти к содержанию

Перехват Api


Inel

Рекомендуемые сообщения

Да какая разница какую API функцию перехватывать,принцип-то один и тот-же.

Собственно разобрался как перехватить API с помощью таблицы импорта.

Пробовал в своем проекте(то-есть в своем процессе).все работает.

Написал DLL.А вот как внедрить в чужой процесс,незнаю.

Подскажите плиз!

Ссылка на комментарий
Поделиться на другие сайты

Вот DLL:

#include "stdafx.h"

 

DWORD adr_MessageBoxA;

unsigned long written;

 

void InterceptFunctions(void);

BOOL WINAPI Intercept_MessageBoxA(HWND hwnd, char *text, char *hdr, UINT utype);

 

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;

}

}

 

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;

}

 

А вот функция внедрения:

//структура описывает поля, в которых содержится код внедрения

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;

 

//открыть процесс с нужным доступом

hProcess=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;

}

 

//инициализировать машинный код

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;

}

 

При выполнии машинного кода

HANDLE z = CreateRemoteThread(hProcess, NULL, 0,

(unsigned long (__stdcall *)(void *))p_code, 0, 0, &id);

Прога (в которую я внедряю DLL)вылетает с ошибкой.

 

Кстати описано ,что при компиляции ,надо указать компилятору ,что-бы он выравнивал структуры побайтово.

Где это указывается в Visual Studio 6.

Может в этом вся проблема?

Ссылка на комментарий
Поделиться на другие сайты

Inel

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

Про выравнивание побайтное: Project->Properties->C/C++->Code Generation->Struct Member Alignment->1 Byte (или просто параметр компилятору /Zp1)

 

Romses

Флудер

Ссылка на комментарий
Поделиться на другие сайты

Inel

Еще вспомнил с лету. Для внедрения в адресное пространство чужого процесса кажется надо изменять права доступа к этой памяти, иначе не получится изменить таблицу импорта.

Ссылка на комментарий
Поделиться на другие сайты

Заархивировано

Эта тема находится в архиве и закрыта для дальнейших ответов.

×
×
  • Создать...