본문 바로가기

카테고리 없음

어셈블리어 해석을 위한 간단 정리

 

 

어셈블리어

  • 기계어로 1:1 매핑이 가능한 가장 낮은 수준의 언어
  • CPU, 레지스터, 메모리 사이에 데이터를 조작함
  • CPU에서 지원하는 함수만 사용 가능
  • 표기법은 인텔 기반과AT&T 기반 

 

 

 

 

 

어셈블리 기본

  • 기본 문법 : Opcode Operands
  • 표기 방식
    - 레지스터: EAX, EBP ..
    - 값 : 16진수 표현
    - 메모리 주소 : [주소값], [레지스터명]
    - 오퍼랜드 방식 : 목적지(dst) <- 소스(src)
  • 메모리 할당 : 값은 스택에 저장(PUSH)
    - DWORD : double word(16bit, 2byte) = 32bit
    -  함수 호출 시 스택에 순서대로 저장
        - RETURN 주소 PUSH
        - 기존의 EBP PUSH
        - EBP에 현재 ESP 값을 저장, EBP 설정

 

 


 

 

 

[데이터 이동]

데이터 이동 방법

  • 값을 직접 레지스터로 대입
  • 레지스터에서 레지스터로 옮기기
  • 값을 직접 메모리로 대입하기
  • 레지스터에서 메모리로 또는 그 반대로 옮기기
  • 메모리에서 메모리로 옮기기

MOV : 값을 넣어줌, operand1 <- operand2

  • MOV EAX, EBX // EBX 레지스터의 값을 EAX 레지스터로 복사
  • MOV EBP, ESP // ESP 값을 EBP로 복사
  • MOV EAX, 42 // 16진수 42를 EAX 레지스터로 복사
  • MOV EAX,[4037C4] // 메모리주소 4037C4에 있는 4바이트 값을 EAX 레지스터로 복사
  • MOV EAX, [EBX] // EBX 레지스터가 명시한 메모리 주소의 4바이트 값을 EAX 레지스터로 복사
  • MOV EAX, [EBX+ESI*4] // EBX+ESI*4 연산결과가 명시한 메모리 주소의 4바이트 값을 EAX 레지스터로 복사

LEA : Load Effective Address 약자로 MOV와 동일, 주소 값을 저장

  • LEA EAX, [EBP+8] // EBP + 8에 저장된 주소를 EAX에 저장
  • MOV EAX,  [EBP+8] // EBP+8 주소에 저장된 값을 EAX에 복사

PUSH : 스택에 값을 저장, 스택 4byte 증가, ESP 4byte 감소

  • PUSH EBP // 스택에 EBP 값을 push
  • PUSH 5 // 스택에 5를 push

POP : 스택 끝에 저장된 값을 가져옴, 스택 4byte 감소, ESP 4byte 증가

  • POP EBP // 스택의 끝 값을 EBP에 저장
  • POP ECX // 스택의 끝 값을 ECX에 저장

 

 

 


 

 

 

 

[산술연산 명령어]

명령 설명 사용 예
ADD 덧셈 ADD ECX, 10
SUB 뺄셈 SUB ECX, 5
INC 오퍼랜드 내용을 1 증가 INC ECX
DEC 오퍼랜드 내용을1 감소 DEC ECX
MUL/IMUL EAX와 오퍼랜드를 곱셈하여 EAX에 저장  MUL EDX
DIV/IDIV EAX와 오퍼랜드를 나누어 EAX에 저장 DIV EDX
NEG 오퍼랜드의 2의 보수 (부호 반전) NEG EAX

 

INC EAX // EAX 1 증가

DEC EAX // EAX 1 감소

ADD EAX, 1A // EAX에 1A(26) 를 더한 뒤 EAX에 저장

SUB ESP, 10 // ESP에서 10(16) 을 뺀 뒤 ESP에 저장 

 

 

 

[비트연산 명령어]

명령 설명
AND 두 비트가 모두 1이면 1, 나머지는 0으로 계삱
OR 두 비트 중 하나라도 1이면 1, 아니면 0으로 계산
XOR 각 비트 값을 비교하여 값이 같으면0, 다르면 1로 계산 
NOT 비트 값을 반대 값(0->1, 1->0)으로 변경
SHL 왼쪽으로 쉬프트 연산
최하위 비트는 0으로 채워지고 기존 값은 CF 플래그 레지스터에 저장
SHR 오른쪽으로 쉬프트 연산
최상위 비트는 부호비트로 채워지고 CF 플래그 레지스터에 저장
ROL/RCL 왼쪽으로 쉬프트 연산, 최하위 비트는 최상위 비트로 채워짐
ROR/RCR 오른쪽으로 쉬프트 연산, 최상위 비트는 최하위 비트로 채워짐

 

 

 

 

 

[제어 명령어]

 

명령 설명 사용 예
CMP 두 개의 오퍼랜드 비교 (뺄셈 연산 후 플래그 설정) CMP EAX,0
TEST 두 개의 오퍼랜드 비교 (AND 연산 수행 후 플래그를 설정) TEST EAX, EAX
CALL 해당되는 주소의 함수를 호출하여 수행 코드 위치로 옮김 CALL 00401990
INT 오퍼랜드로 지정된 예외 처리 수행
중단점으로 디버그용 소프트웨어 트랩
오버플로우 상황시 발생하는 트랩
하드웨어 디버그 트랩
INT 3
LEAVE 함수에서 사용한 지역변수 스택을 비움 LEAVE
RET  스택에 저장된 주소로 복귀 RET
NOP 아무 동작도 수행하지 않음 (기계어 코드 0X90)
공격 코드를 삽입할 대 자주 쓰임
NOP

 

 

 

 

 

