티스토리 뷰
어셈블리어를 보면 다음과 같이 숫자들이 적혀있는 것을 볼 수 있다.
이런 숫자들을 Operation Code라고 한다.
컴퓨터 명령어란 사람이 만든 프로그램(고수준 언어로 작성한 프로그램)을 번역해 컴퓨터가 알아들을 수 있는 명령어(기계 언어)로 바꿔 놓은 것이다. 컴퓨터가 명령을 처리하기 위해서는 이 opcode와 데이터를 찾는 주소(Operand)를 가지고 있어야 한다. opcode와 operand를 합쳐 명령어(instruction)라고 부른다.
위 사진의 첫번째 명령어를 보자.
mov qword ptr ss:[rsp+10],rbx
간단히 rsp+10 주소에 있는 값에 rbx 값을 넣어라. 라는 명령어 이다.
mov가 opcode이고 qword ptr ss:[rsp+10],rbx가 operand이다. 또 rbx는 src operand이고 qword ptr ss:[rsp+10]는 dst operand가 된다.
기계어 구성 방식
위 사진은 인텔 프로세서의 기계어 구성이다.
instruction prefixes - 선택 사항이다.opcode의 의미를 보조하는 역할이다. 4가지의 형태가 있다.
opcode - 프로세서가 이 명령어를 통해 수행해야 할 일의 종류를 명시하는 필드. 1~3바이트 크기.주로 1바이트. operand를 가지고 있으며 종류는 register, memory address, constant이다. 이런 operand에 대한 정보로 ModR/M과 SIB가 붙음.
ModR/M - 오퍼랜드가 레지스터에 있는지 메모리에 있는지를 나타내는 것. operand의 개수, 종류 등을 설명. 1바이트.
SIB(Scale-Index-Base) - ModR/M을 보조함. operand가 memory인 경우 ModR/M과 함께 사용됨. 1바이트.
disaplacement - 번지 지정 시에 offset을 지정할 대 사용. operand가 memory인 경우 offset을 나타냄. 1,2,4바이트.
immediate - operand를 상수 값으로 표현한 것. 1,2,4 바이트.
instruction prefixes 4가지 형태
1. lock and repeat prefixes => 자원의 사용을 독점하거나, 반복적인 명령어를 수행해야 할 때
- LOCK의 역할을 할때는 F0의 prefix 값
- REPNE, PREPNZ의 역할은 F2의 prefix 값
- REP, REPE, REPZ의 역할은 F3의 prefix 값
2. segment override prefixes => 세그먼트를 재정의할 때 사용된다.
- 2E : CS segment override => mov ax, [cs:bx]
- 36 : SS segment override => mov ax, [ss:si+3]
- 3E : DS segment override
- 26 : ES segment override => mov ax,[es:123]
- 64 : FS segment override
- 65 : GS segment override
3. Operand-size override => 오퍼랜드의 크기를 재정의할 때 사용된다.
32비트 환경(EBP 등을 사용함)에서 16비트 오퍼랜드(BP 등을 사용함)를 사용한다면 prefix로 66을 붙여 여기서만 16비트 오퍼랜드로 사용한다고 알린다.
4. Address-size override prefix => 주소의 크기를 재정의할 때 사용된다.
32비트 환경에서 16비트 주소를 사용한다면 prefix로 67을 붙여 여기서만 16비트 주소 크기를 사용함을 알린다.
이제 이 어셈블리어를 컴퓨터가 읽을 수 있도록 바꿔줘야 한다. 그럼 mnemonic을 opcode로 바꿔보고 이를 다시 디스어셈해보자.
1바이트 Opcode 예시
push rbp를 예시로 보자.
아래 링크에서
Intel@ 64 and IA-32 Architectures Software Developer’ s Manuals Volume 2A.pdf
Intel@ 64 and IA-32 Architectures Software Developer’ s Manuals Volume 2B.pdf
이걸 다운 받자.
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
push rbp의 opcode 값은 55이다. 이를 tableA-2-1에서 찾아보면 PUSH rBP/r13이라고 적혀 있다.
rBP는 BP 관련 레지스터인 13번 레지스터를 사용한다는 의미이다.
다른 것도 많지만 나올 때마다 알아봐야 하겠다.
2바이트 opcode 예시
sub rsp, 200을 보자.
48:81EC 00020000을 opcode라고 부르고
48 - instruction prefixes
81 - opcode
EC - ModR/M
00020000 - immediate
를 의미한다. 하나씩 의미를 알아보자.
48 - instruction prefixes로 뒤에 특정한 opcode가 나올 때 사용되어 opcode의 의미를 보조.
tableA-2-2로 48을 확인해 보면 DEC eAX REX.W 가 적혀있다. REX가 어떤 의미인지 알아보자.
REX prefix를 통해서 기존 IA-32의 명령 집합의 구성을 크게 건드리지 않고도 쉽게 64비트 명령들을 사용할 수 있다. REX prefix는 다음의 목적을 위해 사용된다.
- 새로운 GPR과 YMM/XMM 레지스터를 지정
- operand 사이즈를 64비트로 지정
- 추가로 사용할 컨트롤 레지스터를 지정(CR8)
- 추가적인 디버깅용 레지스터를 지정
REX prefix의 구성과 용도는 다음과 같으며, 0x4*의 형태로 앞의 4비트는 0100으로 고정이고 하위 4비트가 의미를 갖는다.
REX.W : 해당 위치가 0이면 기본 오퍼랜드 크기, 1이면 64비트 오퍼랜드 크기를 지정.
REX.R : ModR/M 바이트의 reg 필드를 1비트 확장해서 총 4비트로 16개의 레지스터를 접근할 수 있도록 한다.
REX.X : SIB 바이트의 index 필드를 1비트 확장해서 총 4비트로 16개의 레지스터를 접근할 수 있도록 한다.
REX.B : ModR/M 바이트의 r/m 또는 op필드, SIB 바이트의 base 필드를 1비트 확장해서 총 4비트로 16개의 레지스터를 접근 할 수 있도록 한다.
REX prefix는 0x40~4F의 값을 사용하기 때문에 32비트 명령 INC,DEC와 겹친다. INC는 0x40~47, DEC는 0x48~0x4F의 값을 Opcode로 사용한다. 그러므로 64비트 모드에서 INC와 DEC 명령에 해당하는 opcode는 0xFE와 0xFF로 지원된다.
따라서 위의 48의 의미는 기본 오퍼랜드의 크기를 확장한다는 의미다.
81 - Opcode 값이다. tableA-2-1을 참고해 81을 보면 immediate Grp 1 Eb,lz이다.
이는 Opcode에 해당하는 명령어가 바로 나오지 않고 뒤에 나오는 ModR/M에 따라 instruction을 결정한다.
Eb와 Iz의 의미를 다음 설명들을 참고해서 알아보자.
메모리를 지정해주는 문자.
A => 메모리 주소 직접 지정.
B => vex 접두사
C => ModR/M의 reg가 controll register
D => ModR/M의 reg가 debug register
E => ModR/M 바이트가 opcode를 따르고 operand를 명시, 메모리 주소일 경우 segment regiser로 계산
F => EFLAGS/RFLAGS register
G => ModR/M 바이트의 reg가 범용레지스터임을 의미
I => immediate data를 의미.
J => 명령어는 명령어 포인터 레지스터에 더해지는 상대적인 오프셋을 포함.
M => ModR/M 바이트는 오로지 메모리를 참조해야 함.
O => 명령어가 ModR/M 바이트를 가지지 않음.
R => ModR/M 바이트의 R/M 부분은 범용 레지스터를 참조해야 함.
S => ModR/M 바이트의 reg 필드는 segment register를 선택.
X => 메모리는 ES:rDI 레지스터 쌍으로 주소 지정.
Y => 메모리는 DS:rSI 레지스터 쌍으로 주소 지정.
오퍼랜드 타입 지정 문자.
a => 메모리에서의 2개의 word operand 또는 2개의 DWORD
b => byte
c => byte or word
d => DWORD
dq => double quardword
p => 32bit,48bit,80-bit pointer,operand의 크기 속성에 의존
pd => 128,256-bit double precision floating point data
q => quardword
qq => quard-quardword
si => doubleword integer register
v => 64-bit 상황에서 word, DWORD, QWORD, operand의 크기 속성 보호
w => word
z => 16bit operand 크기를 위한 word 또는 32,64 bit operand 크기를 위한 DWORD
이제 opcode의 값을 다음 표를 이용해 알아보자.
Grp 1 이라는 점과 ModR/M의 Reg값인 101 이용해(아래에서 설명함) 확인해 보면 SUB임을 알 수 있다.
Eb : E -ModR/M 바이트가 opcode를 따르고 operand를 특정한다.operand는 범용 레지스터이거나 메모리 주소이다. b - byte단위로 표시. 첫번째 operand가 Eb형식을 따른다는 의미이다.
Iz : I - 상수값. z - 32,64bit 모드에서는 DWORD이다. 두번째 operand가 lz형식을 따른다는 의미이다.
EC - EC는 ModR/M 값이다. EC를 2진수로 변환하면 11101100인데 이를 11(Mod) | 101(Reg) | 100(R/M) 로 구분한다.
ModR/M값은 다음 테이블로 결정한다.
EC를 찾아 Mod(11)와 R/M(100)이 맞는 곳을 찾아보면
ESP에 관해서라고 나와 있다. 이 값은 Eb에 해당 된다.
Mod부분이 11이면 R/M이 Register
Mod부분이 00이라면 뒤엔 Displacement
00020000 - 리틀엔디안 방식으로 0x0200이다.
'리버싱' 카테고리의 다른 글
Taint Analysis란 (0) | 2022.02.14 |
---|---|
PinTool Opcode binary 출력 구현 (0) | 2022.02.14 |
DBI PIN tool 사용하기 (0) | 2022.01.18 |
PIN API에 대해 (0) | 2022.01.18 |
abex crackme 4 (0) | 2021.02.18 |
- Total
- Today
- Yesterday
- AVTP
- one-to-many
- automotive ethernet
- 크로스 엔트로피
- porks
- AVB
- many-to-many
- 머신러닝
- Ethernet
- automotive
- CAN-FD
- json2html
- 논문 잘 쓰는법
- 회귀
- 이상탐지
- 단순선형회귀
- problem statement
- Python
- 차량용 이더넷
- SOME/IP
- cuckoo
- AE
- 차량 네트워크
- 딥러닝
- HTML
- SVM
- 케라스
- PCA
- 로지스틱회귀
- many-to-one
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |