LOB_번외.bash2의 함정.

해킹/LOB 2016. 1. 29. 20:00

http://satanel001.tistory.com/98

위 포스팅의 darkknight->bugbear를 풀면서 나타났던 문제다.


결론부터 얘기하자면 bash2를 실행시킨 뒤 그 폴더에서 바로 공격을 했을때와 cd 명령어를 한번이라도 실행했을 때 주소에 차이가 나게된다.



1.cd를 한번도 안하고 tmp 폴더에서 bash2를 키고 공격했을 때 /home/darkknight/tmp/bugbear 코어 파일의 buffer 주소:0xbffffa90





2.cd ..을 해서 /home/darkknight/bugbear(원본)공격을 시도한 후 다시 cd tmp로 돌아왔을 때 /home/darkknight/tmp/bugbear(사본) 코어파일의 buffer 주소: 0xbffffa70






이런식으로 같은 파일인데도 불구하고 bash2를 실행시키고 즉시 공격했을 때와 cd..으로 원본 공격을 시도하고 cd tmp로 돌아왔을 때 주소에 차이가 생긴다..

심지 이부분에서 더 헤맸던 이유는 system 함수가 실행되면서 buffer 부분을 덮어버려 core파일 분석도 어려웠기 때문인데...

결론은 cd 명령어를 한번이라도 실행한 후에는 buffer의 주소가 바뀐다.



원인은 이거였다. bash를 처음 실행하고는 export 했을때 OLDPWD라는 환경변수가 없지만 cd ..으로 내려갔다가 돌아왔을 때는 캡쳐에 보이는것 처럼 OLDPWD라는 환경변수가 생겨났다.

저 환경변수의 길이만큼 스택이 밀려났기 때문에 주소에 차이가 생겼던것...


그리고 이상태에서 주소를 구한 뒤에 cd ..으로 아래로 내려가면

PWD="/home/darkknight/tmp"

OLDPWD="/home/darkknight"

에서


PWD="/home/darkknight"

OLDPWD="/home/darkknight/tmp"

이렇게 서로 위치만 바뀌기 때문에 원본파일에서도 buffer의 주소가 같아진다.



이렇게 aslr이 걸려있지 않은 환경에서 주소 오차의 주요 원인은 PWD와 OLDPWD이다.

혹시 주소 오차가 나는데 분석이 불가능한 상태라면 이부분을 체크해보자.



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

LOB_15.giant->assassin  (0) 2016.01.31
LOB_14.bugbear->giant  (0) 2016.01.31
LOB_13.darkknight->bugbear  (0) 2016.01.29
LOB_12.golem->darkknight  (0) 2016.01.28
LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기  (0) 2016.01.27
Tags
Social

LOB_13.darkknight->bugbear

해킹/LOB 2016. 1. 29. 19:16


이제 스텍으로 리턴할 수 없어졌다.

스텍이 나를 배신했단다..ㅎㅎ

윗쪽에 힌트를 보니 RTL이라고 써져있다 Return To Library 즉 라이브러리로 리턴하는 문제이다.


리턴주소를 변조할수는 있되 \xbf가 첫바이트로 들어가서는 안되니 0x40으로 시작하는 라이브러리 영역으로 점프를 하면 된다.

그중에서도 나는 쉘을 실행시키고 싶으니 system함수로 점프해서 인자로 "/bin/sh"를 전달해주면 되겠다.


그러기위해서는 system 함수의 주소와 "/bin/sh"의 주소가 필요하겠다.

"/bin/sh"를 스텍에 넣어주는 방법도 생각했으나 뒤에 널바이트가 필요하다. 페이로드의 맨 뒤에 널과 함께 넣어줘도 될것 같기는 하지만 더 나은 방법이 있어서 패스했다.





이런식으로 라이브러리를 로딩시키기 위해 프로그램을 실행시킨 뒤

p system을 해서 system 함수의 주소를 찾았다.

그리고 그 뒷주소를 검색해보니 저런식으로 얼마 지나지 않아 /bin/sh라는 문자열의 주소가 있는것을 볼 수 있었다.

라이브러리에 저렇게 편리하게 써먹을 수 있는 문자열이 박혀잇는 이유는 system 함수가 /bin/sh -c 명령어 이런식으로 실행되기 때문이란다. 즉 언제나 저 위치에 "/bin/sh"라는 문자열이 박혀있을 수밖에 없다.


아무튼 그렇게 해서 찾은 주소는

system 함수의 주소: 0x40058ae0

"/bin/sh"의 주소:0x400fbff9


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

