Сейчас на форуме: asfa, Rio (+6 невидимых)

 eXeL@B —› Вопросы новичков —› заплатка для DLL
Посл.ответ Сообщение

Ранг: 0.4 (гость), 2thx
Активность: 0=0
Статус: Участник

Создано: 26 марта 2013 03:47 · Поправил: maxidromm
· Личное сообщение · #1

Во-первых, привет всем!

У меня есть вопрос. Возможно кто то знает, дайте направление.

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

Пишу проект VS на C++ (ANSI C в конечном итоге). В одной руке - 5 функций, в другой - DLL, надо слепить их вместе. Операции вроде /force:multiple не помогают (а очень хотелось бы - этот метод отлично работает для static libs). "Легальные" способы типа хитрых настроек линковщика не проходят (или я не знаю). Некрасивые методы типа деассемблирования - тоже неудобное решение (case specific).

Какие есть еще варианты?

Пример того что не работает:
DLL:
__declspec(dllexport) int f1(void)
{ return 1; }

__declspec(dllexport) int f2(void)
{ return f1(); }

Application:
extern"C"{
int f1(void) { return 4; }
extern int f2(void);
}

int _tmain(int argc, _TCHAR* argv[])
{
int k;
k = f1(); // will output 4
k = f2(); // will output 1
...
а мне надо чтобы f2() выдала 4.



Ранг: 281.8 (наставник), 272thx
Активность: 0.250.01
Статус: Участник
Destroyer of protectors

Создано: 26 марта 2013 04:39
· Личное сообщение · #2

maxidromm пишет:
Некрасивые методы типа деассемблирования

это красивые методы. хукай нужные функи и будет тебе счастье, ТУТ всё найдёшь.

| Сообщение посчитали полезным: plutos


Ранг: 622.6 (!), 521thx
Активность: 0.330.89
Статус: Участник
_Вечный_Студент_

Создано: 26 марта 2013 05:04 · Поправил: plutos
· Личное сообщение · #3

Примерно как-то вот так:

Code:
  1. void CAPIHook::ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, 
  2.    PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) {
  3.  
  4.    // Get the address of the module's import section
  5.    ULONG ulSize;
  6.       PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
  7.    __try {
  8.       pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData(
  9.          hmodCaller, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
  10.    } 
  11.    __except (InvalidReadExceptionFilter(GetExceptionInformation())) {
  12.       // Nothing to do in here, thread continues to run normally
  13.       // with NULL for pImportDesc 
  14.    }
  15.    
  16.    if (pImportDesc == NULL)
  17.       return; // This module has no import section or is no longer loaded
  18.  
  19.  
  20.    // Find the import descriptor containing references to callee's functions
  21.    for (; pImportDesc->Name; pImportDesc++) {
  22.       PSTR pszModName = (PSTR) ((PBYTE) hmodCaller + pImportDesc->Name);
  23.       if (lstrcmpiA(pszModName, pszCalleeModName) == 0) {
  24.  
  25.          // Get caller's import address table (IAT) for the callee's functions
  26.          PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) 
  27.             ((PBYTE) hmodCaller + pImportDesc->FirstThunk);
  28.  
  29.          // Replace current function address with new function address
  30.          for (; pThunk->u1.Function; pThunk++) {
  31.  
  32.             // Get the address of the function address
  33.             PROC* ppfn = (PROC*) &pThunk->u1.Function;
  34.  
  35.             // Is this the function we're looking for?
  36.             BOOL bFound = (*ppfn == pfnCurrent);
  37.             if (bFound) {
  38.                if (!WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
  39.                     sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError())) {
  40.                   DWORD dwOldProtect;
  41.                   if (VirtualProtect(ppfn, sizeof(pfnNew), PAGE_WRITECOPY, 
  42.                      &dwOldProtect)) {
  43.  
  44.                      WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, 
  45.                         sizeof(pfnNew), NULL);
  46.                      VirtualProtect(ppfn, sizeof(pfnNew), dwOldProtect, 
  47.                         &dwOldProtect);
  48.                   }
  49.                }
  50.                return; // We did it, get out
  51.             }
  52.          }
  53.       }  // Each import section is parsed until the right entry is found and patched
  54.    }
  55. }


-----
Give me a HANDLE and I will move the Earth.




Ранг: 0.4 (гость), 2thx
Активность: 0=0
Статус: Участник

Создано: 26 марта 2013 06:00 · Поправил: maxidromm
· Личное сообщение · #4

MasterSoft
Деассемблирование - красивый метод, когда кодишь дома. Но что делать когда новая версия дллки выйдет? Для индустрии думаю не совсем годится (кто патчи выпускать будет?). Ссылку, конечно, посмотрю. Спасибо.
PS: уже пробежался... надо время, там много интересного.

plutos
Спасибо, тоже попробую.
Я тут нашел примерно похожее. В принципе, хороший вариант если статически цеплять к проекту и патчить "онлайн". http://software.intel.com/en-us/articles/intercepting-system-api-calls/
но... закодил. VirtualProtect вылетает со свистом stack overflow. хмм... думаю дальше.

В целом - спасибо всем отписавшим. Основное направление я понял.



Ранг: 0.4 (гость), 2thx
Активность: 0=0
Статус: Участник

Создано: 26 марта 2013 23:55 · Поправил: maxidromm
· Личное сообщение · #5

Проблема отпала сама собой, так как выяснилось что платформа так или иначе будет перекомпилироваться через MinGW в любом случае. Всем спасибо.

2Moderator: да, топик можно закрыть, щоб не флудили.




Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 27 марта 2013 09:14
· Личное сообщение · #6

Тогда топик, видимо, можно закрыть.


 eXeL@B —› Вопросы новичков —› заплатка для DLL
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати