pwnlib.shellcraft.aarch64
— Shellcode for AArch64¶
pwnlib.shellcraft.aarch64
¶
- pwnlib.shellcraft.aarch64.breakpoint()[source]¶
Inserts a debugger breakpoint (raises SIGTRAP).
Example
>>> run_assembly(shellcraft.breakpoint()).poll(True) -5
- pwnlib.shellcraft.aarch64.crash()[source]¶
Crashes the process.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
- pwnlib.shellcraft.aarch64.infloop()[source]¶
An infinite loop.
Example
>>> io = run_assembly(shellcraft.infloop()) >>> io.recvall(timeout=1) b'' >>> io.close()
- pwnlib.shellcraft.aarch64.memcpy(dest, src, n)[source]¶
Copies memory.
- Parameters
dest – Destination address
src – Source address
n – Number of bytes
- pwnlib.shellcraft.aarch64.mov(dst, src)[source]¶
Move src into dest.
Support for automatically avoiding newline and null bytes has to be done.
If src is a string that is not a register, then it will locally set context.arch to ‘arm’ 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.Examples
>>> print(shellcraft.mov('x0','x1').rstrip()) mov x0, x1 >>> print(shellcraft.mov('x0','0').rstrip()) mov x0, xzr >>> print(shellcraft.mov('x0', 5).rstrip()) mov x0, #5 >>> print(shellcraft.mov('x0', 0x34532).rstrip()) /* Set x0 = 214322 = 0x34532 */ mov x0, #17714 movk x0, #3, lsl #16
- Parameters
dest (str) – The destination register.
src (str) – Either the input register, or an immediate value.
- pwnlib.shellcraft.aarch64.push(value, register1='x14', register2='x15')[source]¶
Pushes a value onto the stack without using null bytes or newline characters.
If src is a string, then we try to evaluate using
pwnlib.constants.eval()
before determining how to push it.Note that this means that this shellcode can change behavior depending on the value of context.os.
Note
AArch64 requires that the stack remain 16-byte aligned at all times, so this alignment is preserved.
- Parameters
value (int,str) – The value or register to push
register1 (str) – Scratch register to use
register2 (str) – Second scratch register to use
Example
>>> print(pwnlib.shellcraft.push(0).rstrip()) /* push 0 */ mov x14, xzr str x14, [sp, #-16]! >>> print(pwnlib.shellcraft.push(1).rstrip()) /* push 1 */ mov x14, #1 str x14, [sp, #-16]! >>> print(pwnlib.shellcraft.push(256).rstrip()) /* push 0x100 */ mov x14, #256 str x14, [sp, #-16]! >>> print(pwnlib.shellcraft.push('SYS_execve').rstrip()) /* push SYS_execve (0xdd) */ mov x14, #221 str x14, [sp, #-16]! >>> print(pwnlib.shellcraft.push('SYS_sendfile').rstrip()) /* push SYS_sendfile (0x47) */ mov x14, #71 str x14, [sp, #-16]! >>> with context.local(os = 'freebsd'): ... print(pwnlib.shellcraft.push('SYS_execve').rstrip()) ... /* push SYS_execve (0x3b) */ mov x14, #59 str x14, [sp, #-16]!
- pwnlib.shellcraft.aarch64.pushstr(string, append_null=True, register1='x14', register2='x15', pretty=None)[source]¶
Pushes a string onto the stack.
r12 is defined as the inter-procedural scratch register ($ip), so this should not interfere with most usage.
- Parameters
string (str) – The string to push.
append_null (bool) – Whether to append a single NULL-byte before pushing.
register (str) – Temporary register to use. By default, R7 is used.
Examples
>>> string = "Hello, world!" >>> assembly = shellcraft.pushstr(string) >>> assembly += shellcraft.write(1, 'sp', len(string)) >>> assembly += shellcraft.exit() >>> ELF.from_assembly(assembly).process().recvall() b'Hello, world!'
>>> string = "Hello, world! This is a long string! Wow!" >>> assembly = shellcraft.pushstr(string) >>> assembly += shellcraft.write(1, 'sp', len(string)) >>> assembly += shellcraft.exit() >>> ELF.from_assembly(assembly).process().recvall() b'Hello, world! This is a long string! Wow!'
- pwnlib.shellcraft.aarch64.pushstr_array(reg, array, register1='x14', register2='x15')[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.
Example
>>> assembly = shellcraft.execve("/bin/sh", ["sh", "-c", "echo Hello string $WORLD"], {"WORLD": "World!"}) >>> ELF.from_assembly(assembly).process().recvall() b'Hello string World!\n'
- pwnlib.shellcraft.aarch64.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({'x0':1, 'x2':'x3'}).rstrip()) mov x0, #1 mov x2, x3 >>> print(shellcraft.setregs({'x0':'x1', 'x1':'x0', 'x2':'x3'}).rstrip()) mov x2, x3 eor x0, x0, x1 /* xchg x0, x1 */ eor x1, x0, x1 eor x0, x0, x1
- pwnlib.shellcraft.aarch64.trap()[source]¶
Inserts a debugger breakpoint (raises SIGTRAP).
Example
>>> run_assembly(shellcraft.breakpoint()).poll(True) -5
- pwnlib.shellcraft.aarch64.xor(key, address, count)[source]¶
XORs data a constant value.
- Parameters
key (int,str) – XOR key either as a 4-byte integer, If a string, length must be a power of two, and not longer than 4 bytes.
address (int) – Address of the data (e.g. 0xdead0000, ‘rsp’)
count (int) – Number of bytes to XOR.
Example
>>> sc = shellcraft.read(0, 'sp', 32) >>> sc += shellcraft.xor(0xdeadbeef, 'sp', 32) >>> sc += shellcraft.write(1, 'sp', 32) >>> io = run_assembly(sc) >>> io.send(cyclic(32)) >>> result = io.recvn(32) >>> expected = xor(cyclic(32), p32(0xdeadbeef)) >>> result == expected True
pwnlib.shellcraft.aarch64.linux
¶
- pwnlib.shellcraft.aarch64.linux.cat(filename, fd=1)[source]¶
Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'This is the flag\n') >>> shellcode = shellcraft.cat(f) + shellcraft.exit(0) >>> run_assembly(shellcode).recvline() b'This is the flag\n'
- pwnlib.shellcraft.aarch64.linux.cat2(filename, fd=1, length=16384)[source]¶
Opens a file and writes its contents to the specified file descriptor. Uses an extra stack buffer and must know the length.
Example
>>> f = tempfile.mktemp() >>> write(f, 'This is the flag\n') >>> shellcode = shellcraft.cat2(f) + shellcraft.exit(0) >>> run_assembly(shellcode).recvline() b'This is the flag\n'
- pwnlib.shellcraft.aarch64.linux.connect(host, port, network='ipv4')[source]¶
Connects to the host on the specified port. Network is either ‘ipv4’ or ‘ipv6’. Leaves the connected socket in x12.
- pwnlib.shellcraft.aarch64.linux.echo(string, sock='1')[source]¶
Writes a string to a file descriptor
Example
>>> run_assembly(shellcraft.echo('hello\n', 1)).recvline() b'hello\n'
- pwnlib.shellcraft.aarch64.linux.forkexit()[source]¶
Attempts to fork. If the fork is successful, the parent exits.
- pwnlib.shellcraft.aarch64.linux.kill(pid, sig) str [source]¶
Invokes the syscall kill.
See ‘man 2 kill’ for more information.
- Parameters
pid (pid_t) – pid
sig (int) – sig
- Returns
int
- pwnlib.shellcraft.aarch64.linux.killparent()[source]¶
Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
- pwnlib.shellcraft.aarch64.linux.loader(address)[source]¶
Loads a statically-linked ELF into memory and transfers control.
- Parameters
address (int) – Address of the ELF as a register or integer.
- pwnlib.shellcraft.aarch64.linux.loader_append(data=None)[source]¶
Loads a statically-linked ELF into memory and transfers control.
Similar to loader.asm but loads an appended ELF.
- Parameters
data (str) – If a valid filename, the data is loaded from the named file. Otherwise, this is treated as raw ELF data to append. If
None
, it is ignored.
Example:
The following doctest is commented out because it doesn’t work on Travis for reasons I cannot diagnose. However, it should work just fine :-)
>>> payload = shellcraft.echo(b'Hello, world!\n') + shellcraft.exit(0) >>> payloadELF = ELF.from_assembly(payload) >>> loader = shellcraft.loader_append(payloadELF.data) >>> loaderELF = ELF.from_assembly(loader, vma=0, shared=True) >>> loaderELF.process().recvall() b'Hello, world!\n'
- pwnlib.shellcraft.aarch64.linux.readn(fd, buf, nbytes)[source]¶
Reads exactly nbytes bytes from file descriptor fd into the buffer buf.
- Parameters
fd (int) – fd
buf (void) – buf
nbytes (size_t) – nbytes
- pwnlib.shellcraft.aarch64.linux.sh()[source]¶
Execute a different process.
>>> p = run_assembly(shellcraft.aarch64.linux.sh()) >>> p.sendline(b'echo Hello') >>> p.recv() b'Hello\n'
- pwnlib.shellcraft.aarch64.linux.stage(fd=0, length=None)[source]¶
Migrates shellcode to a new buffer.
- Parameters
fd (int) – Integer file descriptor to recv data from. Default is stdin (0).
length (int) – Optional buffer length. If None, the first pointer-width of data received is the length.
Example
>>> p = run_assembly(shellcraft.stage()) >>> sc = asm(shellcraft.echo("Hello\n", constants.STDOUT_FILENO)) >>> p.pack(len(sc)) >>> p.send(sc) >>> p.recvline() b'Hello\n'
- pwnlib.shellcraft.aarch64.linux.syscall(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=None, arg6=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(shellcraft.aarch64.linux.syscall(11, 1, 'sp', 2, 0).rstrip()) /* call syscall(0xb, 1, 'sp', 2, 0) */ mov x0, #1 mov x1, sp mov x2, #2 mov x3, xzr mov x8, #11 svc 0 >>> print(shellcraft.aarch64.linux.syscall('SYS_exit', 0).rstrip()) /* call exit(0) */ mov x0, xzr mov x8, #SYS_exit svc 0 >>> print(pwnlib.shellcraft.openat(-2, '/home/pwn/flag').rstrip()) /* openat(fd=-2, file='/home/pwn/flag', oflag=0) */ /* push b'/home/pwn/flag\x00' */ /* Set x14 = 8606431000579237935 = 0x77702f656d6f682f */ mov x14, #26671 movk x14, #28015, lsl #16 movk x14, #12133, lsl #0x20 movk x14, #30576, lsl #0x30 /* Set x15 = 113668128124782 = 0x67616c662f6e */ mov x15, #12142 movk x15, #27750, lsl #16 movk x15, #26465, lsl #0x20 stp x14, x15, [sp, #-16]! mov x1, sp /* Set x0 = -2 = -2 */ mov x0, #65534 movk x0, #65535, lsl #16 movk x0, #65535, lsl #0x20 movk x0, #65535, lsl #0x30 mov x2, xzr /* call openat() */ mov x8, #SYS_openat svc 0