diff --git a/pwnlib/elf/maps.py b/pwnlib/elf/maps.py index 99c3c194d..54e208647 100644 --- a/pwnlib/elf/maps.py +++ b/pwnlib/elf/maps.py @@ -25,6 +25,6 @@ 'ee058ed24eeeadf26eecc5f26eaeecf28fcd8cd2efa5adf22f0ccef26f0ee0f2ee3fbfa980f39fd2e0ffbff2e0ffdff2e0fffff2e1633f8be2031faa080780d2010000d4222080d22e2088d2c20102caff6322cbe1633f8be80780d2010000d402041f8b4f2080d26c2080d28f010fcae0030faae1633f8b080880d2010000d4' 'e0031faaa80b80d2010000d4', 'riscv64': - 'b7ae2b039b8ebe97939ede00938efe36939ece00938e7e72939ece00938efe022338d1ffb73eb8399b8e7e0b939ece00938ebe97939ede00938ece66233cd1ff130101ff1345c0f99305010033c6ff019348707c93c8f87f73000000374600003301c140930501009348007c93c8f87f730000001306050013051000930501009348f07b93c8f87f73000000' + 'b73e736593ce3e76938e0e80b77f726f9b8fff02939e0e02b3cefe012338d1ffb77e73009b8e1e06b76f2f6d93cfcf66939e0e02b3cefe01233cd1ff130101ff1345c0f9b355014033c6ff019348707c93c8f87f73000000374600003301c140b35501409348007c93c8f87f73000000335605401335f07fb35501409348f07b93c8f87f73000000' '33c5ff019348207a93c8f87f73000000', } diff --git a/pwnlib/shellcraft/templates/riscv64/linux/syscall.asm b/pwnlib/shellcraft/templates/riscv64/linux/syscall.asm index 5b5b22530..7c40dcce6 100644 --- a/pwnlib/shellcraft/templates/riscv64/linux/syscall.asm +++ b/pwnlib/shellcraft/templates/riscv64/linux/syscall.asm @@ -15,22 +15,23 @@ Example: >>> print(pwnlib.shellcraft.riscv64.linux.syscall('SYS_execve', 1, 'sp', 2, 0).rstrip()) /* call execve(1, 'sp', 2, 0) */ - li a0, 1 - mv a1, sp - li a2, 2 + sltiu a0, zero, 0x7ff | 1 + sra a1, sp, zero + xori a2, zero, 0x7ff ^ 2 + xori a2, a2, 0x7ff xor a3, t6, t6 - /* mv a7, 0xdd */ - xori a7, zero, 0x722 + xori a7, zero, 0x7ff ^ SYS_execve /* 0xdd */ xori a7, a7, 0x7ff ecall >>> print(pwnlib.shellcraft.riscv64.linux.syscall('SYS_execve', 2, 1, 0, 20).rstrip()) /* call execve(2, 1, 0, 0x14) */ - li a0, 2 - li a1, 1 + xori a0, zero, 0x7ff ^ 2 + xori a0, a0, 0x7ff + sltiu a1, zero, 0x7ff | 1 xor a2, t6, t6 - li a3, 0x14 - /* mv a7, 0xdd */ - xori a7, zero, 0x722 + xori a3, zero, 0x7ff ^ 0x14 + xori a3, a3, 0x7ff + xori a7, zero, 0x7ff ^ SYS_execve /* 0xdd */ xori a7, a7, 0x7ff ecall >>> print(pwnlib.shellcraft.riscv64.linux.syscall().rstrip()) @@ -42,8 +43,8 @@ Example: ecall >>> print(pwnlib.shellcraft.riscv64.linux.syscall('a3', None, None, 1).rstrip()) /* call syscall('a3', ?, ?, 1) */ - li a2, 1 - mv a7, a3 + sltiu a2, zero, 0x7ff | 1 + sra a7, a3, zero ecall >>> print(pwnlib.shellcraft.riscv64.linux.syscall( ... 'SYS_mmap', 0, 0x1000, @@ -52,29 +53,43 @@ Example: ... -1, 0).rstrip()) /* call mmap(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE', -1, 0) */ xor a0, t6, t6 - lui a1, 1 /* mv a1, 0x1000 */ - li a2, 7 - li a3, 2 - li a4, 0xffffffffffffffff + li a1, 0x1000 + xori a2, zero, 0x7ff ^ (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ + xori a2, a2, 0x7ff + xori a3, zero, 0x7ff ^ MAP_PRIVATE /* 2 */ + xori a3, a3, 0x7ff + xori a4, zero, -1 xor a5, t6, t6 - /* mv a7, 0xde */ - xori a7, zero, 0x721 + xori a7, zero, 0x7ff ^ SYS_mmap /* 0xde */ 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 + lui t4, 0xfffff & ((0x77702f65 >> 12) + 1) + xori t4, t4, 0x7ff & 0x77702f65 + addi t4, t4, -0x800 + lui t6, 0xfffff & ((0x6d6f682f >> 12) + 1) + xori t6, t6, 0x7ff & 0x6d6f682f + addi t6, t6, -0x800 + slli t4, t4, 0x20 + xor t4, t4, t6 sd t4, -16(sp) - li t4, 0x67616c662f6e + lui t4, 0xfffff & (~0x6761 >> 12) + xori t4, t4, ~0x7ff | 0x6761 + addi t4, t4, -0x800 + lui t6, 0xfffff & ((0x6c662f6e >> 12) + 1) + xori t6, t6, 0x7ff & 0x6c662f6e + addi t6, t6, -0x800 + slli t4, t4, 0x20 + xor t4, t4, t6 sd t4, -8(sp) addi sp, sp, -16 - mv a1, sp - xori a0, zero, 0xffffffffffffff9c + sra a1, sp, zero + xori a0, zero, AT_FDCWD /* -0x64 */ xor a2, t6, t6 /* call openat() */ - /* mv a7, 0x38 */ - xori a7, zero, 0x7c7 + xori a7, zero, 0x7ff ^ SYS_openat /* 0x38 */ xori a7, a7, 0x7ff ecall diff --git a/pwnlib/shellcraft/templates/riscv64/mov.asm b/pwnlib/shellcraft/templates/riscv64/mov.asm index 13590b94d..4e3c93ea3 100644 --- a/pwnlib/shellcraft/templates/riscv64/mov.asm +++ b/pwnlib/shellcraft/templates/riscv64/mov.asm @@ -28,28 +28,24 @@ Example: >>> print(shellcraft.riscv64.mov('t0', 0).rstrip()) xor t0, t6, t6 >>> print(shellcraft.riscv64.mov('t0', 0x2000, c=True).rstrip()) - c.lui t0, 2 /* mv t0, 0x2000 */ + c.lui t0, 0xfffff & (0x2000 >> 12) >>> 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, zero, 0x7ff ^ 0x600 xori t5, t5, 0x7ff >>> print(shellcraft.riscv64.mov('t6', 0x181f).rstrip()) - /* mv t6, 0x181f */ - lui t6, 0xffffe - xori t6, t6, 0xfffffffffffff81f + lui t6, 0xfffff & (~0x181f >> 12) + xori t6, t6, ~0x7ff | 0x181f >>> print(shellcraft.riscv64.mov('t5', 0x40b561f).rstrip()) - /* mv t5, 0x40b561f */ - lui t5, 0x40b5 - xori t5, t5, 0x61f + lui t5, 0xfffff & (0x40b561f >> 12) + xori t5, t5, 0x7ff & 0x40b561f >>> print(shellcraft.riscv64.mov('t0', 0xcafebabe).rstrip()) li t0, 0xcafebabe >>> print(shellcraft.riscv64.mov('a0', 't2', c=True).rstrip()) c.mv a0, t2 >>> print(shellcraft.riscv64.mov('t1', 'sp', c=True).rstrip()) - c.mv t6, sp - c.mv t1, t6 /* mv t1, sp */ + sra t1, sp, zero <% @@ -66,7 +62,6 @@ if isinstance(src, str) and src not in registers.riscv: src_reg = registers.riscv.get(src, None) dst_reg = registers.riscv[dst] -tmp = 't6' if dst_reg != registers.riscv['t6'] else 't4' # If source register is zero, treat it as immediate 0 if src_reg == 0: @@ -82,64 +77,68 @@ encodes_no_newline = lambda a, not_a: not (a & 0xf == 0 or (a & 0xff0) >> 8 in [ % elif src_reg is not None: ## Source is a register ## Special case where c.mv would produce a newline -% if c: -% if src_reg == 2 and dst_reg % 2 == 0: - c.mv ${tmp}, ${src} - c.mv ${dst}, ${tmp} /* mv ${dst}, ${src} */ -% else: +% if c and not (src_reg == 2 and dst_reg % 2 == 0): c.mv ${dst}, ${src} -% endif +% elif (src_reg >> 1) not in (0, 10): + sra ${dst}, ${src}, zero % else: -mv ${dst}, ${src} + not ${dst}, ${src} + not ${dst}, ${dst} % endif % else: ## Source is an immediate, normalize to [0, 2**64) -<% src = packing.unpack(packing.pack(src, word_size=64), word_size=64, sign=False) %> +<% srcn = src & 0xffffffffffffffff %> ## Immediates are always sign-extended to 64-bit ## 6-bit immediate for c.li -% if src < 0x20 or src >= 0xffffffffffffffe0: +% if c and (srcn < 0x20 or srcn >= 0xffffffffffffffe0): -% if c: c.li ${dst}, ${pretty(src)} -% elif src == 0: - xor ${dst}, t6, t6 -% else: - li ${dst}, ${pretty(src)} -% endif - ## 6-bit immediate for c.lui -% elif dst_reg != 2 and src & 0xfff == 0 and ((src>>12) < 0x20 or (src>>12) >= 0xffffffffffffffe0): -% if c: - c.lui ${dst}, ${pretty(src>>12)} /* mv ${dst}, ${pretty(src)} */ -% else: - lui ${dst}, ${pretty(src>>12)} /* mv ${dst}, ${pretty(src)} */ -% endif - +% elif c and (dst_reg != 2 and srcn & 0xfff == 0 and ((srcn>>12) < 0x20 or (srcn>>12) >= 0xffffffffffffffe0)): + c.lui ${dst}, 0xfffff & (${pretty(src)} >> 12) ## 12-bit immediate -% elif src < 0x800 or src >= 0xfffffffffffff800: - % if src & 0xf == 0 or (src & 0xfff) >> 8 in [0, 10]: - /* mv ${dst}, ${pretty(src)} */ - xori ${dst}, zero, ${pretty(src ^ 0x7ff)} - xori ${dst}, ${dst}, ${pretty(0x7ff)} +% elif srcn < 0x800 or srcn >= 0xfffffffffffff800: + % if srcn == 0: + xor ${dst}, t6, t6 + % elif srcn == 1: + sltiu ${dst}, zero, 0x7ff | ${pretty(src)} + % elif src & 0xf == 0 or (src & 0xfff) >> 8 in [0, 10]: + xori ${dst}, zero, 0x7ff ^ ${pretty(src)} + xori ${dst}, ${dst}, 0x7ff % else: xori ${dst}, zero, ${pretty(src)} % endif ## 32-bit immediate with lui and xori -% elif (src < 0x80000000 or src >= 0xffffffff80000000) and src & 0x800 == 0 and encodes_no_newline(src, src): - /* mv ${dst}, ${pretty(src)} */ - lui ${dst}, ${pretty(src >> 12)} - xori ${dst}, ${dst}, ${pretty(src & 0xfff)} -% elif (src < 0x80000000 or src >= 0xffffffff80000000) and src & 0x800 == 0x800 and encodes_no_newline(src, ~src): - /* mv ${dst}, ${pretty(src)} */ - lui ${dst}, ${pretty((~src >> 12) & 0xfffff)} - xori ${dst}, ${dst}, ${pretty(src & 0xfff | 0xfffffffffffff000)} +% elif (srcn < 0x80000000 or srcn >= 0xffffffff80000000) and srcn & 0x800 == 0 and encodes_no_newline(srcn, srcn): + lui ${dst}, 0xfffff & (${pretty(src)} >> 12) + xori ${dst}, ${dst}, 0x7ff & ${pretty(src)} +% elif (srcn < 0x80000000 or srcn >= 0xffffffff80000000) and srcn & 0x800 == 0x800 and encodes_no_newline(srcn, srcn + 0x800): + lui ${dst}, 0xfffff & ((${pretty(src)} >> 12) + 1) + xori ${dst}, ${dst}, 0x7ff & ${pretty(src)} + addi ${dst}, ${dst}, -0x800 +% elif (srcn < 0x80000000 or srcn >= 0xffffffff80000000) and encodes_no_newline(srcn, ~srcn): + lui ${dst}, 0xfffff & (~${pretty(src)} >> 12) + xori ${dst}, ${dst}, ~0x7ff | ${pretty(src)} + % if not srcn & 0x800: + addi ${dst}, ${dst}, -0x800 + % endif ## 64-bit immediate with lui, addi, and slli -## FIXME: Make this null and newline free +% elif srcn > 0xfffffffff and srcn < 0xffffffff00000000: + % if src & 0x80000000: + ${riscv64.mov(dst, ~src >> 32)} + ${riscv64.mov('t6', src | ~0x7fffffff)} + % else: + ${riscv64.mov(dst, src >> 32)} + ${riscv64.mov('t6', src & 0x7fffffff)} + % endif + slli ${dst}, ${dst}, 0x20 + xor ${dst}, ${dst}, t6 % else: +## FIXME: Make this null and newline free li ${dst}, ${pretty(src)} % endif diff --git a/pwnlib/shellcraft/templates/riscv64/pushstr.asm b/pwnlib/shellcraft/templates/riscv64/pushstr.asm index 59ee929d4..6cf1f48fe 100644 --- a/pwnlib/shellcraft/templates/riscv64/pushstr.asm +++ b/pwnlib/shellcraft/templates/riscv64/pushstr.asm @@ -16,51 +16,53 @@ Example: addi sp, sp, -8 >>> print(shellcraft.riscv64.pushstr('a').rstrip()) /* push b'a\x00' */ - /* mv t4, 0x61 */ - xori t4, zero, 0x79e + xori t4, zero, 0x7ff ^ 0x61 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 + lui t4, 0xfffff & (~0x6161 >> 12) + xori t4, t4, ~0x7ff | 0x6161 + addi t4, t4, -0x800 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 + lui t4, 0xfffff & (0x61616161 >> 12) + xori t4, t4, 0x7ff & 0x61616161 sd t4, -8(sp) addi sp, sp, -8 >>> print(shellcraft.riscv64.pushstr('aaaaa').rstrip()) /* push b'aaaaa\x00' */ - li t4, 0x6161616161 + xori t4, zero, 0x7ff ^ 0x61 + xori t4, t4, 0x7ff + lui t6, 0xfffff & (0x61616161 >> 12) + xori t6, t6, 0x7ff & 0x61616161 + slli t4, t4, 0x20 + xor t4, t4, t6 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 + lui t4, 0xfffff & (0x61616161 >> 12) + xori t4, t4, 0x7ff & 0x61616161 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, zero, 0x7ff ^ 0xc3 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, zero, 0x7ff ^ 0xc3 xori t4, t4, 0x7ff sd t4, -8(sp) addi sp, sp, -8 >>> print(enhex(asm(shellcraft.riscv64.pushstr("/bin/sh")))) - b79e39349b8e7e7b939ece00938ebe34939ede00938efe22233cd1ff130181ff + b78e97ff93cefeb2938e0e80b76f696e93cfff22939e0e02b3cefe01233cd1ff130181ff >>> print(enhex(asm(shellcraft.riscv64.pushstr("")))) 232c01fe130181ff >>> print(enhex(asm(shellcraft.riscv64.pushstr("\x00", append_null = False)))) diff --git a/pwnlib/shellcraft/templates/riscv64/setregs.asm b/pwnlib/shellcraft/templates/riscv64/setregs.asm index f55ee989d..0df7870b6 100644 --- a/pwnlib/shellcraft/templates/riscv64/setregs.asm +++ b/pwnlib/shellcraft/templates/riscv64/setregs.asm @@ -17,14 +17,14 @@ Example: >>> print(shellcraft.setregs({'t0':1, 'a3':'0'}).rstrip()) xor a3, t6, t6 - li t0, 1 + sltiu t0, zero, 0x7ff | 1 >>> print(shellcraft.setregs({'a0':'a1', 'a1':'a0', 'a2':'a1'}).rstrip()) - mv a2, a1 - mv t4, a1 + sra a2, a1, zero + sra t4, a1, zero xor a1, a0, t4 /* xchg a1, a0 */ - mv t4, a0 + sra t4, a0, zero xor a0, a1, t4 - mv t4, a1 + sra t4, a1, zero xor a1, a0, t4 <% @@ -34,7 +34,7 @@ sorted_regs = regsort(reg_context, registers.riscv) % if not sorted_regs: /* setregs noop */ % else: -% for how, src, dst in regsort(reg_context, registers.riscv): +% for how, src, dst in sorted_regs: % if how == 'xchg': ${riscv64.xor(dst, dst, src)} /* xchg ${dst}, ${src} */ ${riscv64.xor(src, src, dst)} diff --git a/pwnlib/shellcraft/templates/riscv64/xor.asm b/pwnlib/shellcraft/templates/riscv64/xor.asm index 5a506e284..12771b63f 100644 --- a/pwnlib/shellcraft/templates/riscv64/xor.asm +++ b/pwnlib/shellcraft/templates/riscv64/xor.asm @@ -22,12 +22,17 @@ if not isinstance(rs2, str) or rs2 not in registers.riscv: rs1_reg = registers.riscv[rs1] rs2_reg = registers.riscv[rs2] %> -## 0000000 rs2 rs1 -## 0000000 00000 0000 -% if rs1_reg & 0x10 > 0 and (rs2_reg > 1 or rs1_reg & 0xf > 0) and (rs1_reg != 0x10 and rs2_reg != 10): - xor ${dst}, ${rs2}, ${rs1} -% elif rs2_reg & 0x10 > 0 and (rs1_reg > 1 or rs2_reg & 0xf > 0) and (rs2_reg != 0x10 and rs1_reg != 10): + +## always safe +## c.xor rs1d rs2 +## 100011dd d01sss01 + +## xor rs2 rs1 rd +## 0000000s ssssSSSS S100ddddd 0110011 +% if rs2_reg & 0x10 and (rs1_reg >> 1 | ((rs2_reg & 0xf) << 4)) not in (0, 10): xor ${dst}, ${rs1}, ${rs2} +% elif rs1_reg & 0x10 and (rs2_reg >> 1 | ((rs1_reg & 0xf) << 4)) not in (0, 10): + xor ${dst}, ${rs2}, ${rs1} % else: ${riscv64.mov('t4', rs1)} xor ${dst}, ${rs2}, t4