Мобильный код

Тема в разделе "WASM.BEGINNERS", создана пользователем hulk45, 31 янв 2007.

  1. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    Мобильный код-код способный выполняться, будучи скопирован по любому адресу.
    Вот что непонятно:
    Порядок инициализации копии мобильного кода....
    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
     
  2. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    >> может ктонибудь объяснить что за параметры param1, param2, param3?
    под слабомобильным кодом по всей видимости, в данном случае подразумевается мобильный код, который подгружает свою dll-библиотеку
    param1 - имя библиотеки
    param2 - имя импортируемой из неё ф-ции
    param3 - аргумент передаваемый этой ф-ции

    >> Вообще непонятно что делается с 5 ого пункта. Может кто сможет объяснить?
    в конце мобильного кода находятся имена имортируемых ф-ций (хотя я настоятельно рекомендую юзать хеши от имён) когда найдена база кернела, итд. эти имена читаются, и адресса соотв ф-ций ищутся с помощью своего аналога ф-ции GetProcAddress

    фак, что за слово такое "мобильный"? =)) уж лучше называйте базонезависимый код, или шеллкод))
     
  3. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Точно =)
     
  4. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    hulk45
    Видимо, я туго соображаю, но мне абсолютно не понятна суть вопросов.

    asd
    Вы не дочитали - там дальше ещё "слабомобильный" есть.
     
  5. mrhx

    mrhx New Member

    Публикаций:
    0
    Регистрация:
    11 окт 2006
    Сообщения:
    63
    к слову про мобильный код, я недавно сделал попытку написать простенький компилятор ассемблера, так вот то, что получилось, создает как раз мобильный код (nano-assembler получился, в разделе ПРОЕКТЫ, есть соответствующий топик, там ссылки есть).
     
  6. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    уважаемые программисты подскажите пожалуйста
    1. почему в мобильном коде нельзя использовать switch и try.
    2, И что означает этот код
    Получаем базовый адрес текущей копии мобильного кода:
    call a
    a:pop eax
    sub eax,offset a
    (что в регистре eax ?)
     
  7. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    просто из стека вынимается адресс возврата, и от него отминусовывается адресс первой инструкции... таким образом в eax будет адресс, по которому наш код оказался в памяти
     
  8. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    1. почему в мобильном коде нельзя использовать switch и try.
     
  9. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Потому что обе конструкции генерируют непереносимый (в "мобильном" смысле) код.
     
  10. cppasm

    cppasm New Member

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    923
    По поводу кода - почитай про дельта смещение.
    Нифига неправда.
    В eax как раз будет дельта смещение - т.е. разность адресов по которому исполняемый код собирался, и по которому реально загружен в память.
    На эту разность надо коректировать все адреса в программе.
    Код (Text):
    1. call a
    2. a:
    3. pop eax
    В eax адрес метки а на момент выполнения кода.
    А offset a - адрес метки а на момент компиляции.
    Потому что они чаще всего реализуются при помощи таблиц адресов перехода.
    И адреса там не относительные, а абсолютные - потому работать не будет при изменении базы кода.
     
  11. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    при большом количестве case AFAIK
     
  12. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    В одном из требований к мобильному коду написано:
    Все системные функции МОЖНО импортировать только динамически LoadLibrary()+GetProcAddress()
    вопрос:
    1.А почему нельзя статически?
    2. Когда нельзя импортировать? (наверное тупой вопрос)


    И пожалуста ответьте ещё на парочку вопросиков:
    Слабомобильный код :
    Большая часть мобильного кода делается немобильным,мобильным остаётся только загрузчик который грузит оставшуюся часть кода и настраивает все перекрёстные ссылки
    1 Подход :
    Делаем загрузчик вида:
    LoadLibrary(param1);
    p=GetProcADRESS(PARAM2);
    P(PARAM3);
    он грузит в чужое адресное пространство БИБЛИОТЕКУ,однако эти БИБЛИОТЕКИ будут видны программам типа ProcessExplorer (так написано в лекции)

    Вопрос:
    3. Так библиотеку или библиотеки будут видны программам типа ProcessExplorer?

    2 Подход :
    Тоже самое только библиотека загружается руками с использованием своих функций=> не записывается в соответсвующие системные таблицы
    Скрытность лучше чем у первого подхода но хуже чем у молбильного кода. Сложно построитьтаблицы импорта/экспорта(вручную)

    Вопрос:
    4. "только библиотека загружается руками с использованием своих функций". Как "ручками" загружается библиотека?

    Буду очень вам благодарен товарищи.Спасибо тем кто уже отвечал в моей теме.
     
  13. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    1. Потому что при статической вызов функций dll идет не напрямую call XXX, где XXX - адрес функции в dll, а как минимум через таблицу импорта call [YYY], где YYY - адрес в таблице импорта, по которому лежит значение XXX. Ес-но адрес YYY не является "мобильным" - в чужом процессе он может указывать не туда или вообще в никуда ;)
    2. МОЖНО динамически - если нужно, а не потому, что нельзя
    3. Просто опечатка. Программам типа ProcessExplorer видны все dll легально загруженные через LoadLibrary
    4. Фиг его знает ;) Если полностью "ручками" создавать образ dll в памяти, то нужно открыть файл dll, проанализировать PE-заголовок, выделить память в соответсвии с размером образа, прочитать секции из файла в память по соотв.смещениям. Затем начинаются отмеченнные в твоей лекции сложности - нужно "ручками" настроить таблицы импорта и заменить в коде все абсолютные адреса в соответствии с таблицей релоков
     
  14. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    >> 4. "только библиотека загружается руками с использованием своих функций". Как "ручками" загружается библиотека?
    поиск по форуму
     
  15. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    Cr4sh что то не могу найти ничего подходящего, если можешь кинь ссылку пожалуйста.
     
  16. Cr4sh

    Cr4sh New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2006
    Сообщения:
    668
    Код (Text):
    1. DWORD GetSectionProtection(DWORD SC)
    2. {
    3.     DWORD result=0;
    4.  
    5.     if (SC && IMAGE_SCN_MEM_NOT_CACHED != 0)
    6.         result = result || PAGE_NOCACHE;
    7.  
    8.     if (SC && IMAGE_SCN_MEM_EXECUTE != 0)
    9.     {
    10.         if (SC && IMAGE_SCN_MEM_READ != 0)     
    11.         {
    12.             if (SC && IMAGE_SCN_MEM_WRITE != 0)
    13.                 result = result || PAGE_EXECUTE_READWRITE;
    14.             else result = result || PAGE_EXECUTE_READ;
    15.         }
    16.         else if (SC && IMAGE_SCN_MEM_WRITE != 0)
    17.             result = result || PAGE_EXECUTE_WRITECOPY;
    18.         else result = result || PAGE_EXECUTE;
    19.     }
    20.     else if (SC && IMAGE_SCN_MEM_READ != 0)
    21.     {
    22.         if (SC && IMAGE_SCN_MEM_WRITE != 0)
    23.             result = result || PAGE_READWRITE;
    24.         else result = result || PAGE_READONLY;
    25.     }
    26.     else if (SC || IMAGE_SCN_MEM_WRITE != 0)
    27.         result = result || PAGE_WRITECOPY;
    28.     else result = result || PAGE_NOACCESS;
    29.  
    30.     return result;
    31. }
    32.  
    33. void ProcessRelocs(long hMap, DWORD dwImageBaseDelta)
    34. {
    35.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    36.    
    37.     ULONG pImageBaseRelocation = (ULONG)(RVATOVA(hMap,
    38.         pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
    39.  
    40.     while (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress != 0)
    41.     {
    42.         int number = (((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock - 8) / 2;
    43.         WORD* Rel = (WORD *)(pImageBaseRelocation + 8);
    44.        
    45.         for (int i = 0; i < number; i++)
    46.         {
    47.             *(PDWORD)(RVATOVA(hMap,
    48.                 ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->VirtualAddress + ((0x0FFF)&(Rel[i])))) +=
    49.                 dwImageBaseDelta;
    50.         }
    51.  
    52.         pImageBaseRelocation += ((PIMAGE_BASE_RELOCATION)pImageBaseRelocation)->SizeOfBlock;
    53.     }
    54. }
    55.  
    56. void ProcessImports(long hMap)
    57. {
    58.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    59.  
    60.     PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(RVATOVA(hMap,
    61.         pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
    62.  
    63.     while (pImageImportDescriptor->Name != 0)
    64.     {
    65.         IMAGE_THUNK_DATA32 *pThunk;
    66.         HMODULE hLibModule = (HMODULE)GLoadLibraryA((char *)RVATOVA(hMap, pImageImportDescriptor->Name));
    67.         if (hLibModule == NULL)
    68.             return;
    69.  
    70.         if (pImageImportDescriptor->TimeDateStamp == 0)
    71.             pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->FirstThunk);
    72.         else pThunk = (IMAGE_THUNK_DATA32 *)RVATOVA(hMap, pImageImportDescriptor->OriginalFirstThunk);
    73.  
    74.         while (pThunk->u1.Ordinal != 0)
    75.         {
    76.             DWORD dwProcAddr = 0;
    77.             char *ImportedName;
    78.             if (((pThunk->u1.Ordinal) & 0x80000000) != 0)
    79.             {
    80.                 dwProcAddr = (DWORD)GetProcAddress(hLibModule, (char *)(pThunk && 0xFFFF));
    81.             } else {
    82.                 PIMAGE_IMPORT_BY_NAME pImageImportByName = (PIMAGE_IMPORT_BY_NAME)
    83.                     RVATOVA(hMap, pThunk->u1.AddressOfData);
    84.                 ImportedName = (char *)&pImageImportByName->Name;
    85.                 dwProcAddr = (DWORD)GetProcAddress(hLibModule, ImportedName);
    86.             }
    87.             *(PDWORD)pThunk = dwProcAddr;
    88.             pThunk++;
    89.         }
    90.  
    91.         pImageImportDescriptor++;
    92.     }
    93. }
    94.  
    95. DWORD xGetProcAdress(long hMap, int num)
    96. {
    97.     PIMAGE_NT_HEADERS pImageNtHeaders = (PIMAGE_NT_HEADERS)(hMap + ((PIMAGE_DOS_HEADER)hMap)->e_lfanew);
    98.  
    99.     PIMAGE_EXPORT_DIRECTORY pImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(hMap,
    100.             pImageNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
    101.    
    102.     PDWORD AddressOfFunctions = (PDWORD)RVATOVA(hMap, pImageExportDirectory->AddressOfFunctions);
    103.  
    104.     for (int i = 0; i < pImageExportDirectory->NumberOfFunctions; i++)
    105.         if (i == num - 1)
    106.             return RVATOVA(hMap, AddressOfFunctions[i]);
    107.    
    108.     return 0;
    109. }
    110.  
    111. HMODULE xLoadLibrary(PBYTE pbDllBuff)
    112. {
    113.     HMODULE hRet = 0;
    114.     DWORD dwImageBase, dwImageSize, dwHeadersSize, dwImageBaseDelta;
    115.     PIMAGE_NT_HEADERS pImageNtHeaders;
    116.     PBYTE pbImage = NULL;
    117.  
    118.     __try
    119.     {
    120.         pImageNtHeaders = (PIMAGE_NT_HEADERS)
    121.             (pbDllBuff + ((PIMAGE_DOS_HEADER)pbDllBuff)->e_lfanew);
    122.  
    123.         dwImageBase   = pImageNtHeaders->OptionalHeader.ImageBase;
    124.         dwImageSize   = pImageNtHeaders->OptionalHeader.SizeOfImage;
    125.         dwHeadersSize = pImageNtHeaders->OptionalHeader.SizeOfHeaders;
    126.  
    127.         DWORD dwNewBase = dwImageBase;
    128.         while (pbImage == NULL)
    129.         {
    130.             pbImage = (PBYTE)VirtualAlloc((LPVOID)dwNewBase, dwImageSize,
    131.                 MEM_RESERVE, PAGE_NOACCESS);
    132.             dwNewBase += 0x10000;
    133.         }
    134.  
    135.         dwImageBaseDelta = dwNewBase - dwImageBase - 0x10000;
    136.  
    137.         PBYTE pbHeaders = (PBYTE)VirtualAlloc(pbImage, dwHeadersSize,
    138.             MEM_COMMIT, PAGE_READWRITE);
    139.        
    140.         memcpy(pbHeaders, pbDllBuff, dwHeadersSize);
    141.    
    142.         DWORD dwOldProtect;
    143.         VirtualProtect(pbHeaders, dwHeadersSize, PAGE_READONLY, &dwOldProtect);
    144.    
    145.         PIMAGE_SECTION_HEADER pImageSectionHeader = (PIMAGE_SECTION_HEADER)
    146.             (pImageNtHeaders->FileHeader.SizeOfOptionalHeader +
    147.             (long)&(pImageNtHeaders->OptionalHeader));
    148.  
    149.         PBYTE pbMem = NULL;
    150.         DWORD dwRawSectionSize = 0;
    151.  
    152.         for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++)
    153.         {
    154.             if (pImageSectionHeader->SizeOfRawData > pImageSectionHeader->Misc.VirtualSize)
    155.                 dwRawSectionSize = pImageSectionHeader->Misc.VirtualSize;
    156.             else
    157.                 dwRawSectionSize = pImageSectionHeader->SizeOfRawData;
    158.  
    159.             pbMem = (PBYTE)VirtualAlloc((LPVOID)RVATOVA(pbImage, pImageSectionHeader->VirtualAddress),
    160.                 pImageSectionHeader->Misc.VirtualSize, MEM_COMMIT, PAGE_READWRITE);
    161.  
    162.             ZeroMemory(pbMem, pImageSectionHeader->Misc.VirtualSize);
    163.             memcpy(pbMem, (void *)RVATOVA(pbDllBuff, pImageSectionHeader->PointerToRawData), dwRawSectionSize);
    164.  
    165.             pImageSectionHeader++;
    166.         }
    167.  
    168.         for (int i = 0; i < pImageNtHeaders->FileHeader.NumberOfSections; i++)
    169.         {
    170.             VirtualProtect((LPVOID)RVATOVA(pbImage, pImageSectionHeader[i].VirtualAddress),
    171.                 pImageSectionHeader[i].Misc.VirtualSize,
    172.                 GetSectionProtection(pImageSectionHeader[i].Characteristics),
    173.                 &dwOldProtect);
    174.         }
    175.  
    176.         ProcessRelocs((long)pbImage, dwImageBaseDelta);
    177.         ProcessImports((long)pbImage);
    178.  
    179.     } __except (EXCEPTION_EXECUTE_HANDLER)
    180.     {
    181.         goto end;
    182.     }
    183.  
    184.     hRet = (HMODULE)pbImage;
    185.  
    186. end:
    187.  
    188.     return hRet;
    189. }
    вот мой код, тестил только на паре-тройке либ, но вроде работает
     
  17. nitrotoluol

    nitrotoluol New Member

    Публикаций:
    0
    Регистрация:
    5 сен 2006
    Сообщения:
    848
    я думаю тему следует закрыть. Автор без труда смог бы найти кучу инфы, если б поискал... А так ему лень... хочет готовые решения...
     
  18. hulk45

    hulk45 New Member

    Публикаций:
    0
    Регистрация:
    18 дек 2006
    Сообщения:
    10
    Закроем обязательно как только сдам экзамен по Мобильному коду. :)) думал есть проще решения решения по загрузки библиотеки. Спасибо всем кто отвечал.