본문 바로가기
Security/Reversing

레지스터 명령어

by jino22 2020. 12. 1.

틀린 부분이 있다면 언제든지 댓글 남겨주세요! 

 

리버싱 기초 - 레지스터 기본 명령어

 


Opcode (명령어)

 

[명령어] dst, src

 

Data Movement

- mov: src의 을 dst로 옮김 (길이가 반드시 일치해야 함 WORD-WORD, BYTE-BYTE)

   * MOVSX(부호o), MOVZX(부호x)는 길이가 달라도 가능 (BYTE-WORD, WORD-DWORD) 0비트로 채움

- lea: src의 주소를 dst에 저장

 

Arithmetic Operations

- inc / dec: dst의 값을 1 증가/감소 = ++dst / --dst

- neg: dst의 값의 부호를 바꿈 (2의 보수) = -dst

- not: dst의 값의 비트를 반전 = ~dst

- add / sub / imul / idiv: dst의 값에 src를 더함/뺌/곱함/나눔 = dst+=src / dsc-=src / dsc*=src

  * ADC/SBB: 연산시 carry값을 포함해서 더함/뺌

  * 인자가 3개인 경우 명령여 dest source1 source2 ( ex) imul edx, ecx, 0 > ecx * 0 한 값을 edx에 넣음 )

  mul / div: EAX 레지스터의 내용에 src의 값을 곱함/나눠 EAX에 저장 (몫은 EAX에 나머지는 EDX에 저장)

- and / or / xor: dst의 값과 src간에 AND/OR/XOR 논리연산한 결과를 dst에 저장 = dst&=src / dsc|=src / dsc^=src

- shl / shr: dst의 값을 k만큼 왼쪽/오른쪽으로 shift (빈자리는 0으로 채움) = dst << k / dst >> k

- sal / sar: dst의 값을 k만큼 왼쪽/오른쪽으로 shift하는데 부호가 유지됨 (즉 최상위 비트는 바뀌지 않음)

 

Conditional Operations

- test: and연산자와 같이 AND연산을 하지만 결과가 dst에 저장되지 않고 FLAGS의 ZF, SF에 영향
  연산 결과가 음수이면(최상위비트가 1이면) SF=1, 양수이면(0이면) ZF=1

  * test eax, eax 형태로 주로 사용. eax가 0인지 아닌지 확인하기 위함 (0이면 ZF=1이므로 아래에 je가 있는 경우 분기)

- cmp: sub연산자와 같이 SUB연산을 하지만 결과가 dst에 저장되지 않고 FLAGS의 ZF, CF에 영향

  dst=src인 경우 ZF=1/CF=0이고, dst<src인 경우 ZF=0/CF=1이고, dst>src인 경우 ZF=0/CF=0이다

 

[명령어] location

- jmp: 피연산자가 가리키는곳으로 점프

- 연산 수행 결과에 따라 점프의 수행 여부 결정 (jcc=Jump if condition is met)

명령어 의미
JE ZF=1 (equal)
(ZF=1)
JNE ZF=0 (not equal)
(CF=0)
JG (greater) >    (signed)
JGE >=  (signed)
JAE >= (unsigned)
(CF=0)
JL (less) <    (signed)
JLE <=  (signed)
JBE <= (unsigned)
(CF=1 OR ZF =1)
JA (above) >    (unsigned)
(CF=0 AND ZF=0)
JB (below) <    (unsigned)
(CF=1)
JS SF=1 (negative)
(SF=1)
JNS SF=0 (not negative)

 

Operand

(64bit에선 맨앞에 r이, 32bit에선 e가 붙음!)

▶ General-Purpose Registers: 연산을 할 때 어떤 목적으로 사용하든 상관 없음

 

   - ESI:복사할때 복사할 source data 저장

   - EDI: 복사할 destination data 저장

   - EAX(Accumulator for operands and result data): +, -와 같은 연산에 사용, 함수가 끝날때 함수의 반환값(return) 저장

   - EDX: eax와 비슷하게 연산에 사용되지만 return값 반환에는 사용되지 않음

   - ECX(Counter for string and loop operation): Counter register (for문의 i++과 같은 역할)

   - EBX(Pointer to data in the DS Segment): EAX, EDX, ECX가 부족할때 사용하는 여분의 레지스터

   - Flag register: 분기값의 상태

 

레지스터 스택 명령어

- function prologue: 새로운 함수가 시작될 때 스택이 준비

   => rsp에 들어있는 주소에서 충분한 값을 빼 함수 안의 지역변수를 위한 공간 확보

- function epilogue: 함수가 종료될 때 스택이 정리

   => prologue에서 빼준 값 만큼 다시 rsp에 더해 사용한 스택 정리

 

[명령어] r(e)di

 - EBP(=base pointer): stack의 기준점, 즉 시작지점을 지정할때 사용

 - ESP(=stack pointer): stack의 끝 지점, 즉 가장 위쪽 주소로 마지막으로 데이터가 추가된 위치

