# Lista 9 (6 maja 2021)
###### tags: `ask21` `ćwiczenia` `kba`
## Deklaracje
Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie (co najwyżej jedno!) w trakcie dyskusji oznacz je znakiem ==X== na żółtym tle.
**UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!**
:::danger
| | 1 | 2 | 3 | 4 | 5 | 6 | 7(2) |
| ---------------------:| --- | --- | --- | --- | --- | --- | ---- |
| Andriy Bernad | X | X | | | X | | | 3
| Wojciech Bogucki | X | X | X | X | | | X | 6
| Michał Doros | X | X | X | X | X | X | X | 8
| Marko Golovko | | | | | | | | 0
| Magdalena Jarecka | X | X | | | X | | X | 5
| Szymon Jędras | X |==X==| X | X | X | | | 5
| Heorhii Karpenko | X |==X==| | | X | | | 3
| Szymon Kosakowski | | X | X | X | X | | | 4
| Izabella Kozioł | | | | | | | | 0
| Franciszek Malinka | X | X | X | X | X | |==X== | 7
| Filip Pazera | | X | X | X | X | | | 4
| Franciszek Pindel | X | X | X | X | X | X | X | 8
| Kacper Puchalski | | X | X | | X | | | 3
| Kacper Solecki | X | X | X | X | X | | | 5
| Andrzej Tkaczyk | X | X | X | X | X | | | 5
| Łukasz Wasilewski | | X | X | | | | | 2
| Vladyslav Yablonskyi | X | X | | | X | | | 3
| Adam Zyzik |~~X~~| X | X | | | | | 1 (1 punkt karny)
:::
## Zadanie 1
:::success
Autor: Adam Zyzik
:::
```c=
int relo3(int val) {
switch (val) {
case 100:
return val;
case 101:
return val + 1;
case 103:
case 104:
return val + 3;
case 105:
return val + 5;
case 106:
return val + 10;
default:
return val + 6;
}
}
```
Kompilujemy z flagami `-static -fno-pic -O1`, żeby wyniki były bardziej zrozumiałe.
> `objdump -d relo3.o`
```=
relo3.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <relo3>:
0: f3 0f 1e fa endbr64
4: 8d 47 9c lea -0x64(%rdi),%eax
7: 83 f8 06 cmp $0x6,%eax
a: 77 20 ja 2c <relo3+0x2c>
c: 89 c0 mov %eax,%eax
e: 3e ff 24 c5 00 00 00 notrack jmpq *0x0(,%rax,8)
15: 00
16: b8 66 00 00 00 mov $0x66,%eax
1b: c3 retq
1c: 8d 47 03 lea 0x3(%rdi),%eax
1f: c3 retq
20: b8 6e 00 00 00 mov $0x6e,%eax
25: c3 retq
26: b8 74 00 00 00 mov $0x74,%eax
2b: c3 retq
2c: 8d 47 06 lea 0x6(%rdi),%eax
2f: c3 retq
30: 89 f8 mov %edi,%eax
32: c3 retq
```
W sekcji `.text` pod adresem `0x12` chcemy mieć adres tablicy skoków, czyli adres sekcji `.rodata`.
Tablicę skoków chcemy uzupełnić offsetami sekcji `.text`.
> `objdump -r relo3.o`
```
relo3.o: file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000012 R_X86_64_32S .rodata
RELOCATION RECORDS FOR [.rodata]:
OFFSET TYPE VALUE
0000000000000000 R_X86_64_64 .text+0x0000000000000030
0000000000000008 R_X86_64_64 .text+0x0000000000000016
0000000000000010 R_X86_64_64 .text+0x000000000000002c
0000000000000018 R_X86_64_64 .text+0x000000000000001c
0000000000000020 R_X86_64_64 .text+0x000000000000001c
0000000000000028 R_X86_64_64 .text+0x0000000000000020
0000000000000030 R_X86_64_64 .text+0x0000000000000026
RELOCATION RECORDS FOR [.eh_frame]:
OFFSET TYPE VALUE
0000000000000020 R_X86_64_PC32 .text
```
~~Jeżeli procedura relo3 (a więc i sekcja `.text`) została umieszczona pod adresem `0x1000`,
to tablicę skoków należy uzupełnić wartościami z tablicy rekordów realokacji z podmienionym `.text` na `0x1000`.~~
~~Np. pierwszy adres -- `0x1030`.~~
~~W sekcji `.text` pod adresem `0x12` znajdować się będzie adres `0x2000`.~~
## Zadanie 2
:::success
Autor: Szymon Jędras
:::

