티스토리 뷰

리버싱

Opcode에 대해

삼전동해커 2022. 2. 7. 20:58

어셈블리어를 보면 다음과 같이 숫자들이 적혀있는 것을 볼 수 있다.

이런 숫자들을 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

tableA-2-1

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

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의 의미는 기본 오퍼랜드의 크기를 확장한다는 의미다.

 

 

tableA-2-1

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/MRegister

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
링크
«   2024/04   »
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
글 보관함