Сейчас на форуме: jinoweb, bartolomeo (+5 невидимых)

 eXeL@B —› Программирование —› Инжект длл в удаленный процесс фейлится
Посл.ответ Сообщение

Ранг: 7.5 (гость), 1thx
Активность: 0.010
Статус: Участник

Создано: 08 ноября 2016 00:18
· Личное сообщение · #1

Изучаю инжект DLL общим способом. По книге Рихтера и паре статей сделал такой код:

dll.h:
Code:
  1. #ifdef DLL_EXPORTS
  2. #define DLL_API __declspec(dllexport) 
  3. #else
  4. #define DLL_API __declspec(dllimport) 
  5. #endif
  6.  
  7. #include <windows.h>
  8.  
  9. void ShowDllForm();


dll.cpp
Code:
  1. #define DLL_EXPORTS
  2. #include "dll.h"
  3.  
  4.  
  5.  
  6. BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
  7. {
  8.     if(DLL_PROCESS_ATTACH == dwReasonForCall)
  9.     {
  10.         ShowDllForm();
  11.     }
  12.     return TRUE;
  13. }
  14.  
  15.  
  16.  
  17. void ShowDllForm()
  18. {
  19.     MessageBox(NULL, TEXT("Hello, World!"), TEXT("Injected"), MB_OK);
  20. }


ui.h
Code:
  1. #ifndef __UI_H_
  2. #define __UI_H_
  3.  
  4. #include <windows.h>
  5.  
  6. void RegisterWndClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground);
  7.  
  8. #endif
  9.  
  10. ui.cpp
  11. #include "ui.h"
  12.  
  13. void RegisterWndClass(WNDPROC Proc, LPCTSTR szName, UINT brBackground)
  14. {
  15.     WNDCLASSEX wc;
  16.  
  17.     wc.cbSize = sizeof(wc);
  18.     wc.style = CS_HREDRAW | CS_VREDRAW;
  19.     wc.lpfnWndProc = Proc;
  20.     wc.cbClsExtra = 0;
  21.     wc.cbWndExtra = 0;
  22.     wc.hInstance = GetModuleHandle(NULL);
  23.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  24.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  25.     wc.hbrBackground = (HBRUSH)brBackground;
  26.     wc.lpszMenuName = NULL;
  27.     wc.lpszClassName = szName;
  28.     wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  29.  
  30.     if (!RegisterClassEx(&wc))
  31.     {
  32.         MessageBox(NULL, TEXT("Cannot register class"), TEXT("Error"), MB_OK);
  33.     }
  34. }


