Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Перехват упраления программой


Автор: F0b0S 12.10.2004, 18:00
Отцы помогите пожалуйста рашить проблему stena.gif

проблема заключается в следующем:
есть файл1на жестком диске.
есть программа1 которая работает с этим файлом.
нужно:
1. отлавить обращение этой программы к файлу1
2. тормознуть программу1
3. загрузить файлв1память
4. выполнить некотрые действия с ним
5. подсунуть данные файла1 (находящиеся в памяти) этой прогорамме, не сохраняя данные файла1 на диск
6. возобновить работу прграммы1

Очень буду признателен любым советам...

Программа работает с файлом только в режиме ReadOnly.

Автор: Step 12.10.2004, 18:04
точно не скажу... но советую поискать доку по перехвату функци winapi и перехватывать открытие файла... можно конечно и прогу в реалтайме бомбить, но геморно

Автор: <Spawn> 13.10.2004, 11:51
Да, как уже сказал Step, тебе нужно в реалтайме попасть в адресное пространство целевого процесса(например, при помощи хуков) и там перехватывать вызов CreateFile.

Автор: F0b0S 13.10.2004, 14:07
sad.gif В теории это конечно все хорошо (я примерно так себе это и представлял).... А не могли бы Вы дать хоть какое нибудь описание, как это можно сделать.... Например я в курсе о формирование ловушек (хуков), но о попадание внутрь адресного пространства..... это честно говоря немного не понятно....
Рализовывал хуки на перехват глобальных сообщений ОС, но некогда не пробывал перехватить конкретные сообщения конкретной программы...
Если есть такая возможность, дайте какие - нибудь ссылки на документацию по этому вопросу, либо, если не сложно, скиньте мне их на почту [email protected]

Автор: Step 13.10.2004, 14:12
F0b0S, по сути это вопросы системного программирования, которое почемуто в нашем форуме не развиваеться, специалистов такого уровня маловато....
покачто вам придеться искать решения самим...

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

вообщем вам нужно искать...

Автор: F0b0S 13.10.2004, 14:13
Вся задача сводится к перенаправлению запросов программы к файлу в память.... Вся проблема - это сделать перенаправление.....
Добавлено @ 14:15
Step, читая сообщения форума, я уже заметил, что вопросы низкоуровневого программирования здесь почти не обсуждаются....
Добавлено @ 14:20
Step По поводу риалтаймого доступа к самой программе, пробывал, на уровне ассемблера, но здесь загвоздка - поскольку я не знаю структуры работы программы, при молейшем перехвате контроля программа вываливалась с ошибкой, поэтому я сделал вывод, что единственным вариантом является - работа на уровне сообщений системы....

Автор: chipset 14.10.2004, 12:40
Сделаешь - расскажи плз как smile.gif
Одно из моих бредовизмов - сделать защищеный файл и ловить access-denied.

Автор: Step 14.10.2004, 14:30
F0b0S, за щот сообщений винды твой модуль может прикрепиться к приложению а там у него почти все в руках...

Автор: 0bs3rv3r 16.10.2004, 19:47
Недавно писал прогу, которая к мультилекс конектится и выдирает переводы
Вот код длл которая внедряется в нужный процесс:
Код

#include "stdafx.h"
#include <stdio.h>
HWND hLex=0;
HWND hParent=0;
char LexWinClass[]={"MultLexWnd"};//имя класса главного окна
HHOOK hHook=0;
bool IsInLex=false;
int CALLBACK FindLex(HWND wnd,long zero)
{
char tt[512];
GetClassName(wnd,tt,500);
if(strcmp(tt,LexWinClass)==0)
{
 hLex=wnd;
 return 0;
}
return 1;
}

LRESULT CALLBACK DummyHook(int code, WPARAM wParam, LPARAM lParam)
{
long BT;
if(code==1&&wParam==1)
{
 //_asm int 3;
 if(!hHook)
 {
  hHook=SetWindowsHookEx(WH_CALLWNDPROC,DummyHook,(HINSTANCE)hCurModule,0);
  int i=GetLastError();
 }
 else
 {
  UnhookWindowsHookEx(hHook);
 }
  return 0;
}
CallNextHookEx(hHook,code,wParam,lParam);
return 0;
}

BOOL APIENTRY DllMain( HANDLE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
     )
{
hCurModule=hModule;
if(ul_reason_for_call!=DLL_PROCESS_ATTACH)
{
 return true;
}
while(EnumWindows(FindLex,0));
DWORD LexPid;
GetWindowThreadProcessId(hLex,&LexPid);
if(GetCurrentProcessId()!=LexPid)
{
 return true;
}
MessageBox(0,"LexProbe Active!",0,MB_OK);//отсюда мы в нужном процессе
IsInLex=true;
   return TRUE;
}


вызывается это дело так:
Код

HOOKPROC HP;
void LoadToProc()
{
hLib=LoadLibrary("..\\LexProbe.dll");
HP=(HOOKPROC)GetProcAddress(hLib,"DummyHook");
HP(1,1,1);
}
[/s]

далее так (уже в длл)
Код

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; //здесь будет машинный код инструкции перехода
void InterceptFunction(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);
}

а сюды оно обратится
Код

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;
}
[/s]
вторая половина не моя[s]

Автор: 0bs3rv3r 16.10.2004, 20:11
чуть не забыл к проджекту нужно еще .def добавить вида
LIBRARY "LexProbe"
EXPORTS
DummyHook

Автор: menkaur 24.10.2004, 03:13
Следующий класс позволяет заменить в адресном пространстве любого процесса системное api на твое собственное:
class KPEFile
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS pNTHeader;

public:
const char * pModule;

const char * RVA2Ptr(unsigned rva)
{
if ( (pModule!=NULL) && rva )
return pModule + rva;
else
return NULL;
}

KPEFile(HMODULE hModule);
const void * GetDirectory(int id);
PIMAGE_IMPORT_DESCRIPTOR GetImportDescriptor(LPCSTR pDllName);
const unsigned * GetFunctionPtr(PIMAGE_IMPORT_DESCRIPTOR
pImport, LPCSTR pProcName);

FARPROC SetImportAddress(LPCSTR pDllName, LPCSTR pProcName,
FARPROC pNewProc);

FARPROC SetExportAddress(LPCSTR pProcName, FARPROC pNewProc);
};

---------------------------------------------------------------------------------------------------------------------------------------------------
#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include "pehack.h"

KPEFile::KPEFile(HMODULE hModule)
{
pModule = (const char *) hModule;

if ( IsBadReadPtr(pModule, sizeof(IMAGE_DOS_HEADER)) )
{
pDOSHeader = NULL;
pNTHeader = NULL;
}
else
{
pDOSHeader = (PIMAGE_DOS_HEADER) pModule;

if ( IsBadReadPtr(RVA2Ptr(pDOSHeader->e_lfanew),
sizeof(IMAGE_NT_HEADERS)) )
pNTHeader = NULL;
else
pNTHeader = (PIMAGE_NT_HEADERS) RVA2Ptr(pDOSHeader->
e_lfanew);
}
}


// returns address of a PE directory
const void * KPEFile::GetDirectory(int id)
{
return RVA2Ptr(pNTHeader->OptionalHeader.DataDirectory[id].
VirtualAddress);
}


// returns PIMAGE_IMPORT_DESCRIPTOR for an imported module
PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor(
LPCSTR pDllName)
{
// first IMAGE_IMPORT_DESCRIPTOR
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)
GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);

if ( pImport==NULL )
return NULL;

while ( pImport->FirstThunk )
{
if ( stricmp(pDllName, RVA2Ptr(pImport->Name))==0 )
return pImport;

// move to next imported module
pImport ++;
}

return NULL;
}


// returns address of __imp__xxx variable for an import function
const unsigned * KPEFile::GetFunctionPtr(
PIMAGE_IMPORT_DESCRIPTOR pImport, LPCSTR pProcName)
{
PIMAGE_THUNK_DATA pThunk;

pThunk = (PIMAGE_THUNK_DATA) RVA2Ptr(pImport->
OriginalFirstThunk);

for (int i=0; pThunk->u1.Function; i++)
{
bool match;

if ( pThunk->u1.Ordinal & 0x80000000 ) // by ordinal
match = (pThunk->u1.Ordinal & 0xFFFF) ==
((DWORD) pProcName);
else
match = stricmp(pProcName, RVA2Ptr((unsigned)
pThunk->u1.AddressOfData)+2) == 0;

if ( match )
return (unsigned *) RVA2Ptr(pImport->FirstThunk)+i;

pThunk ++;
}

return NULL;
}


BOOL HackWriteProcessMemory(HANDLE hProcess, void * pDest, void * pSource, DWORD nSize, DWORD * pWritten)
{
__try
{
memcpy(pDest, pSource, nSize);
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
__try
{
MEMORY_BASIC_INFORMATION mbi;

VirtualQuery(pDest, & mbi, sizeof(mbi));
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, & mbi.Protect);

memcpy(pDest, pSource, nSize);
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
return FALSE;
}
}

* pWritten = nSize;

return TRUE;
}

FARPROC KPEFile::SetImportAddress(LPCSTR pDllName,
LPCSTR pProcName, FARPROC pNewProc)
{
PIMAGE_IMPORT_DESCRIPTOR pImport =
GetImportDescriptor(pDllName);

if ( pImport )
{
const unsigned * pfn = GetFunctionPtr(pImport, pProcName);

if ( IsBadReadPtr(pfn, sizeof(DWORD)) )
return NULL;

// read the original function address
FARPROC oldproc = (FARPROC) * pfn;

DWORD dwWritten;

// overwrite with new function address
HackWriteProcessMemory(GetCurrentProcess(), (void *) pfn,
& pNewProc, sizeof(DWORD), & dwWritten);

return oldproc;
}
else
return NULL;
}


FARPROC KPEFile::SetExportAddress(LPCSTR pProcName,
FARPROC pNewProc)
{
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)
GetDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);

if ( pExport==NULL )
return NULL;

unsigned ord = 0;

if ( (unsigned) pProcName < 0xFFFF ) // ordinal ?
ord = (unsigned) pProcName;
else
{
const DWORD * pNames = (const DWORD *) RVA2Ptr(pExport->AddressOfNames);
const WORD * pOrds = (const WORD *) RVA2Ptr(pExport->AddressOfNameOrdinals);

// find the entry with the function name
for (unsigned i=0; i<pExport->AddressOfNames; i++)
if ( stricmp(pProcName, RVA2Ptr(pNames[i]))==0 )
{
// get the corresponding ordinal
ord = pExport->Base + pOrds[i];
break;
}
}

if ( (ord<pExport->Base) || (ord>pExport->NumberOfFunctions) )
return NULL;

// use ordinal to get the address where export RVA is stored
DWORD * pRVA = (DWORD *) RVA2Ptr(pExport->AddressOfFunctions) +
ord - pExport->Base;

// read original function address
DWORD rslt = * pRVA;

DWORD dwWritten = 0;
DWORD newRVA = (DWORD) pNewProc - (DWORD) pModule;
HackWriteProcessMemory(GetCurrentProcess(), pRVA, & newRVA, sizeof(DWORD), & dwWritten);

return (FARPROC) RVA2Ptr(rslt);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------
Вот, как это работает на деле:
#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include "..\..\include\pehack.h"

int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR pText, LPCSTR pCaption,
UINT uType)
{
WCHAR wText[MAX_PATH];
WCHAR wCaption[MAX_PATH];

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pText,
-1, wText, MAX_PATH);
wcscat(wText, L" - intercepted");

MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pCaption,
-1, wCaption, MAX_PATH);
wcscat(wCaption, L" - intercepted");

return MessageBoxW(hWnd, wText, wCaption, uType);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
{
KPEFile pe(hInstance);

pe.SetImportAddress("user32.dll", "MessageBoxA", (FARPROC) MyMessageBoxA);

MessageBoxA(NULL, "Test", "SetImportAddress", MB_OK);
}

HMODULE hUser = GetModuleHandle("user32.dll");

KPEFile user32(hUser);

FARPROC oldproc = GetProcAddress(hUser, "MessageBoxA");

user32.SetExportAddress("MessageBoxA", (FARPROC) MyMessageBoxA);

FARPROC newproc = GetProcAddress(hUser, "MessageBoxA");

char temp[64];
wsprintf(temp, "GetProcAddress(MessageBoxA)\n"
"changes from %x to %x", oldproc, newproc);
MessageBoxA(NULL, temp, "SetExportAddress", MB_OK);

return 0;
}

Для внедрения можеш использовать hooks, но мне нравится следующий способ:
HKLM\Software\Microsoft\Windows NT\Current Version\Windows\AppInit_DLLs
Сюда нужно записать полный путь к твоей dll. После етого система автоматически будет внедрять ее в каждый новый процесс. Заменять адреса я можна в DllMain.

Приятных развлечений!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)