This shows you the differences between two versions of the page.
cns:labs:lab-06 [2020/11/14 18:23] mihai.dumitru2201 [T2. Recap: injecting the shellcode using environment variables] |
cns:labs:lab-06 [2020/11/16 11:01] (current) dennis.plosceanu [T1. GCC stack protector [1p]] |
||
---|---|---|---|
Line 125: | Line 125: | ||
All content necessary for the CNS laboratory tasks can be found in [[cns:resources:repo|the CNS public repository]]. | All content necessary for the CNS laboratory tasks can be found in [[cns:resources:repo|the CNS public repository]]. | ||
- | ==== T1. GCC stack protector [1p] ==== | + | ==== T1. GCC stack protector ==== |
Take a look at ''vulnerable.c'' in the [[http://elf.cs.pub.ro/oss/res/labs/lab-06.tar.gz|lab archive]]. We are interested in particular in the ''%%get_user_input%%'' function, which ''read''s from standard input into a local buffer more bytes than are available: | Take a look at ''vulnerable.c'' in the [[http://elf.cs.pub.ro/oss/res/labs/lab-06.tar.gz|lab archive]]. We are interested in particular in the ''%%get_user_input%%'' function, which ''read''s from standard input into a local buffer more bytes than are available: | ||
Line 340: | Line 340: | ||
<note tip> | <note tip> | ||
- | Bypassing ASLR through brute-force is possible only because ''vulnerable'' is a 32-bit binary, although this technique is technically speaking possible on 64-bit if the attacker can leak //address bits//. The key question to ask here is, **how many bits of entropy** does ASLR yield on our architecture? | + | Bypassing ASLR through brute-force is possible only because ''bruteforce'' is a 32-bit binary, although this technique is technically speaking possible on 64-bit if the attacker can leak //address bits//. The key question to ask here is, **how many bits of entropy** does ASLR yield on our architecture? |
We can find the answer quickly through empirical means. We've included a program called ''buf.c'' in the [[http://elf.cs.pub.ro/oss/res/labs/lab-06.tar.gz|lab archive]], which intentionally leaks a stack address. Let's compile it and give it a few runs: | We can find the answer quickly through empirical means. We've included a program called ''buf.c'' in the [[http://elf.cs.pub.ro/oss/res/labs/lab-06.tar.gz|lab archive]], which intentionally leaks a stack address. Let's compile it and give it a few runs: | ||
Line 413: | Line 413: | ||
==== 2. Stackbleed: infoleak + ASLR bypass ==== | ==== 2. Stackbleed: infoleak + ASLR bypass ==== | ||
- | Examine ''vulnerable2.c''. This is very similar to ''vulnerable'', only ''%%get_user_input%%'' calls ''read'' twice: | + | Examine ''stackbleed.c''; ''%%get_user_input%%'' calls ''read'' twice: |
<code C> | <code C> | ||
Line 431: | Line 431: | ||
<code> | <code> | ||
- | $ python -c 'import sys; sys.stdout.write("ABCD")' | SHELLCODE="\x90\x90\x90\x90" ./vulnerable2 | xxd | + | $ python -c 'import sys; sys.stdout.write("ABCD")' | SHELLCODE="\x90\x90\x90\x90" ./stackbleed | xxd |
00000000: 4142 4344 d90f d3ff 010a ABCD...... | 00000000: 4142 4344 d90f d3ff 010a ABCD...... | ||
</code> | </code> | ||
Line 451: | Line 451: | ||
<code> | <code> | ||
log.info("Canary is: 0x{:08x}".format(unpack(canary, 'all', endian='little', sign=False))) | log.info("Canary is: 0x{:08x}".format(unpack(canary, 'all', endian='little', sign=False))) | ||
+ | </code> | ||
+ | |||
+ | Or, if you set the context properly (e.g. ''context.binary = "./stackbleed"''), you can skip the arguments to ''unpack'': | ||
+ | <code> | ||
+ | log.info("Canary is: 0x{:08x}".format(unpack(canary))) | ||
</code> | </code> | ||
</note> | </note> | ||
==== 3. Extra: infoleak + stack canary bypass ==== | ==== 3. Extra: infoleak + stack canary bypass ==== | ||
- | Examine ''vulnerable3.c'' and the resulting ''vulnerable3'' executable file. It is once again very similar to the previous incarnations, but we will use it for something somewhat different: leaking the stack canary and bypassing it. | + | Examine ''canary.c'' and the resulting ''canary'' executable file. It is once again very similar to the previous incarnations, but we will use it for something somewhat different: leaking the stack canary and bypassing it. |
Knowing that ''buf'''s size is 4, we want to determine exactly where the canary value starts. For now, let's take a look at ''vulnerable3'' with GDB: | Knowing that ''buf'''s size is 4, we want to determine exactly where the canary value starts. For now, let's take a look at ''vulnerable3'' with GDB: | ||
<code asm> | <code asm> | ||
- | $ gdb -q ./vulnerable3 | + | $ gdb -q ./canary |
Reading symbols from ./vulnerable3...done. | Reading symbols from ./vulnerable3...done. | ||
gdb-peda$ pdis get_user_input | gdb-peda$ pdis get_user_input | ||
Line 491: | Line 496: | ||
<code> | <code> | ||
gdb-peda$ b *0x08048497 | gdb-peda$ b *0x08048497 | ||
- | Breakpoint 1 at 0x8048497: file vulnerable3.c, line 8. | + | Breakpoint 1 at 0x8048497: file canary.c, line 8. |
gdb-peda$ r < <(echo -n "AAAA\n") | gdb-peda$ r < <(echo -n "AAAA\n") | ||
... | ... | ||
Line 502: | Line 507: | ||
<code> | <code> | ||
$ # we give "ABCD" as an input | $ # we give "ABCD" as an input | ||
- | $ python -c 'import sys; sys.stdout.write("ABCD")' | ./vulnerable3 | xxd | + | $ python -c 'import sys; sys.stdout.write("ABCD")' | ./canary | xxd |
00000000: 4142 4344 0a ABCD. | 00000000: 4142 4344 0a ABCD. | ||
$ # we give "ABCD\n" as an input | $ # we give "ABCD\n" as an input | ||
- | $ python -c 'import sys; sys.stdout.write("ABCD\n")' | ./vulnerable3 | xxd | + | $ python -c 'import sys; sys.stdout.write("ABCD\n")' | ./canary | xxd |
- | *** stack smashing detected ***: ./vulnerable3 terminated | + | *** stack smashing detected ***: ./canary terminated |
... | ... | ||
00000000: 4142 4344 0a7e 3d76 010a ABCD.~=v.. | 00000000: 4142 4344 0a7e 3d76 010a ABCD.~=v.. |