-
|Lord Of Bufferoverflow| #14 bugbear - giantWargame Site/BOF 2019. 6. 23. 17:04
아따~ 길다.. 하지만, 자세히 보면 그렇게 어렵지 않은 코드임을 알 수 있다.
중간에 친절하게 주석처리까지 되어있는 것을 알 수 있다.
// gain address of execve ,//end 인 것으로 알 수 있 듯, execve 의 주소를 가져오는 것이다.
그리고 RET 에 execve 의 주소를 잘 넣어줬는지 확인하는 코드가 보인다.
즉, execve 를 ret 로 두어 문제를 해결해야하는 것이다.
24 번째 줄에서 보이는 저녀석이 걸림돌이 된다.
기존의 풀이 방식을 파헤쳐보면 Core 분석 및 디버깅을 위해 실행파일을 복사했다.
실행파일을 복사하면, 우리의 권한으로 파일을 실행시킬 수 있기 때문에 Core 가 생기며, Core Analysis 를 할 수 있었다.
만약, 이문제에서 giant 를 복사한다고 하더라도
우리의 권한으로는 /home/giant 에 접근할 수 없다.
따라서, giant.c 자체를 수정해서 자유로운 환경을 만들어주자
자유로운 분석환경 만들기
1. giant.c 를 복사한다.
2. /home/bugbear/giant 로 수정해준다.
3. gcc 로 실행파일로 만들어준다.
이로써, 우리에게 익숙한 환경을 갖추었다. 이제 본격적으로 문제풀이에 돌입해보자.
우선, execve 의 주소를 구하는 것이 우선일 것이다.
execve 의 주소 : /lib/libc.so.6 의 주소 + execve 의 offset = 0x40018000 + 0x00091d48 = 0x400a9d48
예외상황 1
하지만.... RET 영역(buffer + 4 ~ buffer + 7)에 execve 의 주소를 넣어주어도 다음과 같은 'You must use execve' 문구가 뜨는 것을 볼 수 있었는데, execve 의 주소가 제대로 들어가지 않았음을 알 수 있었다.
디버깅 결과 0x400a9d48 이 아니라, 0x40009d48 로 들어간 것을 볼 수 있다.
마치, \xff 가 들어갔을 때와 비슷한 현상이 벌어진 것이다.
검색결과 \x0a 가 개행문자로 들어가서 작동이 안된다고 한다.
따라서, \x0a 를 문자 자체로 전달하기 위해서는 `python -c 'print '` 를 전체적으로 감싸주어야 한다는 것을 알았다.
"`python -c 'print '`" 와 같은 형식으로 작성해야한다.
RET 에 값이 제대로 들어간 것을 알 수 있다.
공부를 하면서 항상느낀 건데, 뭔가 문제가 터지고 나서 '이런현상 때문이다' 라고 이해하는 경우가 많은데
마치 문제 답안지를 보고 거기에 풀이를 맞추는 듯한 풀이같다...
이런 기분이 정말 좋지 않지만, 나중에 꼭 짚고 싶은 부분이다.
그러기 위해서는 문제풀이 이상의 개념에 도달해야한다. 그날까지 한걸음은 계속되야한다.
이번 포스팅의 핵심!!
RET 를 조정하여 execve 로 EIP 를 수정한 뒤에 execve 의 프롤로그가 시작된다.
우리가 주목해야할 부분은 EBP 이다.
그 이유는 앞서 풀었던 문제에서도 강조했던 부분으로 EBP 를 기준으로 인자와 지역변수를 구분짓기 때문이다.
즉, EBP 가 ESP 가 있는 곳으로 이동한다는 것이다.
execve 실행전 ESP 는 어디를 향해 있을까?
그렇다. 바로 execve 주소를 적어준 바로 다음부분을 가르키고 있을 것이다.
프롤로그가 시작되면 EBP (SFP 로 넣어줬던 'AAAA') 가 들어갈 것이고 ( 0x400a9d48 push ebp )
그 뒤로, execve 의 다음인자들이 나열되는 구조가 될 것이다.
'기존의 \x48\x9d\x0a\x40 은 SFP 로 덮어질 것이다.'
EBP + 4 : RET 주소 EBP + 8 : 인자 ~
의 구조를 만들어 주면 되는 것이다.
execve 의 기준에서 입력값을 바라볼때
"A"*44 + "\x48\x9d\x0a\x40" + [ RET ] + 인자(execve) ...
의 형태가 되는 것이다.
인자부분에 exit( ) 를 넣어주고, RET 부분에 system 을 넣어주고, 이 또한 execve 의 형태를 생각했을 때 다음과 같은 구조를 지닐 것이다.
system 의 기준에서 입력값을 바라볼때
"A"*44 + "\x48\x9d\x0a\x40" + System + [ RET ] + 인자(system) ...
의 형태가 되는 것이다.
천천히 이해해보면 이해할 수 있다. 나 또한 이 개념을 받아들이기 까지 시간이 많이 걸렸던 것 같다.
하나하나 디버깅을 해보면서 확인하면 잘 알 수 있다.
그럼 최종적으로 작전을 다음과 같이 세우면 될 것이다.
Buffer 44 Byte + execve 의 주소 + system 의 주소 + [ ] + /bin/sh 의 주소
"`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "\xe0\x8a\x05\x40" + "AAAA"+ "\xf9\xbf\x0f\x40"'`"
다음과 같이 정리할 수 있다. [ ] 자리에는 아무값이나 들어가도 상관은 없다.
정상적으로 동작이 되지않아 core 가 생긴다는 점 말고는 이상은 없다.
OpenTRS 에서 Defcon 풀이를 듣던 도중 ROP Chaining 개념이 나왔는데,
Chaining 의 개념을 접근하기 위해 선수되어야하는 문제였던 것 같다.
프로그램 작동원리를 한단계 더 잘 이해할 수 있던 좋은 문제였던 것 같다.
'Wargame Site > BOF' 카테고리의 다른 글
|Lord Of Bufferoverflow| #16 assassin - zombie_assassin (0) 2019.06.29 |Lord Of Bufferoverflow| #15 giant - assassin (0) 2019.06.23 |Lord Of Bufferoverflow| #13 darkknight - bugbear (0) 2019.06.21 |Lord Of Bufferoverflow| #12 golem - darkknight (0) 2019.06.17 |Lord Of Bufferoverflow| #11 skeleton - golem (0) 2019.06.16 댓글