guest@openpesto.com:~$ cat ctf/stack-overflow-visualized.md

# 스택을 그림으로 이해하기: ret2win

ret2win을 글로만 설명하면 오프셋 계산이 추상적으로 느껴진다. 스택을 한 장의 그림으로 보면 왜 b"A"*40 + p64(win) 인지 단번에 이해된다.

스택 레이아웃

아래는 gets(buf) 가 호출될 때의 스택 프레임이다. x86-64에서 스택은 높은 주소 → 낮은 주소 방향으로 자라지만, gets() 같은 입력 함수는 버퍼의 낮은 주소부터 위쪽(높은 주소)으로 써 올라간다.

x86-64 스택 프레임 다이어그램

그림 1 — buf[32] 를 넘어 saved RBP(8B)까지 채운 뒤, 그 위의 return address(8B)를 win() 주소로 덮으면 함수 리턴 시 그곳으로 점프한다.

오프셋 계산

그림에서 바로 읽어낼 수 있다:

offset  = 32      # buf[32]
offset += 8       # saved RBP
# → return address 까지 40 바이트

payload = b"A" * offset + p64(win)
  • 40바이트buf + saved RBP 를 채우는 “패딩”
  • 그다음 8바이트가 진짜 목표인 return address

정렬 주의

win() 내부에서 movaps 같은 16바이트 정렬을 요구하는 명령을 만나면 SIGSEGV 가 날 수 있다. 그럴 땐 return address 앞에 ret 가젯 하나를 끼워 스택을 한 번 더 정렬해주면 된다.

payload = b"A"*40 + p64(ret_gadget) + p64(win)

그림 한 장이 디스어셈블 100줄보다 빠를 때가 있다.

NORMAL guest@openpesto.com ~/ctf/stack-overflow-visualized.md ESC:shell · utf-8 · 2 posts · up 903d