2017-10-05 4 views
0

미안하지만이 질문이 벙어리로 들리지만 쉘 코딩에 익숙하지 않고 32 비트 Linux 컴퓨터에서 작동하는 hello world 예제를 얻으려고했습니다.C 프로그램에서 hello world shellcode를 실행할 때 Segfault

셸 코드이므로 null 바이트를 제거하고 코드를 줄이기 위해 몇 가지 트릭을 사용했습니다. 여기있다 :

$ nasm -f elf print4.asm 
$ ld -o print4 -m elf_i386 print4.o 

을하지만, 내가 그것을 실행 시도 다음과 같은 C 코드 내 : $ 고양이 shellcodetest을 내가 컴파일하고 다음 명령을 연결할 때

section .data 

section .text 
global _start 
_start: 

;Instead of xor eax,eax 
;mov al,0x4 
push byte 0x4 
pop eax 
;xor ebx,ebx 
push byte 0x1 
pop ebx 
;xor ecx,ecx 
cdq ; instead of xor edx,edx 

;mov al, 0x4 
;mov bl, 0x1 
mov dl, 0x8 
push 0x65726568 
push 0x74206948 
;mov ecx, esp 
push esp 
pop ecx 
int 0x80 

mov al, 0x1 
xor ebx,ebx 
int 0x80 

이 코드는 잘 작동합니다. C #INCLUDE

char *shellcode = "\x04\x6a\x58\x66\x01\x6a\x5b\x66\x99\x66\x08\xb2\x68\x68\x68\x65\x69\x48\x54\x66\x59\x66\x80\xcd\x01\xb0\x31\x66\xcd\xdb\x80"; 

int main(void) { 
    (*(void(*)()) shellcode)(); 
} 
$ gcc shellcodetest.c –m32 –z execstack -o shellcodetest 
$ ./shellcodetest 
Segmentation fault (core dumped) 

누군가가 무슨 일이 일어나고 있는지 설명해 주시겠습니까 사용법 #include? 나는 gdb에서 코드를 실행하고 esp에서 이상한 일이 일어나고 있음을 발견했다. 그러나 전에 말했듯이, 나는 아직도 여기서 일어나는 일을 정말로 이해할 수있는 경험이 부족합니다.

미리 감사드립니다.

+0

포인터 값을 가리키는 문자열 리터럴이 아닌 코드로 포인터 값을 실행하고 있습니다. 'const char shellcode [] = "..."'를 사용하십시오. '.data' 섹션 (데이터 세그먼트 = 읽기 + 쓰기)이 아닌 텍스트 세그먼트 (읽기 + 실행)에 들어가는'.rodata' 섹션에 들어가려면'const'이어야합니다. –

+0

이봐, 내가 틀렸다면 나를 바로 잡는다. 그러나 [이 링크] (https://stackoverflow.com/questions/16626857/shellcode-in-c-program)는 바이트 코드가 실제로 포인터에 캐스팅되었다고 설명한다. 매개 변수가없는 함수(). 그래서 16 진수 문자열은 AX 인 .text 섹션에서 끝난다고 생각합니다. 더욱이, LarsH는 endianness를 바꾸는 것만으로 C 코드에서 쉘 코드를 실행할 수있었습니다 (나는 그것을 보지 못해서 멍청한 느낌을 받았습니다 ...). – warsang

+0

예, 제 의견이 잘못되었습니다. C의'shellcode'는'char * shellcode'를 쓸 때 메모리에서 포인터를로드하고, 지시 된 문자열 리터럴 자체는'.rodata'에 있습니다. 그것은'call char [shellcode []'를 사용하기위한 간접적 인 지시를 줄이기 위해 call [absolute_address_of_pointer] 대신'call eax' (또는'call rel32')를 사용합니다. (그리고'char shellcode []'(const가 아닌)는 충돌 할 것입니다.) –

답변

0

정확한 엔디안으로 입력되지 않았기 때문에 쉘 코드가 작동하지 않습니다. 파일 print4에서 바이트를 추출한 방법을 명시하지 않았지만 objdumpxxd 모두 올바른 순서로 바이트를 제공합니다. > '\ x6a X04 \'-

$ xxd print4 | grep -A1 here 
0000060: 6a04 586a 015b 99b2 0868 6865 7265 6848 j.Xj.[...hherehH 
0000070: 6920 7454 59cd 80b0 0131 dbcd 8000 2e73 i tTY....1.....s 
$ objdump -d print4 

print4:  file format elf32-i386 


Disassembly of section .text: 

08048060 <_start>: 
8048060:  6a 04     push $0x4 
8048062:  58      pop %eax 
8048063:  6a 01     push $0x1 
... 

당신이해야 할 변화는 바이트 순서, '\ X04 \ x6a'을 교환하는 것입니다. 이 변경으로 코드를 실행하면 작동합니다!

$ cat shellcodetest.c 
char *shellcode = "\x6a\x04\x58\x6a\x01\x5b\x99\xb2\x08\x68\x68\x65\x72\x65\x68\x48\x69\x20\x74\x54\x59\xcd\x80\xb0\x01\x31\xdb\xcd\x80"; 
int main(void) { 
     (*(void(*)()) shellcode)(); 
} 
$ gcc shellcodetest.c -m32 -z execstack -o shellcodetest 
$ ./shellcodetest 
Hi there$