Работа с Peb->Ldr->*

Тема в разделе "WASM.NT.KERNEL", создана пользователем WIN32, 15 мар 2007.

  1. WIN32

    WIN32 Member

    Публикаций:
    0
    Регистрация:
    20 янв 2007
    Сообщения:
    338
    Привет, в общем мне надо пробежататься по списку всех модулей процесса в его АП и удалить некоторые :) ничего особенного, просто спортивный интерес. Значит что уже сделано, получаю список процессов , получаю их EPROCESS, сравниваю с CurrentProcess и если это не он ( дабы не убивать систему ) я аттачусь к процессу , затем иду до EPROCESS->Peb->Ldr а дальше лес гремучий =( Двухсвязанные списки...в общем вот что я набросал :
    Код (Text):
    1. void    DeleteModulesFromProcess()
    2. {
    3.     /*
    4.     Пробегаеться по списку процессов и приаттачиваеться к ним, потом удаляет заданные модули в PEB этих процессов
    5.     */
    6.     struct _SYSTEM_PROCESS                  *pBuff = NULL;
    7.     struct _SYSTEM_PROCESS                  *pBuff2 = NULL;
    8.  
    9.     ULONG                                   uBuffSize = 0x100000;
    10.     NTSTATUS                                nStat;
    11.     PEPROCESS                               peCurProc;
    12.     PEPROCESS                               peProcess;
    13.     PPEB_LDR_DATA                           pLdrData;
    14.     PLIST_ENTRY                             pUserModuleListHead;
    15.     PLIST_ENTRY                             pUserModuleListPtr;
    16.  
    17.     UNICODE_STRING                          usStr1;
    18.     UNICODE_STRING                          usStr2;
    19.     UNICODE_STRING                          usModuleName;
    20.    
    21.     ANSI_STRING                             szModuleName;
    22.     ANSI_STRING                             process_name;
    23.     ANSI_STRING                             szThisProcessName;
    24.         char                                                                    szMyModule[]="ntdll.dll";
    25.  
    26.  
    27.     // Получаем EPROCESS текущего процесса
    28.     peCurProc = PsGetCurrentProcess();
    29.  
    30.     // Переводим имя образа в верхний регистр
    31.     RtlInitAnsiString(&szThisProcessName,peCurProc->ImageFileName);
    32.     // UPCASE OUR PROCESSNAME
    33.     RtlAnsiStringToUnicodeString(&usStr1,&szThisProcessName,TRUE);
    34.     RtlInitUnicodeString(&usStr2,L"");
    35.     RtlUpcaseUnicodeString(&usStr2,&usStr1,TRUE);
    36.     RtlUnicodeStringToAnsiString(&szThisProcessName,&usStr2,TRUE);
    37.     RtlFreeUnicodeString(&usStr2);
    38.     RtlFreeUnicodeString(&usStr1);
    39.  
    40.     pBuff = ExAllocatePool(PagedPool,uBuffSize);
    41.     nStat = ZwQuerySystemInformation(5,pBuff,uBuffSize,&uBuffSize);
    42.     if (nStat == STATUS_SUCCESS || nStat == STATUS_INFO_LENGTH_MISMATCH)
    43.     {
    44.         pBuff2 = ExAllocatePool(PagedPool,uBuffSize);
    45.         nStat = ZwQuerySystemInformation(5,pBuff2,uBuffSize,&uBuffSize);
    46.         PrintStatus("ZwQuerySystemInformation",nStat);
    47.         DbgPrint("%d",uBuffSize);
    48.         if (NT_SUCCESS(nStat))
    49.         {
    50.             struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)pBuff2;
    51.             struct _SYSTEM_PROCESSES *prev = NULL;                                      
    52.  
    53.             while(curr)                                                                
    54.             {
    55.                 // UPCASE ALL PROCESSES NAMES
    56.                 RtlUnicodeStringToAnsiString(&process_name, &(curr->ProcessName), TRUE);
    57.                 RtlAnsiStringToUnicodeString(&usStr1,&process_name,TRUE);
    58.                 RtlUpcaseUnicodeString(&usStr2,&usStr1,TRUE);
    59.                 RtlFreeAnsiString(&process_name);
    60.                 RtlUnicodeStringToAnsiString(&process_name,&usStr2,TRUE);
    61.                 RtlFreeUnicodeString(&usStr1);
    62.                 RtlFreeUnicodeString(&usStr2);
    63.  
    64.                 // Запущенный процесс szThisProcessName.Buffer
    65.                 // Процесс со списка  process_name.Buffer
    66.                 //#########################################################################################################################
    67.                 if (strstr(process_name.Buffer,szThisProcessName.Buffer))
    68.                 {
    69.                     DbgPrint("Dont Attach to our process");
    70.                 }   else    {
    71.                     nStat = PsLookupProcessByProcessId((HANDLE)curr->ProcessId,&peProcess);
    72.                     if (NT_SUCCESS(nStat))
    73.                     {
    74.                         __try
    75.                         {
    76.                             KeAttachProcess(peProcess);
    77.                             DbgPrint("0x0%X Ldr",&peProcess->Peb->Ldr);
    78.                             KeDetachProcess();
    79.                         }
    80.                         __except(EXCEPTION_EXECUTE_HANDLER)
    81.                         {
    82.                             DbgPrint("KeAttachProcess 0x%X",&peProcess->Peb);
    83.                         }                      
    84.                     }
    85.                 }
    86.                 //#########################################################################################################################
    87.            
    88.                 RtlFreeAnsiString(&process_name);
    89.                
    90.                 if(curr->NextEntryDelta)
    91.                 {
    92.                     ((char *)curr += curr->NextEntryDelta);
    93.                 }   else    {
    94.                     curr = NULL;
    95.                 }
    96.             }
    97.             ExFreePool(pBuff2);
    98.         }
    99.     }
    100. }
    Какие будут идеи ?
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    pEntry - указывает на элемент который тебе надо удалить из списка.
    Код (Text):
    1.                 (pEntry->Blink)->Flink = pEntry->Flink;
    2.                 (pEntry->Flink)->Blink = pEntry->Blink;
    Ну или воспользоваться стандартным макросом RemoveEntryList, код которого повто
     
  3. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    это же элементарно по сравнению со всем остальным кодом =) главное четко себе представлять как они работают.
    Есть поле Flink, указывающее на следующий элемент (Forward link) и Blink, указывающее на предыдущий элемент (Backward link). Чтобы удалить элемент из списка, достаточно чтобы предыдущий и следующий элементы от удаляемого ссылались друг на друга. Это как раз делает приведенный n0name код.
     
  4. WIN32

    WIN32 Member

    Публикаций:
    0
    Регистрация:
    20 янв 2007
    Сообщения:
    338
    Я понял спасибо, вопрос в том как получить имя DLL и что за структуры в Flink,Blink ?
     
  5. nester7

    nester7 New Member

    Публикаций:
    0
    Регистрация:
    5 дек 2003
    Сообщения:
    720
    Адрес:
    Russia
    Разберись со списками, они везде.
    Ручку с бумагой в зубы и фигачим рисуночки )


    http://msk.nestor.minsk.by/kg/2004/39/kg43902.html
    http://beta.delta-z.com/index.php/archives/222
    http://algolist.ncstu.ru/ds/basic/simple_list.php
     
  6. WIN32

    WIN32 Member

    Публикаций:
    0
    Регистрация:
    20 янв 2007
    Сообщения:
    338
    Это понятно, я говорю где данные храняться ? =(
    Блин яд от этого хардкор кодинга чёто плохо себя чуствую :-(
     
  7. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    ты показываешь базовую структуру LIST_ENTRY.
    Все системные списки выглядят примерно так:

    Код (Text):
    1. struct LIST
    2. {
    3.   LIST_ENTRY List;
    4.   void* data;
    5. };
    Короче LIST_ENTRY содержит только указатели. А списочные структуры в себя её включают в качестве первого элемента. Если у тебя есть указатель на LIST* но в виде LIST_ENTRY* тебе надо сделать так:

    Код (Text):
    1. LIST_ENTRY* YourPointer;
    2. ((LIST*)YourPointer)->data // это будут данные
    Мой пример абстрактен, но ты должен был понять главное ) Ложки нет :) блин, меня понесло... короче ты понял надеюсь)
     
  8. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    typedef struct _LDR_MODULE {

    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID BaseAddress;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
    ULONG Flags;
    SHORT LoadCount;
    SHORT TlsIndex;
    LIST_ENTRY HashTableEntry;
    ULONG TimeDateStamp;

    } LDR_MODULE, *PLDR_MODULE;

    Смотри - у тебя есть указатель на структуру _LDR_MODULE . InMemoryOrderModuleList - это и есть тот LIST_ENTRY, из которого ты получаешь предыдущую/следующую структуру. А остальные данные хранятся в самой _LDR_MODULE.
     
  9. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    asd
    ну вообщем я это почти и сказал) просто структуры под рукой не было
     
  10. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Даже EPROCESS? :P
     
  11. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    да ну тебя) я его, конечно, в виду не имел.
     
  12. WIN32

    WIN32 Member

    Публикаций:
    0
    Регистрация:
    20 янв 2007
    Сообщения:
    338
    пойду убьюсь об стену...не лучше посплю...убьюсь и посплю...запутался что сначало ? убиться или поспать ?
     
  13. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    мдя))
    короче. LIST_ENTRY - это шаблонная мини-структурка. Она содержит только указатели вперед и назад. сами данные хранятся после этих указателей сразу же.
    Для удобства определяют "оберточные" структуры типа LDR_MODULE.
     
  14. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Вспомнилась знатная задача Лбиса Керолла. Предположим человек если человек не ел 7 суток, то он помирает, то же самое и для сна. Один человек не ел и не спал почти неделю. Что надо сделать сначала - поесть, или поспать?
     
  15. asd

    asd New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2005
    Сообщения:
    952
    Адрес:
    Russia
    Ну а я твоего поста не видел, когда писал. А стирать не хотелось.

    WIN32
    Вот кое-что нашёл в одном из сорцов. И у MS_Rem-а в статьях про перехват вроде был код на делфи.
    Код (Text):
    1. GetAllModule        proc
    2.     assume  fs:nothing
    3.     mov      eax, fs:[30h]
    4.     mov      eax, [eax+PEB.LoaderData]
    5.     add      eax, PEB_LDR_DATA.InLoadOrderModuleList
    6.     xor edx,edx
    7.     xor ecx,ecx
    8.     mov eax,[eax]
    9. @1:
    10.     push eax                              ;eax - óêàçàòåëü íà LDR_MODULE
    11.     call InterceptAllFunctionInModule
    12.     mov eax, [eax+LDR_MODULE.InLoadOrderModuleList.Flink]
    13.     mov esi, [eax+LDR_MODULE.BaseAddress]
    14.     cmp eax,edx
    15.     jb last_module
    16.     inc ecx
    17.     mov edx,eax
    18.     jmp      @1
    19. last_module:
    20.     ret
    21. GetAllModule        endp
    22.  
    23. InterceptAllFunctionInModule    proc    LDR_:dword
    24.     pushad
    25.     mov eax,LDR_
    26.     lea edi,[eax+LDR_MODULE.BaseDllName]
    27.     mov edi,[edi+UNICODE_STRING.Buffer]     ;pointer on module name
    28.     mov module_name_off,edi
    29. .......