최근 리버싱 공부를 시작했다. 
책 한권을 끝낸 기념으로 리버싱문제를 풀어볼 것이다.

이제 내가 풀이에 접근 가능한 영역이 리버싱이 추가됬다는 사실에 기쁘다!!! :)

써니나타스의 Web 문제만 풀었었는데 이제 Binary 문제도 풀어주마!

9번 문제를 풀 것이다!



(Binary 9번문제)


파일을 다운받으니 Project1 이라는 실행파일이 보인다.




(실행 파일)



올리디버거로 열어본다!





(올리 디버거 실행)



Main 함수에 찾아가는 방법이 여러가지 있겠지만 문자열을 이용해 찾아보겠다.



(사용된 문자열)


사용된 문자열들을 보니 Congratulation ??? 
느낌이 딱 왔다. 어찌저찌 조건을 만족하면 이 문장을 출력해주는구나.

실제 실행파일을 실행해보면 입력하는 란이 나오고 거기에 입력하여 프로그램을 실행시키는 방식이다.
어떤 특정 값(키)를 입력하면 이 문구가 나오는가보다.

냉큼 그 자리로 달려가 Main 함수 시작부분에 BP를 설치해준다.



(BP 설치)


그리고 여기까지 달려준다.

중간에 퍼즈 당하면서 창이 하나 뜨고 입력하라고 나온다. 입력하지 않으면 실행이 안되는데 아마 입력하고 클릭을 누르는 순간 내가 생각하기에 main 함수인 저 함수로 넘어오는 가 보다! 라고 생각했다.
여튼! 우리의 목적은 축하 메세지를 받는 것이므로 이 함수를 분석해야하는 것은 맞다! 메인함수든 뭐든!

입력 값은 D를 몇개 적어주었다. 헥스값으로 보면 0x44 이기 때문에 쉽게 눈에 띌거 같아서 D 몇개를 넣었다.



(D 입력)



이 함수의 맥락을 보니 분기문 전에 CALL을 하는데 여기서 분기문이 갈라지는 조건을 체크하는 듯 했다.



(분기문 전 CALL)



이 함수 안으로 들어가서 봐야겠다.



(분기문 전 CALL 함수)



보니보니 EAX 값을 ESI 에 넣고, EDX를 EDI 넣고 비교한다.

EAX와 EDX에는..!



(레지스터)



내가 입력한 D 여러개와 어떤 문자열이 들어있었다. 
아! 이 문자열과 비교를?



(문자열 입력)



적혀있는 문자열을 적어보았다.



(축하메세지)



???

축하메세지가...
이 키를 입력하면 인증에 성공한다.


'WarGame > 500 Project' 카테고리의 다른 글

(39/500) Suninatas - Binary(11)  (0) 2017.06.27
(38/500) Suninatas - Binary(10)  (0) 2017.06.27
(36/500) Lord of the BOF - death_knight  (0) 2017.06.27
(35/500) Lord of the BOF - xavius  (0) 2017.06.25
(34/500) Lord of the BOF - nightmare  (0) 2017.06.23


BOF 원정대의 마지막 몬스터 death_knight를 잡아보자.!

* death_knight 소스


(death_knight.c)


소스코드를 보니 마지막 문제는 Remote BOF 문제였다.
원격에서 공격하는 방법인데
방법은 크게 두가지가 있다. 바인드쉘을 이용하거나, 리버스쉘을 이용하거나.

나의 계획은 바인드쉘을 이용할 것이었다.
일단 netstat 명령어로 소스코드대로 6666 포트가 열려있는지 확인해본다.


(열린 포트 확인)


파일 권한을 확인해보니 역시 setuid가 설정되어있고 eath_knight가 주인이다.



(setuid)



바인드 쉘을 구해서 테스트해보았다.
1337 포트를 오픈하는 코드이다.



(바인드쉘 테스트)



실행!


(1337 오픈!)



