리모트 BOF이고, fgets로 입력받은 값을 temp에 저장하고, 그 값을 buffer에 strcpy하여 복사해준다.
그 후 sfp를 복원시켜줌.


전에 풀었던 문제와 리모트 빼고 다른게 없는 것 같아서 ret sled를 이용하여 공격해보았다.

| buf[264] | sfp[4] | &ret[4] * 3 | &execl | 
(그리고 미리 execl함수에 의해 실행되는 파일을 심볼릭 링크해야함.. 이부분은 생략.)

nc localhost 7777 로 해보았지만 별다른 반응이 없어서 hell_fire로 시도해 보았더니,
쉘은 따졌지만 권한상승은 안됨.. 왜그런지 잘모르겠다..

 

 

다른 방법으로 찾아서 해봐야겠다..

 

system함수 내부를 살펴보면 do_system함수를 호출한다.
또 do_system함수의 내부 코드를 보면 execve("/bin/sh", "sh –c 인자", 환경변수); 이렇게 수행된다.
이처럼 do_system함수도 명령어 실행을 위해 execve 함수를 호출하여 명령을 수행하는 것을 확인할 수 있다.

 

이러한 이유 때문에 system함수를 이용하여 "/bin/sh"의 주소를 찾을 수 있다.
-------------------------------------------------------

#include<stdio.h>
#include<string.h>

int main()
{

long shell=0x4203f2c0; // ex) system()주소

while(memcmp((void*)shell, "/bin/sh", 8)) shell++;

printf("%p \n", shell);

}

-------------------------------------------------------

 

아무튼 ret영역을 &(do_system+1124)로 덮어씌우면 된다.

 

 

 




다른 문제풀이로 풀어보겠습니다.

fgets함수는 임시버퍼를 사용하는 함수로써 그 부분을 이용하여 공격하겠습니다.
우선 자고 내일 쓰겠음..


| buf[264] | sfp | &mprotect | &shellcode | 인자 1 | 인자 2 | 인자 3 | nop + shellcode | 

이런식의 공격이 안되는 이유는 mprotect함수의 주소는 아스키아머로 인해 1바이트가 \x00인 주소를 갖는다.
그래서 strcpy함수의 특성으로 인해 ret영역 이후의 값들이 buffer에 제대로 복사되지 않는다.


 

[strcpy 특성]

strcpy 는 문자열 복사를 위한 함수로서 길이를 지정안하는 대신 source 문자열이 반드시 '\0' 으로 끝나야합니다.
source 에서 '\0'을 만나면 복사를 종료합니다('\0' 까지 복사됩니다)         



그러면 어떻게 해야할까??

fgets함수가 임시버퍼를 사용한다고 했으니까 거기는 mprotect의 주소에 \x00이 있건 말건 입력해준 모든 값들이 고스란히 있을 것이다.
buffer를 이용한 공격은 strcpy함수의 특성상 buffer에 제대로 복사가 되지 않으니까 갖다 버리고, fgets의 임시버퍼영역을 통해 공격해보겠습니다.
fake ebp를 이용하여 그 영역으로 완전 옮겨가버리면 된다.

우선 임시버퍼영역의 주소가 어디인지 확인해보자

보시면 0xf6ffe000 ~ f6fff000 까지 임시버퍼영역의 고정된 주소로 지정되어있다.



*TIP : gdb를 통해 제대로 들어갔는지 확인

(python -c 'print "A"*264+"BBBB"+"\x43\x43\x00\x43"+"CCCC"';cat) | (python -c 'print "r"';cat) | (python -c 'print "b* main+221"';cat) | gdb -q ./hell_fir3

이처럼 임시버퍼영역에서는 주소에 널바이트가 오더라도 입력해준 값 그대로를 고스란히 담고 있기 때문에 이곳으로 ebp,esp를
옮겨버려서 공격하면 된다.(buffer영역에 안되는 이유는 아까도 말했듯이 strcpy를 하게 되면 널바이트까지만 복사가 이뤄짐..)


임시버퍼영역으로 ebp,esp를 옮기려면 fake ebp 기법을 이용하여 옮길 수 있다.
랜덤스택이라고 해도 상대적인 ebp의 거리는 항상 같다.
예를 들어 설명하자면 메인함수에서 ebp의 위치와 함수호출로 인해 새로 지정된 ebp의 위치의 거리는 같다는 말이다.

이러한 점을 알기 때문에 main함수에서 leave명령이 수행되고 ebp가 가리키는 곳의 위치를 쉽게 구할 수 있다.
(그 거리는 88bytes만큼 차이남)
그럼 main함수에서 leave명령을 수행한 다음 ebp가 가리키는 곳의 값을 0xf6ffe16c로 바꾸고, main함수의 ret영역에 &leaveret으로
덮어씌워주게 되면 아래와 같이 수행된다.(여기서 0xf6ffe16c의 주소는 임시버퍼영역에 해당하는 주소)

