Tinkering with pwntools

Morten Hansen • May 7, 2021

Hello World!

So during the last month I have been practising my Python skills by doing CTF's. During the easter I had a go at the CTF hosted by the Norwegian Police Security Service, and came in contact with other persons with an interests for CTF's. They have given me some good feedback and tips on how to improve my Python skills.

The last couple of days I have been working with the pwntools-librabry for Python. This a "CTF framework and exploit development library" as described at their website. Check out the website for documentation on how to implement it with your Python code. Pwntools can be installed from the terminal using the pip3 install pwntools-command.

It is safe to say that pwntools is capable of many things and that I have justed scratched the surface of what it is capable of. My use so far has been limited to connecting to a remote machine, and to revice and send information over the connection.

During my tinkering I have written down some notes that I would like to share with you! I have written them for myself but who knows? Somebody might find them useful.

PS. The CTF-challenge is from PicoCTF

   

NOTES PWN-TOOLS

Connect to an IP

In order to use pwntools towards an IP-address, connect to the IP-address like this.

#!/usr/bin/env python3
from pwn import *

host = "mercury.picoctf.net"
port = 58913
s = remote(host, port)

s.close() 

This is useful in cases where you normally would connect with 'netcat' or 'nc'.

 

Reciving data

In order to recive data from the connection, use a command like:

  • s.recv() - #this will fetch all output
  • s.recvuntil(":") - #this will fetch output until a marked point
  • s.recvline() - #this will recive the following line
  • s.recvuntilS(":")
  • s.recvlineS()

By usint the .recvuntil() you can type a string to create a stop point, e.g. s.recvuntil("Stop here!")  
 

Converting data

The appended "S" in .recvlineS and `.recvuntilS is used to recive a string (str) instead of bytes. If you recive bytes it could be neccesary to convert it to a string. This can be done like this:

string = b'Hello World!'

type(string) 
>'bytes'

# to convert it use .decode() 

print(string.decode())
>Hello World!

It is also possible to convert from hex-values, eg.

string = '414141'
bytes.fromhex(string).decode()
>'AAA'

 

Sending input

With pwntools it is possible to send input with the following commands.

  • s.sendlineafter()
  • s.sendline()

With the s.sendlineafter() we can define at what point we want to send data, eg.s.sendlineafter('This place', 'my data').

This will send 'my data' after 'this place' has been reached.
   

Keeping track of actions

With pwntools it is easy to get a nice presentation of the available data. pwntools comes with several log-commandsbuilt in. We can display information by using the log.info()command, or start a process we can update further with the log.progress() command.

With a progress ongoing we can update the status with log.progress().status(), and finish it with log.progress().success().

Example:

offset = 11
log.info(f'Offset: {offset}') #we can send variables with f-string 
p = log.progress('Status')
p.status('Sending data')
p.success('Success!')
log.success(f'Flag is: picoCTF{ {decrypted_flag} }')

In the end the use of the commands will be output something like this:

 
And that's that! See you later

Best regards
M.