Study Record

[리버싱] Hack Me 풀이집3 (11,12 단계) 본문

리버싱/Hack Me

[리버싱] Hack Me 풀이집3 (11,12 단계)

초코초코초코 2021. 11. 18. 09:29
728x90

11단계 → 12단계

※ 11단계(level11) 패스워드 : "what!@#$?"

 

풀이 1. 포맷 스트링

 

☞ 기초개념 - 포맷 스트링, 에그쉘, 쉘코드

https://laustudy.tistory.com/66 - 포맷 스트링

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

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

 

㉮ hint 를 확인한다.

# cat hint

hint 의 내용을 보니 /home/level11/attackme 의 소스코드 내용으로 추정된다. printf() 함수를 포맷 스트링 공격에 취약한 방식으로 사용하고 있는 것 같다. ls 명령어를 통해 attackme 가 level12 계정으로 setuid 비트가 걸려있어 이 프로그램이 실행되는 동안에는 level12 권한을 가진다는 것을 확인했다.

 

㉯ 포맷 스트링 공격 가능 여부를 확인한다.

# ./attackme "AAAA %x %x %x %x %x %x %x %x %x %x %x %x"

%x 를 사용했을 때 메모리 주소값처럼 보이는 값들이 보이는 걸로 봐서 포맷 스트링 공격이 가능할 것 같다. 

중간에 4번째 %x 에서 "41414141" 값은 "A" 의 아스키코드값인 0x41 이 출력된 것으로 보아 str 배열의 주소는 %x 를 4번 출력했을 때 볼 수 있다.

 

㉰ 포맷 스트링 공격은 특정 메모리 주소에 원하는 값을 넣을 수 있다. 이 점을 이용하여 attackme 프로그램이 실행되는 동안 쉘을 획득할 수 있어야 한다. 따라서 특정 메모리 주소에는 main 함수가 종료될 때 호출되는 소멸자 함수 대신 쉘코드의 실행 주소로 변조하여 쉘이 실행될 수 있게 해볼 것이다.

※ attackme 프로그램은 실행되는 동안 level12 권한을 가지고 있다.

 

㉱ 먼저 소멸자 함수의 주소를 확인해본다.

# nm ./attackme

0x08049610 주소에 소멸자 함수가 들어있는 것을 확인했다.

 

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

 

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

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

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

 

# egg; getenv;

egg 프로그램으로 환경변수 SUPERDK 에 쉘코드를 등록하고 배시쉘을 새로 실행한 다음 getenv 프로그램으로 환경변수 SUPERDK 의 시작주소값을 가져왔다. 

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

 

㉳ 포맷 스트링 공격에 사용할 주소값들을 전부 구했다. 변조할 메모리는 소멸자 함수가 저장된 위치인 0x08049610 이고, 변조할 값은 0xbffff499 이다.

이것으로 포맷 스트링 공격 구문을 만들면 다음과 같다.

str 배열의 주소는 %x 를 4번 출력했을 때 볼 수 있었고, str의 배열의 4바이트를 소멸자 함수가 저장된 위치인0x08049610 로 저장하고 변조할 값을 0xbffff499 로 바꿔야 한다.

 

☞ 완성된 공격 구문

/home/level11/attackme \ 

$(printf "\x10\x96\x04\x08BBBB\x12\x96\x04\x08")%8x%8x%62589c%n%52070c%n

 

완성된 공격 구문 실행 결과 쉘 코드가 실행되고 패스워드를 획득했다! 반드시 애그쉘이 실행되고 있는 상태에서 공격 구문을 실행해야 한다.

 

풀이 2. 버퍼 오버플로우

 

☞ 기초개념 - 버퍼 오버플로우, 쉘코드, 에그쉘

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

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

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

 

㉮ hint 를 확인한다.

# cat hint

hint 의 내용을 확인한 결과 /home/level11/attackme 프로그램의 소스코드로 추정된다. 소스 코드를 보면, strcpy() 함수에서 인자값(argv[1])을 str 배열에 카피하는데 글자제한을 두고 있지 않은 것 같다. 이점을 이용하여 곧 버퍼 오버플로우 공격을 시도하여 ret 값을 미리 메모리에 올려둔 쉘코드의 주소값으로 바꾸면 쉘코드를 실행하여 쉘을  획득할 수 있을 것 같다.

 

㉯ /home/level11/attackme 를 분석한다.

/home/level11/attackme 코드를 ~/tmp/attackme 로 복사하여 gdb 명령어를 이용해 ~/tmp/attackme 파일을 열어 어셈블리 코드를 확인한다.

# /home/level11/attackme $(perl -e 'print "A"x255') 를 분석한 결과이다.

0xbffffa34 의 값을 확인해본 결과 argv 값이 들어있는 것으로 RET 값은 0x42015574 라는 것을 알았다. RET 값과 str 배열은 사이에 12byte 떨어져 있다는 사실도 알 수 있다.

 

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

 

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

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

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

 

# egg; getenv;

egg 프로그램으로 환경변수 SUPERDK 에 쉘코드를 등록하고 배시쉘을 새로 실행한 다음 getenv 프로그램으로 환경변수 SUPERDK 의 시작주소값을 가져왔다.

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

 

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

buf 배열의 크기는 256byte이고 RET 까지 12byte의 빈공간이 존재한다. 따라서 268byte 를 아무 문자로 채우고 그 뒤 4byte를 미리 메모리에 올려둔 쉘코드의 주소값인 0xbffff499 로 채우면 된다. 리틀 엔디안 방식을 사용하고 있으므로 0xbffff499 는 거꾸로 들어가야 한다.

최종적으로 인자값은 $(perl -e 'print "A"x268,"\x99\xf4\xff\xbf"') 가 되고, 공격 구문은 /home/level11/attackme $(perl -e 'print "A"x268,"\x99\xf4\xff\xbf"') 가 된다.

 

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

# /home/level11/attackme $(perl -e 'print "A"x268,"\x99\xf4\xff\xbf"')

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

 

12단계 → 13단계

※ 12단계(level12) 패스워드 : "it is like this"

 

☞ 기초개념 - 버퍼 오버플로우, 쉘코드, 에그쉘

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

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

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

 

㉮ hint 를 확인한다.

# cat hint

hint 의 내용을 확인한 결과 /home/level12/attackme 프로그램의 소스코드로 추정된다. 소스 코드를 보면, gets() 함수에서 표준 입력으로 받은 값을 str 배열에 저장하는 동작을 하는데 글자제한을 두고 있지 않은 것 같다. 이점을 이용하여 곧 버퍼 오버플로우 공격을 시도하여 ret 값을 미리 메모리에 올려둔 쉘코드의 주소값으로 바꾸면 쉘코드를 실행하여 쉘을  획득할 수 있을 것 같다.

 

㉯ /home/level12/attackme 를 분석한다.

/home/level12/attackme 코드를 ~/tmp/attackme 로 복사하여 gdb 명령어를 이용해 ~/tmp/attackme 파일을 열어 어셈블리 코드를 확인한다.

# $(perl -e 'print "A"x256'; cat) | /home/level12/attackme 를 분석한 결과이다.

0xbfffdd34 의 값을 확인해본 결과 argv 값이 들어있는 것으로 RET 값은 0x42015574 라는 것을 알았다. RET 값과 str 배열은 사이에 12byte 떨어져 있다는 사실도 알 수 있다.

 

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

 

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

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

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

 

# egg; getenv;

egg 프로그램으로 환경변수 EGG 에 쉘코드를 등록하고 배시쉘을 새로 실행한 다음 getenv 프로그램으로 환경변수 EGG의 시작주소값을 가져왔다.

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

 

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

buf 배열의 크기는 256byte이고 RET 까지 12byte의 빈공간이 존재한다. 따라서 268byte 를 아무 문자로 채우고 그 뒤 4byte를 미리 메모리에 올려둔 쉘코드의 주소값인 0xbffff6d4 로 채우면 된다. 리틀 엔디안 방식을 사용하고 있으므로 0xbffff6d4 는 거꾸로 들어가야 한다.

최종적으로 표준입력값은 (perl -e 'print "A"x268,"\xd4\xf6\xff\xbf"') 가 되고, 공격 구문은

(perl -e 'print "A"x268,"\xd4\xf6\xff\xbf"'; cat) | /home/level12/attackme 가 된다.

 

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

# (perl -e 'print "A"x268,"\xd4\xf6\xff\xbf"'; cat) | /home/level12/attackme

공격 결과 쉘을 획득하였고 13단계의 패스워드를  획득했다!

 

728x90