[분기 명령어]

 

  • JMP : 무조건 EIP 주소값으로 점프
  • JCC : CC(조건부코드) 값에 따라 해당 EIP 주소값으로 점프
  • JE(Jump if equal), JNE(Jump if not equal)
CC 설명 플래그 값
E/Z 같은/0인 ZF = 1
NE/NZ 다른/0이 아닌 ZF = 0
L/NGE 작은(부호 있는 연산) (SF^OF)=1(SF!=OF)
G/NLE 큰(부호 있는 연산) ((SF^OF) | ZF) = 0
GE/NL 크거나 같은(부호 있는 연산) (SF^OF) = 0
LE/NG 작거나 같은(부호 있는 연산) ((SF^OF) | ZF) = 1
B/ANE 작은(부호 없는 연산) CF = 1
AE/NB 크거나 같은(부호 없는 연산) CF = 0
P/PE PE가 1이면 (짝수) PF = 1
NP/PO PE가 0이면 (홀수) PF = 0
O OF가 1이면 OF = 1
S SF가 1이면  SF  = 1
ECXZ ECX가 0이면 ECX = 0

 

 

 

 

 

 

[반복]

 

REP : ECX 레지스터 지정횟수만큼 또는 ZF 플래그 조건에 맞을 동안 반복

  •  REP : ECX가 0이 될 때까지 반복
  • REPE,REPZ : ECX가 0이거나 ZF가 0일 때까지 반복
  • REPNE, REPNZ : ECX가 0이 아니거나 ZF가 1일 때까지 반복

LOOP : LOOP영역을 ECX 레지스터 지정 값만큼 반복

  • LOOP 주소 : ECX 카운터 감소시키고, 카운터가 0이 아니면 주소로 이동함
  • LOOPE 주소 : ECX 카운터 감소시키고, 카운터가 0이 아니고 ZF가 1이면 주소로 이동함
  • LOOPNE 주소: ECX 카운터 감소시키고, 카운터가 0이 아니고 ZF가 0이면 주소로 이동함

 

 

 

 

 

[다형성 코드]

 

  • 컴파일 과정에서 코드의 최적화 수행
  • 동일한 결과이나 다른 코드로 생성됨
기계어 어셈블리어 의미
B8 0000000 MOV EAX, 0 EAX에 0을 저장함 
31C0 XOR EAX, EAX
83 E0 00 AND EAX, 0
6A 00
58
PUSH 0
POP EAX
83F8 00 CMP EAX, 0 EAX가 0인지 비교함
85C0 TEST EAX, EAX

 

 

 

 


 

 

 

 

 

[레지스터 종류(32비트)]

구분 명칭 이름 Bit 용도
범용 레지스터
(General Register)
EAX 누산기(Accumulator) 32 주로 산술 연산에 사용(함수 결과값 저장)
EBX 베이스 레지스터 32 특정 주소 저장

ECX 카운터 레지스터 32 반복적으로 실행되는 특정 명령어
(루프 반복 횟수, 시프트 비트 수) 
EDX 데이터 레지스터 32 일반 자료 저장(입출력 동작에 사용
세그먼트 레지스터
(Segment Register)
CS 코드 세그먼트 레지스터  16 실행될 기계 명령어가 저장된 메모리 주소 지정
DS 데이터 세그먼트 레지스터 16 프로그램에 정의된 데이터, 상수, 작업 영역의 메모리 주소 지정
SS 스택 세그먼트 레지스터 16 프로그램이 임시로 저장할 필요가 있거나 사용자의 피호출 서브루틴이 사용할 데이터와 주소 포함 
ES,FS,GS 엑스트라 세그먼트 레지스터 16 문자 연산과 추가 메모리 지정을 위해 사용되는 여분의 레지스터
포인터 레지스터
(Pointer Register)
EBP 베이스 포인터 32 ss레지스터와 함께 사용되어 스택 내의 변수 값을 읽는 데 사용
ESP 스택 포인터 32 ss레지스터와 함께 사용되어 스택의 끝 주소를 가리킴
EIP 명령어(Instruction) 포인터 32 다음 명령어의 오프셋(상대위치주소)를 저장하며 CS 레지스터와 합쳐져 다음에 수행될 명령의 주소 형성 
인덱스 레지스터 
(Index Register)
EDI 목적지(Destination) 인덱스 32 목적지 주소에 대한 값 저장
ESI 출발지(Source)인덱스 32 출발지 주소에 대한 값 저장
플래그 레지스터
(Flag Register)
EFLAGS 플래그 인덱스 32 연산 결과 및 시스템 상태와 관련된 여러 가지 플래그 값 저장

 

 

[윈도우 메모리 구조]

  • 모든 프로그램은 실행하기 전에 메모리로 로드됨
    - 취약점 발생도 가능하며 취약점에 대한 공격도 발생
    - Buffer overflow, Memory Corruption
  • 32Bit 윈도우 메모리 구조
    - 프로세스 별로 4G로 구성
  • 가상메모리
    - 여러 개의 프로그램 실행, 4G 이상 활용
    - 유저영역 2G + 커널영역 2G = 4G
    - 실행되는 프로세서를 할당/적재


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

PUSH EBP

- 이전 스택 프레임의 EBP를 SFP(Stack Frame Pointer)에 저장

 -> 스택 프레임 제거 후 원래 스택 프레임으로 복귀하기 위해서 이전 스택 프레임의 EBP를 저장....