Вновь APC

Тема в разделе "WASM.NT.KERNEL", создана пользователем sysluck, 1 июн 2011.

  1. sysluck

    sysluck New Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    5
    Господа здравствуйте! Уперся в реализацию APC, не могу ее победить. В интернете много информации по этому поводу:

    (более-менее полные статьи)
    http://www.rsdn.ru/article/baseserv/InjectDll.xml
    http://www.opening-windows.com/techart_windows_vista_apc_internals.htm

    Но к сожалению из имеющейся информации сложно собрать нечто работающее.

    Мне требуется заинжектить в режиме юзера тестовую dll'ку в тестовый процесс, выполнить код в этом процессе.

    Код (Text):
    1. bool Inject(HANDLE hProcess, HANDLE hThread, LPCWSTR dllPath)
    2. {
    3.     SIZE_T dllPathLen = wcslen(dllPath);
    4.  
    5.     void *pmem = VirtualAllocEx(hProcess, NULL, dllPathLen + 1, MEM_COMMIT, PAGE_READWRITE);
    6.  
    7.     if (pmem) {
    8.         SIZE_T bytesWritten = 0;
    9.  
    10.         WriteProcessMemory(hProcess, pmem, dllPath, dllPathLen, &bytesWritten);
    11.  
    12.         if (dllPathLen == bytesWritten) {
    13.             if (QueueUserAPC((PAPCFUNC)GetProcAddress(LoadLibraryA("kernel32.dll"), "LoadLibraryA"), hThread, (ULONG_PTR)pmem)) {
    14.                 return true;
    15.             }
    16.         }
    17.     }
    18.  
    19.     return false;
    20. }
    Представленная функция отрабатывает успешно (происходит 'return true'), но библиотека не инжектится, не отрабатывает DllMain. Где я тупанул?

    Заранее благодарен!
     
  2. Xml

    Xml New Member

    Публикаций:
    0
    Регистрация:
    18 май 2011
    Сообщения:
    54
     
  3. sysluck

    sysluck New Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    5
    Уважаемый Xml правильно ли я понял?
    --Получается что APC могут быть добавлены в очередь (на выполнение) тредами которые принадлежат процессу. Иными словами из чужого треда APC добавить не получится, необходимо найти тред целевого процесса и добавить ему в очередь выполнения мой APC?

    Ну с этим все понятно...

    --Получается что тред не инструктируется о необходимости выполнении APC в случае когда он не находится в состоянии "alertable".

    Вопрос состоит в очередности, тред должен перейти в состояние "alertable" после того как я добавил свой APC, или тред необходимо перевести в это состояние до того как добавлять свой APC
     
  4. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    sysluck
    Да, только если перейдет в "alertable".
     
  5. Xml

    Xml New Member

    Публикаций:
    0
    Регистрация:
    18 май 2011
    Сообщения:
    54
    APC будет вызвана только если поток находится в состоянии alertable
    из режима пользователя для удаленного потока в общем случае это(узнать/переключить его состояние) не решить
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    sysluck
    Чужими тоже могут, но это не рекомендуется - типа "кабы чего не вышло" ;)

    Вопрос не в очередности, а в том, можешь ли ты быть уверен в том, что целевой поток вообще когда-либо переходит в состояние alertable, поскольку, если он сам в это состояние не переходит (вызовом соотв-х Ex-функций), то заставить его сделать это извне невозможно (если только исхитриться выставить APC потоку, который уже создан, но еще не начал выполняться - тогда APC будет вызвана перед стартом потока)
     
  7. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    sysluck
    Если бы данное действие было бы реализовано в кернеле, то никто не мешает выставить флаг Alertable в структуре EPROCCESS.
     
  8. Xml

    Xml New Member

    Публикаций:
    0
    Регистрация:
    18 май 2011
    Сообщения:
    54
    и правда, тема то в WASM.NT.KERNEL
     
  9. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    TermoSINteZ
    Насколько я понимаю, этого не достаточно -- надо сделать, чтобы поток уснул, а не только выставлять Alertable.
     
  10. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Mika0x65
    Хм.. ну тут на самом деле я встречался с разными ситуациями , в зависимости от версии Винды. Помоему в 2003 сервере сп1 была такая фигня, что выставляя Alertable, APC все равно не исполнялось. Но уже не помню. Давно делал.
    на всякий случай запощу ссылку, где довольно немало инфы про APC. линк. Вдруг кто не видел еще. Ну и конечно же там 7 страниц, так что не просмотрите.
     
  11. sysluck

    sysluck New Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    5
    Уважаемый leo проблема в каком-то другом месте, инжект APC не происходит для треда который гарантированно переходит в состояние "alertable"

    Программа с потоком который переходит в состояние "alertable" (гарантировано)
    Код (Text):
    1. // alertable.cpp : Defines the entry point for the console application.
    2. //
    3.  
    4. #include "stdafx.h"
    5. #include "windows.h"
    6. #include <iostream>
    7. #include <string>
    8.  
    9. using namespace std;
    10.  
    11. int _tmain(int argc, _TCHAR* argv[])
    12. {
    13.     string str;
    14.  
    15.     while ((cin >> str) != "exit")
    16.     {
    17.         SleepEx(1000, true);
    18.  
    19.         cout << str;
    20.     }
    21.  
    22.     return 0;
    23. }
    Вот код dll'ки которую хочу заинжектить

    Код (Text):
    1. // dllmain.cpp : Defines the entry point for the DLL application.
    2. #include "stdafx.h"
    3.  
    4. BOOL APIENTRY DllMain( HMODULE hModule,
    5.                        DWORD  ul_reason_for_call,
    6.                        LPVOID lpReserved
    7. )
    8. {
    9.     MessageBeep(MB_ICONWARNING);
    10.     return TRUE;
    11. }
    Вот код самого инжектора:
    Код (Text):
    1. // test.cpp : Defines the processEntry point for the console application.
    2. //
    3.  
    4. #include "stdafx.h"
    5. #include <windows.h>
    6. #include <tlhelp32.h>
    7.  
    8. typedef enum _SECTION_INHERIT {
    9.     ViewShare = 1,
    10.     ViewUnmap = 2
    11. } SECTION_INHERIT, *PSECTION_INHERIT;
    12.  
    13. //typedef unsigned long NTSTATUS;
    14.  
    15. typedef struct _UNICODE_STRING {
    16.     USHORT Length;
    17.     USHORT MaximumLength;
    18.  
    19. #ifdef MIDL_PASS
    20.     [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
    21. #else // MIDL_PASS
    22.     PWSTR  Buffer;
    23. #endif // MIDL_PASS
    24. } UNICODE_STRING, *PUNICODE_STRING;
    25.  
    26. typedef struct _OBJECT_ATTRIBUTES {
    27.   ULONG           Length;
    28.   HANDLE          RootDirectory;
    29.   PUNICODE_STRING ObjectName;
    30.   ULONG           Attributes;
    31.   PVOID           SecurityDescriptor;
    32.   PVOID           SecurityQualityOfService;
    33. }  OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
    34.  
    35.  
    36. bool Inject(HANDLE hProcess, HANDLE hThread, LPCWSTR dllPath)
    37. {
    38.     SIZE_T dllPathLen = wcslen(dllPath);
    39.  
    40.     void *pmem = VirtualAllocEx(hProcess, NULL, dllPathLen + 1, MEM_COMMIT, PAGE_READWRITE);
    41.  
    42.     if (pmem)
    43.     {
    44.         SIZE_T bytesWritten = 0;
    45.  
    46.         WriteProcessMemory(hProcess, pmem, dllPath, dllPathLen, &bytesWritten);
    47.  
    48.         if (dllPathLen == bytesWritten)
    49.         {
    50.             if (QueueUserAPC((PAPCFUNC)GetProcAddress(LoadLibraryA("kernel32.dll"), "LoadLibraryA"), hThread, (ULONG_PTR)pmem))
    51.             {
    52.                 return true;
    53.             }
    54.         }
    55.     }
    56.  
    57.     return false;
    58. }
    59.  
    60. int main(void)
    61. {
    62.     HANDLE hThread;
    63.     HANDLE hProcess;
    64.     DWORD threadID;
    65.     DWORD processID;
    66.     OBJECT_ATTRIBUTES attributes = {sizeof(OBJECT_ATTRIBUTES)};
    67.  
    68.     THREADENTRY32 threadEntry;
    69.     PROCESSENTRY32 processEntry;
    70.  
    71.     threadEntry.dwSize = sizeof(THREADENTRY32);
    72.     processEntry.dwSize = sizeof(PROCESSENTRY32);
    73.  
    74.     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, NULL);
    75.  
    76.     if (Process32First(snapshot, &processEntry) == TRUE)
    77.     {
    78.         while (Process32Next(snapshot, &processEntry) == TRUE)
    79.         {  
    80.             if (_wcsicmp(processEntry.szExeFile, L"alertable.exe") == 0)
    81.             {  
    82.                 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID = processEntry.th32ProcessID);
    83.                 break;
    84.             }
    85.         }
    86.     }
    87.  
    88.     if (Thread32First(snapshot, &threadEntry) == TRUE)
    89.     {
    90.         while (Thread32Next(snapshot, &threadEntry))
    91.         {
    92.             if (threadEntry.th32OwnerProcessID == processID)
    93.             {
    94.                 hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadID = threadEntry.th32ThreadID);
    95.                 break;
    96.             }
    97.         }
    98.     }
    99.  
    100.     Inject(hProcess, hThread, L"skunk.dll");
    101.  
    102.     CloseHandle(snapshot);
    103.  
    104.     return 0;
    105. }
     
  12. sysluck

    sysluck New Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    5
    Уважаемый Xml, миллион извинений, NT.KERNEL это то куда я хотел бы попасть... :)
     
  13. shchetinin

    shchetinin Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    715
    Переводить чужой поток в alertable опастное дело ... Не которые функции, не коректно работают с alertable потоками.
    Например connect(кажется она, было не сколько месяцов назад), при входе в которую будет отрабатыватся APC, и функция возврощает success, а вот WSAGetLastError говорил об обратном ... Могут быть крахи приложений ...
     
  14. gaeprust

    gaeprust New Member

    Публикаций:
    0
    Регистрация:
    2 май 2011
    Сообщения:
    188
    Плохой способ. Я бы обождал тред, получил его контекст, получил стек, понизил SFN до необходимого(это например если тред в загрузчике) и выполнил свой код. APC в функциях, в которых не планируется её доставка нарушит работу потока.
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    sysluck
    Оригинально - берешь юникодную строку, копируешь из нее dllPathLen байт и пытаешься вызвать LoadLibraryA в надежде, что из этой каши получится нечто удобоваримое?! ;)
     
  16. sysluck

    sysluck New Member

    Публикаций:
    0
    Регистрация:
    27 май 2011
    Сообщения:
    5
    leo можешь собой гордиться, единственный человек действительно вникнувший в проблему. Порой перемкнет, и проблему пробуешь найти там где ее нет...