0day_dev/pwntools-tutorial/assembly.md
2020-08-07 21:19:09 -07:00

4.1 KiB

Table of Contents

Assembly

Pwntools makes it very easy to perform assembly in almost any architecture, and comes with a wide variety of canned-but-customizable shellcode ready to go out-of-the-box.

In the walkthrough directory, there are several longer shellcode tutorials. This page gives you the basics.

Basic Assembly

The most basic example, is to convert assembly into shellcode.

from pwn import *

print repr(asm('xor edi, edi'))
# '1\xff'

print enhex(asm('xor edi, edi'))
# 31ff

Canned assembly (shellcraft)

The shellcraft module gives you pre-canned assembly. It is generally customizable. The easiest way to find out which shellcraft templates exist is to look at the documentation on RTD.

from pwn import *
help(shellcraft.sh)
print '---'
print shellcraft.sh()
print '---'
print enhex(asm(shellcraft.sh()))
Help on function sh in module pwnlib.shellcraft.internal:

sh()
    Execute /bin/sh
---
    /* push '/bin///sh\x00' */
    push 0x68
    push 0x732f2f2f
    push 0x6e69622f

    /* call execve('esp', 0, 0) */
    push (SYS_execve) /* 0xb */
    pop eax
    mov ebx, esp
    xor ecx, ecx
    cdq /* edx=0 */
    int 0x80
---
6a68682f2f2f73682f62696e6a0b5889e331c999cd80

Command-line Tools

There are three command-line tools for interacting with assembly:

  • asm
  • disasm
  • shellcraft

asm

The asm tool does what it says on the tin. It provides several options for formatting the output. When the output is a terminal, it defaults to hex-encoded.

$ asm nop
90

When the output is anything else, it writes the raw data.

$ asm nop | xxd
0000000: 90                                       .

It also takes data on stdin if no instructions are provided on the command line.

$ echo 'push ebx; pop edi' | asm
535f

Finally, it supports a few different options for specifying the output format, via the --format option. Supported arguments are raw, hex, string, and elf.

$ asm --format=elf 'int3' > ./int3
$ ./halt
Trace/breakpoint trap (core dumped)

disasm

Disasm is the opposite of asm.

$ disasm cd80
   0:    cd 80                    int    0x80
$ asm nop | disasm
   0:    90                       nop

shellcraft

The shellcraft command is the command-line interface to the internal shellcraft module. On the command-line, the full context must be specified, in the order of arch.os.template.

$ shellcraft i386.linux.sh
6a68682f2f2f73682f62696e6a0b5889e331c999cd80

Foreign Architectures

Assembling for a foreign architecture requires that you have an appropriate version of binutils installed. You should see installing.md for more information on this. The only change that is necessary is to set the architecture in the global context variable. You can see more information about context in context.md.

from pwn import *

context.arch = 'arm'

print repr(asm('mov r0, r1'))
# '\x01\x00\xa0\xe1'

print enhex(asm('mov r0, r1'))
# 0100a0e1

Canned Assembly

The shellcraft module automatically switches to the appropriate architecture.

from pwn import *

context.arch = 'arm'

print shellcraft.sh()
print enhex(asm(shellcraft.sh()))
    adr r0, bin_sh
    mov r2, #0
    mov r1, r2
    svc SYS_execve
bin_sh: .asciz "/bin/sh"

08008fe20020a0e30210a0e10b0000ef2f62696e2f736800

Command-line Tools

You can also use the command line to assemble foreign-arch shellcode, by using the --context command-line option.

$ asm --context=arm 'mov r0, r1'
0100a0e1
$ shellcraft arm.linux.sh
08008fe20020a0e30210a0e10b0000ef2f62696e2f736800