나는 학생들을 위해 버퍼 오버플로 운동을 c에 작성하려고한다.ebx가 간단한 함수의 스택 프레임에 저장되는 이유는 무엇입니까?
일반적으로 스택 프레임은 함수 매개 변수, 반환 주소, 기본 포인터 및 로컬 변수로 구성됩니다. 하지만 때로는 추가 포인터가 기본 포인터와 함께 저장된다는 것을 발견했습니다. 수업에서 캐일 (calee)에 저장된 레지스터는 사용하기 전에 저장해야한다는 것을 기억합니다. 그러나 C 코드를 컴파일하여 어셈블리를 생성하는 경우가 있습니다.이 어셈블리는 의도없이 레지스터를 저장하고 사용합니다. 이 행동을 나에게 설명해주십시오.
의 주요 기능
int main (int argc, char** argv) {
func();
return 0;
}
과 기능을 가정
void func() {
char buf[5];
strcpy(buf,"AAAA");
strcpy(buf,"BBBB");
}
내가 gdb를 결과 실행 파일을 디버깅 할 경우
break func
run
info frame
모든 것이 괜찮 스택 프레임은 EBP를 포함 및 eip.
나는 그래서 EBX가 추가로 스택 프레임에 저장됩니다
Saved registers:
ebx at 0xffffd1cc, ebp at 0xffffd1d0, eip at 0xffffd1d4
를 얻을 내가
void func() {
char buf[5];
gets(buf);
}
를 사용하는 경우? 왜? 내가
disas func
을 실행하면 나는 그래서 EBX가 저장됩니다
Dump of assembler code for function func:
0x56555730 <+0>: push %ebp
0x56555731 <+1>: mov %esp,%ebp
0x56555733 <+3>: push %ebx
0x56555734 <+4>: sub $0x8,%esp
0x56555737 <+7>: call 0x5655576e <__x86.get_pc_thunk.ax>
0x5655573c <+12>: add $0x18c4,%eax
=> 0x56555741 <+17>: lea -0x9(%ebp),%edx
0x56555744 <+20>: push %edx
0x56555745 <+21>: mov %eax,%ebx
0x56555747 <+23>: call 0x56555590 <[email protected]>
0x5655574c <+28>: add $0x4,%esp
0x5655574f <+31>: nop
0x56555750 <+32>: mov -0x4(%ebp),%ebx
0x56555753 <+35>: leave
0x56555754 <+36>: ret
End of assembler dump.
얻을. 승인. 그러나 그것은 무엇을 위해 사용 되는가? gets()를 호출하기 전에 eax가 ebx로 옮겨집니다. 그러나 나중에 사용되지 않습니다. 이전 ebx는 스택에서 복원되어 돌아 오기 전에 복원됩니다. 그것은 쓸모없는 것처럼 보인다. Btw. 뭐예요 전체 call get_pc_thunk
물건? 내가 printf와 사용하는 경우
대등 행동, 대신 가져옵니다
void func() {
char buf[5];
strcpy(buf, "AAAA");
printf("%s",buf);
}
GDB 출력 :
(gdb) info frame
Stack level 0, frame at 0xffffd1d8:
eip = 0x56555741 in func (/home/mischa/stuff/test/test.c:35); saved eip = 0x56555779
called by frame at 0xffffd1e0
source language c.
Arglist at 0xffffd1d0, args:
Locals at 0xffffd1d0, Previous frame's sp is 0xffffd1d8
Saved registers:
ebx at 0xffffd1cc, ebp at 0xffffd1d0, eip at 0xffffd1d4
(gdb) disas func
Dump of assembler code for function func:
0x56555730 <+0>: push %ebp
0x56555731 <+1>: mov %esp,%ebp
0x56555733 <+3>: push %ebx
0x56555734 <+4>: sub $0x8,%esp
0x56555737 <+7>: call 0x56555780 <__x86.get_pc_thunk.ax>
0x5655573c <+12>: add $0x18c4,%eax
=> 0x56555741 <+17>: movl $0x41414141,-0x9(%ebp)
0x56555748 <+24>: movb $0x0,-0x5(%ebp)
0x5655574c <+28>: lea -0x9(%ebp),%edx
0x5655574f <+31>: push %edx
0x56555750 <+32>: lea -0x17f0(%eax),%edx
0x56555756 <+38>: push %edx
0x56555757 <+39>: mov %eax,%ebx
0x56555759 <+41>: call 0x565555a0 <[email protected]>
0x5655575e <+46>: add $0x8,%esp
0x56555761 <+49>: nop
0x56555762 <+50>: mov -0x4(%ebp),%ebx
0x56555765 <+53>: leave
0x56555766 <+54>: ret
End of assembler dump.
누군가가 나에게 이것을 설명하시기 바랍니다 수 있습니까?
나는 다음 CMakeLists.txt로 컴파일 cmake를 사용
cmake_minimum_required (VERSION 2.8)
# projectname is the same as the main-executable
project(test)
# compile with 32 bit
add_definitions('-m32')
# Disable compiler optimization
add_definitions('-O0')
# include debugging information
add_definitions('-g')
# Align items on the stack to 4 bytes. This makes stuff easier.
# See https://stackoverflow.com/questions/1061818/stack-allocation-padding-and-alignment
add_definitions('-mpreferred-stack-boundary=2')
# disable compiler buffer overflow protection
add_definitions('-z execstack -z norelro -fno-stack-protector')
# executable source code
add_executable(test test.c)
cmake는 GCC를 사용하는 것 같다.
최적화가 비활성화되었으므로? –
'ebx'는 GOT에 대한 포인터로 사용되지만 실제로는 위치 독립적 인 코드에만 해당됩니다. 너의 cmake 물건들로부터 그것을 컴파일했는지는 분명치 않다. 문제를 재현하기 위해'-fPIC' 명령 행 옵션을'gcc'에 넘겨 주어야했습니다. – Jester
'strcpy (buf, "AAAA");는'movl'에 이어'movb'에 인라인되고 있으므로 함수를 전혀 호출하지 않아서 실행되지 않습니다. (마지막 해체에서 지적한 코드를 참조하십시오.) – rici