-
Notifications
You must be signed in to change notification settings - Fork 13.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce Unknown commands handling from 1 second to 0.5 seconds #13148
Conversation
lib/msf/core/module_manager.rb
Outdated
@@ -96,7 +96,7 @@ def create(name, aliased_as: nil) | |||
module_instance = create(aliased, aliased_as: "#{type}/#{name}") | |||
else | |||
module_reference_name = names.join("/") | |||
module_instance = set.create(module_reference_name) | |||
module_instance = set.has_key?(module_reference_name) ? set.create(module_reference_name) : nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function that takes ~1 second to execute is the PayloadSet's recalculate
method. There's a comment on the code that this approach may not work as we expect:
metasploit-framework/lib/msf/core/payload_set.rb
Lines 7 to 17 in 4c06146
### | |
# | |
# This class is a special case of the generic module set class because | |
# payloads are generated in terms of combinations between various | |
# components, such as a stager and a stage. As such, the payload set | |
# needs to be built on the fly and cannot be simply matched one-to-one | |
# with a payload module. Yeah, the term module is kind of overloaded | |
# here, but eat it! | |
# | |
### | |
class PayloadSet < ModuleSet |
We might need a different approach to the above, but it's worth double checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Poking further at this; I'm concerned that this approach breaks the law of demeter, and may not work well with some of the assumptions that are already in place within framework. In particular it seems like module set already has some nil handling in place:
metasploit-framework/lib/msf/core/module_set.rb
Lines 42 to 50 in 4c06146
# If there is no module associated with this class, then try to demand | |
# load it. | |
if klass.nil? or klass == Msf::SymbolicModule | |
framework.modules.load_cached_module(module_type, reference_name) | |
recalculate | |
klass = fetch(reference_name, nil) | |
end |
Which is actually why the slow recalculate
method gets called in the first place. It might be worth doing a bit of git fu to learn why that logic was added in the first place, to make sure this approach doesn't break existing logic etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cross referencing some discussion on bootup/missing command performance - #7292 (comment)
lib/msf/core/payload/android.rb
Outdated
@@ -9,6 +9,8 @@ module Msf::Payload::Android | |||
include Msf::Payload::TransportConfig | |||
include Msf::Payload::UUID::Options | |||
|
|||
@@jar_signing_key = OpenSSL::PKey::RSA.new(2048) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thoughts on making this lazy instantiated? i.e. Loading this module doesn't create a key, but the first access will:
def signing_key
@@signing_key ||= OpenSSL::PKey::RSA.new(2048)
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, will add it in 👍
lib/msf/core/payload/android.rb
Outdated
@@ -65,11 +68,13 @@ def generate_config(opts={}) | |||
config | |||
end | |||
|
|||
def sign_jar(jar) | |||
def sign_jar(jar, new_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm; Maybe drop the new_key
argument here until there's a valid use case for it? 🤔
Just thinking: If we let this becomes configurable, and every android payload starts generating its own key - then we're back to the same position as before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is true ^^ I'll save it for when it's 100% needed
Using this to time creation of all module types:
These are the unchanged times from master:
Time with cached 2048 JAR signing key:
Time with cached 1024 JAR signing key:
Time with using keys in
Conclusions:
|
Great work! This seems to reduce the startup time (but it's similar to #13171 )
I'm going to land this. If after landing this #13171 still makes a noticeable difference we can consider landing that too. |
Release NotesThis reduces unknown commands handling from 1 second to 0.5 seconds for Android payloads. |
Cuts down unknown command time from 1 second to 0.5 seconds
Creates a class instance key for signing JARs. This cuts down on creation time for new android modules and as a result speeds up boot and incorrect command reset times by 0.5 seconds.
Verification
msfconsole
jimbob
[-] Unknown command: jimbob.
Should be output instantlyexploit/windows/misc/crosschex_device_bof
[-] Unknown command: exploit/windows/misc/crosschex_device_bof.
This is a module we can load. Do you want to use exploit/windows/misc/crosschex_device_bof? [y/N]
Should be output instantlyTL;DR