Skip to content

Replace METHOD string with COMMAND_ID integer (to remove obvious strings) #13395

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

Merged
merged 19 commits into from
Jun 10, 2020

Conversation

OJ
Copy link
Contributor

@OJ OJ commented May 5, 2020

Intro

image

Associated PRs

Description

This may be another longer story. I'm sorry, but detail is important.

Among the many goals we have right now, one of them is to make Meterp less obvious. That is, as a binary on disk/in memory, and with behaviour both on and off the wire.

Meterp is full of "commands". When operators tell meterpreter > to do something, behind the scenes TLV packets are created that contain a "method", which basically represents the identifier of the command the packet represents. That identifier was a string, and not just any string, a string that stands out from the crowd.

For those that haven't seen them, examples include stdapi_fs_file_copy, core_migrate and mimikatz_custom_command.

While these don't matter so much on the wire once TLV packets are encrypted, they do matter in other scenarios, such as strings embedded in binaries. The presence of anything stdapi_ as a string tends to indicate bad things as far as AV is concerned.

The primary goal of this PR is to change TLV_TYPE_METHOD (a string) to TLV_TYPE_COMMAND_ID (an integer). This means that the obvious strings are removed from binaries and aren't present on the wire any more. This should have some impact on the obviousness of the binaries that we're producing.

This does mean that the ABI has been broken again, sorry about that. While doing this work, I was forced to make a bunch of other changes and did some other tidying up as well. But on the whole this PR is summed up as "convert a string to an int".

Changes

Hopefully I haven't missed anything in this list:

  • TLV_TYPE_METHOD no longer exists, and has been replaced by TLV_TYPE_COMMAND_ID which is an integer.
  • Components now have an identifier EXTENSION_ID_*. This serves a few purposes:
    • It allows us to identify an extension by a number (which for $REASONS must be a multiple of 1000.
    • We can put all commands identifiers for that extension within that 1000 number range (as no extension will have more than 1000 commands).
  • Command IDs are grouped based on extension as per above.
  • There's a thing called the ExtensionMapper that is used by the configuration generator and the extension loader. This thing has the responsibility of getting hold of extension classes, as well as being able to provide the identity of an extension based on its name. You can give it "stdapi" and it'll give you 1000 for example.
  • Enumeration of supported extension commands now behaves differently. Instead of asking "what commands do you have for this extension", we now ask "which commands fit within this range". This means that:
    • We don't need to have strings in memory that map to extensions.
    • All extensions have had those strings removed.
    • Asking for support of an extension requires just two numbers.
  • Both loading of extensions and enumerating supported commands both result in an array of command identifier integers rather than strings.
  • Configuration block has been changed a little in the EXTINIT functionality. Given that we don't have string identifiers for the extensions any more, we now us the ID of the extension as an integer. This means that stageless payloads look a little different too.
  • All the Meterpreters have had to change as a result, given the ABI modification. Doing this was FUN :|
  • While refactoring stuff, I noticed that networkpug was still a thing. I removed it after talking to @bcook-r7 about it, because the old linux Meterpreter (which no longer exists) was the only thing that used it. Bye bye networkpug.
  • Various other code tidying and whatnot (including removal of whitespace in certain cases). Sorry, that makes this noisy, but I was there!
  • I exposed the "session remove" feature from the powershell extension while doing stuff. I realise this should be in another PR, but I was there, so it's done. Sorry!

Verification

This may be a little painful, and for that I am sorry. ALL of the Meterps have changed, so full regression testing of stuff will be required. I'm sure I have covered most of the cases, but there's a good chance I've missed something. Please help me make sure I haven't made any mistakes.

  • Pull the updates for mettle and metasploit-paylodas, compile/build/etc and have them all stashed in the appropriate folders under $MSF/data.
  • Create sessions for each with all the different transports/architectures/etc.
  • For each of the sessions, run regression tests to make sure that things don't break.
  • Simple commands should work.
  • Channels should work (this will require a bit of focus to make sure we didn't make a mistake).
  • Run the post test modules.
  • Validate that the newly exposed Powershell extension feature (session removal) works as intended.

Things left to do

Thanks to Channels having a string-based identifier, there's still some evidence of stuff like stdapi_ in the code. Once this PR has been landed, I'll look to fix that up as well. I didn't want it to include that in this PR given it's already so big.

Thanks

Cheers as always to Brent and Caitlin for the support. Thanks to Tim for his help getting more going with the Android stuff. Thanks to Spencer for his original work on the Python side that I stole while doing this.

Attention

Given the depth/breadth of these changes, I'm going to need lots of eyes. There are many of you out there that can help but specifically I need the following folks for their expertise in certain areas: @bcook-r7 @smcintyre-r7 @jmartin-r7 @timwr - changes in MSF might not be that interesting to all of you, but reviews of the stuff I've done in the payloads/mettle PRs would be greatly appreciated. DO YOUR WORST!

Copy link
Contributor

@sempervictus sempervictus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did first pass w/ OJ - tiny fixups nothing major, amazing stuff as always from the master of meterpreter.

@OJ
Copy link
Contributor Author

OJ commented May 5, 2020

Flattery will get you everywhere @sempervictus !

@OJ
Copy link
Contributor Author

OJ commented May 5, 2020

BTW I will fix up the payload cache sizes when we've got the payloads PRs landed.

@OJ
Copy link
Contributor Author

OJ commented May 5, 2020

Ah need to fix up the specs.

@bwatters-r7 bwatters-r7 added the a2k19 Hackathon 2019 in Austin label May 5, 2020
@OJ
Copy link
Contributor Author

OJ commented May 5, 2020

image

Technically, that's where it started. This was a complete rewrite though 🚑

@kernelsmith
Copy link
Contributor

Everyone stop pretending like they know what's going on in this PR and just merge it. Worst case we revert it and send OJ a glitter bomb

@bwatters-r7
Copy link
Contributor

I've not looked too deeply, but it seems like sanity tests should fail because we've changed the dispatching system, but sanity tests have passed?

@jmartin-tech
Copy link
Contributor

Local verification run of sanity test shows the expected failures due to these transport changes. I am investigating why automation did not flag as expected.

Original a2k19 discussion had suggested making this backwards compatible with existing payloads by detecting protocol format on initial connection, was there a conscious decision to make this a breaking change for all existing deployed payloads?

It would be nice to at least allow reverse protocols to be detected and fallback to original TLV formats. I suspect this is may be complex to support and accept if decision has been made to limit scenario is the wild.

This PR may reflect a significant enough change in the how Metasploit communicates to call for a version bump to 5.1.0.

@OJ
Copy link
Contributor Author

OJ commented May 5, 2020

I do remember that discussion. Keeping both wasn't totally out of the question, but boy was the code messy. It just didn't feel like the right thing to do. Thing is, as far as breaking back compat goes this is no worse than the refactor/removal of delay loading, though I'll admit that was just on the Meterp side.

Obviously it's not my call, but I think this has to be done and we just need to go through the pain of dealing with the changes and making sure that people don't upgrade mid-engagement.

@jmartin-tech
Copy link
Contributor

@msjenkins-r7 test this please.

Sanity test should correctly report failure now, once dependent gems are released and spec/lock are bumped in this PR they should pass again.

@OJ
Copy link
Contributor Author

OJ commented May 6, 2020

Thanks @jmartin-r7 !

@OJ OJ added the blocked Blocked by one or more additional tasks label May 8, 2020
@OJ
Copy link
Contributor Author

OJ commented May 8, 2020

Picked up on a few issues so please refrain from landing at this point :) FIXIFICATING!

@OJ OJ removed the blocked Blocked by one or more additional tasks label May 8, 2020
@OJ
Copy link
Contributor Author

OJ commented May 8, 2020

OK back on track.

@bwatters-r7
Copy link
Contributor

@msjenkins-r7 test this please.

1 similar comment
@bwatters-r7
Copy link
Contributor

@msjenkins-r7 test this please.

@bwatters-r7
Copy link
Contributor

Hooray! It is failing as expected, now.

@OJ OJ force-pushed the remove-tlv-command-strings branch from ada53bc to 5b69fe9 Compare June 8, 2020 23:34
Copy link
Contributor

@kernelsmith kernelsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that was anticlimactic ;)

@busterb
Copy link
Contributor

busterb commented Jun 9, 2020

Sometimes that's how the ball bounces @kernelsmith! We'll get this licked yet.

@jmartin-tech
Copy link
Contributor

Automation result here is failing reverse connections, running tests in another lab to validate results. I suspect gremlins I need to clear out of the infrastructure.

Separate lab is passing tests:

testlog:[2020-06-08 22:18:18.967039] COMMIT VERSION OF metasploit-framework on SATA_msf_host: ec2d1a886f70bb34f55c0b007f2e6f8357922b1b
testlog:[2020-06-08 22:18:18.967357] CHECKING SATA_LinuxCentos6x64
testlog:[2020-06-08 22:18:18.967490] CHECKING exploit/multi/handler:linux/x64/meterpreter_reverse_tcp
testlog:[2020-06-08 22:18:18.968189] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Lin_Meterpreter_Simple_1591671961/sessions/linux-x64-meterpreter_reverse_tcp-192x168x18x174-30001.rc.txt
testlog:[2020-06-08 22:18:18.968283] TEST PASSED: SATA_LinuxCentos6x64:linux/x64/meterpreter_reverse_tcp:exploit/multi/handler
testlog:[2020-06-08 22:18:18.968372] CHECKING exploit/multi/handler:linux/x64/meterpreter_reverse_https
testlog:[2020-06-08 22:18:18.969009] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Lin_Meterpreter_Simple_1591671961/sessions/linux-x64-meterpreter_reverse_https-192x168x18x174-30002.rc.txt
testlog:[2020-06-08 22:18:18.969101] TEST PASSED: SATA_LinuxCentos6x64:linux/x64/meterpreter_reverse_https:exploit/multi/handler
testlog:[2020-06-08 22:18:18.969227] CHECKING SATA_LinuxUbuntu1604x64
testlog:[2020-06-08 22:18:18.969379] CHECKING exploit/multi/handler:linux/x64/meterpreter_reverse_tcp
testlog:[2020-06-08 22:18:18.969871] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Lin_Meterpreter_Simple_1591671961/sessions/linux-x64-meterpreter_reverse_tcp-192x168x18x175-30003.rc.txt
testlog:[2020-06-08 22:18:18.969957] TEST PASSED: SATA_LinuxUbuntu1604x64:linux/x64/meterpreter_reverse_tcp:exploit/multi/handler
testlog:[2020-06-08 22:18:18.970041] CHECKING exploit/multi/handler:linux/x64/meterpreter_reverse_https
testlog:[2020-06-08 22:18:18.971214] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Lin_Meterpreter_Simple_1591671961/sessions/linux-x64-meterpreter_reverse_https-192x168x18x175-30004.rc.txt
testlog:[2020-06-08 22:18:18.971323] TEST PASSED: SATA_LinuxUbuntu1604x64:linux/x64/meterpreter_reverse_https:exploit/multi/handler
testlog:[2020-06-08 22:34:43.848418] COMMIT VERSION OF metasploit-framework on SATA_msf_host: ec2d1a886f70bb34f55c0b007f2e6f8357922b1b
testlog:[2020-06-08 22:34:43.848758] CHECKING SSD_Win2016x64
testlog:[2020-06-08 22:34:43.848918] CHECKING exploit/multi/handler:windows/x64/meterpreter/bind_tcp
testlog:[2020-06-08 22:34:43.849779] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-x64-meterpreter-bind_tcp-192x168x18x131-30001.rc.txt
testlog:[2020-06-08 22:34:43.849902] TEST PASSED: SSD_Win2016x64:windows/x64/meterpreter/bind_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.850017] CHECKING exploit/multi/handler:windows/meterpreter/reverse_tcp
testlog:[2020-06-08 22:34:43.850897] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-meterpreter-reverse_tcp-192x168x18x131-30002.rc.txt
testlog:[2020-06-08 22:34:43.851003] TEST PASSED: SSD_Win2016x64:windows/meterpreter/reverse_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.851102] CHECKING exploit/multi/handler:windows/x64/meterpreter_bind_tcp
testlog:[2020-06-08 22:34:43.851854] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-x64-meterpreter_bind_tcp-192x168x18x131-30003.rc.txt
testlog:[2020-06-08 22:34:43.851958] TEST PASSED: SSD_Win2016x64:windows/x64/meterpreter_bind_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.852058] CHECKING exploit/multi/handler:windows/meterpreter_reverse_tcp
testlog:[2020-06-08 22:34:43.852725] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-meterpreter_reverse_tcp-192x168x18x131-30004.rc.txt
testlog:[2020-06-08 22:34:43.852817] TEST PASSED: SSD_Win2016x64:windows/meterpreter_reverse_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.852921] CHECKING SSD_Win10x64_1703
testlog:[2020-06-08 22:34:43.853016] CHECKING exploit/multi/handler:windows/x64/meterpreter/bind_tcp
testlog:[2020-06-08 22:34:43.853645] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-x64-meterpreter-bind_tcp-192x168x18x128-30005.rc.txt
testlog:[2020-06-08 22:34:43.853735] TEST PASSED: SSD_Win10x64_1703:windows/x64/meterpreter/bind_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.853827] CHECKING exploit/multi/handler:windows/meterpreter/reverse_tcp
testlog:[2020-06-08 22:34:43.854453] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-meterpreter-reverse_tcp-192x168x18x128-30006.rc.txt
testlog:[2020-06-08 22:34:43.854545] TEST PASSED: SSD_Win10x64_1703:windows/meterpreter/reverse_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.854637] CHECKING exploit/multi/handler:windows/x64/meterpreter_bind_tcp
testlog:[2020-06-08 22:34:43.855270] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-x64-meterpreter_bind_tcp-192x168x18x128-30007.rc.txt
testlog:[2020-06-08 22:34:43.855364] TEST PASSED: SSD_Win10x64_1703:windows/x64/meterpreter_bind_tcp:exploit/multi/handler
testlog:[2020-06-08 22:34:43.855456] CHECKING exploit/multi/handler:windows/meterpreter_reverse_tcp
testlog:[2020-06-08 22:34:43.856085] /Users/jmartin/rapid7/src/r7-source/metasploit/payload/payload-testing/test_data/Win_Meterpeter_Simple_1591672778/sessions/windows-meterpreter_reverse_tcp-192x168x18x128-30008.rc.txt
testlog:[2020-06-08 22:34:43.856177] TEST PASSED: SSD_Win10x64_1703:windows/meterpreter_reverse_tcp:exploit/multi/handler

