---
# System prepended metadata

title: Lista 9 (6 maja 2021)
tags: [kba, ask21, ćwiczenia]

---

# 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
:::
![](https://i.imgur.com/G6AElt8.png)

#### 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
:::
![](https://i.imgur.com/aIoQii8.png)

**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`:
![](https://i.imgur.com/skK515l.png)
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ć. 

![](https://i.imgur.com/QPiuKfk.png)

Oryginalny opis krok po kroku co tu się dzieje:
![](https://i.imgur.com/Rgclgpe.png)


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:

![](https://i.imgur.com/RaihGTy.png)
