для тех кто "не в теме" вводная статья http://www.xakep.ru/magazine/xa/080/116/1.asp с нее все начиналось утилита для удобного импорта по хешу правила файл x3j11.h всегда подключать последним пример #include <string.h> #include <stdlib.h> #include <conio.h> #include <windows.h> #include <shlwapi.h> #include "x3j11.h" если вы это забудете миллион ошибок гарантированны также помимо генерации файла x3j11.h не забывайте подключать заголовки к соответствующим библиоткам полтому что он их не подключает дальше хм если вы получите такую ошибку error C2914: 'boost::type_of::encode_start' значит вы нарвались на перегруженную функцию типа const char *strstr(const char *_Str, const char *_SubStr) char *strstr(char *_Str, const char *_SubStr) вообще лучше их избегать всегда в WINAPI налог есть но если код уже написан то открываем x3j11.h делаем quick search по символу strstr и видим такое Code: X3J11_CallFunction(strstr,0x4e5cf9ed,0x967c28ff,__VA_ARGS__) надо заменить на Code: X3J11_CallOverload(PCH(PCCH,PCCH),0x4e5cf9ed,0x967c28ff,__VA_ARGS__) дальше хм утилита генератор заголовка обрабатывает библиотеки так как в списке это значит что если первым идет ntdll.dll и в нем есть функция strstr а следом идет msvcrt.dll и в нем тоже есть strstr то импорт будет из ntdll.dll таким образом можно меняя порядок библиотек "тюнить" что откуда "брать" дальше пример переделки реальной программы sdbot'a компилим оптимизируем по размеру выходит 24.5 кб в списке импорта WS2_32.DLL, MSVCRT.DLL, WININET.DLL, KERNEL32.DLL, ADVAPI32.DLL, SHELL32.DLL запускаем утилиту пишем так же через запятую делаем двойной клик и видим два файла x3j11.h и x3j11.cpp добавляем их в проект пробуем скомпилировать ошибка error C2914: 'boost::type_of::encode_start' делаем клик по ошибке и видим что как раз на функции strstr проделываем то что обсуждалось в самом начале и пробуем скомпилить снова все успешно собралось смотри осталось только MSVCRT.DLL импортирующая одну функцию memset это неявный вызов компилятором для обнуления как правило массивов или переменных типа структур у нас это PROCESSENTRY32 pe32 = {0} такой код в самом начале WinMain правим на memset(&pe32, 0, sizeof(pe32)) компилим теперь таблица импорта вообще изчезла и .exe стал чуть меньше 24 кб но главное теперь весь импорт по хешу пример Code: #include <windows.h> #include "x3j11.h" int main() { X3J11_Startup(); MessageBox(0,0,0,0); } минимальный exe 2 кб получается из за включения кода поддержки выше будет расти только от явно написанного кода да кстати все это дело тестировалось на Visual C/C++ 2008 Professional Windows XP SP2 x86 так что если 2008 у вас есть пробовать лучше на нем Code: static volatile LONG lTreeLock; PVOID __stdcall X3J11_Hash2Ptr(DWORD dwFuncHash, DWORD dwModHash) { 004017E0 55 push ebp 004017E1 8B EC mov ebp,esp 004017E3 51 push ecx while (_InterlockedExchange(&lTreeLock, TRUE) == TRUE) 004017E4 B8 01 00 00 00 mov eax,1 004017E9 B9 48 4F 40 00 mov ecx,404F48h 004017EE 87 01 xchg eax,dword ptr [ecx] 004017F0 83 F8 01 cmp eax,1 004017F3 75 08 jne X3J11_Hash2Ptr+1Dh (4017FDh) FuncPtr._SwitchToThread(); 004017F5 FF 15 78 4F 40 00 call dword ptr ds:[404F78h] 004017FB EB E7 jmp X3J11_Hash2Ptr+4 (4017E4h) PVOID pFunc = Tree.Find(dwFuncHash); 004017FD 8B 55 08 mov edx,dword ptr [dwFuncHash] 00401800 52 push edx 00401801 B9 00 30 40 00 mov ecx,403000h 00401806 E8 15 FB FF FF call CHashMap::Find (401320h) 0040180B 89 45 FC mov dword ptr [pFunc],eax if (!pFunc) 0040180E 83 7D FC 00 cmp dword ptr [pFunc],0 00401812 75 25 jne X3J11_Hash2Ptr+59h (401839h) { pFunc = ParseExport(dwFuncHash, dwModHash); 00401814 8B 45 0C mov eax,dword ptr [dwModHash] 00401817 50 push eax 00401818 8B 4D 08 mov ecx,dword ptr [dwFuncHash] 0040181B 51 push ecx 0040181C E8 0F FF FF FF call ParseExport (401730h) 00401821 83 C4 08 add esp,8 00401824 89 45 FC mov dword ptr [pFunc],eax Tree.Add(dwFuncHash, pFunc); 00401827 8B 55 FC mov edx,dword ptr [pFunc] 0040182A 52 push edx 0040182B 8B 45 08 mov eax,dword ptr [dwFuncHash] 0040182E 50 push eax 0040182F B9 00 30 40 00 mov ecx,403000h 00401834 E8 17 FB FF FF call CHashMap::Add (401350h) } _InterlockedExchange(&lTreeLock, FALSE); 00401839 33 C9 xor ecx,ecx 0040183B BA 48 4F 40 00 mov edx,404F48h 00401840 87 0A xchg ecx,dword ptr [edx] return pFunc; 00401842 8B 45 FC mov eax,dword ptr [pFunc] } сейчас поиск в "хранилище" адреса лочится с помощью интринсика <intrin.h> _InterlockedExchange есть еще вариант от которого я отказался даем каждому потоку по "хранилищу" (AVL дерево) для этого досточно объявить как __declspec(thread) CHashMap Tree это работает быстрее так как нет локов (если конечно не создавать и тут же прибивать потоки) но в общем случае такая скорость маппинга адреса api не нужна потому что проседает обычно во время выполнения вызова отправка по сети рисование и прочee есть еще вариант юзать динамический TLS во время первого обращения к "хранилищу" любым потоком выделять память под дерево HeapAlloc TlsSetValue и вызывать RegisterWaitForSingleObject с хендлом этого потока во время его завершения вызовется каллбек и освободит память это вариант можно юзать чтоб отказаться от статический TLS так как он создает секцию .tls 15 кб размером но опять же если потоки создаются и тут же прибиваются то лучше юзать локи так как при использовании TLS будут постоянно резольвиться новые адреса для каждого потока поэтому я оставил самый простой и универсальный вариант чуть не забыл вызовите X3J11_Startup перед вызовами любых других функций библиотеки буста необходимые для сборки (1мб) http://slil.ru/31798581 утилита и примеры http://zalil.ru/31898084