#### Dekorowanie nazw (ang. name mangling)
technika stosowana przez kompilatory w celu wygenerowania unikatowych nazw funkcji, struktur, klas oraz innych typów danych.
#### Przekształcone sygnatury funkcji:
```
_Z4funcPKcRi -> func(char const*, int&)
_Z - zawsze dodawane
4 - długość nazwy funkcji
func - nazwa funkcji
P - pointer
K - const
c - char
R - reference
i - int
_ZN3Bar3bazEPc -> Bar::baz(char*)
_Z - zawsze dodawane
N - namespace/klasa
3 - długość nazwy namespace-u/klasy
Bar - nazwa namespace-u/klasy
3 - długość nazwy funkcji
baz - nazwa funkcji
E - sygnalizator że ostatnia nazwa była nazwą funkcji/teraz będą argumenty
P - pointer
c - char
_ZN3BarC1ERKS_ -> Bar::Bar(Bar const&)
_Z - zawsze dodawane
N - namespace/klasa
3 - długość nazwy namespace-u/klasy
Bar - nazwa namespace-u/klasy
C1 - sygnalizator konstruktora z pełną konstrukcją obiektu, (complete object constructor)
E - zaczynają się argumenty
R - reference
K - const
S_ - argument typu klasy (Bar)
_ZN3foo6strlenER6string -> foo::strlen(string&)
_Z - zawsze dodawane
N - namespace/klasa
3 - długość nazwy namespace-u/klasy
foo - nazwa namespace-u/klasy
6 - długość nazwy funkcji
strlen - nazwa funkcji
E - sygnalizator że ostatnia nazwa była nazwą funkcji/teraz będą argumenty
R - reference
6 - długość nazwy typu
string - nazwa typu
```
#### Które elementy składni podlegają dekorowaniu?
nazwy funkcji, właściwości argumentów (ref, const, pointer,...), typy argumentów, nazwy klas, nazwy namespace-ów, szablony, argumenty szablonowe, modyfikatory (const).
Dekorowaniu nie podlegają typ wyniku, nazwy argumentów, modyfikatory (static, constexpr, noexcept, virtual, override)
#### Czy funkcja dekorująca jest różnowartościowa?
Nie, ponieważ na sygnaturę nie wpływa np. typ zwracany.
## Zadanie 3
:::success
Autor: Wojciech Bogucki
:::
**Przepełnienie bufora** (ang. buffer overflow)
Błąd programistyczny polegający na zapisaniu do wyznaczonego obszaru pamięci (bufora) większej ilości danych niż zarezerwował na ten cel programista. Taka sytuacja prowadzi do zamazania danych znajdujących się w pamięci bezpośrednio za buforem, a w rezultacie do błędnego działania programu. Gdy dane, które wpisywane są do bufora, podlegają kontroli osoby o potencjalnie wrogich intencjach, może dojść do nadpisania struktur kontrolnych programu w taki sposób, by zaczął on wykonywać operacje określone przez atakującego.
**Programowanie zorientowane na powroty** (ang. return-oriented programming)
Technika wykorzystująca lukę w zabezpieczeniach komputera , która umożliwia atakującemu wykonanie kodu w obecności zabezpieczeń, takich jak ochrona przestrzeni wykonywalnej i podpisywanie kodu . W tej technice atakujący przejmuje kontrolę nad stosem wywołań w celu przejęcia przepływu sterowania programem, a następnie wykonuje starannie wybrane sekwencje instrukcji maszynowych , które są już obecne w pamięci maszyny, zwane „gadżetami”. Każdy gadżet zwykle kończy się instrukcją powrotu i znajduje się w podprogramie w ramach istniejącego programu i / lub kodu biblioteki współdzielonej. Połączone ze sobą gadżety umożliwiają atakującemu wykonywanie dowolnych operacji na maszynie wykorzystującej mechanizmy obronne, które udaremniają prostsze ataki.
Wyszukujemy adresów `gadget` i jakiegoś wywołania `syscall`
```
$ objdump -d ropex | grep gadget
0000000000400bf3 <gadget>:
```
```
$ objdump -d ropex | grep syscall
40127c: 0f 05 syscall
```
czyli w porządku little-endian będzie:
* f3 0b 40 00
* 7c 12 40 00
Zmieniamy w pliku ropex.in.txt fragmenty `baad f00d` na znalezione adresy.
Po wywołaniu funkcji, po tym jak na wejsciu podamy `ropex.in` pojawi się nyancat.
Można sprawdzić, ze przed wywołaniem funkcji `readline` adres powrotu jest dobry, ale po nim juz został zmieniony na `gadget`. Instrukcja `lea 0x10(%rsp),%rdi` wydobywa nam adres `/usr/bin/nyancat` hexadecymalnie, a pozniej daje go jako parametr do `syscall`.
## Zadanie 4
:::success
Autor: Filip Pazera
:::

