← Back to Writeups
CUSTOMMediumpwn

Floats

XESXOR9/2/20261 min read
#pwn#custom#medium#ieee754_float_representation#little_endian_byte_interpretat#type_punning

Floats

Platform: spbctf | Category: pwn | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2026-03-11 | Status: Solved Techniques: ieee754_float_representation, little_endian_byte_interpretation, type_punning

Summary

Task: input numeric values (double, int64, uint64) via scanf that form a specific target string in memory. Solution: split the 24-byte target string into three 8-byte chunks and interpret each as the corresponding numeric type in little-endian using struct.unpack, then send the computed values.

Floats — SPB CTF Pwn Season

Description

"Введите числа, чтобы получить флаг"
(Enter numbers to get the flag)

Server: nc 109.233.56.90 11571
Binary: task — ELF 64-bit x86-64, PIE, not stripped
Points: 10

Analysis

Create the string "Never gonna giv\xff you up!" on the stack using scanf("%lf %ld %lu") — which reads a double, int64_t, and uint64_t.

The key insight is that when these numeric values are written to memory, their byte representation forms the target string. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Split the 24-byte target string into three 8-byte chunks and interpret each as the corresponding numeric type in little-endian:

ChunkStringTypeValue
1"Never go"double4.3828968361536734e+228
2"nna giv\xff"int64_t-38727655140266386
3" you up!"uint64_t2409554582912858400

When these values are written to memory, they reconstruct the target string. strcmp passes → system("cat /flag").

python
from pwn import *
import struct
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

io = remote('109.233.56.90', 11571)

# Target string split into 8-byte chunks
chunk1 = b"Never go"
chunk2 = b"nna giv\xff"
chunk3 = b" you up!"

# Interpret as numeric types
double_val = struct.unpack('<d', chunk1)[0]
int64_val = struct.unpack('<q', chunk2)[0]
uint64_val = struct.unpack('<Q', chunk3)[0]

io.sendline(f"{double_val} {int64_val} {uint64_val}".encode())
io.interactive()

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