리버싱 기초 낙서장.
어셈블리어 : CPU가 이해하는 기계어와 1:1 매칭되는 low level 언어.
CPU 아키텍처마다 어셈블리어가 다르다. -> 즉 , 많은 어셈블리어가 존재한다.
기호로 이루어져 있어서 되게 직관적이다
상용되어지는 문법은 2개이다. ( Intel , AT&T )
일반저인 형태 : 명령 operand1 , operand2
(operand : 연산의 대상으로 레지스터나 숫자 등이 올 수 있다. )
ex1) AT&T) mov $0x1, %eax
ex2) Intel) mov eax, 0x1
이번글에서는 Intel 문법을 이용하겠다.
레지스터 : 값을 담아놓는 공간 ( = 다기능변수 ) , CPU에 존재하며 여러가지 레지스터가 존재한다.
범용 레지스터 ( x86 기준)
eax : accumulator register // 함수의 return 값이 저장.
ebx : base
ecx : count
edx : data register
esi : source index
edi : destination index
esp : stack pointer //스택 프레임 포인터
ebp : base pointer //스택 프레임의 기준
eip : instruction pointer // 실행할 코드의 주소
어셈블리 명령
mov : source 값을 destination에 대입한다.
mov destination , source
ex) mov eax , 0x1
lea : source의 주소를 destination에 대입한다.
lea destination , source
ex) lea ebx , [eax] // [] 자체가 포인터 기능을 한다.
add : destination에 source를 더한다.
add destination , source
ex) add esp , 0x4
sub : destination에서 source를 뺀다.
sub destination , source
ex) sub esp , 0x20
inc : 레지스터의 값을 1 올린다.
dec : 레지스터의 값을 1 내린다.
xor : source와 destination을 XOR 연산을 한 뒤 , destination에 담는다.
xor destination , source
ex ) xor ebx , eax
and : source와 destination을 and 연산을 한 뒤 , destination에 담는다.
and destination , source
ex) and esp , 0xffffff20
or : source와 destination을 or 연산을 한 뒤 , destination에 담는다.
or destination , source
cmp : destination과 source를 비교한다. ( destination이 source보다 ~ 할 때 , 조건 성립 )
cmp destination , source
jmp : 지정 주소로 eip 지정.
ex) jmp 0x8048841
jmp 명령어
je ( jump equal ) : 두 값이 같으면 jump
jb ( jump below ) : destination이 더 작으면 jump ( unsigned )
ja ( jump above ) : destination이 더 크면 jump ( unsigned )
jl ( jump less ) : destination이 더 작으면 jump ( signed )
jg ( jump greater ) : destination 이 더 크면 jump ( signed )
jne ( jump not equal ) : 두 값이 같지 않으면 jump
call : 현재 EIP를 memory에 저장 후 지정 주소로 jmp // 함수 호출시 사용
ex ) call 0x8048360
push : esp를 감소시키고 지정한 데이터를 esp가 가리키고 있는 곳에 저장.
ex) push ebp
pop : 현재 esp가 가리키고 있는 값을 해당 레지스터로 복원
ex) pop ebp
ret : 현재 esp가 가리키고 있는 값을 eip로 바꾼다.
memory 구조
스택 : 함수들이 사용할 공간으로 지역변수들이 위치한다.
힙 : 동적 할당을 위한 공간 , ( malloc() 같은 함수들을 통하여 할당 가능 )
데이터 : 문자열이나 정적 변수들이 위치.
BSS : 전역 변수들이 존재한다.
Text(Code) : 실제 프로그램의 코드들이 존재한다. ( opcode)
Stack Frame
- 각 함수마다 사용할 공간을 할당한 것.
- 함수가 끝나면 메모리에 저장해놓은 복귀주소 (Return Address)를 참조하여 이전 주소로 복귀한다.
스택 프레임의 예시
push : esp -= 4 후 , 지정한 값을 스택에 저장
pop : esp의 값을 가져와 지정 레지스터에 저장후 esp += 4
ret : 현재 esp가 가리키고 있는 값을 eip로 저장하고 esp += 4 , pop eip와 같은 기능.
SFP ( Stack Frame Pointer ) 는 이전함수의 EBP를 스택프레임에 저장해두는 역할.
간단한 소스 작성 후 , disas해보자.
소스는 다음과 같다.
gdb를 통해 disas main한 결과다.
+29 , +36 : mov를 통해 지역변수 (a,b)에 값을 넣어준다. ( 0xa = 10 , 0x14 = 20 )
+46 , +49 : push를 통해 함수 호출 전 인자를 정리한다.
+52 : add함수를 호출한다.
add함수를 살펴보자.
+13 , +16 : mov를 통해 매개변수를 전달 받는다.
그리고 함수 종료 전 리턴값을 지정한다.
그리고 복귀주소로 돌아가 printf함수를 통해 값을 출력하고 마무리한다.
'Hacking & Security > Reverse Engineering' 카테고리의 다른 글
Stolen Bytes (0) | 2019.09.26 |
---|---|
x86 그리고 x64 (0) | 2019.09.26 |
Reverse Engineering 2 (0) | 2017.11.23 |
Reverse Engineering (0) | 2017.11.23 |
디버깅 단축키 , 기본 어셈블리어 (0) | 2017.11.19 |