* 아키텍처에 따라 스택이 쌓이는 방향이 다름. Intel x86-64 아키텍처에서는 스택이 낮은 주소(=더 작은 숫자)로 쌓이기 때문에 rsp에 저장된 메모리 주소는 점점 낮아짐

 

- push: 스택에 새로운 데이터 추가

  = sub rsp, 8               mov [rsp], rdi

- pop: 스택의 최상단에 있는 데이터 뺌

  = mov rdi, [rsp]        add rsp, 8

 

- call: 실행할 함수의 주소

   = push retaddr     jmp location

* caller standard register: eax, ecx, edx 

* CALL과 JMP의 차이: CALL은 스택에 다음 주소를 저장함. 즉 CALL함수를 빠져나온 후 돌아가야할 주소가 저장됨. 반면 JMP는 그냥 그 위치로 가고 끝! 

 

- ret: 함수 종료 후 돌아갈 주소로 돌아가는 역할

   = pop rip                 jmp rip

 

 

내가 참고하려고 아무렇게나 추가하는 분석하면서 찾아본 명령어

더보기

PUSHAD :레지스터 값을 스택에 저장

  순서: EDI-ESI-EBP-ESP-EBX-EDX-ECX-EAX

  이때 레지스터의 크기(32BYTE=4BYTE*8)만큼 ESP감소

 

NOP: 아무일도 하지 않음

 

NEG: 2의 보수

 

SHL: 왼쪽 shift

SHR: 오른쪽 shift

SAL: 왼쪽 산술 shift

SAR: 오른쪽 산술 shift

ROL: 왼쪽 회전 shift

ROR: 오른쪽 회전 shift

RCL: 왼쪽 캐리포함 회전

RCR: 오른쪽 캐리포함 회전

SHLD: 2배 정밀도 왼쪽 shift

SHRD: 2배 정밀도 오른쪽 shift

 

LODS(load string): (E)SI주소가 가리키는 값을 (E)AX(AL, RAX)에 로드, ESI의 값은 다음 주소값으로 로드.

 

STOS :EDI가 가리키는 주소에 EAX값을 로드, EDI값은 EAX의 크기만큼 증가. 

 

LEA와 MOV의 차이: LEA는 좌변(레지스터만 가능)에 우변의 주소값(상수 불가)을 로드하고 MOV는 우변의 메모리값(상수 가능)을 로드한다.

 

XCHG:  두 피연산자의 데이터 교환. 즉 temp같은 역할

 

DWORD PTR DS[](StackSegment) :data영역의 주소 4바이트 공간

DWORD PTR SS[](DataSegment) :stack영역의 주소 4바이트 공간

DWORD PTR ES[](ExtraSegment) :목적지 또는 DS의 보조

 

AL: EAX의 하위 8bit

TEST AL, AL : AL이 0이 아니면 ZF=0, JNE(not equal)분기

 

 

STC(Set Carry Flag): 캐리 플래그(CF) =1
CLC(Clear Carry Flag): 캐리 플래그(CF) =0
STD(Set Direction Flag): 방향 플래그(DF) =1

* 방향플래그가 1이면 스트링 인스트럭션 수행 후 ESI/EDI값이 감소

(BYTE -1, WORD -2, DWORD -4)
CLD(Clear Direction Flag): 방향 플래그(DF) =0

* 방향플래그가 0이어야 스트링 인스트럭션 수행 후 ESI/ED값 증가

STI(Set Interrupt Flag): 인터럽트 플래그(IF) =1
CLI(Clear Interrupt Flag): 인터럽트 플래그(IF) =0

 

REPE (Repeat String Equal) =REPZ
문자열 관련 명령을 ECX>0인 동안 ECX -1 하면서 반복. 즉 ECX 를 카운터로  사용하여 문자열을 비교하는 명령어.

같으면 반복해라. ZF=0 이거나 ECX=0이면 멈춤.

= REP(E) CMPS [destination], [source]

* CMPS(CoMPare String). CMPSB(Byte)/W(Word)/D(Double Word)

REPNE SCAS: 간단하게 해당 위치의 문자열 길이를 구한다고 생각. 

 

CMOV  : Conditional Move.

ex) CMOVZ ecx, esi인 경우 ecx가 0(ZF==0)이면 ecx에 esi 대입

 

SETNE: not equal zero, ZF=0 (zero가 아님) 이면 1을 가짐.

SETE: equal zero, ZF=1 (zero임) 이면 1을 가짐.

728x90
반응형

'Security > Reversing' 카테고리의 다른 글

PEB TEB  (0) 2021.02.02
Abex crackme #2 / ollydbg 단축키  (0) 2021.01.25
Reversing Basic Challenge #1  (0) 2020.12.20
Reversing Basic Challenge #0  (0) 2020.12.19
x64dbg 기본 사용법  (0) 2020.12.17

댓글