pwnlib.shellcraft.amd64 — Shellcode for AMD64¶
pwnlib.shellcraft.amd64¶
Shellcraft module containing generic Intel x86_64 shellcodes.
-
pwnlib.shellcraft.amd64.crash()[source]¶ Crash.
Example
>>> run_assembly(shellcraft.crash()).poll(True) -11
-
pwnlib.shellcraft.amd64.itoa(v, buffer='rsp', allocate_stack=True)[source]¶ Converts an integer into its string representation, and pushes it onto the stack.
Parameters: Example
>>> sc = shellcraft.amd64.mov('rax', 0xdeadbeef) >>> sc += shellcraft.amd64.itoa('rax') >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 32) >>> run_assembly(sc).recvuntil('\x00') '3735928559\x00'
-
pwnlib.shellcraft.amd64.memcpy(dest, src, n)[source]¶ Copies memory.
Parameters: - dest – Destination address
- src – Source address
- n – Number of bytes
-
pwnlib.shellcraft.amd64.mov(dest, src, stack_allowed=True)[source]¶ Move src into dest without newlines and null bytes.
If the src is a register smaller than the dest, then it will be zero-extended to fit inside the larger register.
If the src is a register larger than the dest, then only some of the bits will be used.
If src is a string that is not a register, then it will locally set context.arch to ‘amd64’ 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.Example
>>> print shellcraft.amd64.mov('eax','ebx').rstrip() mov eax, ebx >>> print shellcraft.amd64.mov('eax', 0).rstrip() xor eax, eax /* 0 */ >>> print shellcraft.amd64.mov('ax', 0).rstrip() xor ax, ax /* 0 */ >>> print shellcraft.amd64.mov('rax', 0).rstrip() xor eax, eax /* 0 */ >>> print shellcraft.amd64.mov('rdi', 'ax').rstrip() movzx edi, ax >>> print shellcraft.amd64.mov('al', 'ax').rstrip() /* moving ax into al, but this is a no-op */ >>> print shellcraft.amd64.mov('ax', 'bl').rstrip() movzx ax, bl >>> print shellcraft.amd64.mov('eax', 1).rstrip() push 1 pop rax >>> print shellcraft.amd64.mov('rax', 0xc0).rstrip() xor eax, eax mov al, 0xc0 >>> print shellcraft.amd64.mov('rax', 0xc000).rstrip() xor eax, eax mov ah, 0xc000 >> 8 >>> print shellcraft.amd64.mov('rax', 0xc0c0).rstrip() xor eax, eax mov ax, 0xc0c0 >>> print shellcraft.amd64.mov('rdi', 0xff).rstrip() mov edi, 0x1010101 /* 255 == 0xff */ xor edi, 0x10101fe >>> print shellcraft.amd64.mov('rax', 0xdead00ff).rstrip() mov eax, 0x1010101 /* 3735879935 == 0xdead00ff */ xor eax, 0xdfac01fe >>> print shellcraft.amd64.mov('rax', 0x11dead00ff).rstrip() mov rax, 0x101010101010101 /* 76750323967 == 0x11dead00ff */ push rax mov rax, 0x1010110dfac01fe xor [rsp], rax pop rax >>> print shellcraft.amd64.mov('rax', 0xffffffff).rstrip() mov eax, 0xffffffff >>> print shellcraft.amd64.mov('rax', 0x7fffffff).rstrip() mov eax, 0x7fffffff >>> print shellcraft.amd64.mov('rax', 0x80010101).rstrip() mov eax, 0x80010101 >>> print shellcraft.amd64.mov('rax', 0x80000000).rstrip() mov eax, 0x1010101 /* 2147483648 == 0x80000000 */ xor eax, 0x81010101 >>> print shellcraft.amd64.mov('rax', 0xffffffffffffffff).rstrip() push 0xffffffffffffffff pop rax >>> with context.local(os = 'linux'): ... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip() xor eax, eax /* SYS_read */ >>> with context.local(os = 'freebsd'): ... print shellcraft.amd64.mov('eax', 'SYS_read').rstrip() push SYS_read /* 3 */ pop rax >>> with context.local(os = 'linux'): ... print shellcraft.amd64.mov('eax', 'PROT_READ | PROT_WRITE | PROT_EXEC').rstrip() push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop rax
Parameters:
-
pwnlib.shellcraft.amd64.popad()[source]¶ Pop all of the registers onto the stack which i386 popad does, in the same order.
-
pwnlib.shellcraft.amd64.push(value)[source]¶ Pushes a value onto the stack without using null bytes or newline characters.
If src is a string, then we try to evaluate with context.arch = ‘amd64’ 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.Parameters: value (int,str) – The value or register to push Example
>>> print pwnlib.shellcraft.amd64.push(0).rstrip() /* push 0 */ push 1 dec byte ptr [rsp] >>> print pwnlib.shellcraft.amd64.push(1).rstrip() /* push 1 */ push 1 >>> print pwnlib.shellcraft.amd64.push(256).rstrip() /* push 256 */ push 0x1010201 ^ 0x100 xor dword ptr [rsp], 0x1010201 >>> with context.local(os = 'linux'): ... print pwnlib.shellcraft.amd64.push('SYS_write').rstrip() /* push 'SYS_write' */ push 1 >>> with context.local(os = 'freebsd'): ... print pwnlib.shellcraft.amd64.push('SYS_write').rstrip() /* push 'SYS_write' */ push 4
-
pwnlib.shellcraft.amd64.pushad()[source]¶ Push all of the registers onto the stack which i386 pushad does, in the same order.
-
pwnlib.shellcraft.amd64.pushstr(string, append_null=True)[source]¶ Pushes a string onto the stack without using null bytes or newline characters.
Example
>>> print shellcraft.amd64.pushstr('').rstrip() /* push '\x00' */ push 1 dec byte ptr [rsp] >>> print shellcraft.amd64.pushstr('a').rstrip() /* push 'a\x00' */ push 0x61 >>> print shellcraft.amd64.pushstr('aa').rstrip() /* push 'aa\x00' */ push 0x1010101 ^ 0x6161 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('aaa').rstrip() /* push 'aaa\x00' */ push 0x1010101 ^ 0x616161 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('aaaa').rstrip() /* push 'aaaa\x00' */ push 0x61616161 >>> print shellcraft.amd64.pushstr('aaa\xc3').rstrip() /* push 'aaa\xc3\x00' */ mov rax, 0x101010101010101 push rax mov rax, 0x101010101010101 ^ 0xc3616161 xor [rsp], rax >>> print shellcraft.amd64.pushstr('aaa\xc3', append_null = False).rstrip() /* push 'aaa\xc3' */ push -0x3c9e9e9f >>> print shellcraft.amd64.pushstr('\xc3').rstrip() /* push '\xc3\x00' */ push 0x1010101 ^ 0xc3 xor dword ptr [rsp], 0x1010101 >>> print shellcraft.amd64.pushstr('\xc3', append_null = False).rstrip() /* push '\xc3' */ push -0x3d >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr("/bin/sh"))) 48b801010101010101015048b82e63686f2e72690148310424 >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr(""))) 6a01fe0c24 >>> with context.local(): ... context.arch = 'amd64' ... print enhex(asm(shellcraft.pushstr("\x00", False))) 6a01fe0c24
Parameters:
-
pwnlib.shellcraft.amd64.pushstr_array(reg, array)[source]¶ Pushes an array/envp-style array of pointers onto the stack.
Parameters:
-
pwnlib.shellcraft.amd64.ret(return_value=None)[source]¶ A single-byte RET instruction.
Parameters: return_value – Value to return
-
pwnlib.shellcraft.amd64.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({'rax':1, 'rbx':'rax'}).rstrip() mov rbx, rax push 1 pop rax >>> print shellcraft.setregs({'rax': 'SYS_write', 'rbx':'rax'}).rstrip() mov rbx, rax push SYS_write /* 1 */ pop rax >>> print shellcraft.setregs({'rax':'rbx', 'rbx':'rax', 'rcx':'rbx'}).rstrip() mov rcx, rbx xchg rax, rbx >>> print shellcraft.setregs({'rax':1, 'rdx':0}).rstrip() push 1 pop rax cdq /* rdx=0 */
-
pwnlib.shellcraft.amd64.strcpy(dst, src)[source]¶ Copies a string
Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop rax\n' >>> sc += shellcraft.amd64.strcpy('rsp', 'rax') >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 32) >>> sc += shellcraft.amd64.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).recvline() 'Hello, world\n'
-
pwnlib.shellcraft.amd64.strlen(string, reg='rcx')[source]¶ Calculate the length of the specified string.
Parameters: Example
>>> sc = 'jmp get_str\n' >>> sc += 'pop_str: pop rdi\n' >>> sc += shellcraft.amd64.strlen('rdi', 'rax') >>> sc += 'push rax;' >>> sc += shellcraft.amd64.linux.write(1, 'rsp', 8) >>> sc += shellcraft.amd64.linux.exit(0) >>> sc += 'get_str: call pop_str\n' >>> sc += '.asciz "Hello, world\\n"' >>> run_assembly(sc).unpack() == len('Hello, world\n') True
-
pwnlib.shellcraft.amd64.xor(key, address, count)[source]¶ XORs data a constant value.
Parameters: - key (int,str) – XOR key either as a 8-byte integer, If a string, length must be a power of two, and not longer than 8 bytes. Alternately, may be a register.
- address (int) – Address of the data (e.g. 0xdead0000, ‘esp’)
- count (int) – Number of bytes to XOR, or a register containing the number of bytes to XOR.
Example
>>> sc = shellcraft.read(0, 'rsp', 32) >>> sc += shellcraft.xor(0xdeadbeef, 'rsp', 32) >>> sc += shellcraft.write(1, 'rsp', 32) >>> io = run_assembly(sc) >>> io.send(cyclic(32)) >>> result = io.recvn(32) >>> expected = xor(cyclic(32), p32(0xdeadbeef)) >>> result == expected True
pwnlib.shellcraft.amd64.linux¶
Shellcraft module containing Intel x86_64 shellcodes for Linux.
-
pwnlib.shellcraft.amd64.linux.bindsh(port, network)[source]¶ Listens on a TCP port and spawns a shell for the first to connect. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.amd64.linux.cat(filename, fd=1)[source]¶ Opens a file and writes its contents to the specified file descriptor.
-
pwnlib.shellcraft.amd64.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 rbp.
-
pwnlib.shellcraft.amd64.linux.connectstager(host, port, network='ipv4')[source]¶ connect recvsize stager :param host, where to connect to: :param port, which port to connect to: :param network, ipv4 or ipv6? (default: ipv4)
-
pwnlib.shellcraft.amd64.linux.dup(sock='rbp')[source]¶ Args: [sock (imm/reg) = rbp] Duplicates sock to stdin, stdout and stderr
-
pwnlib.shellcraft.amd64.linux.dupsh(sock='rbp')[source]¶ Args: [sock (imm/reg) = rbp] Duplicates sock to stdin, stdout and stderr and spawns a shell.
-
pwnlib.shellcraft.amd64.linux.egghunter(egg, start_address = 0)[source]¶ Searches memory for the byte sequence ‘egg’.
Return value is the address immediately following the match, stored in RDI.
Parameters:
-
pwnlib.shellcraft.amd64.linux.findpeer(port=None)[source]¶ Args: port (defaults to any port) Finds a socket, which is connected to the specified port. Leaves socket in RDI.
-
pwnlib.shellcraft.amd64.linux.findpeersh(port=None)[source]¶ Args: port (defaults to any) Finds an open socket which connects to a specified port, and then opens a dup2 shell on it.
-
pwnlib.shellcraft.amd64.linux.findpeerstager(port=None)[source]¶ Findpeer recvsize stager :param port, the port given to findpeer: :type port, the port given to findpeer: defaults to any
-
pwnlib.shellcraft.amd64.linux.forkexit()[source]¶ Attempts to fork. If the fork is successful, the parent exits.
-
pwnlib.shellcraft.amd64.linux.kill(pid, signal='SIGKILL')[source]¶ Writes a string to a file descriptor
-
pwnlib.shellcraft.amd64.linux.killparent()[source]¶ Kills its parent process until whatever the parent is (probably init) cannot be killed any longer.
-
pwnlib.shellcraft.amd64.linux.listen(port, network)[source]¶ Listens on a TCP port, accept a client and leave his socket in RAX. Port is the TCP port to listen on, network is either ‘ipv4’ or ‘ipv6’.
-
pwnlib.shellcraft.amd64.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.amd64.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
>>> gcc = process(['gcc','-m64','-xc','-static','-Wl,-Ttext-segment=0x20000000','-']) >>> gcc.write(''' ... int main() { ... printf("Hello, %s!\\n", "amd64"); ... } ... ''') >>> gcc.shutdown('send') >>> gcc.poll(True) 0 >>> sc = shellcraft.loader_append('a.out')
The following doctest is commented out because it doesn’t work on Travis for reasons I cannot diagnose. However, it should work just fine :-)
# >>> run_assembly(sc).recvline() == ‘Hello, amd64!n’ # True
-
pwnlib.shellcraft.amd64.linux.membot(readsock=0, writesock=1)[source]¶ Read-write access to a remote process’ memory.
Provide a single pointer-width value to determine the operation to perform:
- 0: Exit the loop
- 1: Read data
- 2: Write data
-
pwnlib.shellcraft.amd64.linux.mmap_rwx(size=4096, protection=7, address=None)[source]¶ Maps some memory
-
pwnlib.shellcraft.amd64.linux.read(fd=0, buffer='rsp', count=8)[source]¶ Reads data from the file descriptor into the provided buffer. This is a one-shot and does not fill the request.
-
pwnlib.shellcraft.amd64.linux.read_upto(fd=0, buffer='rsp', sizereg='rdx')[source]¶ Reads up to N bytes 8 bytes into the specified register
-
pwnlib.shellcraft.amd64.linux.readfile(path, dst='rdi')[source]¶ Args: [path, dst (imm/reg) = rdi ] Opens the specified file path and sends its content to the specified file descriptor.
-
pwnlib.shellcraft.amd64.linux.readinto(sock=0)[source]¶ Reads into a buffer of a size and location determined at runtime. When the shellcode is executing, it should send a pointer and pointer-width size to determine the location and size of buffer.
-
pwnlib.shellcraft.amd64.linux.readloop(sock=0)[source]¶ Reads into a buffer of a size and location determined at runtime. When the shellcode is executing, it should send a pointer and pointer-width size to determine the location and size of buffer.
-
pwnlib.shellcraft.amd64.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.amd64.linux.readptr(fd=0, target_reg='rdx')[source]¶ Reads 8 bytes into the specified register
-
pwnlib.shellcraft.amd64.linux.recvsize(sock, reg='rcx')[source]¶ Recives 4 bytes size field Useful in conjuncion with findpeer and stager :param sock, the socket to read the payload from.: :param reg, the place to put the size: :type reg, the place to put the size: default ecx
Leaves socket in ebx
-
pwnlib.shellcraft.amd64.linux.setregid(gid='egid')[source]¶ Args: [gid (imm/reg) = egid] Sets the real and effective group id.
-
pwnlib.shellcraft.amd64.linux.setreuid(uid='euid')[source]¶ Args: [uid (imm/reg) = euid] Sets the real and effective user id.
-
pwnlib.shellcraft.amd64.linux.sh()[source]¶ Execute a different process.
>>> p = run_assembly(shellcraft.amd64.linux.sh()) >>> p.sendline('echo Hello') >>> p.recv() 'Hello\n'
-
pwnlib.shellcraft.amd64.linux.stage(fd=0, length=None)[source]¶ Migrates shellcode to a new buffer.
Parameters: Example
>>> p = run_assembly(shellcraft.stage()) >>> sc = asm(shellcraft.echo("Hello\n", constants.STDOUT_FILENO)) >>> p.pack(len(sc)) >>> p.send(sc) >>> p.recvline() 'Hello\n'
-
pwnlib.shellcraft.amd64.linux.stager(sock, size, handle_error=False)[source]¶ Recives a fixed sized payload into a mmaped buffer Useful in conjuncion with findpeer. After running the socket will be left in RDI. :param sock, the socket to read the payload from.: :param size, the size of the payload:
-
pwnlib.shellcraft.amd64.linux.syscall(syscall=None, arg0=None, arg1=None, arg2=None, arg3=None, arg4=None, arg5=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 pwnlib.shellcraft.amd64.linux.syscall('SYS_execve', 1, 'rsp', 2, 0).rstrip() /* call execve(1, 'rsp', 2, 0) */ xor r10d, r10d /* 0 */ push SYS_execve /* 0x3b */ pop rax push 1 pop rdi push 2 pop rdx mov rsi, rsp syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('SYS_execve', 2, 1, 0, -1).rstrip() /* call execve(2, 1, 0, -1) */ push -1 pop r10 push SYS_execve /* 0x3b */ pop rax push 2 pop rdi push 1 pop rsi cdq /* rdx=0 */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall().rstrip() /* call syscall() */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('rax', 'rdi', 'rsi').rstrip() /* call syscall('rax', 'rdi', 'rsi') */ /* setregs noop */ syscall >>> print pwnlib.shellcraft.amd64.linux.syscall('rbp', None, None, 1).rstrip() /* call syscall('rbp', ?, ?, 1) */ mov rax, rbp push 1 pop rdx syscall >>> print pwnlib.shellcraft.amd64.linux.syscall( ... 'SYS_mmap', 0, 0x1000, ... 'PROT_READ | PROT_WRITE | PROT_EXEC', ... 'MAP_PRIVATE | MAP_ANONYMOUS', ... -1, 0).rstrip() /* call mmap(0, 4096, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */ push (MAP_PRIVATE | MAP_ANONYMOUS) /* 0x22 */ pop r10 push -1 pop r8 xor r9d, r9d /* 0 */ push SYS_mmap /* 9 */ pop rax xor edi, edi /* 0 */ push (PROT_READ | PROT_WRITE | PROT_EXEC) /* 7 */ pop rdx mov esi, 0x1010101 /* 4096 == 0x1000 */ xor esi, 0x1011101 syscall >>> print pwnlib.shellcraft.open('/home/pwn/flag').rstrip() /* open(file='/home/pwn/flag', oflag=0, mode=0) */ /* push '/home/pwn/flag\x00' */ mov rax, 0x101010101010101 push rax mov rax, 0x101010101010101 ^ 0x67616c662f6e xor [rsp], rax mov rax, 0x77702f656d6f682f push rax mov rdi, rsp xor edx, edx /* 0 */ xor esi, esi /* 0 */ /* call open() */ push SYS_open /* 2 */ pop rax syscall