# `pwnlib.shellcraft.riscv64` — Shellcode for RISCV64

## `pwnlib.shellcraft.riscv64`

Shellcraft module containing generic RISCV64 shellcodes.

pwnlib.shellcraft.riscv64.mov(dst, src)

  Move src into dst without newlines and null bytes.

  Registers t4 and t6 are not guaranteed to be preserved.

  If src is a string that is not a register, then it will locally set context.arch to ‘riscv64’ and use `pwnlib.constants.eval()` to evaluate the string. Note that this means that this shellcode can change behavior depending on the value of context.os.

  Parameters:

    - dst (str) – The destination register.

    - src (str) – Either the input register, or an immediate value.

  Example

      >>> print(shellcraft.riscv64.mov('t0', 0).rstrip())
          c.li t0, 0
      >>> print(shellcraft.riscv64.mov('t0', 0x2000).rstrip())
          c.lui t0, 2 /* mv t0, 0x2000 */
      >>> print(shellcraft.riscv64.mov('t5', 0x601).rstrip())
          xori t5, zero, 0x601
      >>> print(shellcraft.riscv64.mov('t5', 0x600).rstrip())
          /* mv t5, 0x600 */
          xori t5, zero, 0x1ff
          xori t5, t5, 0x7ff
      >>> print(shellcraft.riscv64.mov('t6', 0x181f).rstrip())
          /* mv t6, 0x181f */
          lui t6, 0xffffe
          xori t6, t6, 0xfffffffffffff81f
      >>> print(shellcraft.riscv64.mov('t5', 0x40b561f).rstrip())
          /* mv t5, 0x40b561f */
          lui t5, 0x40b5
          xori t5, t5, 0x61f
      >>> print(shellcraft.riscv64.mov('t0', 0xcafebabe).rstrip())
          li t0, 0xcafebabe
      >>> print(shellcraft.riscv64.mov('a0', 't2').rstrip())
          c.mv a0, t2
      >>> print(shellcraft.riscv64.mov('t1', 'sp').rstrip())
          c.mv t6, sp
          c.mv t1, t6 /* mv t1, sp */

pwnlib.shellcraft.riscv64.nop()

  RISCV64 nop instruction.

pwnlib.shellcraft.riscv64.push(value)

  Pushes a value onto the stack.

  Register t4 is not guaranteed to be preserved.

pwnlib.shellcraft.riscv64.pushstr(string, append_null=True)

  Pushes a string onto the stack without using null bytes or newline characters.

  Example

      >>> print(shellcraft.riscv64.pushstr('').rstrip())
          /* push b'\x00' */
          sw zero, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr('a').rstrip())
          /* push b'a\x00' */
          /* mv t4, 0x61 */
          xori t4, zero, 0x79e
          xori t4, t4, 0x7ff
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr('aa').rstrip())
          /* push b'aa\x00' */
          li t4, 0x6161
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr('aaaa').rstrip())
          /* push b'aaaa\x00' */
          /* mv t4, 0x61616161 */
          lui t4, 0x61616
          xori t4, t4, 0x161
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr('aaaaa').rstrip())
          /* push b'aaaaa\x00' */
          li t4, 0x6161616161
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr('aaaa', append_null = False).rstrip())
          /* push b'aaaa' */
          /* mv t4, 0x61616161 */
          lui t4, 0x61616
          xori t4, t4, 0x161
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr(b'\xc3').rstrip())
          /* push b'\xc3\x00' */
          /* mv t4, 0xc3 */
          xori t4, zero, 0x73c
          xori t4, t4, 0x7ff
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(shellcraft.riscv64.pushstr(b'\xc3', append_null = False).rstrip())
          /* push b'\xc3' */
          /* mv t4, 0xc3 */
          xori t4, zero, 0x73c
          xori t4, t4, 0x7ff
          sd t4, -8(sp)
          addi sp, sp, -8
      >>> print(enhex(asm(shellcraft.riscv64.pushstr("/bin/sh"))))
      b79e39349b8e7e7bb20e938ebe34b60e938efe22233cd1ff6111
      >>> print(enhex(asm(shellcraft.riscv64.pushstr(""))))
      232c01fe6111
      >>> print(enhex(asm(shellcraft.riscv64.pushstr("\x00", append_null =  False))))
      232c01fe6111

  Parameters:

    - string (str) – The string to push.

    - append_null (bool) – Whether to append a single NULL-byte before pushing.

