본문 바로가기

Hacking & Security/Reverse Engineering

#1. Reverse Engineering

리버싱 기초 낙서장.



어셈블리어 : 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