main.cpp
Code:
  1. #include <windows.h>
  2. #include <Shlwapi.h>
  3. #include <TlHelp32.h>
  4. #include <string.h>
  5. #include "ui.h"
  6.  
  7. #pragma comment(lib, "Shlwapi.lib")
  8.  
  9. #define TEXTBOX_PROCESS 3000
  10. #define TEXTBOX_DLL     3001
  11. #define BUTTON_INJECT   3002
  12.  
  13. #define BUFFER_SIZE     128
  14.  
  15. TCHAR processName[BUFFER_SIZE];
  16. TCHAR dllName[BUFFER_SIZE];
  17.  
  18. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  19. BOOL StartInjection();
  20. BOOL Inject(DWORD pid);
  21.  
  22. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  23. {
  24.     HWND hMainWnd;
  25.     MSG msg;
  26.  
  27.     RegisterWndClass(WndProc, TEXT("Injector"), COLOR_WINDOW);
  28.  
  29.     hMainWnd = CreateWindow(TEXT("Injector"), TEXT("Injector"),
  30.         WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
  31.         CW_USEDEFAULT, 0, 250, 130, (HWND)NULL, (HMENU)NULL,
  32.         (HINSTANCE)hInstance, NULL);
  33.  
  34.     if (!hMainWnd)
  35.     {
  36.         MessageBox(NULL, TEXT("Can't create main window."), TEXT("Error"), MB_OK);
  37.         return GetLastError();
  38.     }
  39.  
  40.     ShowWindow(hMainWnd, nCmdShow);
  41.  
  42.     while (GetMessage(&msg, NULL, 0, 0))
  43.     {
  44.         TranslateMessage(&msg);
  45.         DispatchMessage(&msg);
  46.     }
  47. }
  48.  
  49. LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  50. {
  51.     HDC hDC;
  52.     PAINTSTRUCT ps;
  53.     RECT rect;
  54.     TCHAR buffer[BUFFER_SIZE];
  55.  
  56.     switch (uMsg)
  57.     {
  58.     case WM_CREATE:
  59.         /* Create text box containing process name */
  60.         CreateWindow(TEXT("EDIT"), NULL, WS_BORDER | WS_VISIBLE | WS_CHILD | ES_LEFT | ES_MULTILINE,
  61.             10, 10, 120, 20, hWnd, (HMENU)TEXTBOX_PROCESS, NULL, NULL);
  62.         /* Create text box containing dll name */
  63.         CreateWindow(TEXT("EDIT"), NULL, WS_BORDER | WS_VISIBLE | WS_CHILD | ES_LEFT | ES_MULTILINE,
  64.             10, 35, 120, 20, hWnd, (HMENU)TEXTBOX_DLL, NULL, NULL);
  65.         /* Create button to inject dll */
  66.         CreateWindow(TEXT("BUTTON"), TEXT("Inject"), WS_CHILD | BS_PUSHBUTTON | WS_VISIBLE,
  67.             150, 10, 60, 20, hWnd, (HMENU)BUTTON_INJECT, NULL, NULL);
  68.         break;
  69.     case WM_PAINT:
  70.         hDC = BeginPaint(hWnd, &ps);
  71.         GetClientRect(hWnd, &rect);
  72.         EndPaint(hWnd, &ps);
  73.         break;
  74.     case WM_SIZE:
  75.         break;
  76.     case WM_CLOSE:
  77.         DestroyWindow(hWnd);
  78.         break;
  79.     case WM_DESTROY:
  80.         PostQuitMessage(0);
  81.         break;
  82.     case WM_COMMAND:
  83.         switch (LOWORD(wParam))
  84.         {
  85.         case BUTTON_INJECT:
  86.             GetDlgItemText(hWnd, TEXTBOX_PROCESS, buffer, BUFFER_SIZE);
  87.             StrCpyN(processName, buffer, BUFFER_SIZE);
  88.             ZeroMemory(buffer, BUFFER_SIZE);
  89.             GetDlgItemText(hWnd, TEXTBOX_DLL, buffer, BUFFER_SIZE);
  90.             StrCpyN(dllName, buffer, BUFFER_SIZE);
  91.  
  92.             StartInjection();
  93.             break;
  94.         default:
  95.             break;
  96.         }
  97.         break;
  98.     default:
  99.         return DefWindowProc(hWnd, uMsg, wParam, lParam);
  100.     }
  101.     return 0;
  102. }
  103.  
  104. BOOL StartInjection()
  105. {
  106.     DWORD PID = 0;
  107.     PROCESSENTRY32 pe;
  108.     HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  109.     if (INVALID_HANDLE_VALUE == snapshot)
  110.     {
  111.         MessageBox(NULL, TEXT("Snapshot failed"), TEXT("ERROR"), MB_OK);
  112.         return FALSE;
  113.     }
  114.  
  115.     pe.dwSize = sizeof(PROCESSENTRY32); /* If you do not initialize dwSize, Process32First fails */
  116.     BOOL curr = Process32First(snapshot, &pe);
  117.     while (curr)
  118.     {
  119.         CharLowerBuff(pe.szExeFile, lstrlen(pe.szExeFile));
  120.         if (StrStr(pe.szExeFile, processName))
  121.         {
  122.             PID = pe.th32ProcessID;
  123.             break;
  124.         }
  125.         curr = Process32Next(snapshot, &pe);
  126.     }
  127.  
  128.     if (0 == PID)
  129.     {
  130.         MessageBox(NULL, TEXT("Process not found"), TEXT("ERROR"), MB_OK);
  131.         return FALSE;
  132.     }
  133.  
  134.     BOOL result = Inject(PID);
  135.     if (FALSE == result)
  136.     {
  137.         MessageBox(NULL, TEXT("Injection failed"), TEXT("ERROR"), MB_OK);
  138.         return FALSE;
  139.     }
  140.     return TRUE;
  141. }
  142.  
  143. BOOL Inject(DWORD pid)
  144. {
  145.     if (0 == pid)
  146.         return FALSE;
  147.  
  148.     HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
  149.     if (NULL == process)
  150.         return FALSE;
  151.  
  152.     LPVOID loadlib = GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
  153.     if (NULL == loadlib)
  154.         return FALSE;
  155.  
  156.     LPVOID libname = VirtualAllocEx(process, NULL, lstrlen(dllName),  MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  157.     if (NULL == libname)
  158.         return FALSE;
  159.  
  160.     BOOL written = WriteProcessMemory(process, libname, dllName, lstrlen(dllName), NULL);
  161.     if (FALSE == written)
  162.         return FALSE;
  163.  
  164.     HANDLE thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)loadlib, libname, 0, NULL);
  165.     if (NULL == thread)
  166.         return FALSE;
  167.  
  168.     CloseHandle(process);
  169.     return TRUE;
  170. }


В main плохая декомпозиция (завтра выделю две отдельных функции для читаемости), но разобраться можно.

Инжект не получается. Пробовал сделать инжект в сам инжектор и в эксплорер, но ничего не происходит. Когда под отладчиком делаю инжект в себя, то вижу, что успешно создается и завершается удаленный потом, но DLL-ка не подгружается. Что здесь может быть не так? Пусть к DLL прописывал и как InjDLL.dll, и как C:\InjDLL.dll, и как "C:\InjDLL.dll". Не помогло. Думал, что не хватает терминирующего нуля в конце пути к длл, поэтому добавил дополнительные байты в массиве, но это тоже не помогло.




Ранг: 338.5 (мудрец), 349thx
Активность: 2.112.42
Статус: Участник

Создано: 08 ноября 2016 00:33
· Личное сообщение · #2

ZeroMemory

Для начала вынесите MsgBox() из DllMain, так нельзя делать, вероятно оно и виснет у вас из за деадлока.

-----
vx




Ранг: 7.5 (гость), 1thx
Активность: 0.010
Статус: Участник

Создано: 08 ноября 2016 19:06
· Личное сообщение · #3

difexacaw пишет:
так нельзя делать, вероятно оно и виснет у вас из за деадлока

Почему? Можно подробнее? Допустим, у меня есть программа с гуем, которую надо скрыть из процессов. Для этого я хочу сделать ее как DLL и запускать внутри другого процесса. Так нельзя?




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 ноября 2016 23:27
· Личное сообщение · #4

ZeroMemory пишет:
Почему? Можно подробнее?

https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx

-----
IZ.RU





Ранг: 2014.5 (!!!!), 1278thx
Активность: 1.340.25
Статус: Модератор
retired

Создано: 08 ноября 2016 23:32
· Личное сообщение · #5

Подробнее смотри мсдн DllMain и её ограничения.




Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 08 ноября 2016 23:33
· Личное сообщение · #6

https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx#general_best_practices

Что-то из перечисленного в You should never perform the following tasks from within DllMain:,
делать можно, но очень сторожно, конкретное поведение зависит от версии винды и лучше обходиться без этого.

-----
IZ.RU





Ранг: 338.5 (мудрец), 349thx
Активность: 2.112.42
Статус: Участник

Создано: 09 ноября 2016 01:07 · Поправил: difexacaw
· Личное сообщение · #7

DenCoder

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

Есть же dbgprint, зачем гуй трогать, его вообще трогать не следует если кодес не гуй.

А отладчик заюзать это конечно же оверхед.

Синхронизации важны, могу привести известный пример, это бага в нт - если вы трассируете код и возникнет при этом какое либо исключение, то после рестарта инструкции начнёт трассироваться диспетчер исключений, это будет продолжаться до захвата кс, после чего возникнет деадлок. И таких ситуаций очень много, следует понимать что и когда вызвать.

Добавлено спустя 49 минут
ZeroMemory

> Допустим, у меня есть программа с гуем, которую надо скрыть из процессов. Для этого я хочу сделать ее как DLL и запускать внутри другого процесса. Так нельзя?

Гуй(ядро shadow) хранит инфу в огромном числе интернал структур, есть даже механизм пакетной обработки запросов - гуй обрабатывает системные вызовы подобно высокоуровневому фильтру. Учитывая всё сложность этой системы что то там скрыть из юзермода, да и вообще(для работы в шадов ядре нужно переключать сессии етц) - не представляется возможным даже теоретически, более того сейчас концепт скрытия таков - нет скрытых обьектов и нет детекта, тоесть сам факт сокрытия служит детектом и на это весь аверский функционал пилится.

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

