[자꾸 잊어버려서 기록]
2020년 7학기에 배운 시스템 보안 강의에서 Intel 어셈블리 구조를 배우면서 다음과 같은 과제를 수행했었다. 어셈블리어로 되어있는 명령어를 인코딩하고 디코딩 하는 방법을 학습한 후, 16진수로 되어있는 명령어를 디코딩하는 과제를 수행했다.
인코딩 및 디코딩을 하기 위해서는 Intel 64 and IA-32 Architectures Software Developer's Manual이 필요하다
software.intel.com/content/www/us/en/develop/articles/intel-sdm.html
// IA-32 Encoding/Decoding을 위해 알아야 할 사항이다.
Instruction Prefixes | Opcode | Mod R/M | SIB | Displacement | Immediate |
디코딩 해야하는 IA-32 Instruction은 아래와 같다.
BB 03 00 00 00 B8 01 00 00 00 83 C3 06 8B CB 2B D9 03 C8 83 E8 02 03 C1 |
위 Instruction은 아래와 같이 분리할 수 있다.
(왜 아래와 같이 분리할 수 있냐고 묻는다면, Decoding 여러번 해보면 어디서 분리해야 하는지 눈에 보인다...)
BB 03 00 00 00 |
B8 01 00 00 00 |
83 C3 06 |
8B CB |
2B D9 |
03 C8 |
83 E8 02 |
03 C1 |
1. BB 03 00 00 00
Table A-2. One-byte Opcode Map에 따라 BB는 MOV rBX, Iv로 Decoding 된다. rBX는 32-비트의 경우 EBX를 의미하고, Iv는 32-비트 double word 크기의 immediate를 의미한다. 따라서 Opcode BB 뒤의 32 비트를 immediate로 읽어들이라는 의미이다. 이 때, 메모리에 인코딩 된 immediate operand는 little Endian이다.
BB 03 00 00 00
-> MOV rBX, Iv
-> MOV EBX, Iv
-> MOV EBX, 00000003h
2. B8 01 00 00 00
Table A-2. One-byte Opcode Map에 따라 B8은 MOV rAX, Iv로 디코딩된다. rAX는 32-비트의 경우 EAX를 의미하고, Iv는 32-비트 double word 크기의 immediate를 의미한다. 따라서 Opcode B8 뒤의 32비트를 immediate로 읽어들이라는 의미이다. 이 때 메모리에 인코딩 된 immediate operand는 little Endian이다.
B8 03 00 00 00
-> MOV rAX, Iv
-> MOV EAX, Iv
-> MOV EAX, 00000001h
3. 83 C3 06
Table A-2. One-byte Opcode Map에 따라 83은 Immediate Grp1 Ev, Ib로 Decoding 된다. Immediate Grp1 라고 표시 되어있는 것은 Opcode에 해당하는 명령어가 바로 나오지 않는다는 의미이다. Group Instruction은 Opcode 하나에 여러가지 instruction을 묶어놓고 ModR/M에 따라 해당 instruction을 결정한다. 따라서 83 뒤에 있는 C3을 분석한다.
C3을 2진수로 변환하면 11000011이고, ModR/M 분리를 하면 Mod : 11, Reg: 000, R/M: 011 이다. 이 중 Reg 값을 토대로 Table A-6. Opcode Extensions for One-and Two-byte Opcodes by Group Number를 참조하면, ADD가 나온다.
그리고 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하여 C3을 찾아보면, Ev 값이 EBX임을 알 수 있다. Ib는 C3 뒤의 한 바이트를 Immediate로 읽어 들이라는 의미이므로, Ib가 6임을 알 수 있다.
83 C3 06
-> Immediate Grp1 Ev, Ib
-> ADD, Ev, Ib
-> ADD, EBX, Ib
-> ADD, EBX, 6
4. 8B CB
Table A-2. One-byte Opcode Map에 따라 8B는 MOV Gv, Ev로 Decoding된다. 그리고 8B 뒤에 있는 CB는 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하면, Gv는 ECX, Ev는 EBX 임을 알 수 있다.
8B CB
-> MOV Gv, Ev
-> MOV Gv, Ev
-> MOV ECX, Ev
-> MOV ECX, EBX
5. 2B D9
Table A-2. One-byte Opcode Map에 따라 2B는 SUB Gv, Ev로 Decoding된다. 그리고 2B 뒤에 있는 D9는 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하면, Gv는 EBX, Ev는 ECX 임을 알 수 있다.
2B D9
-> SUB Gv, Ev
-> SUB Gv, Ev
-> SUB EBX, Ev
-> SUB EBX, ECX
6. 03 C8
Table A-2. One-byte Opcode Map에 따라 03은 ADD Gv, Ev로 Decoding된다. 그리고 03 뒤에 있는 C8은 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하면, Gv는 ECX, Ev는 EAX 임을 알 수 있다.
03 C8
-> ADD Gv, Ev
-> ADD Gv, Ev
-> ADD ECX, Ev
-> ADD ECX, EAX
7. 83 E8 02
Table A-2. One-byte Opcode Map에 따라 83은 Immediate Grp1 Ev, Ib로 Decoding 된다. Immediate Grp1 라고 표시 되어있는 것은 Opcode에 해당하는 명령어가 바로 나오지 않는다는 의미이다. Group Instruction은 Opcode 하나에 여러가지 instruction을 묶어놓고 ModR/M에 따라 해당 instruction을 결정한다. 따라서 83 뒤에 있는 E8을 분석한다.
E8을 2진수로 변환하면 1110 1000이고, ModR/M 분리를 하면 Mod : 11, Reg: 101, R/M: 000 이다. 이 중 Reg 값을 토대로 Table A-6. Opcode Extensions for One-and Two-byte Opcodes by Group Number를 참조하면, SUB가 나온다.
그리고 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하여 E8을 찾아보면, Ev 값이 EAX임을 알 수 있다. Ib는 E8 뒤의 한 바이트를 Immediate로 읽어 들이라는 의미이므로, Ib가 2임을 알 수 있다.
83 E8 02
-> Immediate Grp1 Ev, Ib
-> SUB, Ev, Ib
-> SUB, EAX, Ib
-> ADD, EAX, 2
8. 03 C1
Table A-2. One-byte Opcode Map에 따라 03은 ADD Gv, Ev로 Decoding된다. 그리고 03 뒤에 있는 C1은 Table 2-2. 32-bit Addressing Forms with the ModR/M Byte를 참조하면, Gv는 EAX, Ev는 ECX 임을 알 수 있다.
03 C1
-> ADD Gv, Ev
-> ADD Gv, Ev
-> ADD EAX, Ev
-> ADD EAX, ECX
- Decoding 결과
MOV EBX, 00000003h |
MOV EAX, 00000001h |
ADD EBX, 6 |
MOV ECX. EBX |
SUB EBX, ECX |
ADD ECX, EAX |
SUB EAX, 2 |
ADD EAX, ECX |