ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Робота з процесами в С / С + +. Основні прийоми
         

     

    Інформатика, програмування

    Робота з процесами в С/С + +. Основні прийоми

    Тимур Хабібуллін

    Дана стаття розповідає про роботу з процесами, модулями, купами і потоками за допомогою біліотекі TOOLHELP

    Робота з процесами - основа, без якої займатися системним програмуванням так само безглуздо, як без знання структури PE-файлів або організації пам'яті. Тому я піднімаю цю тему знову і розповім про роботу з процесами за допомогою функцій TOOLHELP.

    Мова програмування: я вибрав C (без плюсиков, тому що роботи з класами в цій статті не буде - після прочитання ви зможете їх без праці скласти самі) з багатьох причин і в першу чергу через його нізкоуровнего взаємодії з пам'яттю ... записав-вважав, все просто і зрозуміло.

    Перерахувати запущені в системі процеси можна по-різному, я звик користуватися функціями TOOLHELP. Загальна послідовність дій при роботі з цією бібліотекою: робимо "знімок" (Snapshot) системної інформації, яка нам необхідна, потім бігаємо по процесах (а також модулів і купах). Тому почнемо з простого - перерахуємо всі процеси.

    // Перерахування процесів

    int EnumerateProcs (void)

    (

    // створюємо "знімок" інформації про процеси

    // перший параметр функції - константа, яка визначає,

    // яку інформацію нам потрібно "зняти", а друга -

    // ідентифікатор процесу, до якого належить ця

    // інформація. У даному випадку це 0 тому що ми робимо

    // знімок всіх процесів

    HANDLE pSnap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);

    bool bIsok = false;

    // Структура, в яку будуть записані дані процесу

    PROCESSENTRY32 ProcEntry;

    // встановимо її розмір, це необхідну дію

    ProcEntry.dwSize = sizeof (ProcEntry);

    // тепер визначимо перший процес

    // перший параметр функції - Хендлі "знімка" інформації

    // другому - адреса структури PROCESSENTRY32

    // true - у випадку удачі, false - в разі невдачі

    bIsok = Process32First (pSnap, & ProcEntry);

    // тут можна було вставити розкішний цикл for (....) але це

    // не зовсім легкість для читання

    // так що цикл while

    while (bIsok)

    (

    // друкуємо ім'я процесу, ідентифікацію

    // тепер, коли у нас є структура ProcEntry

    // Те, яку інформацію ви з неї візьмете, залежить

    // тільки від завдання))

    printf ( "% s % un ", ProcEntry.szExeFile, ProcEntry.th32ProcessID);

    bIsok = Process32Next (pSnap, & ProcEntry);

    )

    // чистим пам'ять!

    CloseHandle (pSnap);

    return 1;

    )

    Вуаля, список всіх процесів, аки за допомогою диспетчера завдань. Тепер ми зробимо дещо, чого за допомогою диспетчера немає! В адресному просторі кожного процесу (в області пам'яті, виділеної йому системою) знаходяться різні бібліотеки, які, власне, складали ДОДАТОК. Це і Kernel32 і GDI і ще безліч різних. Наше завдання - їх все перерахувати і переписати! Для цього дійства напишемо невелику функцію.

    // Перерахування модулів процесу

    int EnumerateModules (DWORD PID)

    (

    // Вхідний параметр - ідентифікатор процесу, чиї модулі ми збираємося

    // перераховувати. По-перше створимо snapshot інформації про модулях

    // тепер нам потрібна інформація про конкретному процесі -- процесі

    // з ідентифікатором PID

    HANDLE pMdlSnap = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, PID);

    bool bIsok = false;

    // структура з інформацією про модуль

    MODULEENTRY32 MdlEntry;

    // задамо розмір

    MdlEntry.dwSize = sizeof (MODULEENTRY32);

    // і знайдемо перший модуль

    bIsok = Module32First (pMdlSnap, & MdlEntry);

    // і далі, як і з процесами

    while (bIsok)

    (

    // друкуємо ім'я модуля

    printf ( "% s n", MdlEntry.szModule);

    // і переходимо до наступного

    bIsok = Module32Next (pMdlSnap, & MdlEntry);

    )

    // чистим пам'ять!

    CloseHandle (pMdlSnap);

    return 1;

    )

    А тепер трохи пригальмуємо і подивимося, яку ще інформацію про процеси і модулях ми отримуємо:

    typedef struct tagPROCESSENTRY32 (

    DWORD dwSize; //Рамер структур

    DWORD cntUsage;// числі посилання на процес. Процес знищується,// коли число посилань стає 0

    DWORD th32ProcessID;// Ідентифікатор процесу - необхідний

    // в багатьох функціях

    DWORD th32DefaultHeapID;// Ідентифікатор основний купи -- має

    // сенс тільки в функціях toolhelp

    DWORD th32ModuleID;// ідентифікатор модуля - має

    // сенс тільки в функціях toolhelp

    DWORD cntThreads;// Число потоків

    DWORD th32ParentProcessID;// Ідентифікатор батька -- повертається

    // Навіть якщо батька вже немає

    LONG pcPriClassBase;// пріоритет за замовчуванням всіх //створюваних процесом потоків

    DWORD dwFlags;// Зарезервовано

    CHAR szExeFile [MAX_PATH];// Власне ім'я процесу

    ) PROCESSENTRY32, * PPROCESSENTRY32, * LPPROCESSENTRY32;

    typedef struct tagMODULEENTRY32 (

    DWORD dwSize; //розмір структури

    DWORD th32ModuleID;// ідентифікатор модуля

    DWORD th32ProcessID;// ідентифікатор процесу, до якого відноситься

    // модуль

    DWORD GlblcntUsage; //загальне число посилань на цей модуль

    DWORD ProccntUsage; //число посиланням у контексті процесу,

    // по ідентифікатором якого був створений

    // снепшот. Якщо дорівнює 65535 - модуль довантажуючи

    // неявно

    BYTE * modBaseAddr; //адреса модуля в контексті процесу

    DWORD modBaseSize; //розмір проекції

    HMODULE hModule;// посилання на модуль

    char szModule [MAX_MODULE_NAME32 + 1];// Назва модуля

    char szExePath [MAX_PATH];// Повний шлях до модуля

    ) MODULEENTRY32, * PMODULEENTRY32, * LPMODULEENTRY32;

    Зверніть внманіе: посилання на модуль (параметр hModule) - це перший байт ДОС-заголовка! Таким чином, ми отримуємо можливість працювати з проекцією при деякому знанні структури PE-файлів. Зокрема, ми можемо прочіатать таблицю імпорту, і, як правило, - навіть переписати її (це використовується під час перехоплення АПИ). Параметр szExePath має свій "заскок" - іноді повний шлях до модуля повертається з дивними вставками і, наприклад, всесто "c: windowssystem32advapi32.dll" я іноді отримую "c: x86_proc_winsyspathadvapi32.dll". Як правило для системних завдань середньої складності (перехоплення апі, або, навпаки, перехоплення стелс) всього вищеописаного вистачає. Але на цьому можливості toolhelp не вичерпуються і тепер ми побігає по потоках! Робота з потоками дещо відрізняється від роботи з модулями - навіть якщо ми зробимо знімок, задавши ідентифікатор якого-небудь процесу, функція Thread32Next не зупиниться, поки не пробіжить по ВСІХ потоків у системі. Тому ми повинні перевіряти, до якого процесу належить потік - благо, у структурі THREADENTRY32 є член th32OwnerProcessID -- ідентифікатор породжувача потік процесу. Таким чином:

    int EnumerateThreads (DWORD PID)

    (

    // Почнемо з створення знімка

    HANDLE pThreadSnap = CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, PID);

    bool bIsok = false;

    // Структура, що описує потік

    THREADENTRY32 ThrdEntry;

    // ставимо розмір

    ThrdEntry.dwSize = sizeof (THREADENTRY32);

    // Беремо перший потік

    bIsok = Thread32First (pThreadSnap, & ThrdEntry);

    // і бігаємо по всіх потоків ...

    while (bIsok)

    (

    // перевіряємо, тому чи процесу належить потік

    if (ThrdEntry.th32OwnerProcessID == PID)

    (

    // Якщо так, то виводимо некотурую інформацію ...

    // Хоч вона нікому нафіг не потрібна: о)

    printf ( "% u % un ", ThrdEntry.th32OwnerProcessID, ThrdEntry.th32ThreadID);

    )

    bIsok = Thread32Next (pThreadSnap, & ThrdEntry);

    )

    // не забуваємо чистити пам'ять

    CloseHandle (pThreadSnap);

    return 1;

    )

    Ну ось, у нас є потоки. Що ще залишилося? Правильно, залишилися купи. Тут теж все дуже просто:

    int EnumerateHeaps (DWORD PID)

    (

    // Перший параметр - ідентифікатор процесу

    // а друга - основна купа

    // Тепер робимо знімок, щоб перерахувати купки ...

    HANDLE pSnapHeaps = CreateToolhelp32Snapshot (TH32CS_SNAPHEAPLIST, PID);

    bool bIsok = false;

    bool bIsokHeap = false;

    // Структура, в яку будуть записуватися дані списку купи

    HEAPLIST32 HpLst;

    // Структура, в яку будуть записуватися дані

    // непосредствнно БЛОКІВ купи

    HEAPENTRY32 HpEntry;

    // Ставимо розміри ...

    HpLst.dwSize = sizeof (HEAPLIST32);

    HpEntry.dwSize = sizeof (HEAPENTRY32);

    bIsok = Heap32ListFirst (pSnapHeaps, & HpLst);

    while (bIsok)

    (

    // Тепер перераховуємо блоки купи

    // цей код я привів, щоб стало зрозуміло

    // як отримати дані по блоках

    // але він жере багато часу

    // так що я його закомментірую - якщо вам цікаво

    // можете поганяти ...

    /* bIsokHeap = Heap32First (& HpEntry, PID, HpLst.th32HeapID);

    while (bIsokHeap)

    (

    // Виводимо трохи інформації

    printf ( "% u n", HpEntry.dwBlockSize);

    // Крокуємо далі

    bIsokHeap = Heap32Next (& HpEntry);

    }*/

    // виводимо інфу про купу загалом

    printf ( "% u n", HpLst.dwSize);

    // крокуємо далі

    bIsok = Heap32ListNext (pSnapHeaps, & HpLst);

    )

    CloseHandle (pSnapHeaps);

    return 1;

    )

    Ну от, тепер струму залишилося написати про структури THREADENTRY32, HEAPENTRY32 і HEAPLIST32:

    typedef struct tagTHREADENTRY32 (

    DWORD dwSize;// розмір структури

    DWORD cntUsage;// число посилань

    DWORD th32ThreadID;// ідентифікатор

    DWORD th32OwnerProcessID;// батьківський процес

    LONG tpBasePri;// основний пріоритет (при ініціалізації)

    LONG tpDeltaPri;// зміна пріоритету

    DWORD dwFlags;// зарезервовано

    ) THREADENTRY32;

    typedef THREADENTRY32 * PTHREADENTRY32;

    typedef THREADENTRY32 * LPTHREADENTRY32;

    typedef struct tagHEAPENTRY32

    (

    DWORD dwSize; //розмір структури

    HANDLE hHandle; //Хендлі цього блоку

    DWORD dwAddress;// лінійний адреса початку блоку

    DWORD dwBlockSize; //Розмір блоку в байтах

    DWORD dwFlags;// прапори

    /*

    LF32_FIXED Блок пам'яті має фіксовану позицію

    LF32_FREE Блок пам'яті не використовується

    LF32_MOVEABLE Блок пам'яті може переміщатися

    */

    DWORD dwLockCount; число "замків"

    DWORD dwResvd;// зарезервовано

    DWORD th32ProcessID;// батьківський процес

    DWORD th32HeapID;// ідентифікатор купи

    ) HEAPENTRY32;

    typedef HEAPENTRY32 * PHEAPENTRY32;

    typedef HEAPENTRY32 * LPHEAPENTRY32;

    typedef struct tagHEAPLIST32

    (

    DWORD dwSize; //розмір структури

    DWORD th32ProcessID;// батьківський процес

    DWORD th32HeapID;// купа в контексті процесу

    DWORD dwFlags;// прапор. Значення завжди одне:

    // HF32_DEFAULT - основна купа процесу

    ) HEAPLIST32;

    виклики функцій EnumerateHeaps, EnumerateThreads і EnumerateModules можна проводити з EnumerateProcs. Всі скомпіліно в Visual C + + 6.0. У тексті використано інформацію з MSDN і книги Джеффрі Ріхтера "Створення ефективних win32 програм" (имхо ця книга - настільна для системного програміста).

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.realcoding.net

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status