Sending/Receiving Data
You often need to send data to a remote process, and receive data back. Pwntools provides a number of convenience functions to make this easier.
A method not involving pwntools involves the struct
module, which can be used to pack and unpack data based on size and endianness.
More information on struct
documentation, including the format strings they use for packing, can be found here.
Packing Data
Pwntools makes this process easier. We can use p32()
for packing into a 32-bit byte string, and p64()
for packing into a 64-bit byte string.
Pwntools automatically assumes that the binary is written in little-endian architecture. To change this, you must change context.endian
.
Unpacking Data
Pwntools provides u32()
and u64()
for unpacking 32-bit and 64-bit integers, respectively.
This is most often used in conjunction with read()
and recv()
.
Unpacking also supports other sizes, such as u16()
and u8()
.
Sending Data
Pwntools provides send()
and sendline()
for sending data to a remote process. send()
sends the data as-is, while sendline()
appends a newline character () to the end of the data.
These two lines are equivalent.
Pwntools also has a sendafter()
and sendlineafter()
function, which sends data after a given byte string.
Finally, pwntools has a packing mechanism called flat()
that packs multiple sets of data into a single byte string. flat
is packed using context.endian
and context.word_size
.
Receiving Data
There are a number of ways to receive data, each with their own advantages.
recv()
recv()
recv()
takes the number of bytes to receive as its argument. This is useful when you know exactly how many bytes you need to receive.
recvline()
recvline()
recvline()
receives data until it reaches a newline character (). This is useful when you know that the data you need is on a single line.
recvuntil()
recvuntil()
recvuntil()
receives data until it reaches a given byte string. This is useful when you know that the data you need is on a single line, but you don't know what the newline character is.
recvall()
recvall()
recvall()
receives all data until the remote process closes the connection. This is not one that's used very often because the timeout is set to default
by default, which is 10 seconds. This is not very user-friendly.
clean()
clean()
clean()
clears the receive buffer. This is good when you don't know exactly what you're receiving, but want to ensure you've received all data before sending more.
interactive()
interactive()
interactive()
is a function that allows you to interact with the remote process. This is required for popping shells, but also is useful for continuing to interact with the remote process after you've finished exploiting it.
Last updated