disassembly code - function call
#include <stdio.h>
void function(int a, int b, int c)
{
printf("fuction is called\n");
}
void main()
{
printf("main is called");
function(1, 2, 3);
}
위 코드를 gcc로 컴파일하고, gdb로 디스어셈블 해보았다.
` gcc functionCall.c -o functionCall -m32 `
disassemble main
(gdb) disassemble main
Dump of assembler code for function main:
0x0000121c <+0>: endbr32
0x00001220 <+4>: lea 0x4(%esp),%ecx
0x00001224 <+8>: and $0xfffffff0,%esp
0x00001227 <+11>: pushl -0x4(%ecx)
0x0000122a <+14>: push %ebp
0x0000122b <+15>: mov %esp,%ebp
0x0000122d <+17>: push %ebx
0x0000122e <+18>: push %ecx
0x0000122f <+19>: call 0x1269 <__x86.get_pc_thunk.ax>
0x00001234 <+24>: add $0x2da0,%eax
0x00001239 <+29>: sub $0xc,%esp
0x0000123c <+32>: lea -0x1fba(%eax),%edx
0x00001242 <+38>: push %edx
0x00001243 <+39>: mov %eax,%ebx
0x00001245 <+41>: call 0x1080 <printf@plt>
0x0000124a <+46>: add $0x10,%esp
0x0000124d <+49>: sub $0x4,%esp
0x00001250 <+52>: push $0x3
0x00001252 <+54>: push $0x2
0x00001254 <+56>: push $0x1
0x00001256 <+58>: call 0x11ed <function>
0x0000125b <+63>: add $0x10,%esp
0x0000125e <+66>: nop
0x0000125f <+67>: lea -0x8(%ebp),%esp
0x00001262 <+70>: pop %ecx
0x00001263 <+71>: pop %ebx
0x00001264 <+72>: pop %ebp
0x00001265 <+73>: lea -0x4(%ecx),%esp
0x00001268 <+76>: ret
End of assembler dump.
disassemble function
Dump of assembler code for function function:
0x000011ed <+0>: endbr32
0x000011f1 <+4>: push %ebp
0x000011f2 <+5>: mov %esp,%ebp
0x000011f4 <+7>: push %ebx
0x000011f5 <+8>: sub $0x4,%esp
0x000011f8 <+11>: call 0x1269 <__x86.get_pc_thunk.ax>
0x000011fd <+16>: add $0x2dd7,%eax
0x00001202 <+21>: sub $0xc,%esp
0x00001205 <+24>: lea -0x1fcc(%eax),%edx
0x0000120b <+30>: push %edx
0x0000120c <+31>: mov %eax,%ebx
0x0000120e <+33>: call 0x1090 <puts@plt>
0x00001213 <+38>: add $0x10,%esp
0x00001216 <+41>: nop
0x00001217 <+42>: mov -0x4(%ebp),%ebx
0x0000121a <+45>: leave
0x0000121b <+46>: ret
End of assembler dump.
- ` 0x0000121c <+0>: endbr32 `
CET의 indirect branch tracking이라는 jmp/call 이후 비정상적인 행동을 검사하는 보호기법이 있고, 이 보호 기법에서 endbr32나 endbr64라는 새로운 명령어를 사용한다고 한다.
CET가 활성화되면 각 함수 프롤로그에 ENDBR32/ENDBR64 명령어를 삽입하고 JMP와 CALL이후에 ENDBR32/ENDBR64 명령어가 나오지 않는다면 control protection 예외(#CP)가 발생한다. CET를 지원하지 않는 프로세서에서는 nop로 처리된다.
(여기서 CET는 Control-Flow Enforcement Technology Specification의 약자로, ROP/JOP 공격시 보통 흐름을 제어하는 명령인 ret, call, jmp를 사용하는데, 이를 막기 위한 메모리 보호기법이 CET이다. shadow stack, indirect branch tracking을 통해 ROP/JOP 형태의 흐름제어를 막는다고 한다.)
여튼 main 함수가 call 되었고, 이후 비정상적인 행동을 하는가를 검사하는 보호기법이 적용되어서 맨 앞에 이런 명령이 나온 것 같다.
-
` 0x00001220 <+4>: lea 0x4(%esp),%ecx` AT&T syntax에서 0x4(%esp)는 %esp+0x4를 의미하므로, %ecx에 %esp+0x4를 넣어주는 명령이다.
-
` 0x00001224 <+8>: and $0xfffffff0,%esp `
- ` 0x00001227 <+11>: pushl -0x4(%ecx) `
- ` 0x0000122a <+14>: push %ebp `
- ` 0x0000122b <+15>: mov %esp,%ebp `
- ` `위 코드를 gcc로 컴파일하고, gdb로 디스어셈블 해보았다.
9
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
- ``
Reference
- https://chp747.tistory.com/253 (non-classic prologue & epilogue)
- https://ko.wikipedia.org/wiki/%EC%8A%A4%ED%8A%B8%EB%A6%AC%EB%B0%8D_SIMD_%ED%99%95%EC%9E%A5 (SSE instructions)
- https://core-research-team.github.io/2020-05-01/memory (CET indirect branch tracking - endbr32)
- https://dypar-study.tistory.com/84 (CET - endbr32)
- https://stackoverflow.com/questions/3481207/what-does-lea-0x4esp-ecx-mean-in-att-syntax (AT&T syntax - 0x4(%esp))
- https://stackoverflow.com/questions/25667205/what-exactly-does-putsplt-mean (puts@plt)
- https://bpsecblog.wordpress.com/2016/06/10/memory_protect_linux_4/ (<__x86.get_pc_thunk.ax>)
- https://hackyboiz.github.io/2021/10/27/y00n_nms/linux-mitigation/ (PIE)