안 쓰던 블로그
32bit와 64bit - x86과 x64 비교 본문
x86에서 x64가 되면서 구조 뿐만 아니라 스택에도 변화가 생겼다
레지스터 사용법 변화
1) 레지스터 이름 및 크기 변화
EAX(4바이트)->RAX(8바이트)
EBX(4바이트)->RBX(8바이트)
EBP(4바이트)->RBP(8바이트)
앞에 e가 붙으면 x86의 레지스터(32비트), r이 붙으면 x64의 레지스터(64비트)이다
그리고 e~는 4바이트, r~은 8바이트이다
x86에서 x64가 되면서 레지스터 이름과 크기가 변화했기 때문인데, 그렇기 때문에 e~가 사용되지 않는 건 아니다. eax라는 건 rax 레지스터의 하위 4바이트를 의미하는 이름이라고 알면 된다
2) 새로운 레지스터 추가
x86에서는 없던 레지스터 R8, R9 ... R15가 추가되었다
이 중에 R12~15는 비휘발성 레지스터(Non-Volatile Register)로, 자식 함수를 호출하고 리턴된 후에도 호출 전과 값이 동일하게 유지되는 레지스터이다. 모든 함수에서는 비휘발성 레지스터를 사용하기 전에 스택에 백업받고, 리턴하기 전에 복원해 주는 작업을 한다. 이 작업을 함수 프롤로그, 에필로그라고 한다
3) 스택 프레임 포인터 EBP 용도 변화
x86에서는 스택 베이스 포인터 EBP와 스택 포인터 ESP를 이용해 각 프레임 별로 사용 중인 스택 영역을 확인했다. 하지만 x64에서는 RBP 레지스터가 더이상 스택 프레임 포인터로 사용되지 않고 일반적인 목적으로 사용된다. 즉, x64에서는 더 이상 push ebp 후 mov ebp, esp 하는 함수 프롤로그를 볼 수 없다
함수 호출규약 변화
1) 인자 전달 방법의 변화
x86은 _cdecl이나 _stdcall 같은 호출 규약을 사용하기 때문에 대부분의 함수는 호출 시 인자값이 스택을 통해 전달되었다(x86은 스택 기반 인자 전달)
x64에서는 fastcall 호출 규약이 사용되어 레지스터 기반 인자 전달 방식이 되었다
(1) 처음 1번째~3번째 인자까지는 각각 RCX, RDX, R8, R9 네 개의 레지스터에 담겨서 전달된다 (부동소수점이라면 XMM0~)
(2) 5번째 이후의 인자부터는 x86과 동일하게 스택에 저장되어 전달된다
스택 구성의 차이
1) x64에서는 함수 실행 중 스택 사이즈 변경 없음
x86에서는 함수의 프롤로그 (push ebp 후 mov ebp, esp)가 끝나고 나면 함수가 리턴할 때까지는 ebp가 바뀌지 않고 esp는 자식 함수 호출 과정에서 매개변수 push할 때 등 수시로 바뀐다
x64에서는 함수의 프롤로그가 끝나고 나면 함수가 리턴될 때까지 rsp가 바뀌지 않는다. 다른 말로, 함수의 프롤로그를 하며 해당 함수에서 필요한 모든 스택 공간에 한꺼번에 확보된다는 의미이다. 예를 들어 함수의 인자값이 6개면 함수가 호출되면서 6개 분의 스택 공간이 한 번에 확보된다
2) x64에서는 스택 포인터를 기준으로 인자와 지역 변수를 참조
x86에서는 스택 베이스 포인터 ebp를 기준으로 인자 및 지역 변수를 참조했다
-> ebp+xx 는 인자값 (ebp+8h는 첫번째 인자값, ebp+ch는 두번째 인자값..)
-> ebp-xx 는 지역변수
mov dword ptr [ebp-4], 1Eh //로컬변수->[ebp-4] (다음 로컬변수 [ebp-8])
mov eax, dword ptr [ebp+8] //인자1->[ebp+8]
add eax, dword ptr [ebp+0Ch] //인자2->[ebp+Ch]
x64에서는 스택 포인터 rsp를 기준으로 인자 및 지역 변수를 참조한다
-> rsp+xx (xx>현재 스택 사이즈) 는 인자값
-> rsp+xx (xx<현재 스택 사이즈) 는 지역변수
mov dword ptr [rsp], 1Eh //로컬변수->[rsp] (다음 로컬변수 [rsp+4])
mov eax, dword ptr [rsp+28h] //인자1->[rsp+28h]
add eax, dword ptr [rsp+20h] //인자2->[rsp+20h]
'CTF > Pwnable' 카테고리의 다른 글
64it ROP (0) | 2020.11.28 |
---|---|
32bit ROP (0) | 2020.11.10 |
레지스터 (0) | 2020.10.13 |
스택과 SFP와 RET (0) | 2020.10.13 |
pwntools을 이용한 문제 풀이-double pistol (0) | 2020.09.15 |