2013-07-23 16 views
5

Poniżej napisałem zespół x64, który drukuje "Hello, World!" od syscall w systemie Mac OS X 10.8. Montuje się i działa idealnie, gdy jest wykonywany samodzielnie.Testowanie kodu powłoki z C - błąd magistrali 10

; Assemble and link with: 
; nasm -f macho64 -o HelloWorld.o HelloWorld.s 
; ld -arch x86_64 -o HelloWorld HelloWorld.o 

global start 

section .text 

start: 

    push rbp 
    mov rbp, rsp 

    jmp short String 

    xor rdi, rdi 
    mov di, 0x01 

StringRet: 
    pop rsi 

    xor rdx, rdx 
    mov dl, 0xE 

    mov r8b, 0x02 
    shl r8, 24 
    or r8, 0x04 
    mov rax, r8 

    syscall   ; System call for write(4) 

    xor edi, edi 

    mov r8b, 0x02 
    shl r8, 24 
    or r8, 0x01 
    mov rax, r8 

    syscall   ; System call for exit(1) 

    mov rsp, rbp 
    pop rbp 

String: 

    call StringRet 
    db 'Hello, World!' 

Problem, który mam, to próba uruchomienia tego kodu jako kodu powłoki z programu c. Użyłem otool, aby uzyskać następujące opkody maszynowe.

otool -t HelloWorld.o 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21"; 

Poniżej znajduje się program c, którego używam do wykonania tej czynności. Ale wciąż otrzymuję błąd magistrali: 10.

; Compile: 
; gcc -o HelloWorldTest HelloWorldTest.c 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21"; 

int main() 
{ 
    int (*ret)(); 

    ret = (int(*)())code; 

    (int)(*ret)(); 

    return 0; 
} 

Kiedy krok po kroku z gdb dostaję KERN_PROTECTION_FAILURE prawo, gdy egzekucja jest przekazywany do szelkodu.

Updated Pytanie:

Powyższy został rozwiązany przez Carla Norum, to ze względu na ochronę pamięci. Mam inny problem, ale jest podobny do powyższego. Zamiast posiadania kodu powłoki w tym samym pliku, chcę odczytać kod powłoki z pliku .txt i wykonać go. Poniżej próbowałem zaznaczyć część pamięci jako PROT_EXEC i odczytać zawartość pliku .txt i wykonać ją. Ale to nie zadziała, otrzymuję ten sam błąd, KERN_PROTECTION_FAILURE, próbowałem użyć mprotect i mmap do oznaczenia sekcji pamięci jako PROT_EXEC.

#include <stdio.h> 
#include <sys/mman.h> 
#include <string.h> 
#include <stdlib.h> 

int (*ret)(); 

unsigned char* buf; 

int main() 
{ 
    FILE* file; 
    file = fopen("text.txt", "rb"); 

    unsigned int len = ftell(file); 

    buf = (char*)malloc(len); 
    fread(buf, 1, len, file); 

    fclose(file); 

    mprotect(&buf, len, PROT_EXEC); 

    // I also tried mmap, but same error. 
    /*void *ptr = mmap(0, 1024, PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); 

    if (ptr == MAP_FAILED) 
    { 
     perror("mmap"); 
     exit(-1); 
    } 

    memcpy(ptr, buf, 1024);*/ 

    ret = buf; 

    ret(); 

    return 0; 
} 

Jest to plik text.txt Czytam w jej ten sam kod Hello World:

\x55\x48\x89\xe5\xeb\x33\x48\x31\xff\x66\xbf\x01\x00\x5e\x48\x31\xd2\xb2\x0e\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c\x89\xc0\x0f\x05\x31\xff\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89\xc0\x0f\x05\x48\x89\xec\x5d\xe8\xc8\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a 

Odkąd jestem kopiowanie zawartości pliku txt w pamięci PROC_EXEC, ja nie rozumiem, dlaczego dostaję KERN_PROTECTION_FAILURE.

+0

Czy nowy plik tekstowy zawiera odwrotny ukośnik znaków , x, 5, 5 itd.? Czy może zawierać znaki "\ 55" (cyfra 7)? –

+0

Tak, zawiera plik \ x, .txt jest dokładnie taki, jak pokazano powyżej. –

+0

Nie trzeba rzutować wartości zwracanej przez 'malloc' w programie C. –

Odpowiedz

8

Twój program próbuje wykonać kod powłoki z pamięci stronicowanej oznaczonej "execute disable", która jest domyślna dla pamięci w sekcji danych. Właśnie dlatego widzisz KERN_PROTECTION_FAILURE. Trzeba umieścić szelkod w sekcji tekstowej:

__attribute__((section("__TEXT,__text"))) 
char code[] = ... 

Po wykonaniu powyższych czynności, program działa poprawnie:

$ clang -Wall -Wextra -pedantic -O2 example.c -o example 
$ ./example 
Hello, World! 

Redakcja uwaga: Nie musisz się typecast na wskaźnik funkcji wywołania. Po prostu ret(); będzie dobrze. Musisz pozbyć się co najmniej części (int), aby skompilować bez ostrzeżeń.

Edit:

Oto program, który działa bez konieczności do gimnastyki sekcja-ręczne:

#include <sys/mman.h> 
#include <inttypes.h> 
#include <unistd.h> 

char code[] = "\x55\x48\x89\xe5\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c" 
       "\x89\xc0\x48\x31\xff\x66\xbf\x01\x00\xeb\x1e\x5e\x48\x31\xd2\xb2" 
       "\x0e\x0f\x05\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89" 
       "\xc0\x31\xff\x0f\x05\x48\x89\xec\x5d\xe8\xdd\xff\xff\xff\x48\x65" 
       "\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a"; 

int main() 
{ 
    int (*ret)() = (int (*)())code; 
    void *page = (void *)((uintptr_t)code & ~(getpagesize() - 1)); 

    mprotect(page, sizeof code, PROT_EXEC); 

    ret(); 

    return 0; 
} 

Przykład zjazdowe:

$ clang -O2 -Wall -Wextra example.c -o example 
$ ./example 
Hello, World! 
$ gcc -O2 -Wall -Wextra example.c -o example 
$ ./example 
Hello, World! 
+0

Dziękuję, działa z klangiem jak w twoim przykładzie. Jak byłbym w stanie uruchomić to z gcc. Kiedy wstawiam "__attribute __ ((sekcja (" __ TEXT, __ tekst ")))" przed kodowaniem znaków [], pojawia się błąd, typ sekcji lub atrybuty "kodu zmiennej globalnej" nie pasuje do poprzedniego specyfikatora sekcji ". –

+0

Dlaczego chcesz używać gcc, gdy możesz używać klang? Pozwól, że wypróbuję to tutaj. –

+0

Nie ma powodu, nigdy wcześniej nie używałam klangów. Chcę tylko zobaczyć, jak naprawiłbym tego rodzaju błąd z gcc. –