F.R.I.D.A.Y.

[C300] : C002 본문

리버싱/C300

[C300] : C002

F.R.I.D.A.Y. 2018. 9. 23. 01:30
반응형


#include <stdio.h> 

main() 
{ 
	int x;
	int y;
	int z;
		 
	x = 1;
	y = 2;

	z = x + y;
	
	printf( "%d", z );
} 


이번엔 위 코드를 분석한다.

 IDA로 돌리면 아래 이미지와 같은 화면이 나온다.



push 3

push offset _Format

 이 두 줄의 코드로 3과 _Format이 가리키는 주소를 스택에 쌓는다.


 그러면 스택[각주:1]에는 아래 이미지와 같이 데이터가 쌓이게 된다.



 이후 _printf 함수가 호출된다.

add esp, 8

xor eax, eax

 두 줄의 코드를 통해 호출한 함수를 정리한다.


 이제 간단히 의사 코드를 작성하면 아래와 같아진다.



#include <stdio.h>

int main(void){
    printf(_Format, 3);

    return 0;
}

 _Format은 C001 에서 해왔듯이 _Format을 더블클릭을 하거나 Enter[각주:2] 시켜놓음으로서 확인할 수 있다.



 따라서 최종 의사 코드는 다음과 같다.



#include <stdio.h>

int main(void){
    printf("%d", 3);

    return 0;
}


 그런데 여기서 의문점이 든다. 분명 처음에는 변수를 x, y, z를 사용해 작성했는데, 왜 최종 의사 코드에는 x, y, z 변수가 반영되지 않는가? 이유는 컴파일러에 있다. 컴파일러는 불필요한 변수는 제거하고 컴파일을 진행한다. 분명히 z를 [ printf ]함수의 매개변수로 사용하고는 있지만, 컴파일러는 코드 분석을 통해 실제 매개변수에는 3이 들어간다는 것을 알 수 있다. 따라서 프로그램의 효율을 높이기 위해 컴파일러에서 변수를 계산하고, 계산된 값을 매개변수에 바로 넣어버리는 것이다. 리버스 엔지니어링[각주:3]을 통해 원본 코드와 정확히 일치하는 코드를 얻을 수 없는 이유가 바로 이 때문. 컴파일러의 이러한 행위로 인해 프로그램의 효율은 높아진다.

  1. 왼쪽의 숫자는 메모리주소이나, 편의를 위해 임의로 정했다. [본문으로]
  2. _Format 위에 마우스 커서를 위치시키는 행위 [본문으로]
  3. 소프트웨어를 포함해 기계에도 적용할 수 있는 단어 [본문으로]
728x90
반응형

'리버싱 > C300' 카테고리의 다른 글

[C300] : C004  (0) 2018.09.28
[C300] : C003  (0) 2018.09.25
[C300] : C001  (0) 2018.09.22
Comments