기초

2020. 8. 7. 16:52
어셈블리어란?

2진수 형태의 기계어를 사람이 알아볼 수 있는 명령어로 표현한 언어

기계어와 1대1 대응

CPU 아키텍쳐마다 어셈블리어가 다름 (Intel x86 ≠ ARM ≠ MIPS)

 

어셈블리어 = opcode(명령코드) + operand(피연산자)

 

 

어셈블리어 (x86)

MOV

MOV [reg|addr], [imm|reg|mem]

MOV EAX, 4 // 4를 EAX에 저장
MOV ESI, ESP // ESP의 값을 ESI에 저장

 

LEA

LEA [reg], [mem]

LEA EAX, [EBP+10] // EBP+10에 저장된 주소를 EAX에 저장
LEA ESI, [EAX+4] // EAX+4 주소를 ESI에 저장

 

CMP

CMP [reg|mem], [imm|reg|mem]

CMP EAX, 1 // EAX의 값을 1과 비교
CMP EAX, [EBP+4] // EAX의 값이 EBP+4 위치에 있는 값과 같은지 비교
                             ; ZF=1 if eax = *(ebp+4)
                             ; ZF=0 if eax != *(ebp+4)
                             ; CF=1 if eax < *(ebp+4)
                             ; CF=0 if eax > *(ebp+4)

 

TEST

TEST [reg], [imm|reg]

TEST EAX, 1 // EAX의 값을 1과 비교
TEST EAX, [EBP+4] // EAX의 값이 EBP+5 위치에 있는 값과 같은지 비교
                             ; ZF=1 if rax = 0
                             ; SF=1 if rax < 0

 

JMP, JE, JNE

JMP [imm|reg|mem]

JMP 0x400a31 // 0x400a31 번지로 분기
JE 0x400a31 // ZF=1일 경우 분기
JG 0x400a31 // 첫번째가 클 경우 분기

 

CALL

CALL [mem]

CALL printf@plt // printf함수를 호출
CALL 0x8044096 // 0x8044096번지에 있는 함수를 호출

 

CALL vs JMP

JMP : JMP할 주소로 '그냥' 이동

CALL : CALL 다음에 있는 명령어 주소를 '스택에 PUSH'한 뒤 이동

 

RET

현재 ESP가 가리키고 있는 값으로 jump

  -> 스택 최상위에 있는 값으로 jump

  -> ESP가 4 증가한다. (64bit에선 8증가)

 

  함수의 가장 마지막에 오는 명령

 

REP

RCX 레지스터를 1씩 감소 시키면서, 문자열 관련 명령어를 처리한다.

 

STOS

AX를 EDI가 가리키는 주소에 넣음

rep stos byte ptr [EDI]

 

SCAS

AX에 저장된 값과 EDI가 가리키는 곳에 저장된 값을 비교

 

PUSH [reg]

스택 최상위에 값 넣기

POP [reg]

스택 최상위 값 뽑기

PUSH 0x41414141 // 스택에 0x41414141값을 push
POP EAX // 스택 최상단의 값을 EAX 레지스터로 이동

 

ADD eax, 6

eax = eax + 6

SUB eax, 5

eax = eax + 5

MUL eax, 5

eax = eax * 5

DIV eax, 5

eax = eax / 5

※ ADD, SUB, MUL, DIV에 [reg|mem]의 인자를 하나만 던져주면, 바로 전의 [reg|mem]을 첫번째 인자로 받아들여 연산을 수행한다. overflow(OV)가 발생하면 뒤의 4자리는 EAX에, 나머지 자리는 EDX에 저장된다.

※ 간단한 숫자를 위해 16bit의 레지스터 사용

MOV AX, 8000 // AX에 8000 저장
MOV BX, 3 // BX에 3 저장
---
현재 값
AX = 8000
BX = 0003
DX = 0000
NV
---
MUL BX // MUL AX, BX와 같은 구문
-> 8000 * 3을 16진수로 계산 -> 18000, OV가 발생, 뒤의 4자리(OV가 발생한 뒤의 값)을 AX에 저장, 나머지 (OV로 인해 발생된 값)을 DX에 저장한다. { NV -> OV로 바뀌는 시점 }
---
현재 값
AX = 8000
BX = 0003
DX = 0001
OV
---

 

INC ECX

ECX를 1증가

 

DEC ECX

ECX 1감소

 

SFP

스택 프레임을 거치고 함수가 돌아와야할 주소를 가지고 있는 포인터이다.

'[▒] 언어 > Assembly' 카테고리의 다른 글

Shellcode - Shell Reverse TCP Shellcode  (0) 2020.09.11
직접 만든 수제 쉘코드  (0) 2020.09.07
메모리 구조  (0) 2020.08.08

BELATED ARTICLES

more