간단한 C언어 disassemble한 모습에서 질문이 있네요.. ecx관련
안녕하세요
디어셈블한 것을 분석할 일이 있어서 진자 간단한 C프로그램을 짠뒤에 디스어셈블을 해봤습니다.
현재 gcc버전은
gcc version 4.3.3 ( ubuntu 4.3.3-5ubuntu4 )
이구요 stack guard는 disable로 컴파일했습니다.
C프로그램은 단순하게 char array[8]배열을 잡아서 gets(array) 하고 종료하는 것입니다.
0x080483c4 : lea 0x4(%esp),%ecx <------------------------
0x080483c8 : and $0xfffffff0,%esp
0x080483cb : pushl -0x4(%ecx)
0x080483ce : push %ebp
0x080483cf : mov %esp,%ebp
0x080483d1 : push %ecx <------------------------
0x080483d2 : sub $0x14,%esp
0x080483d5 : lea -0xc(%ebp),%eax
0x080483d8 : mov %eax,(%esp)
0x080483db : call 0x80482e4
0x080483e0 : mov $0x0,%eax
0x080483e5 : add $0x14,%esp
0x080483e8 : pop %ecx <------------------------
0x080483e9 : pop %ebp
0x080483ea : lea -0x4(%ecx),%esp <------------------------
0x080483ed : ret
main함수를 disassemble한 모습인데 여기서 궁금한것은 ecx의 역활이 궁금합니다.
디버깅을 다라가다보면 gets함수가 불린다음에 $ecx 에 보면 사용자가 입력한 값이 저장되어있고
$esp에는 사용자가 입력한값이 저장되어있는 주소가 저장이 되어있습니다.
그리고 처음에 저장되어있는 값은 00000001dl 저장되어있는데
확실하게 이해가 안가네요..
답변 주시면 감사하겠습니다~
제가 생성해 본 코드랑 다르네요..
ecx는 caller-saved (scratch) register 입니다.
즉 해당 함수 안에서 임의의 용도로 자유롭게 사용할 수 있으며
원래의 값이 무엇이었지는 고려할 필요가 없습니다.
또한 해당 함수 안에서 다른 함수를 호출한 경우
호출 전과 후에 ecx 레지스터의 값이 바뀔 수 있으므로
(마찬가지로 호출된 함수에서 ecx를 자유롭게 사용할 수 있으니까요)
ecx에 중요한 정보가 들어있다면 호출 전에 미리 스택에 저장해 두어야 합니다.
따라서 함수가 실행된 당시의 값과 다른 함수를 호출하고 난 직후의 ecx 값은 의미가 없습니다.
여기서 ecx가 사용된 부분은 함수의 시작(prologue) 부분에서
esp를 16바이트 단위로 정렬하기 위해 andl 명령을 실행하는 과정에서
원래의 esp 값을 저장하기 위한 용도로 쓰인 것 같습니다.
스택을 16바이트로 정렬하는 이유는 혹시나 쓰일지 모를 SSE 관련 명령 때문입니다.
(SSE에서 사용되는 데이터들은 반드시 16바이트 단위로 정렬되어 있어야 합니다)
지금처럼 그러한 명령들을 사용하지 않는 경우 불필요한 스택 정렬을 막기위해
-mpreferred-stack-boundary=2 옵션을 추가하면 이러한 부분이 사라질 것이며
따라서 ecx도 사용되지 않을 것 같습니다.
대단하십니다!! 컴파
대단하십니다!!
컴파일 옵션으로는 -mpreferred-stack-boundary=2 ... 같은..
옵션들은 어디서 참조 하셨나요?
또는 알게 되셨나요??
저는 그러한 여러 옵션들이 필요 함에도 불구하고 -_-;;
어디서 내가 원하는 걸 찾을것이며 어디서 구할지 참... 답답합니다...
단순히 컴파일 옵션이라고만 하면 너무나도 많은 것이 있더라구요...
답변 감사합니다 :)
궁금한 점이 풀렸네요^^
또하나의 궁금증이 있어서 이렇게 질문을 올려봅니다.
제가 지금 버퍼오버플로우를 일으켜서 다른 함수를 호출해 보려고 하고 있는데
0x080483e8 : pop %ecx
0x080483e9 : pop %ebp
0x080483ea : lea -0x4(%ecx),%esp
0x080483ed : ret
이부분이 어떻게 해석을 해야할지 약간 좀 난감합니다.
pop ecx를 하면서 0000001이란 값이 ecx로 들어가게 되는데
0x080483ea : lea -0x4(%ecx),%esp
이 부분을 통해서 -0x4(%ecx) 를 하게 될 경우
%ecx 가 현재 가르치고 있는 주소값 즉 0000001이 저장되어있는 주소에서 -4를 해서 esp에 저장이 되며
그리고 ret 을 하면서 이제 main을 call 했던 곳으로 다시 돌아가는것을 확인을 하였습니다.
제가 여기서 오버플로우를 일으켜서 ecx 61616161(aaaa)로 덮어 씌우게 되었습니다.
그런데 esp에 올라가 있는 부분을 보니 6161615d로 변경이 되더라구요
그래서 이게 -0x4(%ecx)이부분과 관련이 있는 것 같은데 ecx가 가르치고있는 즉 61616161에서 -4를 하는지
아니면 61616161이 들어가 있는 주소값에 -4를 하는지 햇갈리더라구요..
질문이 약간 이상한 것 같은데 정확하게 -0x4(%ecx)가 어떻게 계산된느지 궁금해서 이렇게 올렸습니다.
만약 ecx가 가르치고있는값 즉 61616161에서 -4를 하는것이라면.. 정상적일때 0000001인데 여기서 -4를 하는것은 아닌것 같은데
의아해서 질문하게 되었습니다
질문이 약간 이상하네요 ... 제가쓰고도..
혹시 이해하시고 현상에 대해서 알고 계시다면 답변 한번 해주시면 감사하겠습니다~
댓글 달기