Self-Improvement
리버싱 기초 2 (어셈블리어) 본문
*어셈블리어
기계어(101010)를 묶어서 의미가있는 형태로 표시한 저수준의 프로그래밍 언어이다.
디스어셈블러 : 기계어 0 과 1을 어셈블리 코드로 변환하는 툴
※각 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 또는 -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, 두개의 비트가 모두 0 또는 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
'리버싱 기초' 카테고리의 다른 글
함수 호출 규약 (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 |