Как сделать снимок с web-камеры на Ассемблере
Как сделать снимок с web-камеры на Ассемблере
Начитался страшных историй про людей, которые опасаются, что через web-камеру их компьютера за ними следят спецслужбы и злые хакеры. Поэтому камеры заклеиваются черной изолентой, паранойя прогрессирует и все такое. Мне стало интересно, как сделать снимок с web-камеры без ведома пользователя?
Самый простой способ - воспользоваться стандартной библиотекой avicap32.dll, которая входит в состав системы еще с Windows 2000. Она предназначена для работы с такими медиа-устройствами как цифровые видеокамеры, web-камеры, видеокарты и т.д. через удобный механизм управления посредством сообщений. Как написано в MSDN, эта библиотека предоставляет достаточно большой набор инструментов для работы с web-камерами, но нас интересует только захват изображения, и желательно без создания видимых окон или чего-то подобного.
Все начинается с обязательного создания окна-перехватчика функцией capCreateCaptureWindow. На сайте MSDN описание слишком лаконичное, поэтому стоит обратить внимание на некоторые ее особенности. В окно-перехватчик отправляются все управляющие сообщения для web-камеры, в него же транслируется видеопоток. Если задать размеры окна, то размер видео будет подгоняться под него, независимо от возможностей камеры. Но если делать снимок, то размеры окна значения не имеют, оно может быть нулевого размера, иметь любые стили или вообще быть скрытым, неважно. Кадр будет сохранен с тем размером, какой пришел непосредственно с камеры. Этим мы и воспользуемся, окно-перехватчик будет невидимым и никак не будет себя демаскировать перед пользователем.
Дальше надо связать окно-перехватчик с web-камерой. К компьютеру может быть подключена более чем одна камера, но в то же время их количество ограничивается 10 устройствами, каждое из которых имеет порядковый индекс от 0 до 9. При этом совершенно не обязательно, что первое доступное устройство имеет индекс 0, поэтому нам надо или предоставить пользователю возможность выбора нужной камеры из списка, или же не привлекать внимания и сделать этот выбор за него. Если при переборе всех возможных индексов не найдено ни одной камеры, доступной для подключения, ну что ж, тут уже ничего не сделать.
Тут есть несколько важных моментов. Проверять наличие и доступность устройства сразу через подключение будет не совсем корректно. Устройство может сразу не подключиться, поэтому перебор индексов устройств осуществляется при помощи функции capGetDriverDescription. Если функция вернула TRUE, то есть драйвер устройства доступен, тогда можно к нему подключаться, при этом в некоторых случаях подключение произойдет не с первой попытки. Следующий момент заключается в том, что при наличии нескольких устройств захвата изображения система может открыть окно для выбора устройства-источника. И такое же окно может появляться даже при наличии только одной камеры. Какой-либо закономерности появления окна в этом случае я не заметил. Если вы делаете снимок легально, то тут ничего страшного, пользователь просто выберет камеру. А вот для скрытного фотографирования придется создавать отдельный поток-наблюдатель, в котором надо будет отслеживать появление этого окна и эмулировать подтверждение выбора.
Если рабочая web-камера найдена, то для выполнения поставленной задачи останется только сохранить кадр в файл с нужным нам именем. После этого можно отключаться от камеры и уничтожать окно-перехватчик. Осталось это все запрограммировать. Вот что будет в сегменте данных:
Code (Assembler) : Убрать нумерацию
- ; Сообщения для взаимодействия с web-камерой
- WM_CAP_DRIVER_CONNECT = WM_USER+10
- WM_CAP_DRIVER_DISCONNECT = WM_USER+11
- WM_CAP_FILE_SAVEDIB = WM_USER+25
- ; Заголовок окна-перехватчика
- title db 'WEBCAM-SPY',0
- ; Номер устройства web-камеры
- device dd 0
- ; Имя файла для захвата с web-камеры (ASCIIZ)
- file1 db 'image_captured_from_camera.bmp',0
Code (Assembler) : Убрать нумерацию
- ; Создать скрытое окно-перехватчик
- invoke capCreateCaptureWindow,0,0,0,0,0,0,HWND_DESKTOP,0
- mov ebx,eax
- ; Попробовать подключиться к первой доступной web-камере
- mov [device],0
- @@:
- ; Получить описание драйвера устройства
- invoke capGetDriverDescription,[device],buff,100h,vers,100h
- cmp eax,TRUE
- je @f
- ; Проверить следующее устройство
- inc [device]
- ; Устройства могут иметь индексы 0..9
- cmp [device],9
- jbe @b
- ; Закрыть окно-перехватчик
- invoke DestroyWindow,ebx
- ; Все устройства проверены, ни к одному не удалось подключиться
- jmp loc_exit
- @@:
- ; Подключиться к драйверу устройства захвата
- invoke SendMessage,ebx,WM_CAP_DRIVER_CONNECT,[device],0
- cmp eax,TRUE
- je @f
- ; Пауза между попытками подключения
- invoke Sleep,10
- jmp @b
- @@:
- ; Сохранить изображение
- invoke SendMessage,ebx,WM_CAP_FILE_SAVEDIB,0,file1
- ; Отключиться от web-камеры
- invoke SendMessage,ebx,WM_CAP_DRIVER_DISCONNECT,title,0
- ; Закрыть окно-перехватчик
- invoke DestroyWindow,ebx
Code (Assembler) : Убрать нумерацию
- ; Структуры для работы с GDI Plus
- struct GdiplusStartupInput
- GdiplusVersion dd ?
- DebugEventCallback dd ?
- SuppressBackgroundThread dd ?
- SuppressExternalCodecs dd ?
- ends
- struct ImageCodecInfo
- Clsid db 16 dup ?
- FormatID db 16 dup ?
- CodecName dd ?
- DllName dd ?
- FormatDescription dd ?
- FilenameExtension dd ?
- MimeType dd ?
- Flags dd ?
- Version dd ?
- SigCount dd ?
- SizeSize dd ?
- SigPattern dd ?
- SigMask dd ?
- ends
- ; Имена файлов для конвертирования GDI Plus (юникод)
- file2 du 'image_captured_from_camera.bmp',0
- file3 du 'image_converted.jpg',0
- ; Кодировщик JPEG
- encoder_type du 'image/jpeg',0
- encoder_clsid db 16 dup ?
- ; Структуры и переменные для GPI Plus
- input GdiplusStartupInput
- token dd ?
- encoders_count dd ? ; Количество кодировщиков
- encoders_size dd ? ; Размер кодировщиков
- gdip_bitmap dd ? ; Загруженная картинка
Code (Assembler) : Убрать нумерацию
- ; Инициализировать GDI Plus
- mov [input.GdiplusVersion],1
- invoke GdiplusStartup,token,input,NULL
- test eax,eax
- jnz loc_exit
- ; Получить количество и размер графических кодировщиков
- invoke GdipGetImageEncodersSize,encoders_count,encoders_size
- test eax,eax
- jnz gdiplus_shutdown
- ; Зарезервировать под них память
- invoke VirtualAlloc,0,[encoders_size],MEM_COMMIT,PAGE_READWRITE
- test eax,eax
- jz gdiplus_shutdown
- mov ebx,eax
- ; Получить список графических кодировщиков
- invoke GdipGetImageEncoders,[encoders_count],[encoders_size],ebx
- test eax,eax
- jnz gdiplus_shutdown
- scan_encoders:
- ; Найти CLSID нужного нам кодировщика (JPEG)
- mov esi,[ebx+ImageCodecInfo.MimeType]
- mov edi,encoder_type
- invoke lstrlen,encoder_type
- mov ecx,eax
- repe cmpsw
- je encoder_found
- add ebx,sizeof.ImageCodecInfo
- dec [encoders_count]
- jnz scan_encoders
- ; Ничего не найдено
- jmp gdiplus_shutdown
- encoder_found:
- ; Сохранить CLSID найденного кодировщика
- lea esi,[ebx+ImageCodecInfo.Clsid]
- mov edi,encoder_clsid
- mov ecx,4
- rep movsd
- ; Очистить память
- invoke VirtualFree,ebx,0,MEM_RELEASE
- ; Загрузить файл с захваченным изображением
- invoke GdipCreateBitmapFromFile,file2,gdip_bitmap
- test eax,eax
- jnz gdiplus_shutdown
- ; Отконвертировать в JPEG и cохранить
- invoke GdipSaveImageToFile,[gdip_bitmap],file3,encoder_clsid,NULL
- ; Прибраться за собой
- invoke GdipDisposeImage,[gdip_bitmap]
- gdiplus_shutdown:
- invoke GdiplusShutdown,[token]
Вот так легко и ненапряжно можно сделать снимок с web-камеры без ведома пользователя. Если, конечно, он не обратит внимание на моргнувший индикатор включения.
Если у вас нет паранойи, это еще не значит, что за вами не следят!
В приложении пример программы с исходным текстом, делающей снимок с первой доступной web-камеры и конвертирующей его в JPEG. Исходный файл захвата также сохраняется.
Просмотров: 11193 | Комментариев: 28
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(25.10.2020 в 16:59):
Немного дополнил статью и улучшил пример. Архив тоже обновлен.
Guest
(25.10.2020 в 13:13):
Спасибы, будым пробывать.
ManHunter
(25.10.2020 в 13:04):
Сделать автокликалку при появлении окна выбора. Попробовать захват через DirectShow, но там тоже не факт, что система не будет предлагать выбор источника.
Guest
(25.10.2020 в 12:27):
А что делать?
Костыли с имитацией выбора городить?
И почему в статье не упомянуто, раз нормальное?
Костыли с имитацией выбора городить?
И почему в статье не упомянуто, раз нормальное?
ManHunter
(25.10.2020 в 12:22):
Это нормальное поведение системы. Скрин не надо.
Guest
(25.10.2020 в 12:13):
На двух разных компьютерах (10 x64 и 7 x??) программа не делает снимок с первой доступной камеры, а выводит диалог запроса "с какой снимать". На десяточном компе одна камера, на семёрочном одна физическая и одна чем-то нашаманенная виртуальная. После выбора успешно делает и конвертит снимок. Принтскрин запроса нужен?
Grey
(14.10.2015 в 14:51):
Ну да. Нашел рабочий пример, разбираюсь.
ManHunter
(14.10.2015 в 08:51):
Ну дык, реверс и предназначен как раз для таких случаев.
А вообще должны же быть какие-то общие API, иначе бы универсальным сканилкам типа VueScan пришлось бы туго. Я не верю, что во всем интернете нет ни одной толковой документации по TWAIN, пусть и применительно не к конкретно этой модели сканера и не именно на Ассемблере.
Grey
(14.10.2015 в 08:39):
Сетевой сканер TWAIN. Ясно что за dll, и список функций. Неясно количество и назначение параметров функций. Можно как то без реверса это узнать если никакой документации и хэлпов на эту библиотеку нет.
Виталий
(05.02.2015 в 10:41):
У меня на семерке 64 при захвате не проходит останов.
Работает захват один раз. после останова зависает.
Повторные запуски дают на идентификаторах ноль.
На XP работает.
ManHunter
(25.09.2014 в 12:46):
Ага, и ничего не надо городить, все уже написано до нас :)
Never
(19.09.2014 в 13:21):
Wolfcoders CamBlocker - Oh! Good! Must have!
ManHunter
(13.09.2014 в 18:38):
Он слишком урезан по функционалу.
капитошка
(13.09.2014 в 17:15):
на сайте фасма в примерах есть FASMCam. может тоже кому пригодится.
morgot
(05.09.2014 в 22:17):
ManHunter, попробовал еще раз на том ноуте - все отлично работает. Так что ложная тревога. Еще раз спасибо за код, пригодится.
ManHunter
(05.09.2014 в 16:24):
На двух рабочих Win7 x64 с USB-камерами фунциклирует нормально. Дело, скорее всего, в особенностях софта камеры, а не в разрядности системы.
morgot
(05.09.2014 в 16:22):
Тестил на своих ноутах (виста х86-32, восьмерка х64), работает отлично. У знакомых на семерке х64 почему-то не отработало, показывает какое-то окошко выбора устройства, и на этом все. Все ноуты - Асусы разных моделей. На семерке пока не могу подебажить, поэтому не пойму, почему так.
ManHunter
(05.09.2014 в 15:06):
google -> "Wolfcoders CamBlocker"
morgot
(01.09.2014 в 15:27):
Спасибо, пригодится.
Кстати, вот еще либа, но на Масм: http://wasm.ru/forum/viewtopic.php?id=46614
Кстати, вот еще либа, но на Масм: http://wasm.ru/forum/viewtopic.php?id=46614
ManHunter
(29.08.2014 в 23:50):
Нет, только web-кодинг для работы, Ассемблер для души и чуть-чуть Python для расширения кругозора. Форт, Бейсик, Фокал и Паскаль благополучно забыл за ненадобностью. C на уровне общего понимания исходников, но не пишу.
Анатолий
(29.08.2014 в 23:44):
Горькая правда. К сожалению, ни один язык, кроме asm'a и pure C "не штырит" =)
ManHunter, а вы программируете на C?
Compiller
(28.08.2014 в 14:30):
Для блондинок - web камера Logitech C500 имеет шторку аппаратную.
той же фирмы QuickCam express - имеет регулятор фокуса, а большинство остальных камер просто можно поворачивать в потолок. А по сути статьи - файла gdiplus.dll в системе может не быть.
C камерой думаю можно работать через twain или wia интерфейсы - правда про работу без отображения окон при этом не уверен.
Про диспетчер устройств - devcon.exe включает одной командой обратно. И ещё одной снова выключает после сделанного снимка.
На WEB камерах при убирании BR фильтра возможен прибор ночного видения. Правда по описанию процесса - очень нежные ручки для этого надо.
http://www.instructables.com/i...sion-Webcam/
судя по картинкам камера типа Logitech QuickCam Express.
той же фирмы QuickCam express - имеет регулятор фокуса, а большинство остальных камер просто можно поворачивать в потолок. А по сути статьи - файла gdiplus.dll в системе может не быть.
C камерой думаю можно работать через twain или wia интерфейсы - правда про работу без отображения окон при этом не уверен.
Про диспетчер устройств - devcon.exe включает одной командой обратно. И ещё одной снова выключает после сделанного снимка.
На WEB камерах при убирании BR фильтра возможен прибор ночного видения. Правда по описанию процесса - очень нежные ручки для этого надо.
http://www.instructables.com/i...sion-Webcam/
судя по картинкам камера типа Logitech QuickCam Express.
ManHunter
(27.08.2014 в 20:50):
На Ассемблере можно написать что угодно, но жизнь коротка.
AyTkACT
(27.08.2014 в 20:22):
Внешнюю камеру как и внешний микрофон можно подключать физически, только по мере надобности и на время этой самой надобности... А вот какие варианты противодействия встроенным устройствам (микрофон/камера), но для конечной домохозяйки?
ManHunter, не думаешь написать для блондинок нечто что подобное (программную изоленту, так сказать)?
ManHunter, не думаешь написать для блондинок нечто что подобное (программную изоленту, так сказать)?
semenov
(27.08.2014 в 14:06):
Я в диспетчере устройств камеру отключаю)
Grey
(27.08.2014 в 14:01):
Супер. У меня товарищ изолентой заклеил.
ManHunter
(27.08.2014 в 09:13):
"Пастернака не читал, но осуждаю" :)
1. Никак. Может быть можно на каких-то единичных моделях, путем манипуляций с прошивками, драйверами и подобной низкоуровневой хрени. Где-то даже проскакивала одна единственная статейка на эту тему, что кому-то удалось на какой-то модели камеры отключить индикатор.
2. Проверено на пяти внешних камерах разных производителей и разного ценового уровня, и на четырех встроенных камерах ноутбуков, тоже разных производителей. Везде все прекрасно работает. Драйвера могут обеспечивать какие-нибудь дополнительные возможности, типа отслеживания лица, поворота камеры, повышения качества изображения. В остальном базовые функции, в том числе и съемка, доступны через WinAPI.
1. Никак. Может быть можно на каких-то единичных моделях, путем манипуляций с прошивками, драйверами и подобной низкоуровневой хрени. Где-то даже проскакивала одна единственная статейка на эту тему, что кому-то удалось на какой-то модели камеры отключить индикатор.
2. Проверено на пяти внешних камерах разных производителей и разного ценового уровня, и на четырех встроенных камерах ноутбуков, тоже разных производителей. Везде все прекрасно работает. Драйвера могут обеспечивать какие-нибудь дополнительные возможности, типа отслеживания лица, поворота камеры, повышения качества изображения. В остальном базовые функции, в том числе и съемка, доступны через WinAPI.
brute
(27.08.2014 в 08:41):
в вопросе не разбираюсь, но ясность внесу: основных проблем (решения которым я не видел) с камерой было две:
1. как отключить индикатор включения
2. некоторые/многие камеры не работают через avicap32.dll/стандартные winAPI. Они имеют свои драйвера.
1. как отключить индикатор включения
2. некоторые/многие камеры не работают через avicap32.dll/стандартные winAPI. Они имеют свои драйвера.
Добавить комментарий
Заполните форму для добавления комментария