Мобильный код-код способный выполняться, будучи скопирован по любому адресу. Вот что непонятно: Порядок инициализации копии мобильного кода.... 1)формируем строку: "KERNEL 32" ((PDWORD)pBUFFER)[0]=Ox4e524454b //asci ((PDWORD)pBUFFER)[1]=Ox... //asci ((PDWORD)pBUFFER)[2]=Ox... //asci 2)получаем базовый адрес KERNEL32.dll Ищем в текущем адресном пространстве (например в таблице импортов exe файлов) адрес функции GetModuleHandle и вызываем её. Либо адрес уже получен от родителя мобильного кода в качестве параметра 3)Импортируем из KERNEL32.dll функцию LocalAlloc() 4)Выделяем память под структуру GLOBAL_DATA 5)Получаем базовый адрес текущей копии мобильного кода: call a a:pop eax sub eax,offset a и записываем этот адресс в GLOBAL_DATA 6)Находим в собственном хвосте таблицу строковых констант и пишем этот адрес в GLOBAL_DATA 7)Импортируем из KERNEL32.dll функции LoadLibrary и GetProcAdress 8)Загружаем остальные библиотеки и используемые функции Вообще непонятно что делается с 5 ого пункта. Может кто сможет объяснить? и вот ещё один кусок: Понятие слобомобильного кода.... Слабомобильный код : Большая часть мобильного кода делается немобильным,мобильным остаётся только загрузчик который грузит оставшуюся часть кода и настраивает все перекрёстные ссылки 1 Подход : Делаем загрузчик вида: LoadLibrary(param1); p=GetProcADRESS(PARAM2); P(PARAM3); он грузит в чужое адресное пространство библиотеку,однако эти библиотеки будут видны программам типа ProcessExplorer 2 Подход : Тоже самое только библиотека загружается руками с использованием своих функций=> не записывается в соответсвующие системные таблицы Скрытность лучше чем у первого подхода но хуже чем у молбильного кода. Сложно построитьтаблицы импорта/экспорта(вручную) может ктонибудь объяснить что за параметры param1, param2, param3? Хотябы какие нибудь предположения по этим param1,param2,param3
>> может ктонибудь объяснить что за параметры param1, param2, param3? под слабомобильным кодом по всей видимости, в данном случае подразумевается мобильный код, который подгружает свою dll-библиотеку param1 - имя библиотеки param2 - имя импортируемой из неё ф-ции param3 - аргумент передаваемый этой ф-ции >> Вообще непонятно что делается с 5 ого пункта. Может кто сможет объяснить? в конце мобильного кода находятся имена имортируемых ф-ций (хотя я настоятельно рекомендую юзать хеши от имён) когда найдена база кернела, итд. эти имена читаются, и адресса соотв ф-ций ищутся с помощью своего аналога ф-ции GetProcAddress фак, что за слово такое "мобильный"? =)) уж лучше называйте базонезависимый код, или шеллкод))
hulk45 Видимо, я туго соображаю, но мне абсолютно не понятна суть вопросов. asd Вы не дочитали - там дальше ещё "слабомобильный" есть.
к слову про мобильный код, я недавно сделал попытку написать простенький компилятор ассемблера, так вот то, что получилось, создает как раз мобильный код (nano-assembler получился, в разделе ПРОЕКТЫ, есть соответствующий топик, там ссылки есть).
уважаемые программисты подскажите пожалуйста 1. почему в мобильном коде нельзя использовать switch и try. 2, И что означает этот код Получаем базовый адрес текущей копии мобильного кода: call a a:pop eax sub eax,offset a (что в регистре eax ?)
просто из стека вынимается адресс возврата, и от него отминусовывается адресс первой инструкции... таким образом в eax будет адресс, по которому наш код оказался в памяти
По поводу кода - почитай про дельта смещение. Нифига неправда. В eax как раз будет дельта смещение - т.е. разность адресов по которому исполняемый код собирался, и по которому реально загружен в память. На эту разность надо коректировать все адреса в программе. Код (Text): call a a: pop eax В eax адрес метки а на момент выполнения кода. А offset a - адрес метки а на момент компиляции. Потому что они чаще всего реализуются при помощи таблиц адресов перехода. И адреса там не относительные, а абсолютные - потому работать не будет при изменении базы кода.
В одном из требований к мобильному коду написано: Все системные функции МОЖНО импортировать только динамически LoadLibrary()+GetProcAddress() вопрос: 1.А почему нельзя статически? 2. Когда нельзя импортировать? (наверное тупой вопрос) И пожалуста ответьте ещё на парочку вопросиков: Слабомобильный код : Большая часть мобильного кода делается немобильным,мобильным остаётся только загрузчик который грузит оставшуюся часть кода и настраивает все перекрёстные ссылки 1 Подход : Делаем загрузчик вида: LoadLibrary(param1); p=GetProcADRESS(PARAM2); P(PARAM3); он грузит в чужое адресное пространство БИБЛИОТЕКУ,однако эти БИБЛИОТЕКИ будут видны программам типа ProcessExplorer (так написано в лекции) Вопрос: 3. Так библиотеку или библиотеки будут видны программам типа ProcessExplorer? 2 Подход : Тоже самое только библиотека загружается руками с использованием своих функций=> не записывается в соответсвующие системные таблицы Скрытность лучше чем у первого подхода но хуже чем у молбильного кода. Сложно построитьтаблицы импорта/экспорта(вручную) Вопрос: 4. "только библиотека загружается руками с использованием своих функций". Как "ручками" загружается библиотека? Буду очень вам благодарен товарищи.Спасибо тем кто уже отвечал в моей теме.
1. Потому что при статической вызов функций dll идет не напрямую call XXX, где XXX - адрес функции в dll, а как минимум через таблицу импорта call [YYY], где YYY - адрес в таблице импорта, по которому лежит значение XXX. Ес-но адрес YYY не является "мобильным" - в чужом процессе он может указывать не туда или вообще в никуда 2. МОЖНО динамически - если нужно, а не потому, что нельзя 3. Просто опечатка. Программам типа ProcessExplorer видны все dll легально загруженные через LoadLibrary 4. Фиг его знает Если полностью "ручками" создавать образ dll в памяти, то нужно открыть файл dll, проанализировать PE-заголовок, выделить память в соответсвии с размером образа, прочитать секции из файла в память по соотв.смещениям. Затем начинаются отмеченнные в твоей лекции сложности - нужно "ручками" настроить таблицы импорта и заменить в коде все абсолютные адреса в соответствии с таблицей релоков
>> 4. "только библиотека загружается руками с использованием своих функций". Как "ручками" загружается библиотека? поиск по форуму
Код (Text): DWORD GetSectionProtection(DWORD SC) { DWORD result=0; if (SC && IMAGE_SCN_MEM_NOT_CACHED != 0) result = result || PAGE_NOCACHE; if (SC && IMAGE_SCN_MEM_EXECUTE != 0) { if (SC && IMAGE_SCN_MEM_READ != 0) { if (SC && IMAGE_SCN_MEM_WRITE != 0) result = result || PAGE_EXECUTE_READWRITE; else result = result || PAGE_EXECUTE_READ; } else if (SC && IMAGE_SCN_MEM_WRITE != 0) result = result || PAGE_EXECUTE_WRITECOPY; else result = result || PAGE_EXECUTE; } else if (SC && IMAGE_SCN_MEM_READ != 0) { if (SC && IMAGE_SCN_MEM_WRITE != 0) result = result || PAGE_READWRITE; else result = result || PAGE_READONLY; } else if (SC || IMAGE_SCN_MEM_WRITE != 0) result = result || PAGE_WRITECOPY; else result = result || PAGE_NOACCESS; return result; } void ProcessRelocs(long hMap, DWORD dwImageBaseDelta) { PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew); ULONG pImageBaseRelocation = (ULONG)(RVATOVA(hMap, pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)); while (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress != 0) { int number = (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock - 8) / 2; WORD* Rel = (WORD *)(pImageBaseRelocation + 8); for (int i = 0; i < number; i++) { *(PDWORD)(RVATOVA(hMap, ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress + ((0x0FFF)&(Rel[i])))) += dwImageBaseDelta; } pImageBaseRelocation += ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock; } } void ProcessImports(long hMap) { PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew); PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(RVATOVA(hMap, pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)); while (pImageImportDescriptor->Name != 0) { IMAGE_THUNK_DATA32 *pThunk; HMODULE hLibModule = (HMODULE)GLoadLibraryA((char *)RVATOVA(hMap, pImageImportDescriptor->Name)); if (hLibModule == NULL) return; if (pImageImportDescriptor->TimeDateStamp == 0) pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->FirstThunk); else pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->OriginalFirstThunk); while (pThunk->u1.Ordinal != 0) { DWORD dwProcAddr = 0; char *ImportedName; if (((pThunk->u1.Ordinal) & 0x80000000) != 0) { dwProcAddr = (DWORD)GetProcAddress(hLibModule, (char *)(pThunk && 0xFFFF)); } else { PIMAGE_IMPORT_BY_NAME pImageImportByName = (PIMAGE_IMPORT_BY_NAME) RVATOVA(hMap, pThunk->u1.AddressOfData); ImportedName = (char *)&pImageImportByName->Name; dwProcAddr = (DWORD)GetProcAddress(hLibModule, ImportedName); } *(PDWORD)pThunk = dwProcAddr; pThunk++; } pImageImportDescriptor++; } } DWORD xGetProcAdress(long hMap, int num) { PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew); PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(hMap, pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress); PDWORD AddressOfFunctions = (PDWORD)RVATOVA(hMap, pImageExportDirectory->AddressOfFunctions); for (int i = 0; i < pImageExportDirectory->NumberOfFunctions; i++) if (i == num - 1) return RVATOVA(hMap, AddressOfFunctions[i]); return 0; } HMODULE xLoadLibrary(PBYTE pbDllBuff) { HMODULE hRet = 0; DWORD dwImageBase, dwImageSize, dwHeadersSize, dwImageBaseDelta; PIMAGE_NT_HEADERS pImageNtHeaders; PBYTE pbImage = NULL; __try { pImageNtHeaders = (PIMAGE_NT_HEADERS) (pbDllBuff + ((PIMAGE_DOS_HEADER)pbDllBuff)->e_lfanew); dwImageBase = pImageNtHeaders->OptionalHeader.ImageBase; dwImageSize = pImageNtHeaders->OptionalHeader.SizeOfImage; dwHeadersSize = pImageNtHeaders->OptionalHeader.SizeOfHeaders; DWORD dwNewBase = dwImageBase; while (pbImage == NULL) { pbImage = (PBYTE)VirtualAlloc((LPVOID)dwNewBase, dwImageSize, MEM_RESERVE, PAGE_NOACCESS); dwNewBase += 0x10000; } dwImageBaseDelta = dwNewBase - dwImageBase - 0x10000; PBYTE pbHeaders = (PBYTE)VirtualAlloc(pbImage, dwHeadersSize, MEM_COMMIT, PAGE_READWRITE); memcpy(pbHeaders, pbDllBuff, dwHeadersSize); DWORD dwOldProtect; VirtualProtect(pbHeaders, dwHeadersSize, PAGE_READONLY, &dwOldProtect); PIMAGE_SECTION_HEADER pImageSectionHeader = (PIMAGE_SECTION_HEADER) (pImageNtHeaders->FileHeader.SizeOfOptionalHeader + (long)&(pImageNtHeaders->OptionalHeader)); PBYTE pbMem = NULL; DWORD dwRawSectionSize = 0; for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++) { if (pImageSectionHeader->SizeOfRawData > pImageSectionHeader->Misc.VirtualSize) dwRawSectionSize = pImageSectionHeader->Misc.VirtualSize; else dwRawSectionSize = pImageSectionHeader->SizeOfRawData; pbMem = (PBYTE)VirtualAlloc((LPVOID)RVATOVA(pbImage, pImageSectionHeader->VirtualAddress), pImageSectionHeader->Misc.VirtualSize, MEM_COMMIT, PAGE_READWRITE); ZeroMemory(pbMem, pImageSectionHeader->Misc.VirtualSize); memcpy(pbMem, (void *)RVATOVA(pbDllBuff, pImageSectionHeader->PointerToRawData), dwRawSectionSize); pImageSectionHeader++; } for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++) { VirtualProtect((LPVOID)RVATOVA(pbImage, pImageSectionHeader[i].VirtualAddress), pImageSectionHeader[i].Misc.VirtualSize, GetSectionProtection(pImageSectionHeader[i].Characteristics), &dwOldProtect); } ProcessRelocs((long)pbImage, dwImageBaseDelta); ProcessImports((long)pbImage); } __except (EXCEPTION_EXECUTE_HANDLER) { goto end; } hRet = (HMODULE)pbImage; end: return hRet; } вот мой код, тестил только на паре-тройке либ, но вроде работает
я думаю тему следует закрыть. Автор без труда смог бы найти кучу инфы, если б поискал... А так ему лень... хочет готовые решения...
Закроем обязательно как только сдам экзамен по Мобильному коду. ) думал есть проще решения решения по загрузки библиотеки. Спасибо всем кто отвечал.