-----
vx





Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 09 ноября 2016 14:13
· Личное сообщение · #8

difexacaw пишет:
и при попытке подгрузки модуля произойдёт деадлок

Есть какие-то условия, при которых MessageBox успешно выполнится из DllMain. Я так думаю, что по меньшей мере для этого требуется наличия инциализированной user32, и может быть, comctl...

difexacaw пишет:
более того сейчас концепт скрытия таков - нет скрытых обьектов и нет детекта, тоесть сам факт сокрытия служит детектом и на это весь аверский функционал пилится.

Смотря какой авер ещё! Аваст, например, просто кладезь для инжектов

-----
IZ.RU





Ранг: 338.5 (мудрец), 349thx
Активность: 2.112.42
Статус: Участник

Создано: 10 ноября 2016 13:15
· Личное сообщение · #9

DenCoder

> наличия инциализированной user32, и может быть, comctl...

Это действительно от фазы луны зависит. В любом случае следует как то отложить управление, до возврата из опасного для синхронизаций кода, например использовать механизм сообщений или синхронно это всё делать из другого потока, прежде создать его; хотя если код начинает в первый раз выполняться и в дллмайн, то старт потока нужно есчо как то обождать, так как опять же вновь созданный тред начнёт выполнять загрузчик и ту же дллмайн, ожидание может привести к взаимоблокировке. Тоесть механизм синхронизаций должен быть заранее проработан. Всегда использовались три метода, это посылка APC самому себе и обработка её перед возвратом из загрузчика, изменение в стартап контексте EP и раскрутка стека для поиска в нём адреса возврата. Есть есчо особо не рассмотренная возможность - пока вновь созданный тред не покинет стартап апк, хоть он и будет выполнять какой то код, но для get/set-context ядро будет работать именно со стартап контекстом, вроде так(позволяет скрыть работу потока :s2, но я подробно это не рассматривал.

> Смотря какой авер ещё!

Смысл был не в кривости авера или как в него залиться, а в динамик детектах, тоесть обычно находится какой то скрытый обьект и только факт его сокрытия говорит об викс активности в системе. Если все обьекты легал, то такой детект не работает. Это не только к обьектам относится, но и к памяти - нет в памяти данных, тогда и найти там сигнатуру невозможно

-----
vx


| Сообщение посчитали полезным: DenCoder


Ранг: 324.3 (мудрец), 221thx
Активность: 0.480.37
Статус: Участник

Создано: 10 ноября 2016 13:42
· Личное сообщение · #10

ZeroMemory пишет:
    BOOL written = WriteProcessMemory(process, libname, dllName, lstrlen(dllName), NULL);
    if (FALSE == written)
        return FALSE;
 
    HANDLE thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)loadlib, libname, 0, NULL);
    if (NULL == thread)
        return FALSE;


тут вообще можно просто второй раз вызвать CreateRemoteThread(), старт рутина - любая функция.

-----
IZ.RU




Ранг: 1.2 (гость), 1thx
Активность: 0=0
Статус: Участник

Создано: 11 ноября 2016 22:25
· Личное сообщение · #11

Меня иногда впечатляют русскоязычные форумы. Это же надо сделать из проблемы, которая отвечена годами назад, активный топик.
Начинать с гугла или отсюда: https://stackoverflow.com/questions/8377569/howto-call-messagebox-in-dllmain

TL; DR
DllMain обычно патчит память процесса, создает поток или что угодно в этом духе, что бы закрепится в процессе. Далее по сигналу должен начать реагировать, например, перехватите вызов ShowWindow, который вам нужен, и начинайте работать оттуда, причем это уже скорее будет в потоке основно приложения.

| Сообщение посчитали полезным: neshta


Ранг: 338.5 (мудрец), 349thx
Активность: 2.112.42
Статус: Участник

Создано: 12 ноября 2016 02:56
· Личное сообщение · #12

nicknamesarehistory

В этом и фишка. Янки не хочет знать механизмы, им надо что бы робило, решить практическую задачу. А вот у нас иначе - решение происходит из знания, причём это разворачивается, что бы понять/обьяснить суть. По этой причине понятия уровня знаний у пиндосов на форумах не существует. И впечатляет вас такое, потому что вы янки :

DllMain обычно патчит память процесса"

Смысл потерян после трансляции языковой.

-----
vx



 eXeL@B —› Программирование —› Инжект длл в удаленный процесс фейлится
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати