본문 바로가기
프로그래밍/SYSTEM HACKING

[SYSTEM HACKING] 어셈블리 call & jmp 명령의 차이 / 스택 메모리를 이용한 인자 전달 / reverse.asm 지역변수 사용해서 표현하는 실습

by B T Y 2017. 11. 1.
반응형

어셈블리 call & jmp 명령의 차이 / 스택 메모리를 이용한 인자 전달 / reverse.asm 지역변수 사용해서 표현하는 실습에 대해서 정리한다.

 

 

1. call & jmp 명령의 차이

 

  - 해당 주소의 명령을 실행

  - 해당 주소를 eip 레지스터에 저장 ( call 명령의 경우 )

 

차이점:

  - jmp 명령어는 해당 주소를 바로 이동

  - call 명령어는 스택에 데이터를 저장하고 이동( 복귀할 주소를 push 해서 스택에 저장 )

 

     * eip 레지스터에는 다음에 실행할 명령어의 주소가 들어있다.

 

 

2. 스택 메모리를 이용한 인자 전달

 

   - 함수는 프롤로그와 에필로그로 구분하기 때문에 main도 함수이므로 적용해줘야 한다.

 

[ 어셈블리 코드 - func.asm ]

extern printf

 

section .data

prompt_hex: db '0x%08x', 10, 00

prompt_int: db '%d', 10, 00

prompt_sum: db 'sum is: %d', 10, 00

 

section .text

global main

 

sum:

push ebp

mov ebp, esp         ;  prologue

mov esp, 4

 

mov eax, dword [ebp+8]

mov dword [ebp-4], eax

 

mov edx, dword [ebp+12]

add dword [ebp-4], edx ;  sum = a+b;

 

mov eax, [ebp-4] ;  return sum;

 

leave         ;  mov esp, ebp ;  pop ebp

ret         ;  pop eip ;  epilogue

main:

push ebp

mov ebp, esp         ;  prologue

sub esp, 12

 

mov dword [ebp-4], 10 ;  int a = 10;

mov dword [ebp-8], 20 ;  int b = 20;

mov dword [ebp-12], 0 ;  int sum = 0;

 

push dword [ebp-8]

push dword [ebp-4]

call sum         ;  push eip ; jmp addr

add esp, 8

 

mov [ebp-12], eax ;  ret = sum(a,b);

push dword [ebp-12]

push prompt_sum

call printf

add esp, 8

 

xor eax, eax         ;  return 0;

 

leave

ret         ;  epilogue

 

 

! C Calling Convenction

  - C 호출 규약에 따른 내용

 

 

1. callee-saved register

  - 콜리가 사용하기 전에 반드시 백업해야 하는 레지스터, 콜러는 사용 가능 ( 스택 메모리에 백업 )

  - ebp, esi, edi, ebx

 

2. caller-saved register

  - 콜러가 사용하기 전에 반드시 백업해야 하는 레지스터, 콜리는 사용 가능

  - eax, ecx, edx

 

 

 

 

[실습]

  - 지난번에 작성했던 reverse.asm 코드를 지역변수를 사용해서 동작하도록 수정

     ( 모든 변수는 스택 메모리를 사용 )

 

 

[ C언어 코드 ]

char buffer[1024];

int len = 0;

int i = 0;

 

int main() {

  gets ( buffer );

 

  while( buffer[len] != '\0' ) {

    len++;

  }

  len--;

 

  for( i = len; i >= 0; i-- ) {

    printf("%c", buffer[i]);

  }

  printf("\n");

 

  return 0;

}

 

 

[ 어셈블리 코드 ]

extern printf

extern gets

 

section .data

print_chr db '%c', 00

print_new db 10, 00

 

section .text

global main

 

main:

push ebp

mov ebp, esp         ;  prologue;

sub esp, 1028

 

lea eax, [ebp-1024]

push eax

call gets          ;  gets( buffer );

 

mov dword [ebp-1028], 0 ;  int len = 0;

while:

mov edx, dword [ebp-1028]

cmp byte [ebp-1024+edx], 0

jz while_end         ;  buffer[len] != 0;

 

inc dword [ebp-1028] ;  len++;

jmp while

while_end:

dec dword [ebp-1028] ;  len--;

for:

cmp dword [ebp-1028], 0

jl end         ;  i >= 0;

 

mov edx, dword [ebp-1028];  i = len;

mov eax, [ebp-1024+edx]

 

push eax

push print_chr

call printf ;  printf("%c", buffer[i]);

 

dec dword [ebp-1028] ;  i--;

jmp for

end:

push print_new

call printf ;  printf("\n");

 

leave

ret         ;  epilogue

 

 

 

 

반응형

댓글