0xf6ffe000(임시버퍼시작주소) + 16c(264 + 4 + 4 + 88 + 4) = 0xf6ffe16c

                  (  buf[264] + SFP[4] + &leaveret[4] + A*88[88] + 0xf6ffe16c[4]  )


| buf[264] | SFP | &leaveret | A*88 | 0xf6ffe16c | &leaveret | &mprotect | &shellcode | parameter1 | parameter2 | parameter3 | nop+shellcode |

           ebp           

<- 낮은 주소                                                                                                                                  높은 주소 ->




| buf[264] | SFP | &leaveret | A*88 | 0xf6ffe16c | &leaveret | &mprotect | &shellcode | parameter1 | parameter2 | parameter3 | nop+shellcode |

                  esp                 ebp

<- 낮은 주소                                                                                                                                  높은 주소 ->

main 함수에서 leave 명령이 수행 된 모습
ret 명령이 수행되면 아래와 같이 된다.



아래는 버퍼영역이다. strcpy함수로 &mprotect함수 주소 이후는 제대로 복사는 안되겠지만...

| buf[264] | SFP | &leaveret | A*88 | 0xf6ffe16c | &leaveret | &mprotect | &shellcode | parameter1 | parameter2 | parameter3 | nop+shellcode |

                                                     esp                  

<- 낮은 주소                                                                                                                                  높은 주소 ->

ret 명령을 수행하면 아래 노랑 네모박스의 모습이 된다.



| buf[264] | SFP | &leaveret | A*88 | 0xf6ffe16c | &leaveret | &mprotect | &shellcode | parameter1 | parameter2 | parameter3 | nop+shellcode |

                                                     ebp(0xf6ffe16c)

<- 낮은 주소                                                                                                                                  높은 주소 ->

위는 임시버퍼영역의 구조이다. ebp가 임시버퍼 영역을 가리킨다.




| buf[264] | SFP | &leaveret | A*88 | 0xf6ffe16c | &leaveret | &mprotect | &shellcode | parameter1 | parameter2 | parameter3 | nop+shellcode |

                                                                   esp

<- 낮은 주소                                                                                                                                  높은 주소 ->

ebp는 어딘가 가리키고 ret명령에 의해 mprotect함수가 수행될 것이다.


payload



아 솔직히 이거 설명하기가 너무힘들다... 차라리 페이로드보고 짜맞추면서 보시면 편하실듯.. 설명포기 ㅠㅠ




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

[Fedora4] dark_stone -> cruel  (0) 2015.11.28
[Fedora3] evil_wizard -> dark_stone  (0) 2015.11.25
[Fedora3] hell_fire -> evil_wizard  (0) 2015.11.23
[Fedora3] iron_golem -> dark_eyes  (0) 2015.11.20
[Fedora3] gate -> iron_golem  (0) 2015.11.19

 



저번 문제와는 달리 fake ebp와 같은 공격을 막기 위해 strcpy를 수행한 후 sfp를 다시 복원시켜주는
프로그램입니다.

[아래 그림과 같이 참조]
그래서 생각한 것이 ret영역을 코드영역에 있는 leave 명령어의 주소로 넣어서 풀면 될 것 같은 느낌이 들어서 봤더니
sfp가 랜덤스택이기 때문에 무작위로 바뀌게 됩니다.
그래서 전에 풀었던 문제처럼 ret영역 이후 부분을 [got영역의주소-8]와 [execl+3]의 주소를 쌍으로 엄청 많이 집어넣고
while문으로 반복실행시키면 언젠간 맨 처음에 스택에 껴있는 sfp가 [got영역의 주소-8]값과 일치하게 되지 않을까 하고 생각했지만
execl의 주소는 아스키아머가 걸려있기 때문에 못하게 된다…

 

 

어쩌다 발견했는데 restore된 sfp값은 buf의 시작주소와 항상 360차이가 난다.
즉 buf의 시작주소가 0xfef88bb0이면 sfp는 0xfef88d18이라서 두 값의 차는360이 된다.

 

이 점을 힌트로 하여 payload를 작성하면
buf[264] + 더미값(sfp) + &leave + "A"*88 + &(got-8) + &(execl+3)
(여기서 "A"*88을 하는 이유는 buf의 시작주소와 sfp의 차이는 360이기 때문에 그 차이를 맞춰주기 위해서.)


./dark_eyes `python -c 'print "A"*264+"BBBB"+"\xb8\x84\x04\x08"+"A"*88+"\x88\x96\x04\x08"+"\x23\x57\x7a"'`

그리고 실행될 파일명을 심볼릭 링크해야함. 그 부분은 전에 풀었던거 ㄱㄱ

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

[Fedora4] dark_stone -> cruel  (0) 2015.11.28
[Fedora3] evil_wizard -> dark_stone  (0) 2015.11.25
[Fedora3] hell_fire -> evil_wizard  (0) 2015.11.23
[Fedora3] dark_eyes -> hell_fire  (0) 2015.11.22
[Fedora3] gate -> iron_golem  (0) 2015.11.19

 

 

