Self-Improvement

리버싱 기초 2 (어셈블리어) 본문

리버싱 기초

리버싱 기초 2 (어셈블리어)

JoGeun 2018. 10. 20. 14:32

*어셈블리어 
기계어(101010)를 묶어서 의미가있는 형태로 표시한 저수준의 프로그래밍 언어이다. 
디스어셈블러 : 기계어 0 과 1을 어셈블리 코드로 변환하는 툴



gdb : GNU 디버거

※각 CPU 마다 고유 어셈블리어 존재 

*어셈블리 구성
윈도우 : Intel 문법 사용
 ex) add (Destination) (Source) 

리눅스 : AT&T 문법 사용
 ex)  add (Source) (Destination)

*어셈블리 명령어 형식
1. opcode 
  ex) std

2. opcode operand1 
  ex) push eax

3. opcode operand1, operand2 
  ex) add 10, eax

4. opcode operand1, operand2, operand3 
  ex) shld 16, edx, eax

*opcode 종류
1. 산술 연산 명령
2. 데이터 전송 명령
3. 논리 연산 명령
4. 제어 전송 명령
5. 스트링 명령
6. 프로세스 제어 명령


*산술 연산 명령
add(Add)
덧셈명령캐리를 포함하지 않는 덧셈을 한다
ex) add $0x10, %esp  :  esp += 10 
ex) add ecx, eax  :  eax += ecx 


sub(Subtract)
캐리를 포함하지 않는 뺄셈(뺄셈 연산 처리에 사용)
ex) sub $0xc, %esp  :  esp -= 0xc 

inc(Increment)
오퍼랜드 값을 1만큼 증가한다.
ex) inc eax  :  eax++ 

dec(Decrement)
오퍼랜드 값을 1만큼 감소한다.
ex) dec eax  :  eax-- 

cmp(Compare)
두 오퍼랜드 비교두수를 비교하여 같으면 0, 다르면 또는 -1을 리
턴하는 명령어이다두 데이터를 비교하여 이를 Flag Register의 ZF(Zero Flag)에 같으면 0으로 다르면 1로 세팅한다두 오퍼랜드 값이 같다는 것을 비교하는 방법은 오퍼랜드를 뺀값이 0이면 참이고 아니면 거짓이다.
ex) cmp ecx, eax  :  if (ecx == eax) ZF=1 else ZF=0 
....
....

*데이터 전송 명령
mov(Move)
데이터 이동하는데 사용. RAM 끼리의 연산은 이루어 지지 않으므로 RAM의 데이터를 레지스터로 옮기거나 레지스터의 데이터를 RAM으로 옮기는 작업을 처리할 때 주로 사용한다.
ex) mov $0x0, %eax  :  EAX = 0 
ex) mov ecx, eax  :  EAX = ECX 

push(Push)
오퍼랜드의 내용을 스택에 넣는다. 레지스터의 데이터 임시 보관등에 사용한다.
ex) push $0x8048680  :  Stack에 0x8048680 값을 저장

pop(Pop)
스택으로 부터 값을 빼낸다. 레지스터의 데이터를 복원할 때 주로 사용한다.
ex) pop eax  :  Stack 값을 EAX에 저장

lea(Load Effective Address to Register) 
유효주소를 레지스터로 로드(Load). RAM에서 CPU에 있는 레지스터에 데이터를 옮길때 로드(Load)라는 단어를 사용반대로 레지스터에서 RAM으로 가는 경우 저장(Store)이라는 표현을 사용한다.
* RAM -- Load --> CPU(Register)
* RAM <-- Save -- CPU(Register)
ex) lea 0xffffffd8(%ebp), %eax  :  RAM(주소(0xffffffd8)의 값)을 eax 저장
....
....

*논리연산 명령
and(AND)
논리 and 연산두수의 곱셈 연산 후 결과를 참과 거짓으로 표현하는 것으로 교집합의 형태와 동일하다대응되는 비트가 둘다 1일 때만 결과가 1이고그 이외에는 모두 0

or(OR)
논리 or 연산두수의 덧셈 연산 후 결과를 참과 거짓으로 표현하는 것으로 합집합의 형태와 동일하다대응되는 비트 중 하나만 1이어도 결과가 1이고둘 다 0인 경우에만 0

xor(Exclusive OR)
배타적 논리 합(OR) 연산두수가 같은 값을 가지면 거짓다른 값을 가지면 참을 반환하는 연산으로 초기화 연산이나 암호화 시에 주로 사용한다대응되는 비트 중에서 한 비트가 1이고 다른 비트가 0이면 1, 두개의 비트가 모두 또는 1일 때 0, 따라서 두개의 비트가 같으면 0, 다르면 1이다.

not(Invert)
오퍼랜드의 1의 보수각 비트별 반대의 값으로 변환하여 1의 보수화

test(And Function to Flags, no result)
첫번째 오퍼랜드와 두번째 오퍼랜드를 and 하여 그 결과로 플래그 세트, and 연산과 같으나 연산 결과를 저장하지 않고 그 결과를 Flag Register에 저장한다데이터 두 값을 비교할 때 사용한다데이터의 변경 없이 단순 비교에 사용된다.
....
....

*제어 전송 명령
JMP(Unconditional Jump)
프로그램을 실행할 주소 또는 라벨로 이동한다.
ex) jmp 04001000  :  if(무조건) 04001000 번지로 jump 

JE(Jump Equal)/JZ(Jump Zero)
(점프조건) ZF == 1
ex) je 04001000  :  
if(ZF == 1) 04001000 번지로 jump 

JNE(Jump not equal)/JNZ(Jump not zero)
(점프조건) ZF == 0
ex) jne 04001000  :  if(ZF == 0) 04001000 번지로 jump 

call(Call)

함수(프로시저호출시 사용된다PUSH(EIP) + JMP(jump)의 두가지 기능을 하는 것으로 함수 호출시 그 함수의 복귀 주소를 push로 stack에 저장 시키며 jmp를 이용하여 그 함수로 이동한다.
ex) call 0x80483a8 <printf>  :  0x80483a8 번지의 printf() 호출(push + jump)


ret(Return)
함수에서 호출(call)한 위치로 돌아갈때 사
용한다. POP(EIP) + JMP(jump)의 두가지 기능을 하는 것으로 함수 지역으로 복귀한다.
....
....

*어셈블리 예제

 #vi test.c



 #gcc -o test test.c
 #gdb test
 (gdb) disassemble main




'리버싱 기초' 카테고리의 다른 글

함수 호출 규약  (0) 2018.11.03
MOV vs LEA  (0) 2018.10.28
리버싱 기초 4 (어셈블러 명령어)  (0) 2018.10.23
리버싱 기초 3 (어셈블러 명령어)  (0) 2018.10.23
리버싱 기초 1 (메모리, 레지스터)  (0) 2018.10.20