pwnlib.shellcraft.riscv64.pushstr_array(reg, array)

  Pushes an array/envp-style array of pointers onto the stack.

  Parameters:

    - reg (str) – Destination register to hold the pointer.

    - array (str,list) – Single argument or list of arguments to push. NULL termination is normalized so that each argument ends with exactly one NULL byte.

pwnlib.shellcraft.riscv64.setregs(reg_context, stack_allowed=True)

  Sets multiple registers, taking any register dependencies into account (i.e., given eax=1,ebx=eax, set ebx first).

  Parameters:

    - reg_context (dict) – Desired register context

    - stack_allowed (bool) – Can the stack be used?

  Example

      >>> print(shellcraft.setregs({'t0':1, 'a3':'0'}).rstrip())
          c.li a3, 0
          c.li t0, 1
      >>> print(shellcraft.setregs({'a0':'a1', 'a1':'a0', 'a2':'a1'}).rstrip())
          c.mv a2, a1
          c.mv t4, a1
          xor a1, a0, t4 /* xchg a1, a0 */
          c.mv t4, a0
          xor a0, a1, t4
          c.mv t4, a1
          xor a1, a0, t4

pwnlib.shellcraft.riscv64.trap()

  A trap instruction.

pwnlib.shellcraft.riscv64.xor(dst, rs1, rs2)

  XOR two registers rs1 and rs2, store result in register dst.

  Register t4 is not guaranteed to be preserved.

## `pwnlib.shellcraft.riscv64.linux`

Shellcraft module containing RISCV64 shellcodes for Linux.

pwnlib.shellcraft.riscv64.linux.syscall(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None)
  Args: [syscall_number, *args]

    Does a syscall

  Any of the arguments can be expressions to be evaluated by `pwnlib.constants.eval()`.

  Example

      >>> print(pwnlib.shellcraft.riscv64.linux.syscall('SYS_execve', 1, 'sp', 2, 0).rstrip())
          /* call execve(1, 'sp', 2, 0) */
          c.li a0, 1
          c.mv a1, sp
          c.li a2, 2
          c.li a3, 0
          /* mv a7, 0xdd */
          xori a7, zero, 0x722
          xori a7, a7, 0x7ff
          ecall
      >>> print(pwnlib.shellcraft.riscv64.linux.syscall('SYS_execve', 2, 1, 0, 20).rstrip())
          /* call execve(2, 1, 0, 0x14) */
          c.li a0, 2
          c.li a1, 1
          c.li a2, 0
          c.li a3, 0x14
          /* mv a7, 0xdd */
          xori a7, zero, 0x722
          xori a7, a7, 0x7ff
          ecall
      >>> print(pwnlib.shellcraft.riscv64.linux.syscall().rstrip())
          /* call syscall() */
          ecall
      >>> print(pwnlib.shellcraft.riscv64.linux.syscall('a7', 'a0', 'a1').rstrip())
          /* call syscall('a7', 'a0', 'a1') */
          /* setregs noop */
          ecall
      >>> print(pwnlib.shellcraft.riscv64.linux.syscall('a3', None, None, 1).rstrip())
          /* call syscall('a3', ?, ?, 1) */
          c.li a2, 1
          c.mv a7, a3
          ecall
      >>> print(pwnlib.shellcraft.riscv64.linux.syscall(
      ...               'SYS_mmap', 0, 0x1000,
      ...               'PROT_READ | PROT_WRITE | PROT_EXEC',
      ...               'MAP_PRIVATE',
      ...               -1, 0).rstrip())
          /* call mmap(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE', -1, 0) */
          c.li a0, 0
          c.lui a1, 1 /* mv a1, 0x1000 */
          c.li a2, 7
          c.li a3, 2
          c.li a4, 0xffffffffffffffff
          c.li a5, 0
          /* mv a7, 0xde */
          xori a7, zero, 0x721
          xori a7, a7, 0x7ff
          ecall
      >>> print(pwnlib.shellcraft.openat('AT_FDCWD', '/home/pwn/flag').rstrip())
          /* openat(fd='AT_FDCWD', file='/home/pwn/flag', oflag=0) */
          /* push b'/home/pwn/flag\x00' */
          li t4, 0x77702f656d6f682f
          sd t4, -16(sp)
          li t4, 0x67616c662f6e
          sd t4, -8(sp)
          addi sp, sp, -16
          c.mv a1, sp
          xori a0, zero, 0xffffffffffffff9c
          c.li a2, 0
          /* call openat() */
          /* mv a7, 0x38 */
          xori a7, zero, 0x7c7
          xori a7, a7, 0x7ff
          ecall