에... 여기서 문제를 간단하게 풀려면 "a"*44+"\x40058ae0"+"bbbb"+"\x400fbff9" 이런식으로 페이로드를 작성하면 된다.

이렇게 하면 프로그램에서 40058ae0으로 리턴한 다음 system 함수의 프롤로그 과정에서 ebp가 "a"*44가 끝나는 부분으로 맞춰진다.

그리고 거기서 8바이트 뒤가 인자를 전달받는 부분이므로 \x400fbff9가 인자로 들어가서 쉘을 실행시켜줄 것이다.

이게 사실 정답이고 가장 합리적으로 이 문제를 푸는 방법이다. 페이로드까지 작성하자면

./bugbear `python -c 'print "a"*44+"\xe0\x8a\x05\x40"+"bbbb"+"\xf9\xbf\x0f\x40"'`

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


음 하지만 나는 fake ebp도 연습할겸 리턴주소 뒷부분(bbbb~)을 채우지 않고 풀어봤다. 아마 나중에 버퍼길이 제한이 있는 문제가 나오면 요긴하게 써먹을 수 있을 것이다.

fake ebp는 함수가 실행될때 ebp 주소를 착각하도록 하는 방식이다.

전에도 다뤘지만 SFP에 들어있는 내용이 leave ret 하면서 ebp로 들어가게 된다.

보통은 이렇게 SFP만 바꿔주면 되지만 0x40058ae0같이 함수의 첫부분으로 이동하게 되면 함수의 프롤로그(push ebp, mov ebp, esp)가 실행되면서 ebp가 esp를 기준으로 다시 맞춰져버린다.

그렇기 때문에 여기서는 프롤로그 3바이트를 뛰어넘어 0x40058ae3으로 리턴할 것이다.

그때 ebp가 가르키는값 +8 부분에 "/bin/sh"의 주소인 0x400fbff9가 들어있으면 되겠다.

즉 스택안에 0x400fbff9라는 값을 집어넣어주고 SFP를 저 값이 들어있는 주소 -8로 조작해주면 된다.




gdb에서 일단 대충 집어넣고 실행시켰다. 블록지정한 0x62626262가 /bin/sh의 주소가 들어갈 부분, 0x63636363과 0x64646464가 각각 SFP와 리턴이 들어갈 부분이다.

어차피 gdb에서 실행했을때와 주소가 다를게 뻔하므로 나와서 다시 실행시킨 뒤 core 파일을 분석해서 정확한 주소를 알아보는게 낫겠다.



똑같이 실행을 시켜준후에 코어파일을 보자.




방금전 buffer가 시작되었던 주소 근처를 뒤져보니 역시나 약간 밀린채로 들어있다.


이제 저 0x62626262부분에 "/bin/sh"가 들어있는 주소인 0x400fbff9를 넣어주고 

SFP에는 0x62626262의 주소 -8인 0xbffffa8c를 넣어준다.

마지막으로 리턴주소는 system함수의 주소 +3(프롤로그 생략) 부분인 0x40058ae3을 넣어주면 된다.


그러면 system함수는 fake ebp인 0xbffffa8c의 8바이트 뒷쪽에서 문자열을 찾을것이고 그부분에 0x400fbff9가 들어있으니 "/bin/sh"가 전달될 것이다.


이제 이 시나리오에 맞게 페이로드를 구성하면

./bugbear `python -c 'print "a"*36+"\xf9\xbf\x0f\x40"+"\x8c\xfa\xff\xbf"+"\xe3\x8a\x05\x40"'`

이렇게 되겠다. 시도해보자.




성공이다.

끝- 하고싶지만 RTL에 들어가면서 \x90을 사용했던 스텍 리턴에 비해 정확한 주소를 요구하게 되면서... bash2와 관련된 예상하지 못했던 심각한 삽질을 요하는 문제가 생겼었다. 주소가 계속 바뀌고 되던 페이로드가 안되는 현상이 있다면 다음 포스팅을 참고하자.

http://satanel001.tistory.com/99

끝-


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

LOB_14.bugbear->giant  (0) 2016.01.31
LOB_번외.bash2의 함정.  (0) 2016.01.29
LOB_12.golem->darkknight  (0) 2016.01.28
LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기  (0) 2016.01.27
LOB_11.skeleton->golem  (0) 2016.01.27
Tags
Social

LOB_12.golem->darkknight

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


음.. 드디어 리턴주소 자체를 덮을 수 없게 되었다.

main에서 problem_child라는 함수를 호출하여 40바이트 버퍼에 41바이트를 strncpy하여 1바이트만 덮도록 되어있다.

즉 problem_child의 SFP, 그중에서도 마지막 1바이트만 덮을 수 있다.



http://satanel001.tistory.com/59

전에 fake ebp관련 공부하면서 함수의 프롤로그와 에필로그에 대해서 공부한 내용이다.

이부분을 어느정도 숙지하고 있어서 이 문제를 해결하는데 그렇게 애를 먹지는 않았다.

모르고있었다면 정말 막막했을듯...



스택에서 이 SFP라는 녀석은 항상 ebp가 가르키는 주소에 들어있는데 바로 뒤 4바이트에 리턴 주소가 들어있다.

둘은 용도도 유사하다. 리턴 함수가 끝나고 돌아갈 코드영역의 주소인것 처럼 SFP는 함수가 끝나고 돌아갈 이전 함수의 ebp를 가지고 있다.

자세한건 위 포스팅을 참고하고.... 이 배경지식을 바탕으로 공격 계획을 짜보면.


1.problem_child의 SFP를 변조한다.

2.이 SFP는 problem_child의 에필로그 과정을 거쳐 함수 main의 ebp로 사용된다.

3.main은 이 조작된 ebp의 다음영역 즉 ebp+4부분을 리턴으로 인식해서 점프할 것이다.

4.그러므로 스텍 어딘가에 쉘코드와 그 시작주소를 넣어주고

5.시작주소 -4부분으로 problem_child의 SFP를 변조해주면 되겠다.



이런 계획을 바탕으로 동적 디버깅을 해보자.






입력값은 a 4자리와 마지막 41번째의 c 한자리, 가운데는 전부 b로 채워줬다.

블록지정한 부분이 SFP 부분인데 보이는것처럼 한바이트가 0x63('c')로 덮혀있다.

이제 할것은 저 a로 덮인 4자리에 리턴주소를 넣어주고 그 앞 4바이트인 0xbffffa80으로 main의 ebp를 바꿔줄 것이다.

그러기 위해선 블록지정한 SFP의 0x63한바이트를 0x80으로 바꿔주면 되겠다.

a에 들어갈 리턴주소는 0x62('b')가 시작되는 부분으로 넣어주면 main이 끝나며 b로 덮힌 영역을 실행할 것이다.

이부분에 쉘코드를 넣어주면 된다.

최종적인 페이로드는



./darkknight `python -c 'print "\x88\xfa\xff\xbf"+"\x90"*11+"\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"+"\x80"'`

이렇게 된다. 시도해보자.



성공했다.

코드를 보니 이런형태의 공격을 FPO라고 하는 모양이다.

끝-


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

LOB_번외.bash2의 함정.  (0) 2016.01.29
LOB_13.darkknight->bugbear  (0) 2016.01.29
LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기  (0) 2016.01.27
LOB_11.skeleton->golem  (0) 2016.01.27
LOB_10.vampire->skeleton  (0) 2016.01.22
Tags
Social

티스토리 페이징을 글목록에 넣는 문제 해결...

프로젝트/블로그 2016. 1. 27. 20:29

http://satanel001.tistory.com/74 

여기서 페이징을 글목록에 넣는 방법을 소개했었는데...

결국 서버에 쿼리를 넣지 못하는 상황에서 자바스크립트의 한계를 마주쳐서 <1,2,3,4,5,...7> 이런식으로 되어있는 페이징에서 <버튼과 >버튼만 따와서 

prev next 버튼으로 만들어줬었다.

당시 나름 머리를 썼다고 좋다고 포스팅을 올렸었는데... 훨씬더 간단한 방법을 소개한다.





먼저 본문내용이 끝나고 </body>태그가 나오기 전 부분에 이런 스크립트들을 주가한다.

첫줄은 j쿼리를 로드시켜주는 내용이고 두번째 줄은 j쿼리를 이용해서 paging이라는 아이디를 가지는 태그를 paging_clone이라는 id를 가지는 태그에 복사하는 내용이다.




그리고 글목록을 표시하는 <s_list>태그 안에 </section>이 나오기 전에 하이라이트된 부분처럼 paging_clone이라는 아이디를 가진 <div>태그를 하나 삽입해주면 된다.






결과는 이런식으로 깔끔하게 성공.... 그전에 나의 삽질은 무엇을 위하여.... 허허ㅋㅋㅋ

역시 사람은 배워야하는듯.

끝-

Tags
Social

LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기

해킹/LOB 2016. 1. 27. 19:54

LD_PRELOAD에 대해서 공부하면서 알게된 사실인데 my-pass파일은 매우 취약하다.

이 프로그램은 geteuid를 해서 사용자의 euid에 맞는 패스워드를 출력해준다.

그런데 LD_PRELOAD라는 환경변수는 특정한 함수를 미리 등록해 둘 수 있다.

그 함수와 같은 이름의 함수를 나중에 libc에서 만나더라도 LD_PRELOAD에 있는 함수를 우선적으로 사용한다.

즉 geteuid가 원하는 단계의 uid를 리턴하도록 LD_PRELOAD를 사용해서 조작할 수 있다.

그러면 my-pass는 조작된 geteuid의 결과에 따라 다른 아이디의 비밀번호를 뱉어낼 것이다.





먼저 gate로 로그인해서 my-pass를 읽어봤다. 500~ 520까지가 LOB의 각 단계를 나타내는 uid들이다.






이런식으로 getuid라는 함수를 단순히 520을 뱉도록 정의하는 geteuid.c 파일을 만들었다.






gcc -o geteuid -shared -fPIC geteuid.c

이런식으로 LD_PRELOAD에 등록할 수 있도록 컴파일을 해준뒤 등록하고 my-pass를 실행시키니

geteuid함수가 520이라는 값을 돌려줘서 my-pass가 최종 비밀번호인 got the life를 뱉는것을 확인했다.





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

LOB_13.darkknight->bugbear  (0) 2016.01.29
LOB_12.golem->darkknight  (0) 2016.01.28
LOB_11.skeleton->golem  (0) 2016.01.27
LOB_10.vampire->skeleton  (0) 2016.01.22
LOB_9.troll->vampire  (0) 2016.01.22
Tags
Social

LOB_11.skeleton->golem

해킹/LOB 2016. 1. 27. 19:32


golem.c의 내용인데 이제 buffer변수로부터 그 위쪽의 스텍을 전부 지워버린다.

메모리를 샅샅히 뒤져봤지만 더이상 입력값이 남아있을만한 공간이 없다.

결론부터 얘기하자면 이 문제는 LD_PRELOAD라는 환경변수를 이용해서 풀었다.


이 환경변수에 파일을 등록해주면 bash에서 프로그램 실행시 해당 파일을 먼저 라이브러리에 로딩해준다.

그리고 libc와 같은 이름의 함수가 있다고 해도 이 파일이 우선순위를 가진다.

쉽게말해서 golem 프로그램에서 사용하는 printf같은 함수를 등록해서 전혀 다른 기능을 하게끔 바꿔버릴 수도 있는 것이다.

printf의 기능을

void printf(){

setreuid(geteuid(), geteuid());

execve("/bin/sh", NULL, NULL);

}

이런식으로 바꿔줄 수도 있는 것이다.


하지만 안타깝게도 setuid가 걸린 프로그램에서는 제대로 동작하지 않는다.

그렇다고 완전히 무시되는 것은 아니고 파일명은 올라가게된다.

LD_PRELOAD에 이름이 쉘코드인 파일을 올려놓으면 프로그램이 실행되면서 어딘가에 쉘코드가 적재될 것이다.

그 주소가 buffer변수의 주소보다 낮은 주소에 올라간다면 stack destroyer의 영향을 받지 않아서 쉘코드를 실행시킬 수 있을 것이다.

그럼 우선 이름이 쉘코드인 라이브러리 파일을 만들어주자.




위와같이 gcc -shared -fPIC 옵션을 사용하면 LD_PRELOAD에 올라갈 파일을 만들어줄 수 있다.

어차피 setuid가 걸린 golem 프로그램에서는 라이브러리가 제대로 실행되지 않기 때문에 oxqo.c의 내용 자체는 별로 중요하지 않다. 이름을 쉘코드로 만들어서 메모리 어딘가에 올리는 것이 목적이다.

주의할점은 "\x2f"가 들어가지 않은 쉘코드를 사용했다는 점이다. 전처럼 디렉토리를 만들어서 해도 되지만 그냥 다양항 방식으로 해보기 위해 48바이트짜리 2f가 없는 쉘코드를 사용했다.

파일을 만들어준 다음 LD_PRELOAD 환경변수에 등록해줬다.

이제 원본 golem프로그램을 복사해와서 동적분석을 통해 쉘코드가 어디에 올라가는지 살펴보자.




main의 프롤로그가 끝나고 나서 살펴보니 ebp의 주소가 0xbffffaa8이다.

저부분을 기준으로 0xbfffffff부분까지 뒷쪽은 전부 memset되어 버릴테니 저것보다 낮은 주소를 검색해보자.





gdb 버전이 높다면 find 명령어를 사용해도 되지만..  사용할수 없을 경우 이런식으로 변수를 이용해서 검색할 수 있다.

