Skip to content

Commit

Permalink
templates
Browse files Browse the repository at this point in the history
  • Loading branch information
Arusekk committed Dec 12, 2024
1 parent 9c87b4a commit e83748b
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 100 deletions.
2 changes: 1 addition & 1 deletion pwnlib/elf/maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
'ee058ed24eeeadf26eecc5f26eaeecf28fcd8cd2efa5adf22f0ccef26f0ee0f2ee3fbfa980f39fd2e0ffbff2e0ffdff2e0fffff2e1633f8be2031faa080780d2010000d4222080d22e2088d2c20102caff6322cbe1633f8be80780d2010000d402041f8b4f2080d26c2080d28f010fcae0030faae1633f8b080880d2010000d4'
'e0031faaa80b80d2010000d4',
'riscv64':
'b7ae2b039b8ebe97939ede00938efe36939ece00938e7e72939ece00938efe022338d1ffb73eb8399b8e7e0b939ece00938ebe97939ede00938ece66233cd1ff130101ff1345c0f99305010033c6ff019348707c93c8f87f73000000374600003301c140930501009348007c93c8f87f730000001306050013051000930501009348f07b93c8f87f73000000'
'b73e736593ce3e76938e0e80b77f726f9b8fff02939e0e02b3cefe012338d1ffb77e73009b8e1e06b76f2f6d93cfcf66939e0e02b3cefe01233cd1ff130101ff1345c0f9b355014033c6ff019348707c93c8f87f73000000374600003301c140b35501409348007c93c8f87f73000000335605401335f07fb35501409348f07b93c8f87f73000000'
'33c5ff019348207a93c8f87f73000000',
}
63 changes: 39 additions & 24 deletions pwnlib/shellcraft/templates/riscv64/linux/syscall.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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,
Expand All @@ -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
</%docstring>
Expand Down
97 changes: 48 additions & 49 deletions pwnlib/shellcraft/templates/riscv64/mov.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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

</%docstring>
<%
Expand All @@ -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:
Expand All @@ -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
Expand Down
32 changes: 17 additions & 15 deletions pwnlib/shellcraft/templates/riscv64/pushstr.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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))))
Expand Down
12 changes: 6 additions & 6 deletions pwnlib/shellcraft/templates/riscv64/setregs.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
</%docstring>
<%
Expand All @@ -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)}
Expand Down
15 changes: 10 additions & 5 deletions pwnlib/shellcraft/templates/riscv64/xor.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e83748b

Please sign in to comment.