pwnlib.shellcraft.riscv64 — Shellcode for RISCV64

pwnlib.shellcraft.riscv64

Shellcraft module containing generic RISCV64 shellcodes.

pwnlib.shellcraft.riscv64.mov(dst, src)[source]

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()[source]

RISCV64 nop instruction.

pwnlib.shellcraft.riscv64.push(value)[source]

Pushes a value onto the stack.

Register t4 is not guaranteed to be preserved.

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

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)[source]

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)[source]

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()[source]

A trap instruction.

pwnlib.shellcraft.riscv64.xor(dst, rs1, rs2)[source]

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)[source]
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