다음 어셈블리 코드를 한줄씩 살펴보고 C코드를 추측해본다.

 

1.

 

- push ebp, mov ebp, esp : 이 부분은 Prolog 영역으로 스택프레임을 생성하는 부분이다.

- sub esp, 0x14 : esp가 가리키는 주소를 0x14 만큼 뺌으로써 스택 사용을 준비한다.

- mov DWORD PTR [ebp-0x4], 0xa : ebp가 가리키는 주소로부터 0x4만큼 떨어진 곳에 0xa를 저장

- mov DWORD PTR [ebp-0x8], 0x14 : ebp가 가리키는 주소로부터 0x8만큼 떨어진 곳에 0x14를 저장

- mov DWORD PTR [ebp-0xc], 0x0 : ebp가 가리키는 주소로부터 0xc만큼 떨어진 곳에 0x0을 저장

- mov eax, DWORD PTR [ebp-0x8] : eax레지스터에 ebp-0x8 주소에 저장된 데이터를 복사

- mov edx, DWORD PTR [ebp-0x4] : edx레지스터에 ebp-0x4 주소에 저장된 데이터를 복사

- add eax, edx : eax레지스터에 eax에 저장된 데이터와 edx에 저장된 데이터의 합을 저장

- mov DWORD PTR [ebp-oxc], eax : eax에 저장된 데이터를 ebp-oxc 주소에 복사

- mov eax, DWORD PTR [ebp-0xc] : ebp-0xc 주소에 저장된 데이터를 eax에 복사

- mov DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax에 저장된 데이터를 복사

- mov DWORD PTR [esp], 0x80484f0 : esp가 가리키는 주소에 0x80484f0을 복사

- call 0x80482f0 <printf@plt> : 0x80482f0 주소를 호출하며 해당 주소는 printf 함수이다.

- leave : leave는 move esp, ebp; pop ebp의 두 명령어를 하나의 어셈블리어로 합친 것이다.

- ret : ret는 pop eip 를 수행하며 이전의 함수로 돌아간다.

 

위 어셈블리 코드를 보면 4바이트 데이터 3개를 스택에 저장(<+6>, <+13>, <+20>)하며 printf 함수를 호출(<+52>)하는 것을 알 수 있다.

이를 바탕으로 C코드를 추측해 보면 다음과 같다.

 

int main()

{

int a = 10, b = 20, c;

c = a + b;

printf("%d", c);

return 0;

}

 

2.

 

- and esp, 0xfffffff0 : esp레지스터를 최적화 하는 코드

- sub esp, 0x20 : esp가 가리키는 주소를 0x20만큼 빼 스택을 준비한다.

- mov DWORD PTR [esp+0x1c], 0x0 : esp+0x1c 주소에 0을 저장

- jmp 0x8048450 <main+51> : 0x8048450 주소로 점프

- cmp DWORD PTR [esp+0x1c], 0x2 : esp+0x1c 주소에 저장된 데이터와 0x2와 비교

- jne 0x804844b <main+46> : esp+0x1c 주소에 저장된 데이터와 0x2가 같지 않으면 0x804844b 주소로 점프

- mov eax, DWORD PTR [esp+0x1c] : eax레지스터에 esp+0x1c 주소에 저장된 데이터를 복사

- mov DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax레지스터에 저장된 데이터를 복사

- mov DWORD PTR [esp], 0x80484f0 : esp레즈서터가 가리키는 주소에 0x80484f0를 복사

- call 0x80482f0 <printf@plt> : 0x80482f0 주소를 호출하며 해당 주소는 printf()함수의 주소이다.

- add DWORD PTR [esp+0x1c], 0x1 : esp+0x1c 주소에 저장된 데이터에 1을 더함

- cmp DWORD PTR [esp+0x1c], 0x4 : esp+0x1c 주소에 저장된 데이터와 0x4를 비교

- jle 0x8048430 <main+19> : 비교 결과 esp+0x1c가 0x4보다 작거나 같으면 0x8048430 주소로 점프

- mov eax, 0x0 : eax 레지스터 초기화

 

위 어셈블리 코드를 보면 데이터를 비교하여 되돌아가는(<+51> <+56>) 부분이 반복되는 것을 알 수 있으며 데이터를 비교하여 처리하는(<+19> <+24) 부분이 있는 것을 알 수 있다.

이를 바탕으로 C코드를 추측해 보면 다음과 같다.

 

int main()

{

int i;

for( i = 0; i < 5; i++ )

{

if( i == 2 )

printf("%d", i);

}

return 0;

}

 

3.

- sub esp, 0x20 : esp가 가리카는 주소를 0x20만큼 빼 스택을 준비

- mov DWORD PTR [esp+0x18], 0xa : esp+0x18 주소에 0xa를 저장

- mov DWORD PTR [esp+0x1c], 0x14 : esp+0x1c 주소에 0x14를 저장

- mov eax, DWORD PTR [esp+0x1c] : eax에 esp+0x1c에 저장된 데이터를 복사

- DWORD PTR [esp+0x4], eax : esp+0x4 주소에 eax에 저장된 데이터를 복사

- mov eax, DWORD PTR [esp+0x18] : eax에 esp+0x18에 저장된 데이터를 복사

- mov DWORD PTR [esp], eax : esp가 가리키는 주소에 eax 데이터를 저장

- call 0x804841d <addVal> : 0x804841d 주소를 호출하며 addVal() 함수의 주소이다.

- mov DWORD PTR [esp+0x4], eax : addVal() 함수의 리턴값을 가진 eax의 데이터를 esp+0x4 주소에 복사

- mov DWORD PTR [esp], 0x8048500 : esp가 가리키는 주소에 0x8048500을 저장

- call 0x80482f0 <print@plt> : 0x80482f0 주소를 호출하며 printf() 함수의 주소이다.

 

- mov eax, DWORD PTR [ebp+0xc] : eax 레지스터에 ebp+0xc에 저장된 데이터를 복사( 첫번째 인자)

- mov edx, DWORD PTR [ebp+0x8] : edx 레지스터에 ebp+0x8에 저장된 데이터를 복사( 두번째 인자)

- add eax, edx : eax에 저장된 값과 edx에 저장된 값을 더해 eax에 저장

- pop ebp : 함수 종료

 

위 2개의 어셈블리 코드를 바탕으로 C코드를 추측해보면 다음과 같다.

 

#include <stdio.h>

 

int addVal(int a, int b);

 

int main()

{

int a = 10, b = 20, c = 0;

c = addVal(a, b);

printf("%d", c);

 

return 0;

}

 

int addVal(int a, int b)

{

return a + b;

}

Posted by Imp3rio