[페도라3의 환경]

 

 


스택 영역을 보면 실행권한이 없습니다.
페도라3 환경처럼 스택에 쉘코드를 올리고 실행시키는 공격은 통하지 않습니다.
그렇다면 음… rtl 나 하면되려나?

 

우선 리턴 주소가 어디인지 확인하겠습니다.



보시면 264bytes 만큼 버퍼 공간을 확보하였습니다.
이는 8bytes 더미가 껴있기 때문입니다.

 

 

대충 리턴주소의 위치를 알아냈습니다.

 

r `python –c 'print "A"*268 + [system함수 주소] + [더미4bytes] + [/bin/sh]


system함수의 주소를 구하겠습니다.

그 다음은 /bin/sh의 주소를 구하겠습니다.

 

r `python –c 'print "A"*268 + \xc0\x07\x75\x00+ "AAAA" + "\x03\x36\x83\x00"'`

음.. 리턴영역에는 00은 아예 쓰여지질 않네요. 즉, 3바이트(\xc0\x07\x75)쓰이고 1바이트는 \x41로 채워져서 다른공격을
생각해봐야겠습니다. 문제 힌트로 fake ebp인데 나와있는거 말고 다른거로 풀고싶은데..음

 

일단 내일 발표준비해야하니까… fake ebp로 풀어봐야겠습니다.

예전에 fake ebp 문제 풀었던 적이 있었는데 그때는 buffer주소로 ebp를 바꿔서 쉘코드를 실행하게 하는 문제였었는데
자꾸 그 문제에 대한 고정관념 때문에 결국 답 봤음..

 


대충 간단히 설명하자면, 함수가 호출될 때 호출 된 함수는 ebp를 기준으로 인자를 참조합니다. (ebp+8, ebp+c 이런식으로)
여기에다가 ret영역을 execl함수의 주소로 덮어씌우는데, 조건이 하나 있습니다..
어떤 조건인가 하면 지금 공격할 방법이 fake ebp이기 때문에 ebp가 변경되지 않는 선에서 ret영역을 덮어 씌워줘야합니다.
무슨 말인가 하면, 함수가 호출되면 프롤로그를 수행합니다.(push ebp, mov ebp esp)
이러한 프롤로그 동작들은 ebp값을 변경시키기 때문에 프롤로그가 끝나는 주소를 ret영역에 덮어씌워줘야 합니다.
그리고 sfp를 변경시켜줄 것인데, 현재 랜덤스택이기 때문에 고정된 값을 지닌 곳을 ebp로 변경시켜 주어야합니다.
그 부분은 got영역으로 할 것인데 한번 살펴보도록 하겠습니다.

 


0x08049618이 got 영역이다.

 

이 정도만 살펴보고 다음으로 execl함수에 대해 알아볼 것인데, 이 함수는
execl(실행파일, argv,…,NULL); 이런식으로 인자 마지막에 NULL이 와야함.
이 함수도 ebp+8로 첫번째 인자를 참조하고 ebp+c, ebp+10… 이런식으로 인자를 참조합니다.

그러면 sfp를 got영역의 임의의 주소로 변경하게 되면 위와 같은 방식에 의해 첫번째 인자는
ebp+8을 참조하게 됩니다. 그러면서 마지막 인자가 NULL이 오는 조건을 만족시키는 주소를 지정하게 된다면..
음.. 그림을 보면서 하도록 하겠습니다.


sfp를 0x08049610으로 덮어씌우면 함수가 종료될 때 leave명령어에 의해 ebp값이 0x08049610으로 이동한다.
그 후 ret영역에 execl+3주소로 점프를 하게 되고, execl함수는 인자를 참조하기위해 ebp+8,ebp+c….을 하게 된다.
그러면 첫번째 인자인 실행파일은 어떤 값이 있을지 살펴보도록 하겠습니다.

 


"\001"이라는 실행파일명이 되겠습니다. 그러면 execl함수에 의해 "\001"을 실행시켰을 때 

쉘이 따지면 되겠습니다.
그렇게 하려면 심볼릭 링크를 통해서 해결하면 되겠습니다.





아참 execl함수 주소는 gdb에서 print execl 하면 됩니다.
안될 경우는 bp걸고 실행 고고~~

blood on the fedora


끝!

자면서 써서 횡설수설합니다ㅋㅋ

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

[Fedora4] dark_stone -> cruel  (0) 2015.11.28
[Fedora3] evil_wizard -> dark_stone  (0) 2015.11.25
[Fedora3] hell_fire -> evil_wizard  (0) 2015.11.23
[Fedora3] dark_eyes -> hell_fire  (0) 2015.11.22
[Fedora3] iron_golem -> dark_eyes  (0) 2015.11.20

+ Recent posts