하지만 이 방법에 문제가 있었다.
(아직 이 문제에 대한 의문은 해결되지 않았다...)
(바로 bof 공격 코드까지 파이썬으로 만든후 공격을 성공시켜서 1337 포트가 열리는 것까지 확인했다.



(포트 오픈)



그런데 이상한점이 있었다.
여기서 '아! 이제 열렸으니 접속을 해볼까?' 하고 접속을 시도하면 짤린다...

와이어샤크로 분석해보니 ack 요청을 보내자마자 서버에서 fin 을 날려 종료시킨다...
이유는 모르겠다. 방화벽때문인가??...
계속 이것저것 시도했지만 여전히 접속이 안되었다...

그리하여 방법을 바꾸어 리버스 쉘을 이용하기로 했다.
내가 포트를 오픈하고 서버에서 나에게 접속을 시도하게 하는 것이다.
만약 이때 짤리면 내 방화벽을 내리면 되기때문에 이 방법으로 전환했다.

shell 코드는 인터넷에서 구했다. 내 호스트 IP 주소와 5555 포트번호로 접속을 시도하는 리버스 쉘코드이다.
이 코드를 이용하여 익스플로잇을 만든 후 실행했다.



(exploit 코드)




(공격 모습)



이 때 나는 nc를 이용하여 5555 포트를 열고 기다리고 있었는데 연결이 성립되면서 쉘을 획득 할 수 있었다.



(공격 성공)



쉘 획득!

이로서.....!

BOF 원정대의 모든 문제를 클리어할 수 있었다.



(all clear!)


'WarGame > 500 Project' 카테고리의 다른 글

(38/500) Suninatas - Binary(10)  (0) 2017.06.27
(37/500) Suninatas - Binary(9)  (0) 2017.06.27
(35/500) Lord of the BOF - xavius  (0) 2017.06.25
(34/500) Lord of the BOF - nightmare  (0) 2017.06.23
(33/500) Lord of the BOF - succubus  (0) 2017.06.23


BOF 원정대의 Xavius를 잡아보자!

* Xavius 코드


(xavius.c)



xavius의 특징
1. ret 주소에 라이브러리 함수를 사용하지 못한다.
2. 0x08, 0xbf 로 시작하는 주소 또한 ret 주소에 넣을 수 없다.
3. 단.! fgets를 사용한다.

fgets 함수의 특징을 알고 있어 이 문제를 쉽게 풀 수 있었다.
바로 fgets 함수는 입력 버퍼가 있어 그 곳에 입력을 저장한 후 실제 스택 버퍼에 옮긴다.
우리의 입력이 어딘가에 또 저장이 되어있다는 말이다.

사실을 확인해보기위해 strace를 통해 실제 시스템콜과 사용되는 메모리 주소를 확인해보자.



(read 시스템콜)



아래 write() 시스템 콜이 보인다. 그리고 그 바로 위에 어딘가에서 read 해오고 있는 모습을 볼 수 있다.
바로 이곳이 우리가 생각했던 임시 버퍼라는 것을 예상해 볼 수 있다.

그렇다면 진위를 파악하기 위해 gdb를 통해 실제 메모리를 확인해보자!


(임시 버퍼)


우리의 예상대로 0x40015000 주소가 바로 fgets의 임시버퍼였다.

우리는 바로 이곳에 쉘코드를 올리고 이곳으로 eip를 떨굴것이다.
그렇다면 ret 주소에 이 주소를 넣어야한다. ret 주소에 이 주소가 들어갈 수 있는지 확인!


(ret 주소)


ret 주소에 해당 주소를 입력해도 괜찮았다.

이제 이 주소에 Nop코드와 쉘코드를 올려주고 ret 주소에 해당 영역의 주소를 넣어준다.

공격!


(공격!)



(공격 성공)


쉘을 획득 할 수 있었다. :)


BOF 원정대의 nightmare를 잡아보자!

* 소스코드


(nightmare.c)


nightmare 특징!
ret 주소에 strcpy를 써야한다는 점.
(이번 문제풀이는 엉뚱땅 삽질을 많이했다. 이 포스트에는 삽질의 과정이 그대로 있습니다. 빠른 해법이 궁금하다면 아래쪽부터!, 초반의 잘못된 판단?생각? 들도 그대로 과정대로 적었습니다.)

strcpy를 통해 쓸만한 영역에다가 system 주소와 /bin/sh 문자열을 구성하여 쉘을 획득하자!
먼저 strcpy 주소를 알아내보자!



(strcpy 주소)



이 주소가 맞는지 한번 체크!



(gdb 실행)



gdb로 실행을 해보니 leave까지 잘 넘어갔다.
그렇다는 것은 ret 주소에 알맞은 주소를 썻다는것!

자 이제 쓸만한 영역을 찾아볼까~


(쓸만한 영역)



스택영역에서 0xbffff714 주소가 눈에 띄였다. 0으로 덮여진 깨끗한 도화지

즉 나는 여기에다가 복사시킬 것이다.

나의 계획!
저 깨끗한 도화지에다가 버퍼를 복사한다. 버퍼에는 system과 인자 구성이 되어있다.
그 후 fake ebp로 0xbffff710 으로 fake ebp를 한다. 그렇다면 0xbffff714 에 있는 system 함수가 호출되게 하여 쉘을 획득하려는 것!

fake ebp를 이루기 위해 leave-ret 주소 찾기



(leave-ret 주소)



그런데 이런생각이 들었다. 스택의 버퍼 주소를 쓰면 스택의 주소는 약간의 오차가 있어서 맞추기가 귀찮다. 그러므로 고정적으로 내 버퍼를 저장해둔 공간이 없을까?
-> printf 로 출력을 하니 출력버퍼가 있을거 같긴하다. (실제로 다른 문제 풀때는 출력버퍼를 이용했었다.)

출력버퍼를 한참 찾다 못찾았지만.. ㅜ strcpy에 내가 적은듯한 것들이 있다? strcpy의 버퍼인가? 무튼 요골 쓰면 괜찮지 않을까?



(좋은것 발견?)



바로 0x400767ea 주소가 strcpy의 버퍼인듯 하다? (그런데 strcpy가 버퍼가 있나?)



(버퍼?)



자 이 주소를 쓰는 거야!



(gdb 실행)



공격 전 메모리를 확인해보자!



(어라?)



이건 뭐지?
-> 아..! 다시 소스코드를 보니 ret 주소 옆에 A로 4개를 덮는다.... (즉 fake ebp 못한다.)
+ 삽질 : strcpy에 버퍼가 어딨어.. ㅜㅜ

아까 본 것은 51... 41(A)가 아닌데.. 착각했다.. (.... )

결국 방향을 바꾸었다.
strcpy로 저 41414141을 덮어쓰자!
바로 system 함수와 + 인자구성으로
그러면 버퍼의 주소 확인하고!


(버퍼주소)



41414141 위치는 core 덤프 파일로 확인하겠다. 어짜피 바뀔거니? (그렇다면 버퍼위치도 core 덤프 파일로 찾지..! ㅎㅎ)

일단 공격


(공격)



덤프 파일로 버퍼부터 찾는다.!



(버퍼 찾기)



찾았다!

이제 41414141로 덮여쓰여지는 ret 다음 주소 찾기!



(41414141 위치)



찾았다!

이제 41414141을 내 system함수 + 인자구성으로 덮어쓴 뒤 system('/bin/sh') 을 실행한다.!

공격!


(공격 성공)


쉘을 획득하였다. :)


BOF 원정대의 succubus를 잡아보자!

* 소스코드


(succubus.c)



succubus의 main함수이다. 특징을 보면 ret주소에 DO라는 함수 주소가 적혀야한다는 점이다.

위에 보면 도 개 걸 윷 모 라는 함수들이 정의되어있다.




(도개걸윷모)



즉 도->개->걸->윷->모 를 차례대로 호출하고 마지막 모의 인자로 "/bin/sh"의 문자열을 전달 하면 쉘을 획득 할 수 있다.

각각의 함수들의 시작 주소를 찾았다.
DO : 0x80487ec 
GYE : 0x80487bc 
GUL : 0x804878c 
YUT : 0x804875c 
MO : 0x8048724

ret주소에 차례대로 넣어주고 마지막 MO의 인자로는 "/bin/sh"의 주소를 넣어주어야하는데 라이브러리 함수를 못쓰니 직접 넣어줄 것이다. 지금은 이 주소를 모르니 C로 채워넣고 뒤에 /bin/sh 주소를 넣어 메모리를 확인해보겠다.



(gdb 실행)




(메모리 상황)



0xbffffa78 주소에 /bin/sh 문자열이 들어가 있는 것을 확인 할 수 있다.

이제 C로 채웠던 부분에 이 문자열 주소를 넣고 공격을 해보자!



(공격 실패)



여기서 스택영역의 주소라 0x10바이트 간격으로 오차가 있다.
core 덤프파일을 확인하여 정확한 주소를 찾아보자.



(core 덤프파일)



파일을 보니 0xbffffa98 부터 /bin/sh 문자열이 들어가있는 것을 확인 할 수 있다.

문자열 주소에 0xbffffa98 주소를 입력하여 다시 공격!



(공격 성공)



쉘을 획득하였다. :)


BOF 원정대의 zombie_assassin 잡기!

* 소스코드

(zombie_assassin.c)



zombie_assassin 특징
-> strcpy가 아니라 strncpy이다.
그렇기에 딱 48바이트만 strcpy 해준다. 즉 ret 주소까지만 복사시켜주기 때문에
이전에 풀었던 방법 ret 슬레이딩을 사용할 수 없다. 또 ret주소에 스택영역주소, 라이브러리 영역 주소를 넣을 수 없다.

그렇기에 여기서는 fake ebp를 사용해서 쉘을 획득할 것이다. leave-ret을 연속으로 2번 실행되게 할 수 있다면 fake ebp를 구성할 수 있다.
처음 leave에서는 우리가 설정한 ebp를 가져가게 되고 그 다음 leave에서 esp가 ebp로 옮겨가는 것이다.

우리에게 필요한 주소인 leave-ret을 실행시켜주게하기 위하여 leave-ret 주소르 찾는다.




(leave-ret 주소)



그 후 fake ebp 할 주소를 찾는다. 0xbffffa7c로 fake ebp를 잡게 되면 두 번째 leave할 때 esp가 이쪽으로 넘어오게 될것이다. 버퍼에서 일부러 4바이트 작은 주소로 잡았다. 그렇게 되면 그 다음 ret 때 버퍼 주소부터 잡아가기 때문이다.




(fake ebp 할 주소)


그러면 버퍼 앞에 system 주소와 /bin/sh 문자열을 인자를 넘겨주면 된다.

gdb를 통해 계획한 대로 인자를 넘겨주고 메모리를 확인해보겠다.



(gdb 실행)


ebp를 확인하여 꺼내갈 ebp자리에 우리가 계획한 ebp가 잘 들어갔는지.
ret 주소에 leave-ret 주소가 잘 들어갔는지 체크한다.




(fake ebp)



fake ebp, leave-ret 주소 확인


(버퍼)



fake ebp된 메모리 주소를 확인해보면 버퍼에 system 주소와 /bin/sh 문자열 주소가 잘 들어간 것을 확인할 수 있다.

공격


(공격 실패)



당연히 실패할 줄 알았다.
바로
스택영역 주소는 0x10바이트 단위로 오차가 있을 수 있기 때문이다.
core 덤프파일을 확인하여 정확한 주소를 체크하자.



(core 덤프 파일)



0x10 바이트 차이가 있었다.
다시 공격



(공격 성공)


쉘을 획득하였다. :)

'WarGame > 500 Project' 카테고리의 다른 글

(34/500) Lord of the BOF - nightmare  (0) 2017.06.23
(33/500) Lord of the BOF - succubus  (0) 2017.06.23
(31/500) Lord of the BOF - assassin  (0) 2017.06.23
(30/500) Lord of the BOF - giant  (0) 2017.06.21
(29/500) Lord of the BOF - bugbear  (0) 2017.06.20


BOF 원정대의 Assassin을 잡아보자!

* 소스코드


(assassin.c)



assassin의 특징이다.
1. 버퍼 40바이트
2. ret주소에 스택주소 입력 불가.
3. ret주소에 라이브러리주소 입력 불가.
4. 버퍼 초기화

바로 전 문제까지 ret주소에 라이브러리 함수를 이용하여 쉘을 획득해왔다.
하지만 이제 라이브러리 함수를 사용하지 못한다??
-> 잘보면 ret주소만 체크하고 있다. 그러므로 우리는 ret주소 그 옆에 주소(4바이트 높은주소)에 넣고 인자를 구성하여 사용할 것이다.

그렇다면 문제는 어떻게 ret주소에 무엇을 넣어야 eip가 그 다음 4바이트를 꺼내갈까?
바로 ret 명령을 이용하는 것이다!

ret 명령은 pop eip 로 이루어져있다. main 함수의 ret 명령 때 ret주소에 적혀있는 주소를 꺼내어 그 곳의 명령을 실행한다. 즉 eip를 그 주소에 있는 것을 가져간다.
여기서 트릭을 쓰는 것이다. ret 주소에 ret명령어를 넣으면?
-> ret 명령이 일어날 때 ret명령의 주소를 가져가게 된다. 그러면 eip에는 ret 명령 주소가 들어가있고 ret명령을 실행시킬 준비가 되있다. 그러면서 pop 이기 때문에 esp가 증가하게 된다.(다음 4바이트를 가리키게 된다.) 여기서 ret 명령을 실행하게 되면 우리가 준비해둔 라이브러리 함수를 만나고 그 주소를 꺼내어 실행하게 되는 것이다.

이런 트릭을 이용해 ret 슬레이딩이라고도 한다. 여기서는 4바이트만 내려가 주는 용도로 사용하여 ret주소 검열을 우회하여 쉘을 획득할 것이다.

필요한 것
1. system 주소


(system 주소)



2. /bin/sh 문자열


(/bin/sh 주소)



3. ret 명령 주소


(ret 명령 주소)



필요한 주소들은 전부 구했다. 이제 gdb에서 메모리에 잘 들어갔는지 체크해보자.
(돌다리도 두들겨보라)


(gdb 실행)



(체크)



0x0804851e (ret명령)이 ret주소에 잘 들어갔고 그 뒤로 system 주소가 잘 들어간 것을 체크!

공격!


(공격 성공)



쉘을 획득하였다. :)



BOF 원정대의 giant를 잡아보자!

* 소스코드


(giant.c)


중간에 복잡해보이는 코드가 있는데 친절하게 주석으로 설명이 되어있다.
ret주소에 execve 함수 주소가 들어가있는지 체크하기 위한 부분이다. 그렇기에 ret 주소에 execve를 넣어 execve 함수를 사용해서 문제를 해결하라는 의도같다.

그렇다면 execve를 어떻게 써야하나 구성인자를 살펴보자!



(execve 함수)



execve 함수의 인자
1. 파일이름(실행할파일)
2. 인자 주소(파일이름 문자열의 주소)
3. Null 문자열

예를 들기위해 C언어로 표현하여 실행해 보겠다



(execve c 코드)



(실행화면)



위와 같이 인자를 넘겨주니 execve 함수가 잘 실행되었다.

자 이제 이대로 인자를 만들어주어야한다.



(ret 주소)



ret 주소는 0x400a9d48 (execve 함수 주소) 를 넣었다.
이제 이 뒤에는 더미(4바이트) 를 넣은 후 그 뒤부터 인자가 들어가게된다.

execve 함수로 실행할 파일은 /bin/sh이다. 이 문자열을 직접 써주어도 되지만 그렇게 되면 문자열 주소를 넘겨주는 두번째 인자를 구성할 때 어려워진다. 왜냐하면 두번째 인자는 포인터 배열이기 때문에 주소와 널문자(4바이트)로 이루어져야하기 때문이다.

그렇기에 이미 로딩된 라이브러리에서 /bin/sh 문자열을 찾아 사용할 것이다.
system 함수 근처에 /bin/sh 문자열이 존재한다는 것을 알고 있기에 간단히 c코드를 만들어 /bin/sh 문자열 위치를 찾아낼 것이다.




(/bin/sh 주소찾기)



(/bin/sh 주소)



직접 gdb를 열어 해당 주소를 검색해보자.



(/bin/sh)



해당 주소에 /bin/sh 문자열이 들어있는 것을 확인 했다.

이제 첫번째 인자로 우리가 찾은 주소를 넣을 것이다.
두번째 인자를 구성해야한다. 일단 지금까지 만든 것을 토대로 메모리를 확인해보자.

A*44 + execve함수주소 + A*4(더미) + "/bin/sh주소" + "/bin/sh주소가 적힌 포인터배열 주소" + NULL

포인터배열을 만들계획이다. 일단 포인터배열 주소를 C*4 로 대체하고 메모리를 확인해보자!



(gdb 실행)


두번째 인자를 만들어줄 위치를 살펴보니 적당한 위치가 나왔다.



(4바이트 NULL)


포인터배열이기 때문에 주소뒤에 Null(4바이트)가 나와야하는데 우리가 입력은 못한다. 그렇기에 이미 존재하는걸 이용해야하는데 0xbffffae8 에 널 4바이트가 있다. 그러므로 그 앞에 문자열 주소를 입력한 후 해당 위치를 두번째 인자로 넘겨줄 것이다.

세번째 인자 Null은 0xbffffae8을 넘겨줄 것이다. 해당 주소가 이미 Null이기 때문에



(포인터배열)



위와 같이 포인터 주소배열을 만들 수 있다.



(포인터 배열)


0xbffffad4 위치에 정확히 포인터 배열이 들어갔다.
이제 두번째 인자로는 0xbffffad4를 
세번째 인자로는 0xbffffad8을 넣어줄 것이다.

마지막으로 확인 해보자.



(최종 확인)



해당 인자에 알맞은 값이 들어갔는지 체크!

공격!
0x10 바이트 앞뒤로 왔다갔다 하면서 올바른 위치를 잡았다.



(공격 성공)



쉘 획득!



BOF 원정대의 bugbear를 잡아보자!

* 소스코드 분석



(bugbear.c)


소스코드를 보니 스택을 사용하지 못할 것 같다.
ret 주소에 bf로 시작하는 주소를 입력하면 빠져나오게 되있는 코드를 볼 수 있다.

그렇다면? 문제의 의도대로 RTL ( Return To Library ) 를 이용해보겠다.
내가 사용할 라이브러리 함수는 system 함수이다.

system 함수를 이용하여 shell을 실행시킬 것이다.
나의 계획은 
더미(44바이트) +  system주소 + 더미(4바이트) + system 주소 인자 + "/bin/sh"
이렇다.
맨 뒤 /bin/sh 문자열은 system 주소의 인자로 넘겨주기 위한 문자열이다. 이 위치의 주소를 알아내어 system 주소 인자 위치에 넣어줄 것이다.

먼저 system 주소의 위치를 파악한다.



(system 주소 확인)



자 이제 system 주소 인자의 위치인 /bin/sh 문자열의 시작위치를 찾아야한다. 일단 주소를 D 4개로 채워넣은 후 실행하여 확인해본다.



(주소 확인)


D 4개가 보이고 그 다음 부터 문자열이 시작된다.
저 주소는 바로 0xbffffaa8이다. 이 주소를 D 4개 넣었던 곳에 넣으면 된다.



(최종 확인)



문자열과 문자열 주소가 잘 들어간 것을 확인해 볼 수 있다.

실제에서는 0x10 바이트 차이가 날 수 있으므로 앞뒤로 왔다갔다하면 찾을 수 있다.



(공격 성공)



쉘 획득

'WarGame > 500 Project' 카테고리의 다른 글

(31/500) Lord of the BOF - assassin  (0) 2017.06.23
(30/500) Lord of the BOF - giant  (0) 2017.06.21
(28/500) Lord of the BOF - darkknight  (0) 2017.06.20
(27/500) Lord of the BOF - golem  (0) 2017.06.20
(26/500) Lord of the BOF - skeleton  (0) 2017.06.20


BOF 원정대의 Darkknight를 잡아보자!

* 소스코드 분석



(darkknight.c)


소스코드를 보니 return 문장이 없고 바로 problem_child 라는 함수를 호출하고 있다.
그리고 그 안에서 argv[1]을 strncpy를 하면서 1바이트 오버플로우를 내고 있다.

fake ebp를 이용해 문제를 해결할 수 있다.
어떤 상황에 처해져있는지 메모리를 확인해보자!

늘 그랬듯이 44더미와 D 4개를 입력해준다. (실제로는 40바이트에 1바이트 오버플로우가 나지만 하던데로 입력해보았다.)



(gdb로 실행)



실행 후 problem_child 함수안에 들어가서 leave 명령어 전의 메모리 상황을 살펴보았다.


(leave 명령어 전)


빨간 박스쳐있는 곳이 이전의 ebp가 저장되어있는 자리이다. 그런데 지금은 한 바이트가 오버플로우 되어서 41이 입력되어있다. leave 명령어가 수행되면 ebp에 저 0xbffffa41이 입력될 것이다.




(leave 명령어 후)


leave 명령어 후 ebp를 살펴보면 0xbffffa41이 입력되있는 것을 확인해 볼 수 있다.
그렇다면 여기서 ret명령이 끝나면?
-> 그 다음 원래 main 함수의 leave + ret 문장을 수행하게 된다.

여기서 leave하게 되면 저장되어있던 ebp에 esp가 옮겨지고 
그 위치의 값을 ebp에 저장시킨다.

leave 하기 직전에 ebp를 살펴보면 0xbffffa41 인 것을 확인 할 수 있다.



(0xbffffa41로 옮겨간 ebp)


이렇게 되면 그 후 leave + ret 명령 수행 후 0xbffffa45에 있는 값이 eip 에 들어가게 된다.

이 것을 이용해서 문제를 해결할 것이다.
우리의 버퍼의 주소 앞으로 ebp를 잡게 해야하므로 주소를 확인한다.




(버퍼 시작 앞 주소)


0xbffffaa0 이다. 이 주소를 넣으려면 맨 마지막에 a0을 입력해주면 된다.

확인해보자!



(0xbffffaa0으로 fake ebp)


ebp 자리를 확인해보자.




(ebp 자리)


이 전 저장된 ebp 주소 자리가 0xbffffaa0 으로 바뀐 것을 확인할수 있다.

바로 이 주소로 ebp가 자리잡게 될것이다.



(ebp 상태)


여기서 main함수의 leave 명령어를 수행하면 그 다음 주소인 0xbffffaa4 주소의 값을 eip에 입력하려 할 것이다.



(ret 전 상황)


여기서 0x41414141 을 꺼내가려는 모습을 확인 할 수 있다.

이 것들을 토대로 다시 생각해본다.



(입력인자 구성)


입력 인자 첫부분에 실행시킬 주소(eip에 넘어갈 주소)를 넣는다. 지금은 D 4개의 값으로 대체한다.
그 후 마지막은 a0으로 입력해준다.

ret 명령 전의 esp를 확인해보면 D 4개를 꺼내가려는 것을 확인할 수 있었으므로 바로 이 자리에 0x41414141 에 nop과 쉘코드가 들어갈 것이므로 0xbffffaa8 을 입력하면 되는 것이다.



(마지막 체크 메모리 상황)



gdb로 최종 공격 전 확인 모습이다.



(최종 확인)


최종 확인 결과 nop이 실행되고 그 다음 쉘코드가 실행 되는 것을 확인 할 수 있었다.

이 토대로 공격을 수행하였다. :)
실제로에서는 메모리에서 0x00000010 바이트씩 차이가 날수 있으므로 왔다갔다 해주면서 위치를 잡으면 된다.



(공격 성공)



쉘을 획득하였다. :)

'WarGame > 500 Project' 카테고리의 다른 글

(30/500) Lord of the BOF - giant  (0) 2017.06.21
(29/500) Lord of the BOF - bugbear  (0) 2017.06.20
(27/500) Lord of the BOF - golem  (0) 2017.06.20
(26/500) Lord of the BOF - skeleton  (0) 2017.06.20
(25/500) Lord of the BOF - vampire  (0) 2017.06.20

+ Recent posts