어셈블리어(Assembly Language)
- 컴퓨터 언어들 중에 낮은 레벨의 언어 (컴퓨터에 가까운 언어!!)
- 기계어와 1:1 대응이 되는 프로그래밍언어
- CPU마다 고유한 어셈블리 언어를 갖는다
어셈블리어의 명령 포맷(X86 CPU : IA-32 기준)
- Opcode(명령어) + Operand(인자)
Opcode | Operand(목적지) | Operand(출발지) |
MOV | EAX | EBX |
레지스터(Register) : 데이터의 저장 공간 용도이다(컴퓨터 언어의 변수 느낌?!)
- EAX(Accmaulator Regist) : 산술 연산, 리턴 값 전달, 가장 많이 사용되는 레지스터!
- EBX(Base Regist) : 포인터에 많이 사용되는 레지스터
- ECX(Count Regist) : 반복 카운팅에 사용되는 레지스터(for 문에 i,j.. 느낌!!)
- EDX(Data Regist) : EAX와 역할은 같지만 리턴 값은 전달하지 않는다, OEP값이 입력되는 레지스터
- ESI(Source Index) : 데이터 출발지 주소에 대한 값, 문자열이나 각종 반복되는 데이터를 처리 또는 메모리를 옮기는데 사용하는 레지스터
- EDI(Destination Index) : 데이터 목적지 주소에 대한 값을 저장하는 레지스터
- EBP(Base Point) :스택의 시작 주소를 저장하는 레지스터
- ESP(Stack Point) : 스택의 끝 주소를 저장하는 레지스터
- EIP(Instruction Point) : 다음 명령어가 실행될 메모리 주소를 저장하는 레지스터
※ PE 추가내용
- ImageBase : PE 파일 저장되는 시작 주소(exe파일은 주로 0x00400000)
- address of entry point : 메모리의 실제 시작 주소
- OEP(Original Entry Point) : 메모리의 실제 시작 주소(ImageBase + address of entry point)
EAX등의 레지스터(EBX, ECX, ...)는 4Byte(32bit) 크기이다
AX는 2Byte(16bit) = AL 1Byte(8bit) + AH 1Byte(8bit)
엔디언(Endian) : 컴퓨터의 메모리와 같은 1차원의 공간에 여러 개의 연속된 대상을 배열하는 것을 의미한다
- 빅 엔디언(Big Ednian) : 데이터가 상위 바이트로부터 메모리에 적재되는 것 (왼쪽 -> 오른쪽)
- ex) DATA : 0x12345678 -> [12] [34] [56] [78]
- 리틀 엔디언(Little Endain) : 데이터가 하위 바이트로부터 메모리에 적재되는 것 (오른쪽 -> 왼쪽)
- ex) DATA : 0x12345678 -> [78] [56] [34] [12]
Little Endian | Big Endian |
낮은 비트 열에 먼저 들어와서 들어오는 족족이 연산을 바로 할 수 있다 |
높은 비트 열에 먼저 들어와서 데이터를 다 받아와야 연산을 할 수 있다 |
산술 연산 속도가 빠르다 | 산술 연산 속도가 느리다 |
비교 연산시에는 불리하다 | 비교 연산시에는 높은 비트열 먼저 비교해서 유리하다 |
Opcode(명령어)
- PUSH [operand] : 스택 영역에 공간을 할당하고 [operand]에 값을 저장한다
- POP [operand] : ESP가 가르키는 곳의 값을 [operand]에 저장하고 ESP가 가르키는 공간 정리
- MOV [operand1] [operand2] : [operand2] 값을 [operand1]으로 넣는다([operand]가 1개일 경우 [operand1]은 EAX!!)
- LEA [operand1] [operand2] : [operand2] 값의 주소를 [operand1]으로 넣는다 ([operand]가 1개일 경우 [operand1]은 EAX!!)
- CMP [operand1] [operand2]: 비교 연산할 때 사용
- JMP [operand] : 주소로 이동 (점프)
- JE [operand] : CMP연산 후 값이 같을 경우 점프
- JNE [operand] : CMP 연산 후 값이 다를 경우 점프
- JZ : CMP 연산 후 값이 0 이면 점프
- JNZ : CMP 연산 후 값이 0이 아니면 점프
- 산술 연산
- ADD [operand1] [operand2] : 더하기 연산 명령어 (ADD EBX일 경우 스택을 정리)
- SUB [operand1] [operand2] : 빼기 연산 명령어 (SUB EBX일 경우 스택을 확보)
- MUL [operand1] [operand2] : (부호가 없는)곱하기 연산 명령어( [operand]가 1개일 경우 [operand1]은 EAX!!)
- IMUL [operand1] [operand2] : (부호가 있는)곱하기 연산 명령어( [operand]가 1개일 경우 [operand1]은 EAX!!)
- EAX * ECX 연산 할 경우 EDX : EAX에 저장된다(상위 비트 = edx, 하위 비트 = EAX)
- AX * CX 연산 할 경우 DX : AX에 저장된다 (상위 비트 = DX, 하위 비트 = AX)
- AL * CL 연산 할 경우 AX에 저장된다
- DIV [operand1] [operand2] : (부호가 없는) 나눗셈 연산 명령어
- IDIV [operand1] [operand2] : (부호가 있는) 나눗셈 연산 명령어
- EAX / ECX 연산 할 경우 EAX : EDX에 저장된다 (몫 = EAX, 나머지 = ECX)
- AX / CX 연산 할 경우 AX : DX에 저장된다 (몫 = AX, 나머지 = DX)
- AL / CL 연산 할 경우 AL : AH에 저장된다 (몫 = AL, 나머지 = AH)
- 논리 비트 연산
- AND [operand1] [operand2] : [operand]를 비교해서 모두 참이라면 참 그외 거짓!
- OR [operand1] [operand2] : [operand]를 비교해서 하나가 참이라면 참 그외 거짓!
- XOR [operand1] [operand2] : [operand]가 서로 다르면 참!!, 주로 레지스터를 초기화 할때 사용(XOR EAX EAX )
- TEST [operand1] [operand1] : [operand]끼리 AND연산, [operand]에 값이 있는지 없는지 확인하는 명령
- NOP : 아무것도 하지 않고 무조건 통과(리버싱할 때 치트키 같은 친구!)
- INC [operand] / DEC [operand] : 1씩 증가, 1씩 감소 (1++, 1--)
- INT [상수만] : 인터럽트를 일으키는 명령어
- CALL [operand] : 함수 호출 명령어
- RET : 함수의 종료 시 사용되는 명령어, 함수가 종료되어 스택에 저장된 복귀주소로 돌아간다!! (POP EIP + ADD ESP와 비슷, return!!)
'개인 공부 > 리버싱' 카테고리의 다른 글
Reverse Engineering-006 PE-01 (0) | 2023.04.17 |
---|---|
Reverse Engineering-005 (0) | 2023.04.13 |
Reverse Engineering-004(C++) (0) | 2023.04.12 |
Reverse Engineering-003(구조체 & API) (0) | 2023.04.12 |
Reverse Engineering-002(문법) (0) | 2023.04.10 |