Skip to content

Instantly share code, notes, and snippets.

@dbwodlf3
Last active December 10, 2020 08:14
Show Gist options
  • Select an option

  • Save dbwodlf3/5c04a52b98513d9dbaae8cad7c35ce92 to your computer and use it in GitHub Desktop.

Select an option

Save dbwodlf3/5c04a52b98513d9dbaae8cad7c35ce92 to your computer and use it in GitHub Desktop.
SMC in C
===============================================================================
C 언어에서 나타나는 SMC 코드.
===============================================================================
C 언어에서의 메모리 모델은 다음과 같다.
High Address
stack (almost end of address. in gcc-x86 is 0xfffffff0, gcc-x64 is 0xfffffffffffffff0)
heap
uninitialized data
initalized data (data 영역)
text (code 영역)
Low Address
===============================================================================
example code1
```c
#include <stdio.h>
#include <sys/mman.h>
int getMemoryPermission(void*);
char code[] =
"\xb8\x01\x00\x00\x00"
"\xcd\x80";
int main(){
getMemoryPermission(&code);
((void(*)())code)();
printf("This is not excuted");
return 0;
}
int getMemoryPermission(void *addr){
int page_size = 4096;
addr -= (unsigned long)addr % page_size;
if(mprotect(addr, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1){
return -1;
}
return 0;
}
```
example code2
```c
#include <stdio.h>
#include <sys/mman.h>
int getMemoryPermission(void*);
int main(){
char code[] =
"\xb8\x01\x00\x00\x00"
"\xcd\x80";
getMemoryPermission(&code);
((void(*)())code)();
printf("This is not excuted");
return 0;
}
int getMemoryPermission(void *addr){
int page_size = 4096;
addr -= (unsigned long)addr % page_size;
if(mprotect(addr, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1){
return -1;
}
return 0;
}
```
위의 example code1과 2는 elf32, elf64 에서 작동하는 코드이다.
C언어에서 function scope 바깥에 위치해 있는 모든 초기화 가능한 변수는
initalized data 메모리 영역에 정적으로 위치해 있다. 따라서 엄밀히 말할 경우 example
code 1은 SMC 코드가 아니다.
C언어에서 function scope 내에 선언 되어 있는 모든 변수는 stack 을 이용하여 동적으로
할당된다. 따라서 example code2의 어셈블리 코드는 동적으로 스택메모리에서 만들어지고,
동적으로 만들어진 코드가 실행한다.
다음의 binary 형태를 보면 더욱 분명하다.
===============================================================================
example code1 objdump
```
000000000000068a <main>:
68a: 55 push %rbp
68b: 48 89 e5 mov %rsp,%rbp
68e: 48 8d 3d 7b 09 20 00 lea 0x20097b(%rip),%rdi # 201010 <code>
695: e8 26 00 00 00 callq 6c0 <getMemoryPermission>
69a: 48 8d 15 6f 09 20 00 lea 0x20096f(%rip),%rdx # 201010 <code>
6a1: b8 00 00 00 00 mov $0x0,%eax
6a6: ff d2 callq *%rdx
6a8: 48 8d 3d f5 00 00 00 lea 0xf5(%rip),%rdi # 7a4 <_IO_stdin_used+0x4>
6af: b8 00 00 00 00 mov $0x0,%eax
6b4: e8 97 fe ff ff callq 550 <printf@plt>
6b9: b8 00 00 00 00 mov $0x0,%eax
6be: 5d pop %rbp
6bf: c3 retq
```
example code2 objdump
```
00000000000006fa <main>:
6fa: 55 push %rbp
6fb: 48 89 e5 mov %rsp,%rbp
6fe: 48 83 ec 10 sub $0x10,%rsp
702: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
709: 00 00
70b: 48 89 45 f8 mov %rax,-0x8(%rbp)
70f: 31 c0 xor %eax,%eax
711: 48 8b 05 40 01 00 00 mov 0x140(%rip),%rax # 858 <_IO_stdin_used+0x18>
718: 48 89 45 f0 mov %rax,-0x10(%rbp)
71c: 48 8d 45 f0 lea -0x10(%rbp),%rax
720: 48 89 c7 mov %rax,%rdi
723: e8 37 00 00 00 callq 75f <getMemoryPermission>
728: 48 8d 55 f0 lea -0x10(%rbp),%rdx
72c: b8 00 00 00 00 mov $0x0,%eax
731: ff d2 callq *%rdx
733: 48 8d 3d 0a 01 00 00 lea 0x10a(%rip),%rdi # 844 <_IO_stdin_used+0x4>
73a: b8 00 00 00 00 mov $0x0,%eax
73f: e8 7c fe ff ff callq 5c0 <printf@plt>
744: b8 00 00 00 00 mov $0x0,%eax
749: 48 8b 4d f8 mov -0x8(%rbp),%rcx
74d: 64 48 33 0c 25 28 00 xor %fs:0x28,%rcx
754: 00 00
756: 74 05 je 75d <main+0x63>
758: e8 53 fe ff ff callq 5b0 <__stack_chk_fail@plt>
75d: c9 leaveq
75e: c3 retq
```
example code1 에서 .data 영역에 있는 값을 direct 하게 바로 사용하는 것을 알 수 있다.
```
((void(*)())code)()=>
69a: 48 8d 15 6f 09 20 00 lea 0x20096f(%rip),%rdx # 201010 <code>
6a1: b8 00 00 00 00 mov $0x0,%eax
6a6: ff d2 callq *%rdx
```
example code2 에서 .rodata 영역에 있는 값을 stack에 동적으로 할당하여 사용하는 것을
알 수 있다.
```
char code[] = "\xb8\x01\x00\x00\x00\xcd\x80" =>
711: 48 8b 05 40 01 00 00 mov 0x140(%rip),%rax # 858 <_IO_stdin_used+0x18>
718: 48 89 45 f0 mov %rax,-0x10(%rbp)
71c: 48 8d 45 f0 lea -0x10(%rbp),%rax
((void(*)())code)()=>
728: 48 8d 55 f0 lea -0x10(%rbp),%rdx
72c: b8 00 00 00 00 mov $0x0,%eax
731: ff d2 callq *%rdx
```
===============================================================================
example code1, example code2 모두 함수포인터를 이용하여 해당 어셈블리 코드를 실행
한다. 함수포인터를 사용하여 call 하는 것이기 때문에 binary level 에서 해당 명령어가
call 명령어로 나타난다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment