반응형


1.3. add() 함수 파라미터 입력 및 add() 함수 호출




add() 함수에는 a, b 2개의 파라미터가 존재합니다.

401034 ~ 40103B 주소의 명령어들은 변수 a, b 를 스택에 저장하고 있습니다.



[EBP-8]에는 2가 [EBP-4]에는 1이 저장되게 되는데 C언어의 입력 순서와는 반대로 2부터 저장이 되고있습니다.


1.3.1 복귀주소



CALL 명령어( 40103C )가 실행되어 해당 함수로 들어가기 전에 CPU는 무조건 해당 함수가 종료될 때 복귀할 주소를 스택에 저장합니다.



CALL 명령어 ( 40103C )를 실행한 직후 스택에는 복귀주소가 저장되어 있습니다.


1.4. add() 함수 시작 & 스택 프레임 생성




① StackFrame 게시물의 Main() 함수 부분과 동일합니다.

원래의 EBP 값을 스택에 저장 후 현재의 ESP를 EBP에 넣습니다.


1.5. add() 함수의 로컬 변수( x, y )세팅




① : 스택 메모리 영역 ( 8 byte ) 확보

② : [ EBP + 8 ] = a

③ : [ EBP - 8 ] = x

④ : [ EBP + C ] = b

⑤ : [ EBP - 4 ] = y



1.6. ADD 연산




① : EBP-8에 있는 변수 x의 값 1을 MOV명령어를 통해 EAX로 넣는다.

② : EBP-4에 있는 변수 y의 값 2를 ADD명령어를 통해 EAX의 값 1과 더한다 = 3


1.7. add() 함수의 스택 프레임 해제 & 함수 종료 ( 리턴 )


이제 add() 함수의 스택 프레임을 해제 시키고 함수를 리턴시킬 차례입니다.



앞선 MOV EBP, ESP에 대응하는 명령어입니다.

add() 함수가 시작할 때 ESP값을 EBP에 넣어 보존했다가 함수가 종료될 때 ESP값을 복원시키는 겁니다.



앞선 PUSH EBP에 대응하는 명령어입니다.

add() 함수가 시작되면서 스택에 백업한 EBP값을 복원하고 스텍프레임을 해제시킵니다.


이제, RETN명령어를 실행시키게되면 스택에 저장된 복귀 주소로 리턴하게됩니다.



add() 함수를 호출하기 전의 스택상태로 돌아왔습니다.


1.8. add() 함수 파라미터 제거 ( 스택 정리 )



add() 함수가 완전히 종료되었기 떄문에 파라미터 a,b가 필요 없습니다.

따라서 ESP에 8을 더하여 스택을 정리하는 부분입니다.


1.9. printf() 함수 호출


자, 이제 프로그래밍 공부를하며 늘 써왔고 궁금했던 printf() 에 대해 알아보겠습니다.



이전의 과정에서 EAX에 1과 2를 더한 3을 넣어놨었습니다.

PUSH 40B384에는 %d가 들어있고 CALL 401067 명령어는 printf() 함수입니다.

printf() 안에 2개의 파라미터가 있기 때문에 ADD ESP, 8 로 정리해줍니다.


1.10. 리턴 값 세팅




'XOR' Exclusive OR bit 연산은 같은값 끼리 XOR하면 0이 되는 연산입니다.

MOV EAX, 0 명령어보다 실행속도가 빨라 자주 사용된다고합니다.


XOR 아래의 코드들은 나머지 부분은 앞에서했던 MOV, POP RETN 으로 같은 동작을 하며 메인 함수가 종료됩니다.



이번 실습을 진행하면서 막히는 부분도 많았고 꽤 어려웠습니다.

하지만 스택 프레임을 어설프게나마 공부해보니 실력이 많이 향상된 것 같고 리버싱 공부 의지가 더욱 불타는 것 같습니다.


오늘은 여기까지입니다 감사합니다 !




참고서적 이승원 「리버싱 핵심원리」 인사이트(2018) p82~91

+ Recent posts