C calling convention 에서...
글쓴이: advanced / 작성시간: 화, 2003/12/09 - 9:45오전
컴퓨터 보안을 수강하고 있는 학생입니다. 수업진도를 따라가다가
Bof 에 대해 공부하게 되었습니다. 그러던중 phrack 49호 에 있는
그 유명한 Smashing The Stack For Fun And Profit 라는 글을
보게 되었지요.
그런데 첫 소스를 만났는데 그 내용이 이렀습니다
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);
}
그 문서에 의하면 이것을 Assembly 로 변경하면 이렇다더군요
main 에서의 함수 호출 부분 pushl $3 pushl $2 pushl $1 call function 이것은 function 의 내용 pushl %ebp movl %esp,%ebp subl $20,%esp
위 내용은 이해가 갑니다
C calling convention 에서 함수를 call 하기 위해서 파라메터를
역순으로 stack에 집어넣고 함수를 call 하면, call 당한 함수(여기서는
function)에서는 현재의 base pointer register 값을 보존하기 위해
stack 에 push 한다. 그리고 함수내에서 지역변수등을 참조하는데 사용하기
위해 stack pointer 를 %ebp 에 넣는다.
그리고 지역변수를 위해 stack 에 공간을 예약하는데 1 word 씩 처리하므로
5byte 는 8byte 로 10 byte 는 12byte 로 계산하여 8+12 = 20 을 sp 에서
감산하는걸로 이해하였습니다.
그러나 제가 작성한 소스를 직접 어셈코드로 출력한 내용은 아래와 같습니다
.file "example1.c"
.text
.globl function
.type function,@function
function:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
leave
ret
.Lfe1:
.size function,.Lfe1-function
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $3, 8(%esp)
movl $2, 4(%esp)
movl $1, (%esp)
call function
movl $0, %eax
leave
ret
.Lfe2:
.size main,.Lfe2-main
.ident "GCC: (GNU) 3.2.3 20030422 (Gentoo Linux 1.4 3.2.3-r3, propolice)"
여기서 function 의 내용중에 subl $40,%esp 의 내용이 이해가 잘 안가는 군요.
저는 위의 문서에 나온 예제에 처럼 subl $20,%esp 로 된다고 생각했거든요
찾아 보려 해도 찾기가 쉽지가 않더군요. 가르침을 주세요 ^^;
- advanced -
Forums:


[code:1] .file "a.c"
.file "a.c" .version "01.01" gcc2_compiled.: .text .align 4 .globl function .type function,@function function: pushl %ebp movl %esp,%ebp subl $20,%esp .L1: leave ret .Lfe1: .size function,.Lfe1-function .align 4 .globl main .type main,@function main: pushl %ebp movl %esp,%ebp pushl $3 pushl $2 pushl $1 call function addl $12,%esp .L2: leave ret .Lfe2: .size main,.Lfe2-main .ident "GCC: (GNU) egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)"제 리눅스에서는 $0x14로 되는군요..
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
넘어가는 인자도 스택에 들어간다면 대충 맞을 듯 한데요? 또 char 배
넘어가는 인자도 스택에 들어간다면 대충 맞을 듯 한데요? 또 char 배열의 크기가 5, 10인 경우 8, 16에 맞춰질 가능성도 있구요.
하지만, 이건 컴파일러간 또는 컴파일러 옵션에 따라서도 틀려질 수 있습니다. 최적화 옵션에 따라 인자가 레지스터로 넘어갈 수도 있고 스택에 놓이는 변수나 인자들의 묶음을 4바이트 경계나 16바이트 경계로 맞추는 경우도 있습니다.
하지만 참고..두번째 것이.. 이유이네요.http://gcc.
하지만 참고..
두번째 것이.. 이유이네요.
http://gcc.gnu.org/ml/gcc-bugs/2003-02/msg00355.html
http://www.ale.org/archive/ale/ale-2002-08/msg00147.html
좀 더 자세한 테스트..
http://www.trapkit.de/papers/gcc_stack_layout_v1_20030830.pdf
울랄라~ 호기심 천국~!!
http://www.ezdoum.com
choissi 님의 경우에는 main 에서 call function 후에
choissi 님의 경우에는 main 에서 call function 후에 add 를 하네요...
choissi 님의 링크는 정말 저와 일치하는 군요맨 아래 pdf
choissi 님의 링크는 정말 저와 일치하는 군요
맨 아래 pdf 는 어느나라 말인지는 모르겠지만 그 소스만으로도
충분히 훌륭하네요.
조금더 자세히 살펴 봐야 겠지만 이 문서들이 제 궁금증을 해소 시켜 줄것 같네요.
감사합니다
흐~ 몇일 계속 삽질을 했는데 계속 원하는데로 안되더군요그래서 G
흐~ 몇일 계속 삽질을 했는데 계속 원하는데로 안되더군요
그래서 GDB 로 살펴보던중 정말 의아한것을 발견했습니다.
함수가 ret 했을때 돌아가서 실행되어야 할 instrunction point 가
일반적으로 stack 의 sfp 위에 있지않고 전혀 엉뚱한곳에 위치한것이었습니다.
갑자기 젠투머신 설치할때 컴파일중 그냥 흘겨 넘겼던 메시지가 떠올랐습니다
그 메시지 인즉 stack guard 에 관한 내용이었는데...
젠투 포럼에서 찾아보니 컴파일 할때 보호코드를 집어 넣는다더군요..
관련 링크 : http://www.research.ibm.com/trl/projects/security/ssp/
젠투에서 gcc -v 로 옵션을 확인하면
에서 propolice 를 확인할 수 있는데 이것이 그 패치가 적용 된거라네요
그래서 데비안에서 woody 에서 해보니 원활히 잘 되는군요..
- advanced -
댓글 달기