System Hacking

[pwnable.kr] passcode

BIGFROG 2019. 7. 17. 20:56

passcode.c의 내용이다.

bof문제일거라고 생각했는데 아니었다.

소스코드에서 주목할 부분은

1. fflush

2. scanf

이다.

 

입력버퍼를 비워주는 fflush(STDIN)을 이용한 것으로 보아, 버퍼오버플로우에 대한 문제는 아니다.

scanf에서는 주소 연산자 &를 사용하지 않는데, 문제 내용으로 보아 의도적인 취약점이며,

GOT Overwrite를 사용할 수 있는 힌트가 되었다.


&연산자가 없다는 의미는,

%d로 입력하는 정수 값이 그대로 passcode1,2의 주소가 된다는 말이다.

입력해주는 값이 1234라면 그대로 주소가 1234가 된다는 말인데,

주소값을 맘대로 바꿔주려는 시도를 하니까 Segmentation Fault가 나타난다.

 

원래대로라면 &연산자가 존재하여, 주소 값 변경 없이 입력해주는 1234는 passcode의 주소가 가리키는 '값'이 되어야 한다는 것.

 


gdb로 열어보자.

소스코드에서도 보았듯이, 중요한 부분은 main이 아니라 login부분이다.

소스코드랑 매칭시켜서 볼 때,

0x80485e3부분은 system()함수의 파라미터로 들어가기 때문에,

"/bin/cat flag"부분임을 알 수 있다. 이 주소를 메모해놓자.

 

또한,

main+97 부분을 보면, if문을 나타낸 것임을 알 수 있는데,

passcode1부분과 338150(0x528e6)를 비교하는 부분이다.

따라서 ebp-0x10은 passcode1 부분이다.

 

name 버퍼 문자열이 스택에 쌓이는 부분은 ebp-0x70인데,

0x70-0x10 = 0x60(96byte)이다.

따라서 96byte만큼 아무 값(A,NOP 등)을 쌓아주면, passcode1부분을 덮을 수 있다.

 

passcode1 부분을 덮을 대상은?

 

GOT Overwrite의 대상은 fflush()함수이다. 

소스코드에서 scanf로 passcode1에 값을 전달해주고 바로 등장하는 fflush()가 타겟이다.

 

fflush()의 got주소 fflush@got은 0x804a004이다.

이는 프로그램에서 아직 등장하지 않았으므로, 주소가 쓰여지지 않은 상태이다.

그래서 0x804a004가 가리키는 곳은 0x08048436인데, 이는 plt+6 부분임을 알 수 있다.

 

여태까지의 내용을 종합하면 우리가 알고 있는 것은

[1]. name 버퍼에서 passcode1까지의 거리 = 96 Bytes

[2]. fflush@got 주소 : 0x804a004

[3]. 덮어씌울 주소(원하는 함수의 주소) : 0x080485e3 - system함수의 인자("/bin/cat flag")가 시작하는 주소.

 


요약

- scanf()함수에서 &연산자를 사용하지 않아, 넣어주는 값 그대로 passcode1의 주소가 된다.

- passcode1은 96 bytes만큼 채워주고 나서 원하는 값으로 덮을 수 있다.

- scanf()함수 이후 fflush()함수가 등장한다.

- 따라서 passcode1에 fflush()함수의 GOT주소로 덮어준다.

- GOT주소의 첫 번째 호출이므로 GOT Overwrite를 이용해 주소 값을 조작하기 위함이다.

- 원래 형태는 scanf("%d", passcode1);

- 바뀐 형태는 scanf("%d", fflush@got);

- 여기서 입력 값(%d)부분에 "내가 원하는 주소"를 넣어주면

- "내가 원하는 주소"가 fflush@got에 '그대로' 박힌다(overwrite)

- "내가 원하는 주소"는 system("/bin/cat flag") 부분임.

- system()함수의 인자가 시작되는 부분 : 0x080485e3을 %d에 넣어주면 된다.

- fflush@got 주소에 내가 원하는 system함수의 인자가 시작하는 부분의 주소가 들어갔다.

- scanf()함수가 끝나고 fflush()함수를 "두 번째 호출"한다.

- @got에 저장된 주소인 0x080485e3이 참조된다.


추가적으로, scanf함수에서 %d로 받아오니까(10진수 정수)

우리도 마찬가지로 10진수 정수 형태로 값을 넣어줘야 한다.

0x080485e3의 10진수는 134514147이므로,

페이로드는 아래와 같다.

 

 

'System Hacking' 카테고리의 다른 글

[pwnable.kr] Input  (0) 2019.07.28
[pwnable.kr] flag  (0) 2019.07.17
[pwnable.kr] bof  (0) 2019.07.17
[pwnable.kr] fd  (0) 2019.07.17
[Root-me]ELF x86 - Stack buffer overflow basic 1  (0) 2019.07.03