**kanarek** - specjalna wartość umieszczana na stosie. Jeżeli w trakcie wykonywania procedury ulegnie zmianie, wiemy, że nastąpiło uszkodzenie stosu.
**uszkodzenie stosu** - nadpisanie zawartości stosu w niekontrolowany sposób, np. poprzez przepełnienie bufora.
Po włączeniu opcji `-fstack-protector` widzimy, że uszkodzenie stosu jest już wykrywane:
```
$ ./ropex ropex.in
��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��ޭ��g@
*** stack smashing detected ***: terminated
Aborted (core dumped)
```
**randomizacja rozkładu przestrzeni adresowej** - technika obrony przed atakami wykorzystującymi przepełnienie bufora. Polega na umieszczaniu sekcji programu, stosu i sterty pod losowymi adresami za każdym uruchomieniem programu. Utrudnia to atakującemu przewidzenie pozycji interesujących go instrukcji.
**gadżet** - krótki fragment kodu programu zakończony instrukcją `ret`. Złożenie kilku gadżetów umożliwia wykonanie wielu instrukcji z rzędu. Wykorzystywany między innymi w atakach ROP.
Aby włączyć randomizację w `gdb` można użyć instrukcji:
`>>> set disable-randomization off`
Po włączeniu opcji `-z noexestack` widzimy, że stos nie jest wykonywalny:
```
$ pmap `pidof ropex`
...
00007ffe6cb5b000 132K rw--- [ stack ]
...
```
## Zadanie 5
:::info
Autor: Michał Doros
:::
```c=
.globl foobar #sprawia, że symbol jest widoczny dla linkera
.type foobar, @function #ustawienie typu symbolu
foobar:
// .LFB0:
// .cfi_startproc
// pushq %rbp
// .cfi_def_cfa_offset 16
// .cfi_offset 6, -16
// movq %rsp, %rbp
// .cfi_def_cfa_register 6
// movl $5, %eax
// popq %rbp
// .cfi_def_cfa 7, 8
// ret
// .cfi_endproc
// .LFE0:
.size foobar, .-foobar #ustawienie rozmiaru symbolu, -foobar oblicza odległość do labela foobar
```
```c=
.section .rodata
.align 16
.type baz, @object #ustawienie typu symbolu
.size baz, 24 #ustawienie rozmiaru symbolu
baz:
.ascii "abc" #przyjmuje string
.zero 1 #wypełnienie zerami
.long 42 #przyjmuje 4 bajtową liczbę
.quad -3 #przyjmuje 8 bajtową liczbę
.long 1068827777 #przyjmuje 4 bajtową liczbę
.zero 4 #wypełnianie zerami
.text
.globl main
.type main, @function
```
```c=
.globl array
.bss
.align 32 #wyrównuje sekcje do 32
.type array, @object
.size array, 800
array:
.zero 800
.text
.globl main
.type main, @function
```
## Zadanie 6
:::success
Autor: Franciszek Pindel
:::
> Jądro systemu Linux nie potrafi samodzielnie załadować do pamięci pliku wykonywalnego skonsolidowanego dynamicznie. Musi o to poprosić konsolidator dynamiczny opisany w podręczniku systemowym ld.so(8). Na podstawie ld.elf_so(1) opisz proces ładowania pliku pliku wykonywalnego «/bin/sleep» do pamięci. Wyświetl jego sekcję «.dynamic» i wskaż pliki konfiguracyjne na podstawie których konsolidator odnajdzie na dysku bibliotekę «libc.so.6». Wykonaj polecenie «LD_DEBUG=all /bin/sleep 1». Wskaż w wydruku proces wyszukiwania i ładowania bibliotek, wiązania symboli (ang. symbol resolution) w trakcie
ładowania programu i po jego uruchomieniu.
- konsolidator dynamiczny - program ładujący plik elf używający bibliotek dynamicznych i odnajdujący potrzebne odwołania
- wiązanie symboli - proces skojarzania odwołań z odpowiednimi symbolami z zewnętrznych bibliotek
1. Jądro ładuje `/bin/sleep`, zamiast je uruchomić, przekazuje kontrole konsolidatorowi dynamicznemu
(poprawka: jądro ładuje konsolidator określony w nagłówku `/bin/sleep` - sekcja `.init`, który ładuje potrzebne biblioteki i uruchamia `/bin/sleep`)
3. Na podstawie sekcji dynamic odbywa się odnajdywanie potrzebnych plików
4. Odbywa się relokacja odwołań do symboli
5. Następuje inizjalizacja i przekazanie kontroli programowi `/bin/sleep`
```
$ readelf -d /bin/sleep
Dynamic section at offset 0x8c78 contains 27 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
```
Pliki konfiguracyjne z ścieżkami
```
$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
$ cat /etc/ls.so.conf.d/x86_64-linux-gnu.conf
# Multiarch support
/usr/local/lib/x86_64-linux-gnu
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
```
```
...
74890: symbol=__vdso_getcpu; lookup in file=linux-vdso.so.1 [0]
74890: binding file linux-vdso.so.1 [0] to linux-vdso.so.1 [0]: normal symbol `__vdso_getcpu' [LINUX_2.6]
74890: symbol=__vdso_clock_getres; lookup in file=linux-vdso.so.1 [0]
74890: binding file linux-vdso.so.1 [0] to linux-vdso.so.1 [0]: normal symbol `__vdso_clock_getres' [LINUX_2.6]
74890:
74890: file=libc.so.6 [0]; needed by /bin/sleep [0]
74890: find library=libc.so.6 [0]; searching
74890: search cache=/etc/ld.so.cache
74890: trying file=/lib/x86_64-linux-gnu/libc.so.6
...
75008: symbol=malloc; lookup in file=/bin/sleep [0]
75008: symbol=malloc; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
75008: binding file /bin/sleep [0] to /lib/x86_64-linux-gnu/libc.so.6 [0]: normal symbol `malloc' [GLIBC_2.2.5]
...
74890: calling init: /lib/x86_64-linux-gnu/libc.so.6
74890:
74890:
74890: initialize program: /bin/sleep
74890:
74890:
74890: transferring control: /bin/sleep
74890:
74890: symbol=_dl_find_dso_for_object; lookup in file=/bin/sleep [0]
74890: symbol=_dl_find_dso_for_object; lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
74890: symbol=_dl_find_dso_for_object; lookup in file=/lib64/ld-linux-x86-64.so.2 [0]
74890: binding file /lib/x86_64-linux-gnu/libc.so.6 [0] to /lib64/ld-linux-x86-64.so.2 [0]: normal symbol `_dl_find_dso_for_object' [GLIBC_PRIVATE]
```
## Zadanie 7
:::success
Autor: Franciszek Malinka
:::
**Kod relokowalny** - po angielsku PIC, Position-Independent Code, to część kodu, który nie potrzebuje wykonania relokacji. Można kompilator poprosić o wygenerowanie takiego kodu używając flagi `-fpic`.
**Leniwe wiązanie** - rozwiązywanie adresu procedury w kodzie relokowalnym dopiero w momencie, kiedy wołamy ją poraz pierwszy. Użyteczne np. korzystając z bibliotek współdzielonych. W momencie uruchomienia programu nie wiemy w jakim miejscu w pamięci znajdują się funkcje z tych bibliotek, więc konsolidator dynamiczny wskaże to miejsce dopiero w run-time.
Aby leniwe wiązanie mogło się udać potrzebne nam są dwie dodatkowe sekcje: **.got** (*global offset table*) oraz **.plt** (*procedure linkage table*). W sekcji `.got` znajduje się tablica 8-bajtowych elementów, w których utrzymywane są adresy na odpowiednie miejsca bibliotek współdzieonych czy do zmiennych globalnych (to jest konieczne, jeśli chcemy żeby wszystkie relokacje zostały rozwiązane w momencie kompilacji). W tablicy `GOT` pod adresem 0 znajduje się adres sekcji `.dynamic` (potrzebny konsolidatorowi dynamicznemu), pod adresem znajduje się adres tablicy relokacji, pod adresem 2 znajduje się adres linkerda dynamicznego, a pod następnymi znajdują się (początkowo takie "mock" adresy) adresy do procedur z bibliotek współdzielonych. Kompilator kompilując kod który ma być `PIC` generuje dla każdego elementu z `GOT` relo entry, po to, żeby konsolidator dynamiczny wiedział gdzie ma rozwiązywać potrzebne adresy.
Sekcja `.plt` składa się z tablicy 16-bajtowych **wykonywalnych** elementów, które są regułkami leniwego rozwiązywania adresów współdzielonych bibliotek (dlatego jest tylko do odczytu).
W sekcji .dynamic znajdują się informacje dla konsolidatora dynamicznego. Dokładny opis jak wyglądają te informacje można [znaleźć tutaj](https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-42444.html). Dla przykadu, sekcja `.dynamic` programu `lazy`:

