Study Record

[리버싱] Hack Me 풀이집4 (13,14단계) 본문

리버싱/Hack Me

[리버싱] Hack Me 풀이집4 (13,14단계)

초코초코초코 2021. 11. 19. 09:35
728x90

13단계 → 14단계

※ 13단계(level13) 패스워드 : "have no clue"

 

☞ 기초개념 - 버퍼 오버플로우, 쉘코드, 에그쉘, 메모리 보호 기법

https://laustudy.tistory.com/65 - 버퍼 오버플로우

https://laustudy.tistory.com/73 - 에그쉘

https://laustudy.tistory.com/70 - 쉘코드

https://laustudy.tistory.com/69 - 메모리 보호 기법

 

㉮ hint 를 확인해본다.

# cat hint

hint 내용은 /home/level13/attackme 의 내부 소스 코드인 것 같다. 소스 코드에서 strcpy() 함수로 인자값으로 받은 argv[1] 값을 buf 배열에 저장하는 과정에서 글자 제한을 두고 있지 않기 때문에 버퍼 오버플로우 공격이 가능하다. RET 값을 미리 메모리에 올려둔 쉘 실행 코드의 시작 주소값으로 변조하면 쉘을 획득할 수 있을 것이다.

 

㉯ gdb로 attackme 를 분석해보자. (cp /home/level13/attackme /home/level13/tmp/; cd tmp;)

hint 를 통해서 스택 카나리 역할을 하는 변수 i 와  char buf 배열이 1024바이트만큼 차지하고 있다. 따라서 strcpy(buf, argv[1]) 을 통해 char buf 배열에 argv[1](인자값) 값을 넣을 때 1024개만큼 'A'를 넣으면 '0x41' 다음이 char buf 의 끝이라는 것을 알 수 있다. gdb를 통해 $(perl -e 'print "A"x1024') 를 인자값 실행시키고 프로그램이 끝나기 전에 분석작업을 해보자.

분석 결과, buf 배열과 스택 카나리(변수 i) 사이에는 12byte의 빈 공간이 존재하고 스택 카나리(변수 i)에서 RET 까지 12byte 빈공간이 존재한다.

hint 를 통해 스택 카나리(변수 i) 가 변조되면 "Warnning: Buffer Overflow !!! \n"를 출력하고 kill 명령어가 실행되면서 강제로 종료된다. 따라서 버퍼 오버플로우 공격을 시도할때 스택 카나리(변수 i)값은 0x01234567 로 설정해야 한다.

 

㉯ 에그쉘을 사용하여 쉘 코드를 메모리에 올려 쉘 코드의 실행 주소를 확인한다.

 

→ 에그쉘과 쉘코드에 대한 설명

https://laustudy.tistory.com/73 - 에그쉘

https://laustudy.tistory.com/70 - 쉘코드

 

# egg; getenv;

쉘 코드의 실행 주소는 0xbffff6b8 이다.

 

 버퍼 오버플로우 공격을 위해 필요한 정보들을 다 모았으니 공격 구문을 만들어볼 수 있다.

buf 배열의 크기는 1024byte이고 스택 카나리(변수 i)까지 12byte 빈 공간이 존재하고 스택 카나리(변수 i)에는 0x01234567 값이 들어가야 하고, 스택 카나리(변수 i)에서 RET 사이에 12byte의 빈공간이 존재한다. 따라서 1036byte 를 아무 문자로 채우고 스택 카나리(변수 i)값을 0x01234567 로 설정하고 그 뒤 12byte를 다시 아무 문자로 채운뒤, RET자리에 미리 메모리에 올려둔 쉘코드의 주소값인 0xbffff6b8  로 채우면 된다. 

리틀 엔디안 방식을 사용하고 있으므로 쉘코드의 값(0xbffff6b8) 과 스택 카나리(변수 i)의 값(0x01234567) 은 거꾸로 들어가야 한다.

최종적으로 인자값은 $(perl -e 'print "A"x1036,"\x67\x45\x23\x01","A"x12,"\xb8\xf6\xff\xbf"') 가 되고, 공격 구문은 /home/level13/attackme $(perl -e 'print "A"x1036,"\x67\x45\x23\x01","A"x12,"\xb8\xf6\xff\xbf"') 가 된다.

 

 공격 구문을 실행해본다. 반드시 /home/level12/tmp/egg 가 실행되고 있어야 한다.

sh-e.05b$ /home/level13/attackme $(perl -e 'print "A"x1036,"\x67\x45\x23\x01","A"x12,"\xb8\xf6\xff\xbf"')

공격 결과 쉘을 얻을 수 있었고 level14 의 패스워드를 획득했다!

 

14단계 → 15단계

※ 14단계(level14) 패스워드 : "what that nigga want?"

 

☞ 기초개념 - 버퍼 오버플로우

https://laustudy.tistory.com/65 - 버퍼 오버플로우

 

㉮ hint 를 확인해본다.

# cat hint

hint 의 내용을 확인한 결과 /home/level14/attackme 프로그램의 소스코드로 추정된다. 코드의 흐름을 보아 fgets 함수에서 buf 배열의 크기는 20byte인데 표준 입력으로 45byte까지 쓸 수 있게 되어있다. 따라서 이 함수를 이용해 버퍼 오버플로우 공격을 실행할 수 있다. 버퍼 오버플로우 공격으로 check 변수의 값을 0xdeadbeef 로 바꾸면 다음 단계로 쉘을 실행시켜 주고 있다.

 

버퍼 오버플로우 공격을 하기 전, check 변수buf 배열 사이가 얼만큼 떨어져 있는지 확인해본다.

attackme 코드를 ~/tmp/attackme 로 복사하여 gdb 명령어를 이용해 ~/tmp/attackme 파일을 열어 main 함수의 어셈블리 코드를 확인해본다. (gdb ~/tmp/attackme)

어셈블리 코드 확인 결과 buf 배열은 [ebp – 56] 에 위치하고 check 변수는 [ebp - 16] 에 있는걸 보니 check 변수와 buf 배열 사이는 40만큼의 차이가 있고 buf 배열은 20byte 크기를 가지고 있으므로 buf 배열과 check 변수 사이는 20byte 만큼의 빈 공간이 존재한다.

 

버퍼 오버플로우 공격을 위해 필요한 정보들을 다 모았으니 공격 구문을 만들어본다.

먼저, fgets(buf, 45, stdin); 함수로 표준 입력으로 buf 배열의 시작 주소부터 최대 45byte만큼 값을 쓸 수 있다. buf 배열의 크기는 20byte이고 check변수까지 20byte의 빈공간이 존재한다. 따라서 40byte 를 아무 문자로 채우고 그 뒤 4byte를 0xdeadbeef 로 채운다. 리틀 엔디안 방식을 사용하고 있으므로 0xdeadbeef 는 거꾸로 들어가야 한다.

최종적으로 표준 입력값은 (perl -e 'print "A"x40,"\xef\xbe\xad\xde"') 가 되고, 공격 구문은

(perl -e 'print "A"x40,"\xef\xbe\xad\xde"'; cat) | /home/level14/attackme 가 된다.

 

공격 구문을 실행해본다.

# (perl -e 'print "A"x40,"\xef\xbe\xad\xde"'; cat) | /home/level14/attackme 

공격 결과 쉘을 획득하였고 15단계의 패스워드 “guess what" 이다!

728x90