ebp주소부터 1씩 빼가면서 쉘코드의 앞부분과 일치하는지 살펴본 결과 0xbffff68a부분에 쉘코드가 로드된 것을 볼 수 있다.

복사본 golem에서 저주소로 리턴을 주고 공격하자 segmetationfalt가 뜬다. 아마 gdb에서 실행될때와 주소차이가 좀 있는듯.




core파일을 분석해서 정확한 주소를 알아냈다. 0xbffff64a

찾는방법은 위와 동일하게 메모리를 가르키는 변수를 하나 주고 감소시키면서 찾았다.




성공했다.

자세히 보면 tmp 폴더에서 ../golem으로 원본파일을 실행시킨 것이 보이는데 LD_PRELOAD=./쉘코드 이런식으로 입력을 해줘서 원본이 있는 폴더에서 실행시키자 로드할 파일을 못찾는 사태가 발생했다. 원래부터 LD_PRELOAD에 전체경로를 입력했으면 이렇게 안해도 되었으나... 포스팅의 완성도가 조금 떨어진다는것 빼고는 별 다를점은 없으므로 패스

끝-

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

LOB_12.golem->darkknight  (0) 2016.01.28
LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기  (0) 2016.01.27
LOB_10.vampire->skeleton  (0) 2016.01.22
LOB_9.troll->vampire  (0) 2016.01.22
LOB_8.orge->troll  (0) 2016.01.22
Tags
Social

가짜 수신메세지 어플리케이션을 만들었다...

프로젝트/블로그 2016. 1. 23. 23:20

처음하는 안드로이드 어플 제작인데도 생각보다 쉽게쉽게 만들어졌다.

첫 안드로이드 어플을 제작했다는 뿌듯함과 그 첫 어플리케이션이 이런거라는 자괴감이 동시에 들지만... 일단은 공부한것이므로 버그좀 더 잡고 밑에 메세지 버튼도 좀 없앤다음에 코드에 대해서 포스팅을 해볼 생각이다.


Tags
Social

LOB_10.vampire->skeleton

해킹/LOB 2016. 1. 22. 23:47


드디어 모든 argv를 다 memset해버렸다..

이것참 이제 어디에 쉘코드가 들어갈수 있을까 한참을 고민하다 찾아본 결과 argv[0] 이외에도 프로그램의 경로, 이름이 스텍 어딘가에 저장된다고 한다.

그럼 우선 전처럼 쉘코드를 경로로 가지는 심볼릭 링크를 만들어주자.



이렇게 해서 경로가 쉘코드인 심볼릭 링크를 만들었다. 자세한 설명은 http://satanel001.tistory.com/89 참조

gdb로 분석해보자.





어차피 메모리상 어디에 있는지 모르니 굳이 실행시키며 볼 필요 없이 main 시작부분에 bp를 걸고 쉘코드를 찾아봐야한다.

gdb로 메모리에서 특정 값을 검색하는 방법이 있다.




이렇게 하면 된다. find명령어를 제공하는 gdb도 있는 모양인데 잘 모르겠고... 나는 보통 이렇게 해왔다.

먼저 첫번째줄에서 x라는 변수에 0xbfff0000이라는 값을 집어넣고(이것보다 더 낮은주소에 있을리는 없다)

x의 주소를 증가시키면서 해당주소의 값이 쉘코드의 첫부분인 0x31b0c031과 일치할때까지 while문이 도는 방식이다.


그래서 쉘코드의 위치를 찾긴 했는데... 밑에 0x61이 잔뜩 있는걸 보니 여기는 argv[0]부분이다. 나중에 memset당할 부분이므로 사용할 수 없다. 아직 프로그램을 끝까지 실행하지 않아서 남아있는 것 뿐이다.




x의 초기값을 argv 뒷부분으로 잡아주고 다시 검색하니 0xbfffffd2부분에 정말로 쉘코드(파일명)가 들어있는걸 확인했다!!

스텍의 최대범위인 0xbfffffff에서 딱 4바이트의 null만 남겨두고 채워진걸 보니 항상 스텍의 최상단에 위치하는 모양이다.

이제 심볼릭링크를 원본파일에 걸어주고 0xbfffffd2를 리턴값으로 덮어주면 된다.





익스플로잇에 성공했다. LOB 절반 클리어... 이제부터는 풀어본적 없는 문제들이다. 차근차근 해보자.

끝-

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

LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기  (0) 2016.01.27
LOB_11.skeleton->golem  (0) 2016.01.27
LOB_9.troll->vampire  (0) 2016.01.22
LOB_8.orge->troll  (0) 2016.01.22
LOB_7.darkelf->orge  (0) 2016.01.21
Tags
Social