2012-03-31 4 views
6

리눅스 64 비트 머신에서 16 진수 바이트 코드를 실행할 수있는 간단한 C 메소드가 필요합니다. 여기에 내가 가지고있는 C 프로그램입니다 :16 진수 바이트 코드를 실행하는 C 코드를 얻는 방법?

char code[] = "\x48\x31\xc0"; 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
     int (*func)(); 
     func = (int (*)()) code; 
     (int)(*func)(); 
     printf("%s\n","DONE"); 
} 

내가 (정말 아무것도 안거야)

.text 
.globl _start 
_start: 
     xorq %rax, %rax 

이 간단한 조립 프로그램을 writting에 의해 획득 ("\x48\x31\xc0")를 실행하려고 코드 그런 다음 바이트 코드를 얻기 위해 컴파일하고 obj 덤프한다.

그러나 C 프로그램을 실행하면 세그먼트 화 오류가 발생합니다. 어떤 아이디어?

+5

? 하나의 명령을 실행 한 다음 나중에 명령 (제어하지 않음)을 실행 한 다음 명령을 실행하여 합법적 인 코드 또는 segfault를 트리거하는 코드를 나타내지 않는 메모리에 도달 할 때까지 실행합니다. –

+1

간접 함수 호출은 반환 주소를 스택에 푸시하는'call '이어야하기 때문에'ret'에 바이트 코드를 추가해야합니다. Atleast, 이것은 내 최고의 교육 추측이며, 나는 이런 것을 본 적이 없다. – Chris

+0

나는 이것이 아무 것도하지 않기를 기대하지만, 나는 충돌없이 달릴 수 있기를 바랍니다. – Nosrettap

답변

13

다음은 간단한 예입니다.

main.c를 : 나는 어셈블리에 쉽게 코드를 제대로 실행되었는지 확인 할 수 있도록 (2) _exit을하기로 결정했습니다

./main ;echo $? 

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

int main() 
{ 
    /*                
     mov rax, 60   ; sys_exit 
     mov rdi, 2 
     syscall             
    */ 
    char code[] = { 
     0x48, 0xb8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x48, 0xbf, 0x02, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x0f, 0x05 
    }; 

    void *buf; 

    /* copy code to executable buffer */  
    buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANON,-1,0); 
    memcpy (buf, code, sizeof(code)); 

    /* run code */ 
    ((void (*) (void))buf)(); 

    return 0; 
} 

실행이. 실제로는 컨트롤의 반환을 위해 코드 끝에 ret를 추가하려고합니다.

+0

예, 'ret'는 호출 함수로 다시 돌아 오는 것이 중요합니다. – Chris

+1

도움을 주셔서 감사합니다. 난 그 objdump 추가 싶어요 - 당신에게 실행 파일에 대한 바이트 코드를 얻을 수 있습니다. – Jeff

4

기계 코드는 사용 가능하지만 CPU 개체 일 수 있습니다.

최신 CPU는 메모리를 세그먼트 단위로 관리합니다. 정상적인 작동에서 운영 체제는 프로그램 텍스트 세그먼트에 새 프로그램을로드하고 데이터 세그먼트에 스택을 설정합니다. 운영 체제는 데이터 세그먼트에서 코드를 실행하지 않도록 CPU에 지시합니다. 귀하의 코드는 데이터 세그먼트의 code[]에 있습니다. 따라서 segfault.

2

약간의 노력이 필요합니다.

귀하의 code 변수는 실행 파일의 .data 섹션에 저장됩니다

$ readelf -p .data exploit 

String dump of section '.data': 
    [ 10] H1À 

H1À은 변수의 값입니다.

.data 섹션 하지 실행 가능 :

$ readelf -S exploit 
There are 30 section headers, starting at offset 0x1150: 
Section Headers: 
    [Nr] Name    Type    Address   Offset 
     Size    EntSize   Flags Link Info Align 
[...] 
    [24] .data    PROGBITS   0000000000601010 00001010 
     0000000000000014 0000000000000000 WA  0  0  8 

나는 페이지 테이블에서 기본적으로 지원 비 실행 페이지를 잘 알고 모든 64 비트 프로세서. 대부분의 새로운 32 비트 프로세서 (PAE를 지원하는 프로세서)는 운영 체제가 하드웨어 비 실행 페이지를 에뮬레이트하기 위해 페이지 테이블에 충분한 공간을 제공합니다. 고대 OS 또는 고대 프로세서를 실행하여 .data 섹션을 실행 가능으로 표시해야합니다.

이들은 실행 파일의 플래그 일 뿐이므로 다른 메커니즘을 통해 X 플래그를 설정할 수 있어야하지만 그렇게하는 방법을 알지 못합니다. 그리고 운영 체제는 심지어 쓰기가 가능한 페이지가 모두 인 페이지를 가질 수 없습니다.

관련 문제