진행 기간: 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.
재배치를 수행하여 코드가 정상적으로 실행되도록 합니다.