zj3t

email: euntaejang@gmail.com

Latest Posts

FTZ-level16

By 오후 10:01 ,

level16은 코드만 보면 조금 어렵게 느낄 수 있겠지만 레벨 15보다도 훨훨훨씬 쉬었습니다.


풀이 하겠씁니다~



#include <stdio.h>
 
void shell() {
  setreuid(3097,3097);
  system("/bin/sh");
}
 
void printit() {
  printf("Hello there!\n");
}
 
main()
{ int crap;
  void (*call)()=printit;
  char buf[20];
  fgets(buf,48,stdin);
  call();
}   

이런 코드입니다. 많이 긴가민가 하셨을 부분이 아마도 void (*call)()=printit; 부분이라고 생각 됩니다.

void (*call)()=printit; 부분은 C언어에서 함수 포인터라고 합니다.

함수포인터란 말 그대로 함수를 가리키는 포인터 입니다. 함수도 다른 변수들처럼 메모리에 저장이 되기 때문에 시작주소가 존재하고 그럼으로써 시작주소를 가리킬 수 있게 되는 것 입니다.

원형으로는

리턴타입 *변수명(인자)=함수의시작주소

그렇다면 저 코드를 보자면 | buf |dummy| call |dummy| crap | 과 같은 구조로 스택이 되어있습니다.
지금까지 문제를 푸신분들은 감이 오셨을 거에요 buf에서 입력을 받아 buf[20]을 채우고 dummy까지를 채운뒤 call변수의 값으로 shell()함수의 주소를 넣어주면 됩니다.

그럼 어떻게 shell함수의 시작주소를 알 수가 있을까요??

이렇게 gdb를 이용해서 함수의 시작주소를 찾을 수 있습니다. 

리눅스에서는 objdump라는 명령이 존재합니다. 이 명령으로 시작 주소를 찾으신 분들도 계셨습니다.


시작 주소는 모두 찾았습니다. 이제 해야할 건 공격코드를 만드는 것입니다. 
그러기 위해서는 dummy의 크기를 알아야하는데 노가다를 하기 싫어 약간의 실험(?)을 해보았습니다.


리버싱을 해서 그런지 어셈블리어에서 함수가 호출될 때 인자가 어떤 방식으로 들어가는지 를 알아서 대충 그려봤습니다.

즉 ebp-56이 변수 buf이고 printit()이 call변수에 저장되는 곳이 ebp-16이였습니다. 따라서 이 거리는 40이라고 알 수 있었습니다. 
햇갈리시는 분들은 위의 hint에 있는 attackme.c코드와 스택구조를 같이보시면 이해가 쉬우실 겁니다.



끝났습니다.

레벨 15가 저한테는 굉장히 어려워서 그런지 이 문제는 굉장히 쉬웠었습니다.



You Might Also Like

0 개의 댓글