2013-07-23 2 views
5

이하, 필자는 'Hello, World!'를 인쇄하는 x64 어셈블리를 작성했습니다. Mac OS X 10.8의 syscall에서. 독립 실행 형으로 실행되면 완벽하게 실행됩니다.C - 버스 오류 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!' 

문제는 내가이 코드를 C 프로그램에서 쉘 코드로 실행하려고 할 때 발생합니다. otool을 사용하여 다음 기계 opcode를 얻습니다.

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"; 

다음은이 프로그램을 실행하는 데 사용하는 C 프로그램입니다. 그러나 나는 버스 오류가 계속 : 나는 gdb를 통해 단계 때 실행이 쉘 코드에 전달 될 때 (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; 
} 

나는 KERN_PROTECTION_FAILURE 권리를 얻는다.

업데이트 질문 :

위는 칼 Norum에 의해 해결되었다, 그것은 메모리 보호 때문. 나는 다른 문제가 있지만 위와 비슷합니다. 동일한 파일에 셸 코드가있는 대신 .txt 파일에서 셸 코드를 읽고 실행하려고합니다. 아래에서는 PROT_EXEC로 메모리 섹션을 표시하고 .txt 파일의 내용을 읽고 실행 해 보았습니다. 하지만 작동하지 않습니다, 나는 같은 오류, KERN_PROTECTION_FAILURE, mprotect 및 mmap 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; 
} 

은 그 같은 안녕하세요 세계 코드 내가에서 읽고있어 text.txt 파일입니다

\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 

내가 PROC_EXEC 메모리에 txt 파일의 내용을 복사하고 있습니다 때문에, I 내가 KERN_PROTECTION_FAILURE를 얻는 이유를 이해하지 못한다.

+0

새로운 텍스트 파일은 문자 백 슬래시 포함되어 있습니까

은 다음 섹션 - 재정의 체조를 할 필요없이 작동하는 프로그램입니다 , x, 5, 5 등? 또는 '\ x55'(숫자 7 IIRC) 문자가 포함되어 있습니까? –

+0

예. \ x, .txt 파일은 위와 동일합니다. –

+0

C 프로그램에서'malloc'의 리턴 값을 캐스트 할 필요가 없습니다. –

답변

8

프로그램이 데이터 섹션의 메모리 기본값 인 "execute disable"이라고 표시된 페이징 된 메모리에서 쉘 코드를 실행하려고합니다. 그래서 KERN_PROTECTION_FAILURE이 표시됩니다. 당신은 텍스트 섹션에서 쉘 코드를 넣어해야합니다

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

는 그 일을 한 후, 프로그램이 잘 작동 :

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

편집 주 : 당신은 당신의 함수 포인터 호출에 배역이 필요하지 않습니다. 그냥 ret(); 괜찮을 것입니다. 경고없이 컴파일하려면 적어도 (int) 부분을 제거해야합니다.

편집 :

#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; 
} 

예를 실행 :

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

감사합니다. 귀하의 예처럼 clang과 호환됩니다. 어떻게 gcc에서 이걸 실행할 수 있을까요? char code [] 앞에 "__attribute __ ((__ TEXT, __ text"))) "를 입력하면"전역 변수 '코드의 섹션 유형 또는 속성이 이전 섹션 지정자와 일치하지 않습니다. "라는 오류가 발생합니다. –

+0

왜 clang을 사용할 수있을 때 gcc를 사용하고 싶습니까? 내가 여기서 그것을 시도하자. –

+0

아무 이유없이, 전 결코 clang을 사용하지 않았습니다. gcc에서 이런 종류의 오류를 어떻게 해결할 수 있는지보고 싶습니다. –