Próbuję wykonać kilka eksperymentów z użyciem różnych segmentów oprócz domyślnego segmentu kodu i danych użytkownika oraz jądra. Mam nadzieję, że uda się to osiągnąć poprzez użycie lokalnej tabeli deskryptorów i wywołania systemowego modify_ldt. Poprzez wywołanie systemowe utworzyłem nowy wpis w LDT, który jest deskryptorem segmentu z adresem bazowym zmiennej globalnej, którą chcę "izolować" i limitem 4 bajtów.Korzystanie z LDT (lokalnej tablicy deskryptorów)
Próbuję załadować rejestr segmentów danych za pomocą selektora segmentów mojego niestandardowego wpisu LDT za pomocą wbudowanego zestawu w programie C, ale gdy spróbuję uzyskać dostęp do zmiennej, otrzymuję błąd segmentacji.
Podejrzewam, że występuje problem z przesunięciem mojej zmiennej globalnej, a kiedy adres jest obliczany, przekracza limit mojego segmentu niestandardowego, powodując błąd seg.
Czy ktoś wie o pracy w tej sytuacji?
Och, przy okazji, jest to na architekturze x86 w Linuksie. Po raz pierwszy zadaję takie pytanie na forum, więc jeśli są jakieś inne informacje, które mogą okazać się przydatne, proszę dać mi znać.
Z góry dziękuję.
Edit: I sobie sprawę, że prawdopodobnie powinien zawierać kod źródłowy :)
struct user_desc* table_entry_ptr = NULL;
/* Allocates memory for a user_desc struct */
table_entry_ptr = (struct user_desc*)malloc(sizeof(struct user_desc));
/* Fills the user_desc struct which represents the segment for mx */
table_entry_ptr->entry_number = 0;
table_entry_ptr->base_addr = ((unsigned long)&mx);
table_entry_ptr->limit = 0x4;
table_entry_ptr->seg_32bit = 0x1;
table_entry_ptr->contents = 0x0;
table_entry_ptr->read_exec_only = 0x0;
table_entry_ptr->limit_in_pages = 0x0;
table_entry_ptr->seg_not_present = 0x0;
table_entry_ptr->useable = 0x1;
/* Writes a user_desc struct to the ldt */
num_bytes = syscall(__NR_modify_ldt,
LDT_WRITE, // 1
table_entry_ptr,
sizeof(struct user_desc)
);
asm("pushl %eax");
asm("movl $0x7, %eax"); /* 0111: 0-Index 1-Using the LDT table 11-RPL of 3 */
asm("movl %eax, %ds");
asm("popl %eax");
mx = 0x407CAFE;
Usterka seg występuje w tej ostatniej instrukcji.
To prawda. Adres 'mx' * w stosunku do nowego' DS' * jest teraz '0'. Zamiast ładować nowy deskryptor segmentu do 'DS', należy go załadować do' ES' i użyć nadpisań segmentów, aby uzyskać do niego dostęp (ładowanie 'DS' wpłynie na * wszystkie * dostępy do danych w twoim kodzie C). – caf
To co mam, kiedy demontować ELF z objdump: 8048a48: c7 05 8c 9e 04 08 fe movl $ 0x3424cafe, 0x8049e8c 8048a4f: ca 24 34 Jest to dość nowy materiał podlega dla mnie, więc jestem nie wiem, który z bajtów jest używany dla modyfikatora zastąpienia rejestru segmentu. Czy adres wyświetlony w kodzie zespołu jest przesunięty w domyślnym segmencie danych? Jeśli tak jest, czy muszę zmienić adres miejsca, w którym zainicjowano zmienną? – Brian
To jest podział: 'c7' to kod operacji dla' MOV r/m32, imm32'. '05' to bajt MOD/RM, który mówi, że operand pamięci jest adresowany tylko przez przemieszczenie. Przesunięcie występuje w następujących czterech bajtach: '0x08049e8c'. Następne cztery bajty to natychmiastowe '0x3424cafe'. Oznacza to, że przesunięcie 'mx' wewnątrz domyślnego segmentu danych to' 0x08049e8c', i jest to przesunięcie wewnątrz nowego 'DS', do którego uzyskujesz dostęp. –