pwnlib.shellcraft.arm — Shellcode for ARM¶
pwnlib.shellcraft.arm¶
Shellcraft module containing generic ARM little endian shellcodes.
-
pwnlib.shellcraft.arm.crash()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
-
pwnlib.shellcraft.arm.itoa(v, buffer='sp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack. Uses registers r0-r5.
Parameters: Example
>>> sc = shellcraft.arm.mov('r0', 0xdeadbeef) >>> sc += shellcraft.arm.itoa('r0') >>> sc += shellcraft.arm.linux.write(1, 'sp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.arm.memcpy(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.arm.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.arm.mov('r0','r1').rstrip() mov r0, r1 >>> print shellcraft.arm.mov('r0', 5).rstrip() mov r0, #5 >>> print shellcraft.arm.mov('r0', 0x34532).rstrip() movw r0, #0x34532 & 0xffff movt r0, #0x34532 >> 16 >>> print shellcraft.arm.mov('r0', 0x101).rstrip() movw r0, #0x101 >>> print shellcraft.arm.mov('r0', 0xff << 14).rstrip() mov r0, #0x3fc000 >>> print shellcraft.arm.mov('r0', 0xff << 15).rstrip() movw r0, #0x7f8000 & 0xffff movt r0, #0x7f8000 >> 16 >>> print shellcraft.arm.mov('r0', 0xf00d0000).rstrip() eor r0, r0 movt r0, #0xf00d0000 >> 16 >>> print shellcraft.arm.mov('r0', 0xffff00ff).rstrip() mvn r0, #(0xffff00ff ^ (-1)) >>> print shellcraft.arm.mov('r0', 0x1fffffff).rstrip() mvn r0, #(0x1fffffff ^ (-1))
Parameters:
-
pwnlib.shellcraft.arm.push(word, register='r12')[source]¶ Pushes a 32-bit integer onto the stack. Uses r12 as a temporary register.
r12 is defined as the inter-procedural scartch register ($ip), so this should not interfere with most usage.
Parameters:
-
pwnlib.shellcraft.arm.pushstr(string, append_null=True, register='r7')[source]¶ Pushes a string onto the stack.
Parameters: Examples
>>> print shellcraft.arm.pushstr("Hello!").rstrip() /* push 'Hello!\x00A' */ movw r7, #0x4100216f & 0xffff movt r7, #0x4100216f >> 16 push {r7} movw r7, #0x6c6c6548 & 0xffff movt r7, #0x6c6c6548 >> 16 push {r7}
-
pwnlib.shellcraft.arm.pushstr_array(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.arm.ret(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return Examples
>>> with context.local(arch='arm'): ... print enhex(asm(shellcraft.ret())) ... print enhex(asm(shellcraft.ret(0))) ... print enhex(asm(shellcraft.ret(0xdeadbeef))) 1eff2fe1 000020e01eff2fe1 ef0e0be3ad0e4de31eff2fe1
-
pwnlib.shellcraft.arm.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: Example
>>> print shellcraft.setregs({'r0':1, 'r2':'r3'}).rstrip() mov r0, #1 mov r2, r3 >>> print shellcraft.setregs({'r0':'r1', 'r1':'r0', 'r2':'r3'}).rstrip() mov r2, r3 eor r0, r0, r1 /* xchg r0, r1 */ eor r1, r0, r1 eor r0, r0, r1
-
pwnlib.shellcraft.arm.udiv_10(N)[source]¶ Divides r0 by 10. Result is stored in r0, N and Z flags are updated.
- Code is from generated from here:
- https://raw.githubusercontent.com/rofirrim/raspberry-pi-assembler/master/chapter15/magic.py
- With code:
- python magic.py 10 code_for_unsigned
-
pwnlib.shellcraft.arm.xor(key, address, count)[source]¶ XORs data a constant value.
Parameters: 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.arm.linux¶
Shellcraft module containing ARM shellcodes for Linux.
-
pwnlib.shellcraft.arm.linux.cacheflush()[source]¶ Invokes the cache-flush operation, without using any NULL or newline bytes.
Effectively is just:
mov r0, #0 mov r1, #-1 mov r2, #0 swi 0x9F0002How this works:
… However, SWI generates a software interrupt and to the interrupt handler, 0x9F0002 is actually data and as a result will not be read via the instruction cache, so if we modify the argument to SWI in our self-modifyign code, the argument will be read correctly.
-
pwnlib.shellcraft.arm.linux.cat(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
Example
>>> f = tempfile.mktemp() >>> write(f, 'FLAG\n') >>> run_assembly(shellcraft.arm.linux.cat(f)).recvline() 'FLAG\n'
-
pwnlib.shellcraft.arm.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 R6.
-
pwnlib.shellcraft.arm.linux.dir(in_fd='r6', size=2048, allocate_stack=True)[source]¶ Reads to the stack from a directory.
Parameters: You can optioanlly shave a few bytes not allocating the stack space.
The size read is left in eax.
-
pwnlib.shellcraft.arm.linux.echo(string, sock='1')[source]¶ Writes a string to a file descriptor
Example
>>> run_assembly(shellcraft.echo('hello\n', 1)).recvline() 'hello\n'
-
pwnlib.shellcraft.arm.linux.egghunter(egg, start_address = 0, double_check = True)[source]¶ Searches for an egg, which is either a four byte integer or a four byte string. The egg must appear twice in a row if double_check is True. When the egg has been found the egghunter branches to the address following it. If start_address has been specified search will start on the first address of the page that contains that address.
-
pwnlib.shellcraft.arm.linux.forkexit()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.arm.linux.killparent()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.arm.linux.open_file(filepath, flags='O_RDONLY', mode=420)[source]¶ Opens a file. Leaves the file descriptor in r0.
Parameters: - filepath (str) – The file to open.
- flags (int/str) – The flags to call open with.
- mode (int/str) – The attribute to create the flag. Only matters of
flags & O_CREATis set.
-
pwnlib.shellcraft.arm.linux.sh()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.arm.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.arm.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.arm.linux.syscall(11, 1, 'sp', 2, 0).rstrip() /* call syscall(11, 1, 'sp', 2, 0) */ mov r0, #1 mov r1, sp mov r2, #2 eor r3, r3 /* 0 (#0) */ mov r7, #0xb svc 0 >>> print shellcraft.arm.linux.syscall('SYS_exit', 0).rstrip() /* call exit(0) */ eor r0, r0 /* 0 (#0) */ mov r7, #SYS_exit /* 1 */ svc 0 >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00A' */ movw r7, #0x41006761 & 0xffff movt r7, #0x41006761 >> 16 push {r7} movw r7, #0x6c662f6e & 0xffff movt r7, #0x6c662f6e >> 16 push {r7} movw r7, #0x77702f65 & 0xffff movt r7, #0x77702f65 >> 16 push {r7} movw r7, #0x6d6f682f & 0xffff movt r7, #0x6d6f682f >> 16 push {r7} mov r0, sp eor r1, r1 /* 0 (#0) */ eor r2, r2 /* 0 (#0) */ /* call open() */ mov r7, #SYS_open /* 5 */ svc 0