This represents passing sanity test.

I will investigate automation side.

@OJ
Copy link
Contributor Author

OJ commented Jun 9, 2020

Thank you @jmartin-r7 !

@kernelsmith
Copy link
Contributor

Agreed @busterb. To be clear, I was only referring to OJ's last commit as being anticlimactic, not the precess. The process is awesome

@jmartin-tech
Copy link
Contributor

@msjenkins-r7 test this please.

Copy link
Contributor

@zeroSteiner zeroSteiner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this with the Python, PHP, Java, Linux x86 and Windows x64 Meterpreters. While doing so, I was specifically attentive towards channels by verifying TCP client and file channels. TCP client channels were verified using using a few techniques like the connect command, pivoting modules and the SOCKS5 server. File channels were verified using the post/test/file module and checking for errors.

I'll have this merged in soon.

smcintyre-r7 added a commit that referenced this pull request Jun 10, 2020
@smcintyre-r7 smcintyre-r7 merged commit ec2d1a8 into rapid7:6.x Jun 10, 2020
@smcintyre-r7
Copy link
Contributor

Landed after a minor bug fix for the powershell_session_remove command in commit 6ca3368.

powershell_session_remove test results:

[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.31:49172) at 2020-06-10 16:37:57 -0400

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo 
Computer        : WIN-9NSI4A6AIHJ
OS              : Windows 7 (6.1 Build 7601, Service Pack 1).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 1
Meterpreter     : x64/windows
meterpreter > load powershell
Loading extension powershell...Success.
meterpreter > powershell_shell -s test
PS > $msg='Hello World'
PS > ^Z
Background channel 1? [y/N]  y
meterpreter > powershell_shell -s test
PS > Write-Host $msg
Hello World
PS > ^Z
Background channel 2? [y/N]  y
meterpreter > powershell_session_remove -h
Usage: powershell_session_remove -s session-id

Removes a named session from the powershell instance.

OPTIONS:

    -h        Help banner
    -s <opt>  Specify the id/name of the Powershell session to interact with (cannot be "default").

meterpreter > powershell_session_remove -s test
[+] Session 'test' removed.
meterpreter > powershell_shell -s test
PS > Write-Host $msg

PS >

@OJ
Copy link
Contributor Author

OJ commented Jun 10, 2020 via email

@smcintyre-r7
Copy link
Contributor

smcintyre-r7 commented Jun 10, 2020

Release Notes

Updated the TLV protocol used by Meterpreter to use numeric identifiers for commands instead of string values. This makes the traffic (and certain generated binaries) less conspicuous by removing strings that are obviously associated with Meterpreter such as stdapi_fs_file_copy, core_migrate and mimikatz_custom_command. NOTE: older payloads are incompatible with this change and users should take care to not upgrade to this version during active operations lest those incompatible sessions and payloads become unresponsive.

@kernelsmith
Copy link
Contributor

yeah

@OJ OJ deleted the remove-tlv-command-strings branch June 10, 2020 22:24
@pbarry-r7 pbarry-r7 added the rn-enhancement release notes enhancement label Aug 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a2k19 Hackathon 2019 in Austin enhancement library meterpreter msf6 PRs that need to be landed into the msf 6 branch rn-enhancement release notes enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants