Search

1.1 바이너리란 무엇인가

진행 기간: 21.06.28 ~ 21.07.02 Host: Windows 10 19041.1052 Guest: Ubuntu 18.04
C
복사

1.1 C/C++ Language 컴파일 과정

1.
전처리 단계
2.
C/C++ 컴파일러 단계
3.
어셈블러
4.
링커
5.
바이너리

1.1.1 전처리 단계

테스트 소스코드
/* Name: test.c Desc: 테스트 용 소스코드 */ #include <stdio.h> // 전처리 구문 /* 매크로 구문 시작 */ #define FORMAT_STRING "%s" #define MESSAGE "Hello, world!\n" /* 매크로 구문 종료 */ int main (int argc, char* argv[]){ printf(FORMAT_STRING,MESSAGE); return 0; }
C
복사
전처리 결과
모든 주석 제거되었습니다.
전처리 구문 위치에 해더 파일 소스 복사됩니다.
#include <stdio.h> /*전처리 구문 위치에 stdio.h 소스코드가 들어가게 됨*/
C
복사
매크로 부분이 치환됩니다.
printf(FORMAT_STRING,MESSAGE); /*해당 부분이*/ printf("%s","Hello, world!\n"); /*으로 치환됨*/
C
복사
전처리 결과 코드
/*전처리 결과 코드*/ # gcc -E -P test.c typedef long unsigned int size_t; typedef unsigned char __u_char; typedef unsigned short int __u_short; typedef unsigned int __u_int; typedef unsigned long int __u_long; typedef signed char __int8_t; typedef unsigned char __uint8_t; typedef signed short int __int16_t; typedef unsigned short int __uint16_t; typedef signed int __int32_t; typedef unsigned int __uint32_t; typedef signed long int __int64_t; typedef unsigned long int __uint64_t; typedef long int __quad_t; typedef unsigned long int __u_quad_t; typedef long int __intmax_t; typedef unsigned long int __uintmax_t; typedef unsigned long int __dev_t; typedef unsigned int __uid_t; typedef unsigned int __gid_t; typedef unsigned long int __ino_t; typedef unsigned long int __ino64_t; typedef unsigned int __mode_t; typedef unsigned long int __nlink_t; typedef long int __off_t; typedef long int __off64_t; typedef int __pid_t; typedef struct { int __val[2]; } __fsid_t; typedef long int __clock_t; typedef unsigned long int __rlim_t; typedef unsigned long int __rlim64_t; typedef unsigned int __id_t; typedef long int __time_t; typedef unsigned int __useconds_t; typedef long int __suseconds_t; typedef int __daddr_t; typedef int __key_t; typedef int __clockid_t; typedef void * __timer_t; typedef long int __blksize_t; typedef long int __blkcnt_t; typedef long int __blkcnt64_t; typedef unsigned long int __fsblkcnt_t; typedef unsigned long int __fsblkcnt64_t; typedef unsigned long int __fsfilcnt_t; typedef unsigned long int __fsfilcnt64_t; typedef long int __fsword_t; typedef long int __ssize_t; typedef long int __syscall_slong_t; typedef unsigned long int __syscall_ulong_t; typedef __off64_t __loff_t; typedef char *__caddr_t; typedef long int __intptr_t; typedef unsigned int __socklen_t; typedef int __sig_atomic_t; struct _IO_FILE; typedef struct _IO_FILE __FILE; struct _IO_FILE; typedef struct _IO_FILE FILE; typedef struct { int __count; union { unsigned int __wch; char __wchb[4]; } __value; } __mbstate_t; typedef struct { __off_t __pos; __mbstate_t __state; } _G_fpos_t; typedef struct { __off64_t __pos; __mbstate_t __state; } _G_fpos64_t; typedef __builtin_va_list __gnuc_va_list; struct _IO_jump_t; struct _IO_FILE; typedef void _IO_lock_t; struct _IO_marker { struct _IO_marker *_next; struct _IO_FILE *_sbuf; int _pos; }; enum __codecvt_result { __codecvt_ok, __codecvt_partial, __codecvt_error, __codecvt_noconv }; struct _IO_FILE { int _flags; char* _IO_read_ptr; char* _IO_read_end; char* _IO_read_base; char* _IO_write_base; char* _IO_write_ptr; char* _IO_write_end; char* _IO_buf_base; char* _IO_buf_end; char *_IO_save_base; char *_IO_backup_base; char *_IO_save_end; struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno; int _flags2; __off_t _old_offset; unsigned short _cur_column; signed char _vtable_offset; char _shortbuf[1]; _IO_lock_t *_lock; __off64_t _offset; void *__pad1; void *__pad2; void *__pad3; void *__pad4; size_t __pad5; int _mode; char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; }; typedef struct _IO_FILE _IO_FILE; struct _IO_FILE_plus; extern struct _IO_FILE_plus _IO_2_1_stdin_; extern struct _IO_FILE_plus _IO_2_1_stdout_; extern struct _IO_FILE_plus _IO_2_1_stderr_; typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes); typedef __ssize_t __io_write_fn (void *__cookie, const char *__buf, size_t __n); typedef int __io_seek_fn (void *__cookie, __off64_t *__pos, int __w); typedef int __io_close_fn (void *__cookie); extern int __underflow (_IO_FILE *); extern int __uflow (_IO_FILE *); extern int __overflow (_IO_FILE *, int); extern int _IO_getc (_IO_FILE *__fp); extern int _IO_putc (int __c, _IO_FILE *__fp); extern int _IO_feof (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__)); extern int _IO_ferror (_IO_FILE *__fp) __attribute__ ((__nothrow__ , __leaf__)); extern int _IO_peekc_locked (_IO_FILE *__fp); extern void _IO_flockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__)); extern void _IO_funlockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__)); extern int _IO_ftrylockfile (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__)); extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict, __gnuc_va_list, int *__restrict); extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict, __gnuc_va_list); extern __ssize_t _IO_padn (_IO_FILE *, int, __ssize_t); extern size_t _IO_sgetn (_IO_FILE *, void *, size_t); extern __off64_t _IO_seekoff (_IO_FILE *, __off64_t, int, int); extern __off64_t _IO_seekpos (_IO_FILE *, __off64_t, int); extern void _IO_free_backup_area (_IO_FILE *) __attribute__ ((__nothrow__ , __leaf__)); typedef __gnuc_va_list va_list; typedef __off_t off_t; typedef __ssize_t ssize_t; typedef _G_fpos_t fpos_t; extern struct _IO_FILE *stdin; extern struct _IO_FILE *stdout; extern struct _IO_FILE *stderr; extern int remove (const char *__filename) __attribute__ ((__nothrow__ , __leaf__)); extern int rename (const char *__old, const char *__new) __attribute__ ((__nothrow__ , __leaf__)); extern int renameat (int __oldfd, const char *__old, int __newfd, const char *__new) __attribute__ ((__nothrow__ , __leaf__)); extern FILE *tmpfile (void) ; extern char *tmpnam (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ; extern char *tmpnam_r (char *__s) __attribute__ ((__nothrow__ , __leaf__)) ; extern char *tempnam (const char *__dir, const char *__pfx) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__malloc__)) ; extern int fclose (FILE *__stream); extern int fflush (FILE *__stream); extern int fflush_unlocked (FILE *__stream); extern FILE *fopen (const char *__restrict __filename, const char *__restrict __modes) ; extern FILE *freopen (const char *__restrict __filename, const char *__restrict __modes, FILE *__restrict __stream) ; extern FILE *fdopen (int __fd, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ; extern FILE *fmemopen (void *__s, size_t __len, const char *__modes) __attribute__ ((__nothrow__ , __leaf__)) ; extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __attribute__ ((__nothrow__ , __leaf__)) ; extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __attribute__ ((__nothrow__ , __leaf__)); extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, int __modes, size_t __n) __attribute__ ((__nothrow__ , __leaf__)); extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, size_t __size) __attribute__ ((__nothrow__ , __leaf__)); extern void setlinebuf (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int fprintf (FILE *__restrict __stream, const char *__restrict __format, ...); extern int printf (const char *__restrict __format, ...); extern int sprintf (char *__restrict __s, const char *__restrict __format, ...) __attribute__ ((__nothrow__)); extern int vfprintf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg); extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg); extern int vsprintf (char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __attribute__ ((__nothrow__)); extern int snprintf (char *__restrict __s, size_t __maxlen, const char *__restrict __format, ...) __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 4))); extern int vsnprintf (char *__restrict __s, size_t __maxlen, const char *__restrict __format, __gnuc_va_list __arg) __attribute__ ((__nothrow__)) __attribute__ ((__format__ (__printf__, 3, 0))); extern int vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __arg) __attribute__ ((__format__ (__printf__, 2, 0))); extern int dprintf (int __fd, const char *__restrict __fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) ; extern int scanf (const char *__restrict __format, ...) ; extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __attribute__ ((__nothrow__ , __leaf__)); extern int fscanf (FILE *__restrict __stream, const char *__restrict __format, ...) __asm__ ("" "__isoc99_fscanf") ; extern int scanf (const char *__restrict __format, ...) __asm__ ("" "__isoc99_scanf") ; extern int sscanf (const char *__restrict __s, const char *__restrict __format, ...) __asm__ ("" "__isoc99_sscanf") __attribute__ ((__nothrow__ , __leaf__)); extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __attribute__ ((__format__ (__scanf__, 2, 0))) ; extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __attribute__ ((__format__ (__scanf__, 1, 0))) ; extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0))); extern int vfscanf (FILE *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vfscanf") __attribute__ ((__format__ (__scanf__, 2, 0))) ; extern int vscanf (const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vscanf") __attribute__ ((__format__ (__scanf__, 1, 0))) ; extern int vsscanf (const char *__restrict __s, const char *__restrict __format, __gnuc_va_list __arg) __asm__ ("" "__isoc99_vsscanf") __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__format__ (__scanf__, 2, 0))); extern int fgetc (FILE *__stream); extern int getc (FILE *__stream); extern int getchar (void); extern int getc_unlocked (FILE *__stream); extern int getchar_unlocked (void); extern int fgetc_unlocked (FILE *__stream); extern int fputc (int __c, FILE *__stream); extern int putc (int __c, FILE *__stream); extern int putchar (int __c); extern int fputc_unlocked (int __c, FILE *__stream); extern int putc_unlocked (int __c, FILE *__stream); extern int putchar_unlocked (int __c); extern int getw (FILE *__stream); extern int putw (int __w, FILE *__stream); extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) ; extern __ssize_t __getdelim (char **__restrict __lineptr, size_t *__restrict __n, int __delimiter, FILE *__restrict __stream) ; extern __ssize_t getdelim (char **__restrict __lineptr, size_t *__restrict __n, int __delimiter, FILE *__restrict __stream) ; extern __ssize_t getline (char **__restrict __lineptr, size_t *__restrict __n, FILE *__restrict __stream) ; extern int fputs (const char *__restrict __s, FILE *__restrict __stream); extern int puts (const char *__s); extern int ungetc (int __c, FILE *__stream); extern size_t fread (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) ; extern size_t fwrite (const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __s); extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream) ; extern size_t fwrite_unlocked (const void *__restrict __ptr, size_t __size, size_t __n, FILE *__restrict __stream); extern int fseek (FILE *__stream, long int __off, int __whence); extern long int ftell (FILE *__stream) ; extern void rewind (FILE *__stream); extern int fseeko (FILE *__stream, __off_t __off, int __whence); extern __off_t ftello (FILE *__stream) ; extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); extern int fsetpos (FILE *__stream, const fpos_t *__pos); extern void clearerr (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int feof (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern int ferror (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern void clearerr_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int feof_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern int ferror_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern void perror (const char *__s); extern int sys_nerr; extern const char *const sys_errlist[]; extern int fileno (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern int fileno_unlocked (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern FILE *popen (const char *__command, const char *__modes) ; extern int pclose (FILE *__stream); extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__)); extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); int main (int argc, char* argv[]){ printf("%s","Hello, world!\n"); return 0; }
C
복사

1.1.2 컴파일 단계

1.
컴파일 단계에서 최적화 작업을 수행합니다.
최적화 적용 정도에 따라 어셈블리 코드가 매우 큰 차이를 보이므로 유의해야 합니다.
2.
컴파일 단계에서 바이너리를 생성하지 않고, 어셈블리 코드만을 생성하는 이유는
a.
다양한 언어 > 어셈블리 코드 > 바이너리 코드로 변환하는 것이 다양한 언어 > 바이너리 코드로 바로 컴파일 하는 것보다 효율적이기 때문입니다.
어셈블리 코드도 CPU 아키텍쳐에 따라 매우 다른 차이를 보입니다. (arm64, x86 등)
# gcc -S -masm=intel test.c # ls test.c test.s # cat test.s .file "test.c" .intel_syntax noprefix .text .section .rodata .LC0: .string "Hello, world!" .text .globl main .type main, @function main: .LFB0: .cfi_startproc // 함수 시작 push rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 mov rbp, rsp .cfi_def_cfa_register 6 sub rsp, 16 mov DWORD PTR -4[rbp], edi mov QWORD PTR -16[rbp], rsi lea rdi, .LC0[rip] call puts@PLT mov eax, 0 leave .cfi_def_cfa 7, 8 ret .cfi_endproc // 함수 끝 .LFE0: .size main, .-main .ident "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0" .section .note.GNU-stack,"",@progbits #
C
복사

1.1.3 어셈블 단계

# gcc -c test.c # ls test.c test.o test.s # file test.o test.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
C
복사
1.
ELF 64-BIT LSB relocatable
a.
ELF 64BIT 파일
b.
LSB (Least Significant Bit) 메모리 최하위 비트부터 순서대로 정렬합니다.
4의 이진수의 경우 00000100로 표기하며
오른쪽 비트부터 사용하기 때문에 Right-Most bit로도 표기합니다.
c.
relocatable
메모리에서 재배치가 가능하며
file의 출력 결과에서 해당 용어가 표시됐다면 아직 목적 파일입니다.

1.1.4 링킹 단계

1.
모든 Object 파일을 병합해 하나의 실행 파일로 생성합니다.
2.
해당 파일이 메모리의 특정 주소 공간에 로드되도록 합니다.
3.
링크를 수행할 때 Symbol 기반으로 링크를 수행합니다.
4.
DLL(동적 링크 라이브러리)의 경우 Symbol 만 가지고 Runtime시 확인하여 로드합니다.
# file a.out a.out: ELF 64-bit LSB shared object, // LSB 공유 오브젝트 파일 x86-64, version 1 (SYSV), dynamically linked, // 동적 링크 // DLL 참조시 의존성 문제 해결을 위한 동적 링커. Runtime에 DLL을 로드하여 함수를 실행함 interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=bad98683bacd9b0a76aa34d7c623579b5d26f45c, not stripped #
C
복사
LSB Shared Object 와 Exe Executable 파일은 거의 동일합니다. 시스템 메모리 시작 주소만 다를 뿐이죠!

1.2 심벌(Symbol)과 스트립 바이너리

컴파일러는 컴파일 시 Symbol이라는 것을 생성한다.
Symbol은 컴파일된 파일의 함수 명, 변수 명, 주소 등에 매칭되어 있어 디버깅 시 유용하게 사용된다.
Symbol은 디버깅 시 상당히 유용한 정보를 제공합니다. 그렇기 때문에 대부분의 소프트웨어에서 심볼을 제공하지 않습니다.

1.2.1 심벌 정보 확인하기

# readelf --syms a.out Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 63 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000238 0 SECTION LOCAL DEFAULT 1 2: 0000000000000254 0 SECTION LOCAL DEFAULT 2 3: 0000000000000274 0 SECTION LOCAL DEFAULT 3 4: 0000000000000298 0 SECTION LOCAL DEFAULT 4 5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5 6: 0000000000000360 0 SECTION LOCAL DEFAULT 6 7: 00000000000003e2 0 SECTION LOCAL DEFAULT 7 8: 00000000000003f0 0 SECTION LOCAL DEFAULT 8 9: 0000000000000410 0 SECTION LOCAL DEFAULT 9 10: 00000000000004d0 0 SECTION LOCAL DEFAULT 10 11: 00000000000004e8 0 SECTION LOCAL DEFAULT 11 12: 0000000000000500 0 SECTION LOCAL DEFAULT 12 13: 0000000000000520 0 SECTION LOCAL DEFAULT 13 14: 0000000000000530 0 SECTION LOCAL DEFAULT 14 15: 00000000000006d4 0 SECTION LOCAL DEFAULT 15 16: 00000000000006e0 0 SECTION LOCAL DEFAULT 16 17: 00000000000006f4 0 SECTION LOCAL DEFAULT 17 18: 0000000000000730 0 SECTION LOCAL DEFAULT 18 19: 0000000000200db8 0 SECTION LOCAL DEFAULT 19 20: 0000000000200dc0 0 SECTION LOCAL DEFAULT 20 21: 0000000000200dc8 0 SECTION LOCAL DEFAULT 21 22: 0000000000200fb8 0 SECTION LOCAL DEFAULT 22 23: 0000000000201000 0 SECTION LOCAL DEFAULT 23 24: 0000000000201010 0 SECTION LOCAL DEFAULT 24 25: 0000000000000000 0 SECTION LOCAL DEFAULT 25 26: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 27: 0000000000000560 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones 28: 00000000000005a0 0 FUNC LOCAL DEFAULT 14 register_tm_clones 29: 00000000000005f0 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux 30: 0000000000201010 1 OBJECT LOCAL DEFAULT 24 completed.7698 31: 0000000000200dc0 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fin 32: 0000000000000630 0 FUNC LOCAL DEFAULT 14 frame_dummy 33: 0000000000200db8 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_ 34: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c 35: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 36: 0000000000000834 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 37: 0000000000000000 0 FILE LOCAL DEFAULT ABS 38: 0000000000200dc0 0 NOTYPE LOCAL DEFAULT 19 __init_array_end 39: 0000000000200dc8 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC 40: 0000000000200db8 0 NOTYPE LOCAL DEFAULT 19 __init_array_start 41: 00000000000006f4 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR 42: 0000000000200fb8 0 OBJECT LOCAL DEFAULT 22 _GLOBAL_OFFSET_TABLE_ 43: 00000000000006d0 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini 44: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 45: 0000000000201000 0 NOTYPE WEAK DEFAULT 23 data_start 46: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@@GLIBC_2.2.5 47: 0000000000201010 0 NOTYPE GLOBAL DEFAULT 23 _edata 48: 00000000000006d4 0 FUNC GLOBAL DEFAULT 15 _fini 49: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 50: 0000000000201000 0 NOTYPE GLOBAL DEFAULT 23 __data_start 51: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 52: 0000000000201008 0 OBJECT GLOBAL HIDDEN 23 __dso_handle 53: 00000000000006e0 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used 54: 0000000000000660 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init 55: 0000000000201018 0 NOTYPE GLOBAL DEFAULT 24 _end 56: 0000000000000530 43 FUNC GLOBAL DEFAULT 14 _start 57: 0000000000201010 0 NOTYPE GLOBAL DEFAULT 24 __bss_start 58: 000000000000063a 34 FUNC GLOBAL DEFAULT 14 main 59: 0000000000201010 0 OBJECT GLOBAL HIDDEN 23 __TMC_END__ 60: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 61: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.2 62: 00000000000004e8 0 FUNC GLOBAL DEFAULT 11 _init
C
복사
1.
.dynsym에는 동적으로 호출하는 함수들이 정리되어 있습니다.
a.
소스코드에서는 printf를 사용했지만 puts를 호출하는 이유는 최적화를 수행하기 위해 printf 대신 puts를 호출합니다.
2.
58번 Main 함수
a.
Value 값의 0x63a는 ASLR 적용 이후 BaseAddress에서의 주소값 (offset)으로 보입니다.
Linux 시스템에서는 DWARF 형식의 Debug Symbol Windows 시스템에서는 PDB 형식의 Debug Symbol을 가집니다.

1.1.2 바이너리 스트립: 관련 정보 은닉하기

# strip --strip-all a.out # file a.out a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=bad98683bacd9b0a76aa34d7c623579b5d26f45c, stripped
C
복사
1.
not stripped 가 stripped로 변경되었습니다.
# readelf --syms a.out Symbol table '.dynsym' contains 7 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.2.5 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 4: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 5: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 6: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.2.5 (2) root@DESKTOP-2HBCL3H:~#
C
복사
1.
.dynsym을 제외한 .symtab의 내용은 모두 삭제되었습니다.

1.3 바이너리 디스어셈블(disassemble)

해당 파트에서는 objdump를 이용하여 object 파일 및 바이너리를 디스어셈블합니다.

1.3.1 Object 파일

.rodata section 확인
# objdump -sj .rodata test.o // .rodate section의 정보를 보여줍니다. test.o: file format elf64-x86-64 Contents of section .rodata: 0000 48656c6c 6f2c2077 6f726c64 2100 Hello, world!. // index, hex, string #
C
복사
Disassemble
# objdump -M intel -d test.o test.o: file format elf64-x86-64 // File format Disassembly of section .text: 0000000000000000 <main>: 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 48 83 ec 10 sub rsp,0x10 8: 89 7d fc mov DWORD PTR [rbp-0x4],edi b: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi f: 48 8d 3d 00 00 00 00 lea rdi,[rip+0x0] # 16 <main+0x16> 16: e8 00 00 00 00 call 1b <main+0x1b> 1b: b8 00 00 00 00 mov eax,0x0 20: c9 leave 21: c3 ret
C
복사
1.
메인 함수만 표시되는 이유는 소스코드에 메인 함수만 작성 했기 때문입니다.
2.
main+0x0f, main+0x16의 Source 값이 0인 이유
a.
object 파일의 경우 링커에서 아직 링킹을 하지 않았기 때문입니다.
relocs symbol 확인
# readelf --relocs test.o Relocation section '.rela.text' at offset 0x220 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000012 000500000002 R_X86_64_PC32 0000000000000000 .rodata - 4 000000000017 000b00000004 R_X86_64_PLT32 0000000000000000 puts - 4 Relocation section '.rela.eh_frame' at offset 0x250 contains 1 entry: Offset Info Type Sym. Value Sym. Name + Addend 000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0 #
C
복사
1.
main+0x12에 .rodate -4(Hello, world!) 의 값이 들어갑니다.
2.
main+0x17에 puts -4 의 값이 들어갑니다.
각각 main+0x0f, main+0x16이 아닌 경우는 opcode가 존재하기 때문입니다. Disassemble 파트에 파란색으로 강조된 부분이 opcode 입니다.

1.3.2 단독으로 실행 가능한 바이너리 파일 분석하기

Not Stripped Binary File
root@DESKTOP-2HBCL3H:~# objdump -M intel -d a.out a.out: file format elf64-x86-64 Disassembly of section .init: // main 함수 호출 전 해당 section의 코드를 실행합니다. 00000000000004e8 <_init>: 4e8: 48 83 ec 08 sub rsp,0x8 4ec: 48 8b 05 f5 0a 20 00 mov rax,QWORD PTR [rip+0x200af5] # 200fe8 <__gmon_start__> 4f3: 48 85 c0 test rax,rax 4f6: 74 02 je 4fa <_init+0x12> 4f8: ff d0 call rax 4fa: 48 83 c4 08 add rsp,0x8 4fe: c3 ret Disassembly of section .plt: 0000000000000500 <.plt>: 500: ff 35 ba 0a 20 00 push QWORD PTR [rip+0x200aba] # 200fc0 <_GLOBAL_OFFSET_TABLE_+0x8> 506: ff 25 bc 0a 20 00 jmp QWORD PTR [rip+0x200abc] # 200fc8 <_GLOBAL_OFFSET_TABLE_+0x10> 50c: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 0000000000000510 <puts@plt>: 510: ff 25 ba 0a 20 00 jmp QWORD PTR [rip+0x200aba] # 200fd0 <puts@GLIBC_2.2.5> 516: 68 00 00 00 00 push 0x0 51b: e9 e0 ff ff ff jmp 500 <.plt> Disassembly of section .plt.got: 0000000000000520 <__cxa_finalize@plt>: 520: ff 25 d2 0a 20 00 jmp QWORD PTR [rip+0x200ad2] # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 526: 66 90 xchg ax,ax Disassembly of section .text: 0000000000000530 <_start>: 530: 31 ed xor ebp,ebp 532: 49 89 d1 mov r9,rdx 535: 5e pop rsi 536: 48 89 e2 mov rdx,rsp 539: 48 83 e4 f0 and rsp,0xfffffffffffffff0 53d: 50 push rax 53e: 54 push rsp 53f: 4c 8d 05 8a 01 00 00 lea r8,[rip+0x18a] # 6d0 <__libc_csu_fini> 546: 48 8d 0d 13 01 00 00 lea rcx,[rip+0x113] # 660 <__libc_csu_init> 54d: 48 8d 3d e6 00 00 00 lea rdi,[rip+0xe6] # 63a <main> 554: ff 15 86 0a 20 00 call QWORD PTR [rip+0x200a86] # 200fe0 <__libc_start_main@GLIBC_2.2.5> 55a: f4 hlt 55b: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0] 0000000000000560 <deregister_tm_clones>: 560: 48 8d 3d a9 0a 20 00 lea rdi,[rip+0x200aa9] # 201010 <__TMC_END__> 567: 55 push rbp 568: 48 8d 05 a1 0a 20 00 lea rax,[rip+0x200aa1] # 201010 <__TMC_END__> 56f: 48 39 f8 cmp rax,rdi 572: 48 89 e5 mov rbp,rsp 575: 74 19 je 590 <deregister_tm_clones+0x30> 577: 48 8b 05 5a 0a 20 00 mov rax,QWORD PTR [rip+0x200a5a] # 200fd8 <_ITM_deregisterTMCloneTable> 57e: 48 85 c0 test rax,rax 581: 74 0d je 590 <deregister_tm_clones+0x30> 583: 5d pop rbp 584: ff e0 jmp rax 586: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 58d: 00 00 00 590: 5d pop rbp 591: c3 ret 592: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 596: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 59d: 00 00 00 00000000000005a0 <register_tm_clones>: 5a0: 48 8d 3d 69 0a 20 00 lea rdi,[rip+0x200a69] # 201010 <__TMC_END__> 5a7: 48 8d 35 62 0a 20 00 lea rsi,[rip+0x200a62] # 201010 <__TMC_END__> 5ae: 55 push rbp 5af: 48 29 fe sub rsi,rdi 5b2: 48 89 e5 mov rbp,rsp 5b5: 48 c1 fe 03 sar rsi,0x3 5b9: 48 89 f0 mov rax,rsi 5bc: 48 c1 e8 3f shr rax,0x3f 5c0: 48 01 c6 add rsi,rax 5c3: 48 d1 fe sar rsi,1 5c6: 74 18 je 5e0 <register_tm_clones+0x40> 5c8: 48 8b 05 21 0a 20 00 mov rax,QWORD PTR [rip+0x200a21] # 200ff0 <_ITM_registerTMCloneTable> 5cf: 48 85 c0 test rax,rax 5d2: 74 0c je 5e0 <register_tm_clones+0x40> 5d4: 5d pop rbp 5d5: ff e0 jmp rax 5d7: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0] 5de: 00 00 5e0: 5d pop rbp 5e1: c3 ret 5e2: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 5e6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 5ed: 00 00 00 00000000000005f0 <__do_global_dtors_aux>: 5f0: 80 3d 19 0a 20 00 00 cmp BYTE PTR [rip+0x200a19],0x0 # 201010 <__TMC_END__> 5f7: 75 2f jne 628 <__do_global_dtors_aux+0x38> 5f9: 48 83 3d f7 09 20 00 cmp QWORD PTR [rip+0x2009f7],0x0 # 200ff8 <__cxa_finalize@GLIBC_2.2.5> 600: 00 601: 55 push rbp 602: 48 89 e5 mov rbp,rsp 605: 74 0c je 613 <__do_global_dtors_aux+0x23> 607: 48 8b 3d fa 09 20 00 mov rdi,QWORD PTR [rip+0x2009fa] # 201008 <__dso_handle> 60e: e8 0d ff ff ff call 520 <__cxa_finalize@plt> 613: e8 48 ff ff ff call 560 <deregister_tm_clones> 618: c6 05 f1 09 20 00 01 mov BYTE PTR [rip+0x2009f1],0x1 # 201010 <__TMC_END__> 61f: 5d pop rbp 620: c3 ret 621: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0] 628: f3 c3 repz ret 62a: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0] 0000000000000630 <frame_dummy>: 630: 55 push rbp 631: 48 89 e5 mov rbp,rsp 634: 5d pop rbp 635: e9 66 ff ff ff jmp 5a0 <register_tm_clones> 000000000000063a <main>: 63a: 55 push rbp 63b: 48 89 e5 mov rbp,rsp 63e: 48 83 ec 10 sub rsp,0x10 642: 89 7d fc mov DWORD PTR [rbp-0x4],edi 645: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi 649: 48 8d 3d 94 00 00 00 lea rdi,[rip+0x94] # 6e4 <_IO_stdin_used+0x4> 650: e8 bb fe ff ff call 510 <puts@plt> 655: b8 00 00 00 00 mov eax,0x0 65a: c9 leave 65b: c3 ret 65c: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 0000000000000660 <__libc_csu_init>: 660: 41 57 push r15 662: 41 56 push r14 664: 49 89 d7 mov r15,rdx 667: 41 55 push r13 669: 41 54 push r12 66b: 4c 8d 25 46 07 20 00 lea r12,[rip+0x200746] # 200db8 <__frame_dummy_init_array_entry> 672: 55 push rbp 673: 48 8d 2d 46 07 20 00 lea rbp,[rip+0x200746] # 200dc0 <__init_array_end> 67a: 53 push rbx 67b: 41 89 fd mov r13d,edi 67e: 49 89 f6 mov r14,rsi 681: 4c 29 e5 sub rbp,r12 684: 48 83 ec 08 sub rsp,0x8 688: 48 c1 fd 03 sar rbp,0x3 68c: e8 57 fe ff ff call 4e8 <_init> 691: 48 85 ed test rbp,rbp 694: 74 20 je 6b6 <__libc_csu_init+0x56> 696: 31 db xor ebx,ebx 698: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 69f: 00 6a0: 4c 89 fa mov rdx,r15 6a3: 4c 89 f6 mov rsi,r14 6a6: 44 89 ef mov edi,r13d 6a9: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 6ad: 48 83 c3 01 add rbx,0x1 6b1: 48 39 dd cmp rbp,rbx 6b4: 75 ea jne 6a0 <__libc_csu_init+0x40> 6b6: 48 83 c4 08 add rsp,0x8 6ba: 5b pop rbx 6bb: 5d pop rbp 6bc: 41 5c pop r12 6be: 41 5d pop r13 6c0: 41 5e pop r14 6c2: 41 5f pop r15 6c4: c3 ret 6c5: 90 nop 6c6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 6cd: 00 00 00 00000000000006d0 <__libc_csu_fini>: 6d0: f3 c3 repz ret Disassembly of section .fini: 00000000000006d4 <_fini>: 6d4: 48 83 ec 08 sub rsp,0x8 6d8: 48 83 c4 08 add rsp,0x8 6dc: c3 ret root@DESKTOP-2HBCL3H:~#
C
복사
1.
.init, .fini Section
a.
해당 프로그램이 실행 될 때, 종료 될때 실행 될 코드가 존재하는 섹션입니다.
2.
.plt, .plt.got Section
Procedure Linkage Table (PLT), Global Offset Table (GOT)에 대해서는 부록에서 따로 정리하도록 하겠습니다.
3.
.text Section
a.
기본적으로 실행되는 코드들이 존재하는 섹션입니다.
b.
Object 파일에서 메인함수의 링킹이 되지 않았던 부분도 링킹 되어있습니다.
Not Stripped 바이너리 파일의 경우 함수가 잘 분류되어 있습니다
아래는 Stripped 바이너리 파일입니다.
Stripped Binary File
# objdump -M intel -d a.out a.out: file format elf64-x86-64 Disassembly of section .init: 00000000000004e8 <.init>: 4e8: 48 83 ec 08 sub rsp,0x8 4ec: 48 8b 05 f5 0a 20 00 mov rax,QWORD PTR [rip+0x200af5] # 200fe8 <__cxa_finalize@plt+0x200ac8> 4f3: 48 85 c0 test rax,rax 4f6: 74 02 je 4fa <puts@plt-0x16> 4f8: ff d0 call rax 4fa: 48 83 c4 08 add rsp,0x8 4fe: c3 ret Disassembly of section .plt: 0000000000000500 <puts@plt-0x10>: 500: ff 35 ba 0a 20 00 push QWORD PTR [rip+0x200aba] # 200fc0 <__cxa_finalize@plt+0x200aa0> 506: ff 25 bc 0a 20 00 jmp QWORD PTR [rip+0x200abc] # 200fc8 <__cxa_finalize@plt+0x200aa8> 50c: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 0000000000000510 <puts@plt>: 510: ff 25 ba 0a 20 00 jmp QWORD PTR [rip+0x200aba] # 200fd0 <__cxa_finalize@plt+0x200ab0> 516: 68 00 00 00 00 push 0x0 51b: e9 e0 ff ff ff jmp 500 <puts@plt-0x10> Disassembly of section .plt.got: 0000000000000520 <__cxa_finalize@plt>: 520: ff 25 d2 0a 20 00 jmp QWORD PTR [rip+0x200ad2] # 200ff8 <__cxa_finalize@plt+0x200ad8> 526: 66 90 xchg ax,ax Disassembly of section .text: 0000000000000530 <.text>: 530: 31 ed xor ebp,ebp 532: 49 89 d1 mov r9,rdx 535: 5e pop rsi 536: 48 89 e2 mov rdx,rsp 539: 48 83 e4 f0 and rsp,0xfffffffffffffff0 53d: 50 push rax 53e: 54 push rsp 53f: 4c 8d 05 8a 01 00 00 lea r8,[rip+0x18a] # 6d0 <__cxa_finalize@plt+0x1b0> 546: 48 8d 0d 13 01 00 00 lea rcx,[rip+0x113] # 660 <__cxa_finalize@plt+0x140> 54d: 48 8d 3d e6 00 00 00 lea rdi,[rip+0xe6] # 63a <__cxa_finalize@plt+0x11a> 554: ff 15 86 0a 20 00 call QWORD PTR [rip+0x200a86] # 200fe0 <__cxa_finalize@plt+0x200ac0> 55a: f4 hlt 55b: 0f 1f 44 00 00 nop DWORD PTR [rax+rax*1+0x0] 560: 48 8d 3d a9 0a 20 00 lea rdi,[rip+0x200aa9] # 201010 <__cxa_finalize@plt+0x200af0> 567: 55 push rbp 568: 48 8d 05 a1 0a 20 00 lea rax,[rip+0x200aa1] # 201010 <__cxa_finalize@plt+0x200af0> 56f: 48 39 f8 cmp rax,rdi 572: 48 89 e5 mov rbp,rsp 575: 74 19 je 590 <__cxa_finalize@plt+0x70> 577: 48 8b 05 5a 0a 20 00 mov rax,QWORD PTR [rip+0x200a5a] # 200fd8 <__cxa_finalize@plt+0x200ab8> 57e: 48 85 c0 test rax,rax 581: 74 0d je 590 <__cxa_finalize@plt+0x70> 583: 5d pop rbp 584: ff e0 jmp rax 586: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 58d: 00 00 00 590: 5d pop rbp 591: c3 ret 592: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 596: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 59d: 00 00 00 5a0: 48 8d 3d 69 0a 20 00 lea rdi,[rip+0x200a69] # 201010 <__cxa_finalize@plt+0x200af0> 5a7: 48 8d 35 62 0a 20 00 lea rsi,[rip+0x200a62] # 201010 <__cxa_finalize@plt+0x200af0> 5ae: 55 push rbp 5af: 48 29 fe sub rsi,rdi 5b2: 48 89 e5 mov rbp,rsp 5b5: 48 c1 fe 03 sar rsi,0x3 5b9: 48 89 f0 mov rax,rsi 5bc: 48 c1 e8 3f shr rax,0x3f 5c0: 48 01 c6 add rsi,rax 5c3: 48 d1 fe sar rsi,1 5c6: 74 18 je 5e0 <__cxa_finalize@plt+0xc0> 5c8: 48 8b 05 21 0a 20 00 mov rax,QWORD PTR [rip+0x200a21] # 200ff0 <__cxa_finalize@plt+0x200ad0> 5cf: 48 85 c0 test rax,rax 5d2: 74 0c je 5e0 <__cxa_finalize@plt+0xc0> 5d4: 5d pop rbp 5d5: ff e0 jmp rax 5d7: 66 0f 1f 84 00 00 00 nop WORD PTR [rax+rax*1+0x0] 5de: 00 00 5e0: 5d pop rbp 5e1: c3 ret 5e2: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 5e6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 5ed: 00 00 00 5f0: 80 3d 19 0a 20 00 00 cmp BYTE PTR [rip+0x200a19],0x0 # 201010 <__cxa_finalize@plt+0x200af0> 5f7: 75 2f jne 628 <__cxa_finalize@plt+0x108> 5f9: 48 83 3d f7 09 20 00 cmp QWORD PTR [rip+0x2009f7],0x0 # 200ff8 <__cxa_finalize@plt+0x200ad8> 600: 00 601: 55 push rbp 602: 48 89 e5 mov rbp,rsp 605: 74 0c je 613 <__cxa_finalize@plt+0xf3> 607: 48 8b 3d fa 09 20 00 mov rdi,QWORD PTR [rip+0x2009fa] # 201008 <__cxa_finalize@plt+0x200ae8> 60e: e8 0d ff ff ff call 520 <__cxa_finalize@plt> 613: e8 48 ff ff ff call 560 <__cxa_finalize@plt+0x40> 618: c6 05 f1 09 20 00 01 mov BYTE PTR [rip+0x2009f1],0x1 # 201010 <__cxa_finalize@plt+0x200af0> 61f: 5d pop rbp 620: c3 ret 621: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0] 628: f3 c3 repz ret 62a: 66 0f 1f 44 00 00 nop WORD PTR [rax+rax*1+0x0] 630: 55 push rbp 631: 48 89 e5 mov rbp,rsp 634: 5d pop rbp 635: e9 66 ff ff ff jmp 5a0 <__cxa_finalize@plt+0x80> 63a: 55 push rbp 63b: 48 89 e5 mov rbp,rsp 63e: 48 83 ec 10 sub rsp,0x10 642: 89 7d fc mov DWORD PTR [rbp-0x4],edi 645: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi 649: 48 8d 3d 94 00 00 00 lea rdi,[rip+0x94] # 6e4 <__cxa_finalize@plt+0x1c4> 650: e8 bb fe ff ff call 510 <puts@plt> 655: b8 00 00 00 00 mov eax,0x0 65a: c9 leave 65b: c3 ret 65c: 0f 1f 40 00 nop DWORD PTR [rax+0x0] 660: 41 57 push r15 662: 41 56 push r14 664: 49 89 d7 mov r15,rdx 667: 41 55 push r13 669: 41 54 push r12 66b: 4c 8d 25 46 07 20 00 lea r12,[rip+0x200746] # 200db8 <__cxa_finalize@plt+0x200898> 672: 55 push rbp 673: 48 8d 2d 46 07 20 00 lea rbp,[rip+0x200746] # 200dc0 <__cxa_finalize@plt+0x2008a0> 67a: 53 push rbx 67b: 41 89 fd mov r13d,edi 67e: 49 89 f6 mov r14,rsi 681: 4c 29 e5 sub rbp,r12 684: 48 83 ec 08 sub rsp,0x8 688: 48 c1 fd 03 sar rbp,0x3 68c: e8 57 fe ff ff call 4e8 <puts@plt-0x28> 691: 48 85 ed test rbp,rbp 694: 74 20 je 6b6 <__cxa_finalize@plt+0x196> 696: 31 db xor ebx,ebx 698: 0f 1f 84 00 00 00 00 nop DWORD PTR [rax+rax*1+0x0] 69f: 00 6a0: 4c 89 fa mov rdx,r15 6a3: 4c 89 f6 mov rsi,r14 6a6: 44 89 ef mov edi,r13d 6a9: 41 ff 14 dc call QWORD PTR [r12+rbx*8] 6ad: 48 83 c3 01 add rbx,0x1 6b1: 48 39 dd cmp rbp,rbx 6b4: 75 ea jne 6a0 <__cxa_finalize@plt+0x180> 6b6: 48 83 c4 08 add rsp,0x8 6ba: 5b pop rbx 6bb: 5d pop rbp 6bc: 41 5c pop r12 6be: 41 5d pop r13 6c0: 41 5e pop r14 6c2: 41 5f pop r15 6c4: c3 ret 6c5: 90 nop 6c6: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0] 6cd: 00 00 00 6d0: f3 c3 repz ret Disassembly of section .fini: 00000000000006d4 <.fini>: 6d4: 48 83 ec 08 sub rsp,0x8 6d8: 48 83 c4 08 add rsp,0x8 6dc: c3 ret
C
복사
Stripped 파일의 경우 Not Stripped 파일에 비해 보기 힘들게 되어 있습니다.
Symbol이 사라졌기 때문에 함수들의 정보가 사라졌기 때문입니다.

1.4 바이너리 로딩과 실행

1.
Process 할당합니다.
2.
해당 Process에 할당할 Virtual Memory를 할당합니다.
3.
Binary를 Virtual Memory에 적재합니다.
Binary의 Offset과 Memory에 적재된 Binary의 Offset은 무조건 매칭되지는 않습니다.
4.
재배치를 수행하여 코드가 정상적으로 실행되도록 합니다.

99. Reference