2012-11-10 2 views
0

이 쉘 코드에 문제가 있습니다. 어셈블러 코드를 실행할 때 caracter를 인쇄하지만, C에서 함수로 호출하면 그렇지 않습니다. gdb를 사용하여 실행 된 모든 명령어를 테스트했으며 모든 명령어를 실행 한 것으로 보입니다. asm과 c 버전 모두를 디버깅했기 때문에 매우 이상합니다. 그러나 int 0x80에서는 C 코드를 인쇄하지 않습니다.쉘 코드 인쇄 문자 (64 비트)

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

int (*sc)(); 
/**************************************************************** 
    0000000000000000 <main>:         /
     0: 48 31 c9    xor %rcx,%rcx   /
     3: 48 31 c0    xor %rax,%rax   /
     6: eb 13     jmp 1b <n>    /
                   /
    0000000000000008 <et>:          /
     8: 59      pop %rcx     /
     9: 48 31 c0    xor %rax,%rax   /
     c: 48 31 db    xor %rbx,%rbx   /
     f: 48 31 d2    xor %rdx,%rdx   /
     12: b0 04     mov $0x4,%al    /
     14: b3 01     mov $0x1,%bl    /
     16: b2 01     mov $0x1,%dl    /
     18: cd 80     int $0x80    /
     1a: c3      retq      /
                   /
    000000000000001b <n>:          /
     1b: e8 e8 ff ff ff   callq 8 <et>    /
                   /
    0000000000000020 <abc>:          /
     20: 77      .byte 0x77     /
     ...              /
******************************************************************/ 



char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw"; 

int main(int argc, char **argv) { 

    char *ptr = mmap(0, sizeof(shellcode), 
      PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON 
      | MAP_PRIVATE, -1, 0); 

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

    memcpy(ptr, shellcode, sizeof(shellcode)); 
    sc = ptr; 

    (void)((void(*)())ptr)(); 
    printf("\n"); 

    return 0; 
} 

이것은 NASM 코드는 다음과 같습니다 : 이것은 C 코드

global main 

main:       ; main 

xor rcx, rcx   ; eficient way turning register to 0 
xor rax, rax   ; exclusive or 

jmp n    
et: 
pop rcx 

xor rax, rax 
xor rbx, rbx 
xor rdx, rdx 
mov al, 4      ; Number of system call (write) 
mov bl, 1      ; argument(1=stdout) 
mov dl, 1      ; number of characters 
int 0x80 

ret 

n: 
call et 
abc: db 'w'    

편집 : 나는이 문제를 해결했다. 이 웹 페이지에서 : http://www.exploit-db.com/papers/13065/ 64 비트에서 시스템 호출은 0x80의 syscall insted를 사용하여 호출해야하며 인수의 레지스터는 다릅니다. 다음이 다른 웹 페이지를 발견했습니다 : http://cs.lmu.edu/~ray/notes/linuxsyscalls/. 이 시스템 콜을하는 것에 대한 몇 가지 예가 있습니다. 좋은 웹 페이지라고 생각하십시오.

그러나 지금 질문은 왜 Nasm 코드에서 작동 했습니까? 호환성과 관련이 있습니까? 어셈블러가 int 0x80 명령어를 감지했기 때문에 컴파일러가 쉘 코드를 해석 할 수 없기 때문에 어셈블러 코드가 호환 모드에서 실행 중일 수 있습니다.

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

int (*sc)(); 
/**************************************************************** 
    0000000000000000 <main>:         /
     0: 48 31 c9    xor %rcx,%rcx   /
     3: 48 31 c0    xor %rax,%rax   /
     6: eb 16     jmp 1e <n>    /
                   /
    0000000000000008 <et>:         /
     8: 5e      pop %rsi    /
     9: 48 31 c0    xor %rax,%rax   /
     c: 48 31 db    xor %rbx,%rbx   /
     f: 48 31 d2    xor %rdx,%rdx   /
     12: b0 01     mov $0x1,%al   /
     14: b3 01     mov $0x1,%bl   /
     16: 48 89 df    mov %rbx,%rdi   /
     19: b2 01     mov $0x1,%dl   /
     1b: 0f 05     syscall     /
     1d: c3      retq      /
                   /
    000000000000001e <n>:          /
     1e: e8 e5 ff ff ff   callq 8 <et>    /
                   /
    0000000000000023 <abc>:         /
     23: 77      .byte 0x77    /
                   /
****************************************************************/ 


char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x16\x5e\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x01\xb3\x01\x48\x89\xdf\xb2\x01\x0f\x05\xc3\xe8\xe5\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x13\x59\x48\x31\xc0\x48\x31\xdb\x48\x31\xd2\xb0\x04\xb3\x01\xb2\x01\xcd\x80\xc3\xe8\xe8\xff\xff\xffw"; 
//char shellcode[] = "\x48\x31\xc9\x48\x31\xc0\xeb\x11\x59\xb0\x04\xb3\x01\xb2\x01\xcd\x80\x48\x31\xc0\x48\xff\xc0\xcd\x80\xe8\xea\xff\xff\xffw"; 

int main(int argc, char **argv) { 

    char *ptr = mmap(0, sizeof(shellcode), 
      PROT_EXEC | PROT_WRITE | PROT_READ, MAP_ANON 
      | MAP_PRIVATE, -1, 0); 

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

    memcpy(ptr, shellcode, sizeof(shellcode)); 
    sc = ptr; 

    (void)((void(*)())ptr)(); 
    printf("\n"); 

    return 0; 
} 

답변

1

당신은 아마 32 비트 것과 ELF 파일을 구축했다 :

은 여기 작업 C 코드를 둡니다. OS가 64 비트이더라도 바이너리가 32라면 호환 모드로 실행됩니다.

Windows (Windows-on-Windows-64 또는 WOW64)에서와 동일한 현상이 발생합니다.

+1

맞을 수도 있습니다. 나중에 컴파일하려고 시도하고 exec가 32 비트인지 알려줍니다. 답변 해주셔서 감사합니다. (저는 리눅스를 사용하고있었습니다.) – user1754322

+0

확실합니다. 64 비트 머신의 write syscall은 1이며 rax 레지스터에 저장해야하며 syscall 명령어 (int 0x80이 아님)로 호출해야합니다. 그는 32 비트 명령어와 64 비트 레지스터를 혼합합니다. – sinkmanu

관련 문제