물먹는산세베리아

64bit 레지스터 / 32bit, 64bit 함수호출규약 본문

Waregame & CTF/Reversing

64bit 레지스터 / 32bit, 64bit 함수호출규약

suntall 2021. 9. 11. 23:50

1. 64bit 레지스터

1.1. 레지스터 변화

EAX (4byte) → RAX (8byte)
EBX (4byte) → RBX (8byte)
EBP (4byte) → RBP (8byte)
...

사이즈와 이름이 달라지긴 했으나 x64에서 EAX, EBX, ..가 사용되지 않는 건 아니다. EAX는 RAX의 하위 4byte를 의미하기 때문이다.

1.2. 새로 추가된 레지스터

x64에서 범용 레지스터의 크기는 64비트(8바이트)로 확장되었다. R8~R15 레지스터가 추가되어 개수도 18개로 늘어났다. 모든 범용 레지스터들의 이름은 'R'로 시작한다. (x86은 'E'로 시작한다.)

 

새로 추가된 64비트 모드에서만 사용 가능한 레지스터는 64비트 모드에서 호환 모드로 전환 한 후 64비트 모드로 다시 전환되는 동안 보존된다. 하지만 옛날의 호환 모드 혹은 실제 모드로 전환 후 호환 모드를 통해 64비트 모드로 돌아가면 정의되지 않는다.

 

참고로, 64bit Native Mode에서 Segment Register(CS, DS, ES, SS, FSGS)들은 사용되지 않고 오직 32비트 하위 호환용으로만 제공된다.

 

1.3. 스택 프레임 포인터(EBP) 용도 변화

x86에서는 EBP(스택 베이스 포인터)와 ESP(스택 포인터)를 이용해 프레임별로 사용 중인 스택 영역을 확인 할 수 있지만 x64에서는 RBP 레지스터가 스택  프레임 포인터로 사용되지 않고 일반적인 목적으로 사용된다.

 

 

 

*사진 바꾸기..

 

 

참고

https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/x64-architecture

 

x64 Architecture - Windows drivers

x64 Architecture

docs.microsoft.com

[리버싱 핵심원리] 이승원 저

https://kuaaan.tistory.com/449


리눅스는 System V AMD64 ABI 함수호출 규약을 따른다.

2. 32bit 함수 호출 규약

cdecl

  • C언어에서 사용되는 방식으로 call(함수를 호출한 곳)하는 쪽에서 스택을 정리한다.
  • 매개변수를 스택에 push하여 함수 호출 시 전달한다.
  • main 함수에서 add함수를 호출하는 경우 main함수에서 스택을 정리한다. (ex. ADD사용하여 esp 값 증가)

stdcall

  • cdel과 반대로 호출된 함수에서 스택을 정리한다.
  • c언어는 기본적으로 cedcl이므로 해당 방식으로 컴파일 하려면 함수 앞에 _stdcall 키워드를 붙여야 한다.
  • 매개변수를 스택에 push하여 함수 호출 시 전달한다.
  • main 함수에서 스택을 정리하지 않고 ADD함수의 RETURN 명령에 정리할 스택의 크기를 포함시켜 정리한다. RETN 8(RETN + POP8) 명령어를 사용 (코드의 길이가 줄어든다는 장점)

fastcall

  • stdcall 방식과 같되, 함수에 전달하는 파라미터 일부(최대 2개까지)를 스택이 아닌 레지스터를 이용한다.
  • 이때 이용하는 레지스터는 ECX, EDX이다.

 

3. 64bit 함수 호출 규약

fastcall 방식(함수의 인자가 레지스터로 전달 방식)만 이용한다.

다만 변형된 fastcall로 함수 파라미터 4개까지 레지스터에 저장하여 전달한다.

Parameter 정수형 실수형
1st RCX XMM0
2nd RDX XMM1
3rd R8 XMM2
4th R9 XMM3

 

각 파라미터 순서에 대한 레지스터가 결정되어 있다.

*리눅스 기준

정수 → RDI, RSI, RDX, RCX, R8, R9 (6개 이상은 스택에 저장한다)

실수 → XMM0~XMM7

 

*윈도우 기준

정수 → RCX, RDX, R8, R9

실수 → XMM0~XMM3

 

레지스터를 사용하여 파라미터 전달

 

반환값은 일반적으로 

정수 → RAX (하위 64bit), RDX (상위 64bit)

실수 → XMM0 (하위 128bit), XMM1(상위 128bit)

레지스터로 넘겨진다.

 

단, 매개변수 레지스터들이 비어있지 않은 경우 오류가 발생할 수 있다.

 

 

 

참고 

https://sunrinjuntae.tistory.com/34

 

https://too-march.tistory.com/25

 

'Waregame & CTF > Reversing' 카테고리의 다른 글

PE 파일 구조 : PE 헤더  (0) 2021.09.28
어셈블리 명령어 모음  (0) 2021.09.26
[dreamhack.io]rev-basic-1  (0) 2021.09.11
[dreamhack.io] rev-basic-0  (0) 2021.09.11
[CodeEngn] Basic RCE L17  (0) 2021.02.27