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_CREAT
is 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