-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
Add support for RISC-V 32-bit / 64-bit Little Endian payloads #19518
Conversation
This PR is ready for testing. Tests are passing, with the exception of an unrelated PHP-related test which failed after 15+ minutes. HardwareMilk-V and Pine64 sell cheap (US$10) RISC-V boards capable of running Linux + userland utlities. Tested on:
EmulationQEMUQEMU supports RISC-V. QEMU versions 8.2.93 and 9.1.50 emulate RISC-V well. Debian Quick Image Baker images can be used to easily emulate a Debian RISC-V Linux system. Ubuntu and Fedora images are also available. I can provide QEMU command line arguments for these if required. TinyEMUAlso tested with tinyemu: |
@dwelch-r7, if you happen to create an emulated RISC-V Ubuntu VM, could I talk you into installing kernel 5.19 and testing #19460 ? 😄 |
FWIW; here's a working QEMU invocation for Ubuntu 22.04.1 Server with
Use the commented You may need the |
|
I've also added Linux Execute Command 32-bit/64-bit RISC-V LE payloads. @bwatters-r7 These payloads should be useful for the Overlay exploit. Both payloads were tested successfully in an emulator. The 64-bit payload was also tested on real hardware. Linux Execute Command (64-bit)
Linux Execute Command (32-bit)
|
4831d26
to
c2ec04a
Compare
[0x96958593].pack('V*') + # addi a1,a1,-1687 | ||
[0x01234637].pack('V*') + # lui a2,0x1234 | ||
[0x56760613].pack('V*') + # addi a2,a2,1383 | ||
[0x08e00893].pack('V*') + # li a7,142 |
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.
li
is a pseudo instruction, I think this instruction is actually addi a7,zero,142
, I'm not sure why the dissassembler spat out a pseudo instruction for you, kinda strange
But now that it's been brought up I do prefer the readability of the pseudo instruction, I'm wondering if you have an opinion on whether we should use pseudo instructions in the comments here or just the actual instructions
so for example https://github.com/rapid7/metasploit-framework/pull/19518/files#diff-f60b8a7586ea5a797f5469b4ccee7ec48e56651fcd9788717f0ebd7d1267bb99R32-R33:
# lui a0,0xfee1e
# addi a0,a0,-339
comes from a single pseudo instruction that is IMO much more understandable
li a7, 0xfee1dead
Or maybe there's a nice not too cluttered way of showing both
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.
li
is a pseudo instruction, I think this instruction is actuallyaddi a7,zero,142
, I'm not sure why the dissassembler spat out a pseudo instruction for you, kinda strange
It is default behaviour for objdump
(disabled with -Mno-aliases
).
But now that it's been brought up I do prefer the readability of the pseudo instruction, I'm wondering if you have an opinion on whether we should use pseudo instructions in the comments here or just the actual instructions so for example https://github.com/rapid7/metasploit-framework/pull/19518/files#diff-f60b8a7586ea5a797f5469b4ccee7ec48e56651fcd9788717f0ebd7d1267bb99R32-R33:
# lui a0,0xfee1e # addi a0,a0,-339
comes from a single pseudo instruction that is IMO much more understandable
li a7, 0xfee1dead
Or maybe there's a nice not too cluttered way of showing both
I like objdump's default output as it is easy to generate (and maintain). I'm indifferent toward psuedo instructions for single-line instructions (-Mno-aliases
).
I've never booted a 32-bit RISC-V Linux system on QEMU (not sure that I tried), but was able to with TinyEmu with riscv buildroot.
Here's my simple
|
Here are my QEMU RISC-V 64-bit Linux test systems:
Here are the Ubuntu was built using an installer ISO (slow). The typical workflow is to boot from an ISO, install, then boot from the disk. Use the commented out line to boot from ISO. You may need the debian-20221211-convert_riscv64-virt
debian-20240128-convert_riscv64-virt
Fedora-Minimal-Rawhide-20200108.n.0-riscv64
ubuntu-22.04.1-live-server-riscv64
|
Release NotesAdd support for RISC-V 32-bit / 64-bit Little Endian payloads. Includes Linux Execute Command payloads and Linux Reboot payloads for testing. |
Add support for RISC-V 32-bit / 64-bit Little Endian payloads. Includes Linux Execute Command payloads and Linux Reboot payloads for testing.
riscv32
successfullyriscv64
successfullyNote: We don't handle
syscall
failure or callexit
. This saves a few bytes.Note: Executing 32-bit payloads in a 64-bit environment will fail.
Note: Executing the Linux Reboot payloads as a low privileged user will crash.
reboot
is a privileged syscall.Note: Executing the Linux Execute Command payloads in a Linux environment where
/bin/sh
is a symlink to BusyBox/bin/busybox
(such as MilkV Duo default image) will crash. This is a WontFix for me. For testing purposes, you can work around this with:sudo cp /bin/sh /bin/sh.old && sudo cp /bin/bash /bin/sh
.Motivation
This PR lays the foundation for further development of RISC-V payloads.
RISC-V is gaining popularity. Major Linux distributions (Ubuntu, Debian, and Fedora) offer RISC-V development builds. RISC-V based SBCs and consumer-grade laptops are slowly entering the market.
Verification
Linux Reboot
Generate a Linux Reboot payload (with optional NOP sled):
./msfvenom -n 100 --format elf -p linux/riscv64le/reboot > reboot.elf
Execute the payload with QEMU (I suggest doing this within an emulated Linux environment):
/home/user/qemu/build/qemu-riscv64 -strace ./reboot
sudo /home/user/qemu/build/qemu-riscv64 -strace ./reboot
Linux Execute Command
Generate a Linux Execute Command payload (with optional NOP sled):
./msfvenom --format elf -p linux/riscv64le/exec "CMD=echo Hello, World\!>/tmp/asdf" > exec.elf
Execute the payload with QEMU (optionally within an emulated Linux environment):
/home/user/qemu/build/qemu-riscv64 -strace ./exec
Hello, World!
should now exist in/tmp/asdf
.Linux Reboot
Source (64-bit)
Source (32-bit)
Linux Execute Command
Source (64-bit)
Uses modexp's RISC-V 64-bit shellcode.
Source (32-bit)
Uses modexp's RISC-V 64-bit shellcode modified for RISC-V 32-bit.