Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

TH3 6R3@T H@CK

Assembly 본문

Study/Reverse Engineering

Assembly

vvh0am1 2024. 3. 23. 21:19

· 옵코드 opcode: 명령어

- ex) mov, push

 

· 오퍼랜드 operand: 인자, 명령어 다음에 "어떤 장소로 값을 넣을 것인지" 또는 "명령어에 해당하는 값"

- 오퍼랜드가 2개인 경우 → 앞의 오퍼랜드: destination / 뒤의 오퍼랜드: source

 

· EAX: Accumulator

- 산술 계산을 하며, 리턴값을 전달

 

· EDX: Data

- EAX와 역할은 같되, 리턴 값의 용도로는 사용되지 않음

 

· ECX: Count

- 루프문을 수행할 때 카운팅하는 역할

- 미리 루프를 돌 값을 넣어놓고 감소시키며 루프 카운터가 0이 될 때까지 카운팅

 

· EBX: Base

- 레지스터가 하나쯤 더 필요하거나 공간이 필요할 때 등 적당한 용도를 프로그래머나 컴파일러가 알아서 만들어서 사용

 

· ESI: Source Index

· EDI: Destination Index

 

 

· AX: 16bit / 2byte

· AH, AL: 8bit / 1byte

 

32bit 16bit 상위 8bit 하위 8bit
EAX AX AH AL
EDX DX DH DL
ECX CX CH CL
EBX BX BH BL

 

 

· PUSH, POP

- 순서대로 스택에 값을 넣는 것 / 스택에 있는 값을 가져오는 것

- PUSHAD, POPAD: 모든 레지스터를 PUSH하고 POP하라는 명령어

- 오퍼랜드는 1개만

 

· MOV

- 단지 값을 넣는 역할

 

· LEA

- 주소를 가져옴 (*MOV는 값을 가져옴)

- 가져올 src 오퍼랜드가 주소라는 의미로 대부분 []로 둘러싸여 있음

 

예시)

가정: 레지스터와 메모리에 다음과 같은 값이 들어있다.

 

esi : 0x401000 (esi에는 0x401000이라는 값이 들어있다)

*esi : 5640EC83 (esi가 가리키는 번지에는 5640EC83라는 값이 들어있다)

esp+8 : 0x13FF40

*(esp+8) : 33

 

lea eax, dword ptr ds : [esi]

esi가 0x401000이므로 eax에는 0x401000이 들어온다

 

mov eax, dword ptr ds : [esi]

esi가 0x401000이므로 eax에는 0x401000 번지가 가리키는 5640EC83이라는 값이 들어온다

 

lea eax, dword ptr ss : [esp+8]

esp+8은 스택이며, eax에는 0x13FF40라는 값이 들어온다

 

mov eax, dword ptr ss : [esp+8]

esp+8은 스택이며, eax에는 0x13FF40가 가리키는 값인 33이 들어온다

 

· ADD

- src에서 dest로 값을 더하는 명령어

 

· SUB

- ADD와 반대되는 뺄셈 명령어

 

· INT

- 인터럽트를 일으키는 명령어

 

· CALL

- 함수를 호출하는 명령어

- CALL 뒤에 오퍼랜드로 번지가 붙음

- 해당 번지를 호출하고 작업이 끝나면 CALL 다음 번지로 되돌아옴 (CALL로 호출된 코드 안에서는 반드시 RET를 만나게 되어 다시 호출한 쪽으로 돌아오기 때문)

 

· INC, DEC

- 순서대로 i++; / i--;

 

· AND, OR, XOR

- dest와 src를 연산

- XOR은 dest와 src를 동일한 오퍼랜드로 처리 가능

ex) XOR EAX, EAX → EAX는 0

 

· NOP

- 아무것도 하지 말라는 명령어

 

· CMP, JMP

- 비교해서 점프하는 명령어

 

· 리버스 엔지니어링에 필요한 스택

1. 함수 호출 시 파라미터가 들어가는 방향

2. 리턴 주소

3. 지역 변수 사용

 

예시)

push ebp

ebp 레지스터를 스택에 넣음

 

mov ebp, esp

현재 esp 값을 ebp에 넣음

→ ebp와 esp가 같아지면서 이 함수에서 지역변수는 ebp에서부터 얼마든지 게산 가능 (ebp를 기준으로 오프셋을 더하고 빼는 작업으로 스택을 처리할 수 있음)

 

sub esp, 50h

esp에서 50h만큼 뺌 → 50h만큼 지역변수 사용

 

예시) HelloFunction이라는 함수, DWORD 타입으로 3개의 인자를 받는 함수 타입

DWORD HelloFunction(DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)

 

HelloFunction 호출

main()

{

    DWORD dwRet = HelloFunction(0x37, 0x38, 0x39);

    if (dwRet)

    // .....

}

 

push 39h

push 38h

push 37h

call 401300h

 

- 함수의 인자는 스택에 값을 LIFO 순서대로 넣기 때문에 실제로 소스 코드에서 호출한 것과는 반대로 들어감

- 파라미터를 push로 넣어 놓았기 때문에 이 값들에 접근하려면 ebp에서 오프셋을 더하는 방식으로 계산해야 함 → ebp+x 형태- ebp+8: 첫 번째 인자인 37h / ebp+0xc: 두 번째 인자인 38h / ebp+0x10: 세 번째 인자인 39h