Wpisy w tej sekcji mają postać `tag:int`. `tag` to tak naprawdę informacja o tym jak należy interpretować to co znajduje się w `int`. Dla przykładu, `tag = 1` oznacza, że w `int` jest informacja o bibliotece współdzielonej potrzebnej naszemu programowi.
Przykład:
Dajmy na to, że mamy kod który korzysta ze współdzielonej biblioteki `libvector.so`. Początkowo w tablicy `GOT` pod adresami potrzebnych nam procedur znajdują się adresy do odpowiednich wpisów w tablicy `PLT`. Jeżeli program (podczas run-time) pierszy raz wywoła którąś funkcję z biblioteki współdzielonej, to na podstawie `GOT` wskoczy (dzięki skokowi pośredniemu) do `PLT`, która następnie przekieruje flow programu do konsolidatora dynamicznego, który zmieni wpis w tablicy `GOT` na faktyczny adres potrzebnej nam procedury, po czym odda sterowanie spowrotem naszemu procesowi. Teraz, przy następnych wywołaniach procedury, w tablicy `GOT` będzie się znajdował jej faktyczny adres, więc od razu będziemy już mogli do niej przechodzić.

Oryginalny opis krok po kroku co tu się dzieje:

Przy każdych następnych wywołaniach funkcji `addvec` tabica `GOT` będzie juz zaktualizowana, i proces wołania tej procedury będzie znacznie krótszy:
