본문 바로가기

카테고리 없음

2024.8.19 리버싱 공부(나뭇잎 책)

64비트 CPU

x64 - AMD64, Intel64 CPU

x86 - 32bit CPU

 

64bit 운영체제 - 32비트 호환 가능성이 중요했음.

 

32bit 윈도우는 ILP32 데이터 모델 사용(Integer, Long Pointer 32비트)

 

64bit 윈도우는 LLP64 데이터 모델 사용 ( long long, pointer가 64비트)

 

64bit UNIX계열은 LP64 데이터 모델 사용( long, long long, pointer가 64비트)

 

64비트 프로그램 만들 때 기존의 Win32 API를 거의 그대로 사용함. Win64는 없음

 

64비트 OS에서 기존 32비트 프로그램이 잘 실행되는게 중요함.

 

WOW64(Windows On Windows 64)가 기존 32bit 프로그램을 64bit OS에서 실행시켜주는 메커니즘임.

 

64bit Windows에서 32bit,64bit 프로그램이 실행되는데 64bit 프로그램은 kernel32.dll(64bit), ntdll.dll(64bit)로딩함. 

 

32bit 프로그램은 kernel32.dll(32bit), ntdll.dll(32bit)로딩하는데 중간에 , WOW64가 ntdll.dll(32bit)의 API 호출을 ntdll.dll(64bit)로 리다이렉션 시킴.

 

system32 폴더에는 64bit 시스템 파일 존재, SysWOW64 폴더에는 32bit 시스템 파일 존재.

 

 

 

 

32bit 프로그램에서 SysWOW64 폴더는 system32 로 변경되어 보임.

 

레지스트리도 32,64bit 따로 구분되어있음.

 

Program Files는 64bit

 

Program Files(x86)은 32bit

 

 

 

x64에서 추가 변경된 사항

 

1.메모리가 4바이트에서 8바이트가 됨(pointer가 8바이트)

그래서 절대 주소도 8바이트, 레지스터와 스택의 기본 단위도 64bit(8Byte)

 

2.가상메모리 크기가 4GB(32bit) 에서 16TB(64bit)로 바뀜. 커널, 유저 영역 각 8TB

 

3. 범용 레지스터 64비트로 확장 및 개수 추가.

X64 범용 레지스터의 이름이 R로 시작함. (32bit는 E로 시작함)

 

4. CALL/JMP 명령어

 

32bit에선  FF15/ FF25 다음 4바이트가 절대주소로 해석돼서 jmp call했음.

64bit에선 FF15 다음 4바이트의 주소가 오는데, 상대주소로 해석함.

00000001 00401000 :  FF15 3FFA일 경우 

CALL 명령어 주소 + 상대주소 + 명령어 길이 = 변환된 절대주소 로 해석됨.

00000001 00401000 + 3FFA + 6 = 0000000100405000

 

5. 함수 호출 규약

64bit에선 변형된 fastcall 하나로 통일됨.

파라미터 4개까지 레지스터에 저장하고 넘어가면 스택 사용.

 

정수형 파라미터 RCX,RDX,R8,R9

실수형 파라미터 XMM0, XMM1, XMM2, XMM3

 

순서대로 채워짐.

스택 정리는 caller가 함

 

6. stack, stackFrame

함수에서 필요한 크기보다 훨씬 크게 스택을 확보함.

push로 파라미터 전달 안하고 레지스터와 확보된 스택에 mov로 전달함.

스택프레임을 RBP를 안 이용하고 RSP레지스터를 이용해  구현함.

 

 

 

이런 프로그램이 있따면

 

 

왼쪽이 64bit 오른쪽이 32bit의 경우이다.

 

64bit의 경우

sub rsp 38로 상당히 스택을 늘리고

ecx에 a, edx에 b를 넣고 함수를 호출한다.

함수 안에서도 스택을 18만큼 늘리고 스택 접근은 rsp로 하는 것을 볼 수 있다.

 

 

32bit의 경우 push ebp, mov ebp, esp로 스택프레임을 만들고 ebp로 스택에 접근하고 push명령어로 인자를 넣어주고 함수를 호출한다.

함수에서도 마찬가지로 스택프레임을 만든 후 연산하는 것을 볼 수 있다.