https://chacker.pl/
Jeśli naszym zamiarem jest zbudowanie ROP lub ret2lib, który działa niezależnie od znajomości układu pliku binarnego, będziemy potrzebować prymitywu odczytu zdolnego do dostępu do pełnej przestrzeni adresowej. Jednym ze sposobów osiągnięcia tego jest manipulowanie wskaźnikiem używanym przez standardowe żądanie urządzenia, które zwraca dane do hosta. Dobrym kandydatem na standardowe żądanie jest GET_DESCRIPTOR. Kiedy przekazujemy USB_DT_STRING w wValue żądania, jest ono przetwarzane przez usb_desc_string (zdefiniowane w /qemu/hw/usb/desc.c):


Funkcja usb_desc_string wywołuje usb_desc_get_string (1), aby iterować po liście dev->strings (2), aż do znalezienia indeksu. Następnie usb_desc_string kopiuje zawartość zwróconego wskaźnika, aż do znalezienia bajtu zerowego lub osiągnięcia maksymalnego rozmiaru bufora (3). Możliwe jest nadpisanie nagłówka listy w dev->strings i sprawienie, aby wskazywał na obiekt USBDescString utworzony przez nas. Później możemy wysłać żądanie GET_DESCRIPTOR i zwrócić dane z naszego kontrolowanego wskaźnika s->str. Dobrym miejscem na umieszczenie naszego fałszywego obiektu USBDescString jest wnętrze s->data_buf. Zawartość może zostać zapisana w jednym ujęciu podczas wyzwalania przepełnienia bufora. Aby to zrobić, wymagane są pewne zmiany w prymitywie relative_write (/labs/qemu_xpl.py), więc napiszmy nowy:

Teraz dowolny zapis przyjmuje nowy argument (data_buf_contents), który jest IOVector przekazanym do usb_out (1) podczas wyzwalania przepełnienia bufora. W ten sposób możemy umieścić dodatkowe dane w s->data_buf. Może to być przypadek, gdy wiemy z góry, z których adresów chcemy wyciekać. Zamiast tworzyć pojedynczy USBDescString i wywoływać prymityw raz dla każdego adresu, możemy skorzystać z argumentu indeksu usb_desc_string:

Metoda pomocnicza descr_build (1) przyjmuje listę adresów i produkuje listę powiązaną elementów USBDescString, a każdy element (2) ma numer indeksu przypisany do określonego adresu. Drugi argument (start_addr) to adres wewnątrz s->data_buf. Nowy prymityw leak_multiple (3) buduje tę listę powiązaną i nadpisuje s->strings (4) adresem nagłówka listy. Lista powiązana zaczyna się od &s->data_buf[256] , pozostawiając pierwsze 256 bajtów bufora wolnych dla zawartości zwróconej przez desc_string. Na koniec desc_string jest wielokrotnie wywoływany dla każdego numeru indeksu (5) powiązanego z adresami jednej listy, które mają przeciekać.
UWAGA: desc_string jest zaimplementowany w ehci.py i służy do wysyłania żądania GET_DESCRIPTOR z argumentami USB_DT_STRING i index.