Вывод в "чужую" консоль

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

  1. set

    set New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2006
    Сообщения:
    27
    Как можно реализовать ввод/вывод из/в чужую консоль? Вообще это возможно?
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    в смысле "чужую". если добудешь себе хендл этой "чужой" консоли, выводи сколько хочешь. хендл можешь добыть через удаленное выполнение кода с DuplicateHandle
     
  3. set

    set New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2006
    Сообщения:
    27
    DuplicateHandle копирует не все типы хендлов. Именно stdhadle's он некопирует
     
  4. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    ну тогда просто инжектни код в другой процесс по выводу и вводу и все ) и обмену с твоим процессом какнить, например, через shared-секцию или Read/WriteProcessMemory
     
  5. set

    set New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2006
    Сообщения:
    27
    Это будет слишком грамоздко и не удобно. Надо что нибудь по-проще. Только что-то не могу придумать.
     
  6. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    не так уж и громоздко.

    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3.  
    4. #pragma comment(linker, "/BASE:0x2a000000")
    5.  
    6. HWND hWndConsole = NULL;
    7.  
    8. BOOL WINAPI EnumWindowProc( HWND hWnd, LPARAM )
    9. {
    10.     char title[1024];
    11.     GetWindowText( hWnd, title, 1024 );
    12.     if( !stricmp(title, "H:\\WINDOWS\\System32\\cmd.exe") )
    13.     {
    14.         hWndConsole = hWnd;
    15.         return FALSE;
    16.     }
    17.     return TRUE;
    18. }
    19.  
    20. bool TransferProgramEx(HANDLE hProcess)
    21. {
    22.     HMODULE g_module = GetModuleHandle(0);
    23.     VirtualFreeEx(hProcess, g_module, 0, MEM_RELEASE);
    24.    
    25.     DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(g_module) + ((PIMAGE_DOS_HEADER)(g_module))->e_lfanew +
    26.         sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
    27.  
    28.     char *pMem = (char *)VirtualAllocEx(hProcess, g_module, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    29.     if(pMem == NULL) return FALSE;
    30.        
    31.     DWORD dwOldProt, dwNumBytes, i;
    32.     MEMORY_BASIC_INFORMATION mbi;
    33.      
    34.     VirtualQueryEx(hProcess, pMem, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    35.     while (mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0)
    36.     {
    37.         if (!(mbi.Protect & PAGE_GUARD))
    38.         {
    39.             for (i = 0; i < mbi.RegionSize; i += 0x1000)
    40.             {
    41.                 VirtualProtectEx(hProcess, pMem + i, 0x1000,PAGE_EXECUTE_READWRITE, &dwOldProt);
    42.                 WriteProcessMemory(hProcess, pMem + i, pMem + i, 0x1000, &dwNumBytes);
    43.             }
    44.         }
    45.         pMem += mbi.RegionSize;
    46.         VirtualQueryEx(hProcess, pMem, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    47.     }
    48.  
    49.     return true;
    50. }
    51.  
    52. DWORD WINAPI RemoteWriteThread( LPVOID p )
    53. {
    54.     HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
    55.  
    56.     char *msg = (char*)p;
    57.     DWORD t;
    58.  
    59.     WriteConsole( hConsole, msg, strlen(msg), &t, 0 );
    60.  
    61.     return 0;
    62. }
    63.  
    64. int main( )
    65. {
    66.     EnumWindows( EnumWindowProc, 0 );
    67.     if( hWndConsole == NULL )
    68.         return printf("Console window searching failed\n"),0;
    69.  
    70.     DWORD ProcessId, ThreadId = GetWindowThreadProcessId( hWndConsole, &ProcessId );
    71.  
    72.     HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, 0, ProcessId );
    73.     if( hProcess == NULL )
    74.         return printf("Cannot open process\n"), 0;
    75.  
    76.     if( !TransferProgramEx( hProcess ) )
    77.         return printf("Cannot copy body\n"), 0;
    78.  
    79.     DWORD thID;
    80.     HANDLE hTh;
    81.  
    82.     printf("Writing..\n");
    83.     hTh = CreateRemoteThread( hProcess, 0, 0, RemoteWriteThread, "Hello, World!!", 0, &thID);
    84.     WaitForSingleObject( hTh, INFINITE );
    85.  
    86.     CloseHandle( hProcess );
    87.     return 0;
    88. }
     
  7. roman_pro

    roman_pro New Member

    Публикаций:
    0
    Регистрация:
    9 фев 2007
    Сообщения:
    291
    Ну можно в CreateProcess указать перенаправление в пайпы например и делать ввод/вывод через них.
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    roman_pro
    я думаю, что CreateProcess ему не нужен, ему надо вводить/выводить в консоль работающего процесса
     
  9. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Great
    Чёт в упор не пойму зачем это переписывать сам в себя
     
  10. wasm_test

    wasm_test wasm test user

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

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Н-да, надо было идти спать)
    [added]
    Ну а всё-таки можно же было скопировать на свободное место и только код потока? Зачем обязательно затирать? Тем более мы даже не суспендим ничего, а так просто, поверх. Да и зачем столько проверок по VirtualQuery? /предположение заведомо, что кроме нас кто-то меняет атрибуты на отдельные страницы? Почему бы сразу весь объём памяти не перенести?/
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    можно. только влом реализовывать было, а этот код у меня давно валяется уже и юзался не раз. довольно красивый и классический способ - просто скопировать всю память начиная с хидеров и до последней секции в чужое АП.
    предположение, что память по этим адресам не используется. весьма смелое, конечно) но все таки.
    лучшим вариантом было бы собрать прогу с релоками, и, если адреса заняты, скопировать на другие адреса и применить релоки.
     
  13. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Мне кажется, что простое копирование кода нити (с его локальными переменными релоки которым и не нужны) на пустое место, куда безопаснее для пропатчиваемой программы т.к. ничего критичного не затирается (да и вообще ничего не затирается), а результат тот же. Да и перемещение всего тела программы даже и не знаю зачем оно нужно...?
     
  14. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    asmfan
    ну дык этот код же будет использовать импорт, глобальные переменные и прочее, что мы не скопировали. выбирать и копировать все, что он будет юзать - геморрой на свои вторые девяносто, проще перенести всю память. занимаемую образом.
    с какой стати. ты все равно некторую облась память оккупируешь кодом нити.
    + тебе придется позаботиться об импортах и секции данных
     
  15. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Great
    Код же не копирует динамичекие библиотеки в памяти, поэтму не факт что сможем использовать их в чужой программе. (Хотя GetProcAddr и будет доступна вместе с LoadLib, чего в принципе достаточно... Опять же импорт копировать только ради этих 2х ф-ий... ну громоздко это, проще самому в нити найти все эти).
    Ну пямять то выделится на пустом месте, если не указывать явно, а значит будет свободна.
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    я ща пишу улучшенную версию функции копирования, которая ищет первый свободный регион достаточного размера (если, конечно, память занята. если свободна, просто копирует), копирует туда тело и применяет фиксапы.
     
  17. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Ну данные можно и с потоком скопировать, передав их адрес как параметр в создаваемый поток (тока вот эта идея пришла).
     
  18. wasm_test

    wasm_test wasm test user

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

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    И в итоге при копировании всего образа, можно только надеятся на ограниченный набор загруженных дефолтно библиотек жертвы (см. пост #15). Импорт по GetModuleHandle/либо в PEB/ == 0 несодержащий нужных библиотек, так или иначе, всё-равно придётся восстанавливать, если конечно не пользоваться только кернелом.
     
  20. set

    set New Member

    Публикаций:
    0
    Регистрация:
    13 янв 2006
    Сообщения:
    27
    правильно понял.

    Вообще-то мне кажется вы далеко ушли от темы. Думаю на эту проблемку можно взглянуть с другой стороны.

    Не совсем понял, как происходит чтение?