в смысле "чужую". если добудешь себе хендл этой "чужой" консоли, выводи сколько хочешь. хендл можешь добыть через удаленное выполнение кода с DuplicateHandle
ну тогда просто инжектни код в другой процесс по выводу и вводу и все ) и обмену с твоим процессом какнить, например, через shared-секцию или Read/WriteProcessMemory
не так уж и громоздко. Код (Text): #include <windows.h> #include <stdio.h> #pragma comment(linker, "/BASE:0x2a000000") HWND hWndConsole = NULL; BOOL WINAPI EnumWindowProc( HWND hWnd, LPARAM ) { char title[1024]; GetWindowText( hWnd, title, 1024 ); if( !stricmp(title, "H:\\WINDOWS\\System32\\cmd.exe") ) { hWndConsole = hWnd; return FALSE; } return TRUE; } bool TransferProgramEx(HANDLE hProcess) { HMODULE g_module = GetModuleHandle(0); VirtualFreeEx(hProcess, g_module, 0, MEM_RELEASE); DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(g_module) + ((PIMAGE_DOS_HEADER)(g_module))->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage; char *pMem = (char *)VirtualAllocEx(hProcess, g_module, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); if(pMem == NULL) return FALSE; DWORD dwOldProt, dwNumBytes, i; MEMORY_BASIC_INFORMATION mbi; VirtualQueryEx(hProcess, pMem, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); while (mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0) { if (!(mbi.Protect & PAGE_GUARD)) { for (i = 0; i < mbi.RegionSize; i += 0x1000) { VirtualProtectEx(hProcess, pMem + i, 0x1000,PAGE_EXECUTE_READWRITE, &dwOldProt); WriteProcessMemory(hProcess, pMem + i, pMem + i, 0x1000, &dwNumBytes); } } pMem += mbi.RegionSize; VirtualQueryEx(hProcess, pMem, &mbi, sizeof(MEMORY_BASIC_INFORMATION)); } return true; } DWORD WINAPI RemoteWriteThread( LPVOID p ) { HANDLE hConsole = GetStdHandle( STD_OUTPUT_HANDLE ); char *msg = (char*)p; DWORD t; WriteConsole( hConsole, msg, strlen(msg), &t, 0 ); return 0; } int main( ) { EnumWindows( EnumWindowProc, 0 ); if( hWndConsole == NULL ) return printf("Console window searching failed\n"),0; DWORD ProcessId, ThreadId = GetWindowThreadProcessId( hWndConsole, &ProcessId ); HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, 0, ProcessId ); if( hProcess == NULL ) return printf("Cannot open process\n"), 0; if( !TransferProgramEx( hProcess ) ) return printf("Cannot copy body\n"), 0; DWORD thID; HANDLE hTh; printf("Writing..\n"); hTh = CreateRemoteThread( hProcess, 0, 0, RemoteWriteThread, "Hello, World!!", 0, &thID); WaitForSingleObject( hTh, INFINITE ); CloseHandle( hProcess ); return 0; }
roman_pro я думаю, что CreateProcess ему не нужен, ему надо вводить/выводить в консоль работающего процесса
asmfan из адресного пространства нашего процесса в чужой постранично копируем всю прогу. стандартный прием
Н-да, надо было идти спать) [added] Ну а всё-таки можно же было скопировать на свободное место и только код потока? Зачем обязательно затирать? Тем более мы даже не суспендим ничего, а так просто, поверх. Да и зачем столько проверок по VirtualQuery? /предположение заведомо, что кроме нас кто-то меняет атрибуты на отдельные страницы? Почему бы сразу весь объём памяти не перенести?/
можно. только влом реализовывать было, а этот код у меня давно валяется уже и юзался не раз. довольно красивый и классический способ - просто скопировать всю память начиная с хидеров и до последней секции в чужое АП. предположение, что память по этим адресам не используется. весьма смелое, конечно) но все таки. лучшим вариантом было бы собрать прогу с релоками, и, если адреса заняты, скопировать на другие адреса и применить релоки.
Мне кажется, что простое копирование кода нити (с его локальными переменными релоки которым и не нужны) на пустое место, куда безопаснее для пропатчиваемой программы т.к. ничего критичного не затирается (да и вообще ничего не затирается), а результат тот же. Да и перемещение всего тела программы даже и не знаю зачем оно нужно...?
asmfan ну дык этот код же будет использовать импорт, глобальные переменные и прочее, что мы не скопировали. выбирать и копировать все, что он будет юзать - геморрой на свои вторые девяносто, проще перенести всю память. занимаемую образом. с какой стати. ты все равно некторую облась память оккупируешь кодом нити. + тебе придется позаботиться об импортах и секции данных
Great Код же не копирует динамичекие библиотеки в памяти, поэтму не факт что сможем использовать их в чужой программе. (Хотя GetProcAddr и будет доступна вместе с LoadLib, чего в принципе достаточно... Опять же импорт копировать только ради этих 2х ф-ий... ну громоздко это, проще самому в нити найти все эти). Ну пямять то выделится на пустом месте, если не указывать явно, а значит будет свободна.
я ща пишу улучшенную версию функции копирования, которая ищет первый свободный регион достаточного размера (если, конечно, память занята. если свободна, просто копирует), копирует туда тело и применяет фиксапы.
Ну данные можно и с потоком скопировать, передав их адрес как параметр в создаваемый поток (тока вот эта идея пришла).
asmfan я хотел так сделать. в итоге чето окончательно напутал с передаваемыми структрами и забил ) ща короче напишу чтобы вся прога переносилась по любому адресу
И в итоге при копировании всего образа, можно только надеятся на ограниченный набор загруженных дефолтно библиотек жертвы (см. пост #15). Импорт по GetModuleHandle/либо в PEB/ == 0 несодержащий нужных библиотек, так или иначе, всё-равно придётся восстанавливать, если конечно не пользоваться только кернелом.
правильно понял. Вообще-то мне кажется вы далеко ушли от темы. Думаю на эту проблемку можно взглянуть с другой стороны. Не совсем понял, как происходит чтение?