Search

1.4 libbfd를 이용한 바이너리 로더 제작 연습문제

4.1 섹션 덤프

4.1.1 소스코드

/* Demonstrate the binary loader from ../inc/loader.cc */ #include <stdio.h> #include <stdint.h> #include <string.h> #include "../inc/loader.h" int main(int argc, char *argv[]) { size_t i; Binary bin; Section *sec; Symbol *sym; std::string fname; if(argc < 2) { printf("Usage: %s <binary>\n", argv[0]); return 1; } fname.assign(argv[1]); if(load_binary(fname, &bin, Binary::BIN_TYPE_AUTO) < 0) { return 1; } printf("loaded binary '%s' %s/%s (%u bits) entry@0x%016jx\n", bin.filename.c_str(), bin.type_str.c_str(), bin.arch_str.c_str(), bin.bits, bin.entry); for(i = 0; i < bin.sections.size(); i++) { sec = &bin.sections[i]; if(argc == 3) { if(strcasecmp(argv[2],sec->name.c_str()) == 0) { int line = 0; printf(" 0x%016jx %-8ju %-20s %s\n", sec->vma, sec->size, sec->name.c_str(), sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA"); printf("Section Data\n offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n 000000 "); for(int bc = 0; bc < sec->size ; bc++) { printf("%02x ",sec->bytes[bc]); if((bc+1)%16 == 0 && bc != 0 && bc != sec->size-1) { line ++; printf("\n %05x0 ",line); } } printf("\n"); break; } } else { printf(" 0x%016jx %-8ju %-20s %s\n", sec->vma, sec->size, sec->name.c_str(), sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA"); } } if(bin.symbols.size() > 0) { printf("scanned symbol tables\n"); "loader_demo.cc" 82L, 1801C 1,1 Top if(bin.symbols.size() > 0) { printf("scanned symbol tables\n"); for(i = 0; i < bin.symbols.size(); i++) { sym = &bin.symbols[i]; printf(" %-40s 0x%016jx %s\n", sym->name.c_str(), sym->addr, (sym->type & Symbol::SYM_TYPE_FUNC) ? "FUNC" : ""); } } unload_binary(&bin); return 0; }
C
복사

4.1.2 결과

binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo /bin/ls .data loaded binary '/bin/ls' elf64-x86-64/i386:x86-64 (64 bits) entry@0x00000000004049a0 0x000000000061e3a0 608 .data DATA Section Data offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000020 01 00 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 000030 c4 69 41 00 00 00 00 00 ce 69 41 00 00 00 00 00 000040 02 00 00 00 00 00 00 00 c8 67 41 00 00 00 00 00 000050 01 00 00 00 00 00 00 00 bd 65 41 00 00 00 00 00 000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000070 01 00 00 00 00 00 00 00 d6 64 41 00 00 00 00 00 000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000a0 05 00 00 00 00 00 00 00 da 69 41 00 00 00 00 00 0000b0 05 00 00 00 00 00 00 00 e0 69 41 00 00 00 00 00 0000c0 02 00 00 00 00 00 00 00 ef 69 41 00 00 00 00 00 0000d0 05 00 00 00 00 00 00 00 e6 69 41 00 00 00 00 00 0000e0 05 00 00 00 00 00 00 00 ec 69 41 00 00 00 00 00 0000f0 05 00 00 00 00 00 00 00 ec 69 41 00 00 00 00 00 000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000120 05 00 00 00 00 00 00 00 f2 69 41 00 00 00 00 00 000130 05 00 00 00 00 00 00 00 e6 69 41 00 00 00 00 00 000140 05 00 00 00 00 00 00 00 f8 69 41 00 00 00 00 00 000150 05 00 00 00 00 00 00 00 fe 69 41 00 00 00 00 00 000160 05 00 00 00 00 00 00 00 04 6a 41 00 00 00 00 00 000170 05 00 00 00 00 00 00 00 0a 6a 41 00 00 00 00 00 000180 05 00 00 00 00 00 00 00 10 6a 41 00 00 00 00 00 000190 05 00 00 00 00 00 00 00 16 6a 41 00 00 00 00 00 0001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0001b0 03 00 00 00 00 00 00 00 1c 6a 41 00 00 00 00 00 0001c0 01 00 00 00 00 00 00 00 01 01 3f 00 01 00 00 00 0001d0 10 8b 41 00 00 00 00 00 60 9f 40 00 00 00 00 00 0001e0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000200 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000230 00 00 00 00 00 00 00 00 e0 e5 61 00 00 00 00 00 000240 00 01 00 00 00 00 00 00 20 f2 61 00 00 00 00 00 000250 01 00 00 00 00 00 00 00 10 26 41 00 00 00 00 00 scanned symbol tables __ctype_toupper_loc 0x0000000000000000 FUNC __uflow 0x0000000000000000 FUNC getenv 0x0000000000000000 FUNC sigprocmask 0x0000000000000000 FUNC raise 0x0000000000000000 FUNC localtime 0x0000000000000000 FUNC __mempcpy_chk 0x0000000000000000 FUNC abort 0x0000000000000000 FUNC __errno_location 0x0000000000000000 FUNC strncmp 0x0000000000000000 FUNC _exit 0x0000000000000000 FUNC strcpy 0x0000000000000000 FUNC __fpending 0x0000000000000000 FUNC isatty 0x0000000000000000 FUNC sigaction 0x0000000000000000 FUNC iswcntrl 0x0000000000000000 FUNC wcswidth 0x0000000000000000 FUNC localeconv 0x0000000000000000 FUNC mbstowcs 0x0000000000000000 FUNC readlink 0x0000000000000000 FUNC clock_gettime 0x0000000000000000 FUNC setenv 0x0000000000000000 FUNC textdomain 0x0000000000000000 FUNC fclose 0x0000000000000000 FUNC opendir 0x0000000000000000 FUNC getpwuid 0x0000000000000000 FUNC bindtextdomain 0x0000000000000000 FUNC stpcpy 0x0000000000000000 FUNC dcgettext 0x0000000000000000 FUNC __ctype_get_mb_cur_max 0x0000000000000000 FUNC strlen 0x0000000000000000 FUNC __lxstat 0x0000000000000000 FUNC __stack_chk_fail 0x0000000000000000 FUNC getopt_long 0x0000000000000000 FUNC mbrtowc 0x0000000000000000 FUNC strchr 0x0000000000000000 FUNC getgrgid 0x0000000000000000 FUNC __overflow 0x0000000000000000 FUNC strrchr 0x0000000000000000 FUNC fgetfilecon 0x0000000000000000 FUNC gmtime_r 0x0000000000000000 FUNC lseek 0x0000000000000000 FUNC gettimeofday 0x0000000000000000 FUNC __assert_fail 0x0000000000000000 FUNC __strtoul_internal 0x0000000000000000 FUNC fnmatch 0x0000000000000000 FUNC memset 0x0000000000000000 FUNC fscanf 0x0000000000000000 FUNC ioctl 0x0000000000000000 FUNC close 0x0000000000000000 FUNC closedir 0x0000000000000000 FUNC __libc_start_main 0x0000000000000000 FUNC memcmp 0x0000000000000000 FUNC _setjmp 0x0000000000000000 FUNC fputs_unlocked 0x0000000000000000 FUNC calloc 0x0000000000000000 FUNC lgetfilecon 0x0000000000000000 FUNC strcmp 0x0000000000000000 FUNC signal 0x0000000000000000 FUNC dirfd 0x0000000000000000 FUNC getpwnam 0x0000000000000000 FUNC __memcpy_chk 0x0000000000000000 FUNC sigemptyset 0x0000000000000000 FUNC memcpy 0x0000000000000000 FUNC getgrnam 0x0000000000000000 FUNC getfilecon 0x0000000000000000 FUNC tzset 0x0000000000000000 FUNC fileno 0x0000000000000000 FUNC tcgetpgrp 0x0000000000000000 FUNC __xstat 0x0000000000000000 FUNC readdir 0x0000000000000000 FUNC wcwidth 0x0000000000000000 FUNC fflush 0x0000000000000000 FUNC nl_langinfo 0x0000000000000000 FUNC ungetc 0x0000000000000000 FUNC __fxstat 0x0000000000000000 FUNC strcoll 0x0000000000000000 FUNC __freading 0x0000000000000000 FUNC fwrite_unlocked 0x0000000000000000 FUNC realloc 0x0000000000000000 FUNC stpncpy 0x0000000000000000 FUNC fdopen 0x0000000000000000 FUNC setlocale 0x0000000000000000 FUNC __printf_chk 0x0000000000000000 FUNC timegm 0x0000000000000000 FUNC strftime 0x0000000000000000 FUNC mempcpy 0x0000000000000000 FUNC memmove 0x0000000000000000 FUNC error 0x0000000000000000 FUNC open 0x0000000000000000 FUNC fseeko 0x0000000000000000 FUNC unsetenv 0x0000000000000000 FUNC strtoul 0x0000000000000000 FUNC __cxa_atexit 0x0000000000000000 FUNC wcstombs 0x0000000000000000 FUNC getxattr 0x0000000000000000 FUNC freecon 0x0000000000000000 FUNC sigismember 0x0000000000000000 FUNC exit 0x0000000000000000 FUNC fwrite 0x0000000000000000 FUNC __fprintf_chk 0x0000000000000000 FUNC fflush_unlocked 0x0000000000000000 FUNC mbsinit 0x0000000000000000 FUNC iswprint 0x0000000000000000 FUNC sigaddset 0x0000000000000000 FUNC strstr 0x0000000000000000 FUNC __ctype_tolower_loc 0x0000000000000000 FUNC __ctype_b_loc 0x0000000000000000 FUNC __sprintf_chk 0x0000000000000000 FUNC _fini 0x0000000000413c5c FUNC _init 0x00000000004022b8 FUNC free 0x0000000000402340 FUNC _obstack_memory_used 0x0000000000412930 FUNC _obstack_begin 0x0000000000412750 FUNC _obstack_free 0x00000000004128c0 FUNC localtime_r 0x00000000004023a0 FUNC _obstack_allocated_p 0x0000000000412890 FUNC _obstack_begin_1 0x0000000000412770 FUNC _obstack_newchunk 0x0000000000412790 FUNC malloc 0x0000000000402790 FUNC
C
복사

4.2 Weak Symbol과 Strong Symbol

4.2.1 결과

gvar에 관해서 WEAK과 STRONG 둘 다 추가했으나 STRONG만 찍힘
binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo ./test/test loaded binary './test/test' elf64-x86-64/i386:x86-64 (64 bits) entry@0x0000000000400430 0x0000000000400238 28 .interp DATA 0x0000000000400254 32 .note.ABI-tag DATA 0x0000000000400274 36 .note.gnu.build-id DATA 0x0000000000400298 28 .gnu.hash DATA 0x00000000004002b8 96 .dynsym DATA 0x0000000000400318 63 .dynstr DATA 0x0000000000400358 8 .gnu.version DATA 0x0000000000400360 32 .gnu.version_r DATA 0x0000000000400380 24 .rela.dyn DATA 0x0000000000400398 48 .rela.plt DATA 0x00000000004003c8 26 .init CODE 0x00000000004003f0 48 .plt CODE 0x0000000000400420 8 .plt.got CODE 0x0000000000400430 402 .text CODE 0x00000000004005c4 9 .fini CODE 0x00000000004005d0 21 .rodata DATA 0x00000000004005e8 52 .eh_frame_hdr DATA 0x0000000000400620 244 .eh_frame DATA 0x0000000000600e10 8 .init_array DATA 0x0000000000600e18 8 .fini_array DATA 0x0000000000600e20 8 .jcr DATA 0x0000000000600e28 464 .dynamic DATA 0x0000000000600ff8 8 .got DATA 0x0000000000601000 40 .got.plt DATA 0x0000000000601028 20 .data DATA scanned symbol tables .interp 0x0000000000400238 LOCAL 0x00105 .note.ABI-tag 0x0000000000400254 LOCAL 0x00105 .note.gnu.build-id 0x0000000000400274 LOCAL 0x00105 .gnu.hash 0x0000000000400298 LOCAL 0x00105 .dynsym 0x00000000004002b8 LOCAL 0x00105 .dynstr 0x0000000000400318 LOCAL 0x00105 .gnu.version 0x0000000000400358 LOCAL 0x00105 .gnu.version_r 0x0000000000400360 LOCAL 0x00105 .rela.dyn 0x0000000000400380 LOCAL 0x00105 .rela.plt 0x0000000000400398 LOCAL 0x00105 .init 0x00000000004003c8 LOCAL 0x00105 .plt 0x00000000004003f0 LOCAL 0x00105 .plt.got 0x0000000000400420 LOCAL 0x00105 .text 0x0000000000400430 LOCAL 0x00105 .fini 0x00000000004005c4 LOCAL 0x00105 .rodata 0x00000000004005d0 LOCAL 0x00105 .eh_frame_hdr 0x00000000004005e8 LOCAL 0x00105 .eh_frame 0x0000000000400620 LOCAL 0x00105 .init_array 0x0000000000600e10 LOCAL 0x00105 .fini_array 0x0000000000600e18 LOCAL 0x00105 .jcr 0x0000000000600e20 LOCAL 0x00105 .dynamic 0x0000000000600e28 LOCAL 0x00105 .got 0x0000000000600ff8 LOCAL 0x00105 .got.plt 0x0000000000601000 LOCAL 0x00105 .data 0x0000000000601028 LOCAL 0x00105 .bss 0x000000000060103c LOCAL 0x00105 .comment 0x0000000000000000 LOCAL 0x00105 crtstuff.c 0x0000000000000000 LOCAL 0x04005 __JCR_LIST__ 0x0000000000600e20 LOCAL 0x10001 deregister_tm_clones 0x0000000000400460 FUNC 0x00009 deregister_tm_clones 0x0000000000400460 LOCAL 0x00009 register_tm_clones 0x00000000004004a0 FUNC 0x00009 register_tm_clones 0x00000000004004a0 LOCAL 0x00009 __do_global_dtors_aux 0x00000000004004e0 FUNC 0x00009 __do_global_dtors_aux 0x00000000004004e0 LOCAL 0x00009 completed.7585 0x000000000060103c LOCAL 0x10001 __do_global_dtors_aux_fini_array_entry 0x0000000000600e18 LOCAL 0x10001 frame_dummy 0x0000000000400500 FUNC 0x00009 frame_dummy 0x0000000000400500 LOCAL 0x00009 __frame_dummy_init_array_entry 0x0000000000600e10 LOCAL 0x10001 main.c 0x0000000000000000 LOCAL 0x04005 test.c 0x0000000000000000 LOCAL 0x04005 crtstuff.c 0x0000000000000000 LOCAL 0x04005 __FRAME_END__ 0x0000000000400710 LOCAL 0x10001 __JCR_END__ 0x0000000000600e20 LOCAL 0x10001 0x0000000000000000 LOCAL 0x04005 __init_array_end 0x0000000000600e18 LOCAL 0x00001 _DYNAMIC 0x0000000000600e28 LOCAL 0x10001 __init_array_start 0x0000000000600e10 LOCAL 0x00001 __GNU_EH_FRAME_HDR 0x00000000004005e8 LOCAL 0x00001 _GLOBAL_OFFSET_TABLE_ 0x0000000000601000 LOCAL 0x10001 __libc_csu_fini 0x00000000004005c0 FUNC 0x0000a __libc_csu_fini 0x00000000004005c0 GLOBAL 0x0000a _ITM_deregisterTMCloneTable 0x0000000000000000 WEAK 0x00080 data_start 0x0000000000601028 WEAK 0x00080 _edata 0x000000000060103c GLOBAL 0x00002 _fini 0x00000000004005c4 FUNC 0x0000a _fini 0x00000000004005c4 GLOBAL 0x0000a printf@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008 __libc_start_main@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008 __data_start 0x0000000000601028 GLOBAL 0x00002 __gmon_start__ 0x0000000000000000 WEAK 0x00080 __dso_handle 0x0000000000601030 GLOBAL 0x10002 _IO_stdin_used 0x00000000004005d0 GLOBAL 0x10002 __libc_csu_init 0x0000000000400550 FUNC 0x0000a __libc_csu_init 0x0000000000400550 GLOBAL 0x0000a _end 0x0000000000601040 GLOBAL 0x00002 _start 0x0000000000400430 FUNC 0x0000a _start 0x0000000000400430 GLOBAL 0x0000a __bss_start 0x000000000060103c GLOBAL 0x00002 main 0x0000000000400526 FUNC 0x0000a main 0x0000000000400526 GLOBAL 0x0000a _Jv_RegisterClasses 0x0000000000000000 WEAK 0x00080 __TMC_END__ 0x0000000000601040 GLOBAL 0x10002 _ITM_registerTMCloneTable 0x0000000000000000 WEAK 0x00080 gvar 0x0000000000601038 GLOBAL 0x10002 _init 0x00000000004003c8 FUNC 0x0000a _init 0x00000000004003c8 GLOBAL 0x0000a printf 0x0000000000000000 FUNC 0x08008 __libc_start_main 0x0000000000000000 FUNC 0x08008 __gmon_start__ 0x0000000000000000 WEAK 0x08080
C
복사

4.2.2 소스코드

//test.c int gvar = 5; //main.c #include <stdio.h> int gvar; int main() { printf("shared gvar %d \n",gvar); return 0; } //command gcc -o test main.c test.c
C
복사
로더 소스코드의 경우 연습문제 4.3과 동일
4.1 → 4.3 → 4.2 순서대로 문제를 진행하였음

4.3 타입 추가

4.3.1 결과

개인적으로 기본적인 Flags값을 가지고 있는 경우 enum이 아닌 define을 사용하여 전부 보여줘야 한다고 생각함.
binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo ../chapter2/compilation_example loaded binary '../chapter2/compilation_example' elf64-x86-64/i386:x86-64 (64 bits) entry@0x0000000000400430 0x0000000000400238 28 .interp DATA 0x0000000000400254 32 .note.ABI-tag DATA 0x0000000000400274 36 .note.gnu.build-id DATA 0x0000000000400298 28 .gnu.hash DATA 0x00000000004002b8 96 .dynsym DATA 0x0000000000400318 61 .dynstr DATA 0x0000000000400356 8 .gnu.version DATA 0x0000000000400360 32 .gnu.version_r DATA 0x0000000000400380 24 .rela.dyn DATA 0x0000000000400398 48 .rela.plt DATA 0x00000000004003c8 26 .init CODE 0x00000000004003f0 48 .plt CODE 0x0000000000400420 8 .plt.got CODE 0x0000000000400430 402 .text CODE 0x00000000004005c4 9 .fini CODE 0x00000000004005d0 18 .rodata DATA 0x00000000004005e4 52 .eh_frame_hdr DATA 0x0000000000400618 244 .eh_frame DATA 0x0000000000600e10 8 .init_array DATA 0x0000000000600e18 8 .fini_array DATA 0x0000000000600e20 8 .jcr DATA 0x0000000000600e28 464 .dynamic DATA 0x0000000000600ff8 8 .got DATA 0x0000000000601000 40 .got.plt DATA 0x0000000000601028 16 .data DATA scanned symbol tables .interp 0x0000000000400238 LOCAL 0x00105 .note.ABI-tag 0x0000000000400254 LOCAL 0x00105 .note.gnu.build-id 0x0000000000400274 LOCAL 0x00105 .gnu.hash 0x0000000000400298 LOCAL 0x00105 .dynsym 0x00000000004002b8 LOCAL 0x00105 .dynstr 0x0000000000400318 LOCAL 0x00105 .gnu.version 0x0000000000400356 LOCAL 0x00105 .gnu.version_r 0x0000000000400360 LOCAL 0x00105 .rela.dyn 0x0000000000400380 LOCAL 0x00105 .rela.plt 0x0000000000400398 LOCAL 0x00105 .init 0x00000000004003c8 LOCAL 0x00105 .plt 0x00000000004003f0 LOCAL 0x00105 .plt.got 0x0000000000400420 LOCAL 0x00105 .text 0x0000000000400430 LOCAL 0x00105 .fini 0x00000000004005c4 LOCAL 0x00105 .rodata 0x00000000004005d0 LOCAL 0x00105 .eh_frame_hdr 0x00000000004005e4 LOCAL 0x00105 .eh_frame 0x0000000000400618 LOCAL 0x00105 .init_array 0x0000000000600e10 LOCAL 0x00105 .fini_array 0x0000000000600e18 LOCAL 0x00105 .jcr 0x0000000000600e20 LOCAL 0x00105 .dynamic 0x0000000000600e28 LOCAL 0x00105 .got 0x0000000000600ff8 LOCAL 0x00105 .got.plt 0x0000000000601000 LOCAL 0x00105 .data 0x0000000000601028 LOCAL 0x00105 .bss 0x0000000000601038 LOCAL 0x00105 .comment 0x0000000000000000 LOCAL 0x00105 crtstuff.c 0x0000000000000000 LOCAL 0x04005 __JCR_LIST__ 0x0000000000600e20 LOCAL 0x10001 deregister_tm_clones 0x0000000000400460 FUNC 0x00009 register_tm_clones 0x00000000004004a0 FUNC 0x00009 __do_global_dtors_aux 0x00000000004004e0 FUNC 0x00009 completed.7585 0x0000000000601038 LOCAL 0x10001 __do_global_dtors_aux_fini_array_entry 0x0000000000600e18 LOCAL 0x10001 frame_dummy 0x0000000000400500 FUNC 0x00009 __frame_dummy_init_array_entry 0x0000000000600e10 LOCAL 0x10001 compilation_example.c 0x0000000000000000 LOCAL 0x04005 crtstuff.c 0x0000000000000000 LOCAL 0x04005 __FRAME_END__ 0x0000000000400708 LOCAL 0x10001 __JCR_END__ 0x0000000000600e20 LOCAL 0x10001 0x0000000000000000 LOCAL 0x04005 __init_array_end 0x0000000000600e18 LOCAL 0x00001 _DYNAMIC 0x0000000000600e28 LOCAL 0x10001 __init_array_start 0x0000000000600e10 LOCAL 0x00001 __GNU_EH_FRAME_HDR 0x00000000004005e4 LOCAL 0x00001 _GLOBAL_OFFSET_TABLE_ 0x0000000000601000 LOCAL 0x10001 __libc_csu_fini 0x00000000004005c0 FUNC 0x0000a _ITM_deregisterTMCloneTable 0x0000000000000000 WEAK 0x00080 data_start 0x0000000000601028 WEAK 0x00080 puts@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008 _edata 0x0000000000601038 GLOBAL 0x00002 _fini 0x00000000004005c4 FUNC 0x0000a __libc_start_main@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008 __data_start 0x0000000000601028 GLOBAL 0x00002 __gmon_start__ 0x0000000000000000 WEAK 0x00080 __dso_handle 0x0000000000601030 GLOBAL 0x10002 _IO_stdin_used 0x00000000004005d0 GLOBAL 0x10002 __libc_csu_init 0x0000000000400550 FUNC 0x0000a _end 0x0000000000601040 GLOBAL 0x00002 _start 0x0000000000400430 FUNC 0x0000a __bss_start 0x0000000000601038 GLOBAL 0x00002 main 0x0000000000400526 FUNC 0x0000a _Jv_RegisterClasses 0x0000000000000000 WEAK 0x00080 __TMC_END__ 0x0000000000601038 GLOBAL 0x10002 _ITM_registerTMCloneTable 0x0000000000000000 WEAK 0x00080 _init 0x00000000004003c8 FUNC 0x0000a puts 0x0000000000000000 FUNC 0x08008 __libc_start_main 0x0000000000000000 FUNC 0x08008 __gmon_start__ 0x0000000000000000 WEAK 0x08080
C
복사

4.3.2 소스코드

./inc/loader.cc
#include <stdlib.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include <errno.h> #include <string> #include <vector> #include <bfd.h> #include "loader.h" static bfd* open_bfd(std::string &fname) { static int bfd_inited = 0; bfd *bfd_h; if(!bfd_inited) { bfd_init(); bfd_inited = 1; } bfd_h = bfd_openr(fname.c_str(), NULL); if(!bfd_h) { fprintf(stderr, "failed to open binary '%s' (%s)\n", fname.c_str(), bfd_errmsg(bfd_get_error())); return NULL; } if(!bfd_check_format(bfd_h, bfd_object)) { fprintf(stderr, "file '%s' does not look like an executable (%s)\n", fname.c_str(), bfd_errmsg(bfd_get_error())); return NULL; } /* Some versions of bfd_check_format pessimistically set a wrong_format * error before detecting the format, and then neglect to unset it once * the format has been detected. We unset it manually to prevent problems. */ bfd_set_error(bfd_error_no_error); if(bfd_get_flavour(bfd_h) == bfd_target_unknown_flavour) { fprintf(stderr, "unrecognized format for binary '%s' (%s)\n", fname.c_str(), bfd_errmsg(bfd_get_error())); return NULL; } return bfd_h; } static int load_symbols_bfd(bfd *bfd_h, Binary *bin) { int ret; long n, nsyms, i; asymbol **bfd_symtab; Symbol *sym; bfd_symtab = NULL; n = bfd_get_symtab_upper_bound(bfd_h); if(n < 0) { fprintf(stderr, "failed to read symtab (%s)\n", bfd_errmsg(bfd_get_error())); goto fail; } else if(n) { bfd_symtab = (asymbol**)malloc(n); if(!bfd_symtab) { fprintf(stderr, "out of memory\n"); goto fail; } nsyms = bfd_canonicalize_symtab(bfd_h, bfd_symtab); if(nsyms < 0) { fprintf(stderr, "failed to read symtab (%s)\n", bfd_errmsg(bfd_get_error())); goto fail; } for(i = 0; i < nsyms; i++) { if(bfd_symtab[i]->flags & BSF_FUNCTION) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_FUNC; sym->name = std::string(bfd_symtab[i]->name); sym->addr = bfd_asymbol_value(bfd_symtab[i]); sym->ctype = bfd_symtab[i]->flags; } else if(bfd_symtab[i]->flags & BSF_WEAK) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_WEAK; sym->name = std::string(bfd_symtab[i]->name); sym->addr = bfd_asymbol_value(bfd_symtab[i]); sym->ctype = bfd_symtab[i]->flags; } else if(bfd_symtab[i]->flags & BSF_GLOBAL) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_GLOBAL; sym->name = std::string(bfd_symtab[i]->name); sym->addr = bfd_asymbol_value(bfd_symtab[i]); sym->ctype = bfd_symtab[i]->flags; } else if(bfd_symtab[i]->flags & BSF_LOCAL) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_LOCAL; sym->name = std::string(bfd_symtab[i]->name); sym->addr = bfd_asymbol_value(bfd_symtab[i]); sym->ctype = bfd_symtab[i]->flags; } /*else { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->ctype = bfd_symtab[i]->flags; sym->name = std::string(bfd_symtab[i]->name); sym->addr = bfd_asymbol_value(bfd_symtab[i]); }*/ } } ret = 0; goto cleanup; fail: ret = -1; cleanup: if(bfd_symtab) free(bfd_symtab); return ret; } static int load_dynsym_bfd(bfd *bfd_h, Binary *bin) { int ret; long n, nsyms, i; asymbol **bfd_dynsym; Symbol *sym; bfd_dynsym = NULL; n = bfd_get_dynamic_symtab_upper_bound(bfd_h); if(n < 0) { fprintf(stderr, "failed to read dynamic symtab (%s)\n", bfd_errmsg(bfd_get_error())); goto fail; } else if(n) { bfd_dynsym = (asymbol**)malloc(n); if(!bfd_dynsym) { fprintf(stderr, "out of memory\n"); goto fail; } nsyms = bfd_canonicalize_dynamic_symtab(bfd_h, bfd_dynsym); if(nsyms < 0) { fprintf(stderr, "failed to read dynamic symtab (%s)\n", bfd_errmsg(bfd_get_error())); goto fail; } for(i = 0; i < nsyms; i++) { if(bfd_dynsym[i]->flags & BSF_FUNCTION) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_FUNC; sym->name = std::string(bfd_dynsym[i]->name); sym->addr = bfd_asymbol_value(bfd_dynsym[i]); sym->ctype = bfd_dynsym[i]->flags; } else if(bfd_dynsym[i]->flags & BSF_WEAK) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_WEAK; sym->name = std::string(bfd_dynsym[i]->name); sym->addr = bfd_asymbol_value(bfd_dynsym[i]); sym->ctype = bfd_dynsym[i]->flags; } else if(bfd_dynsym[i]->flags & BSF_GLOBAL) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_GLOBAL; sym->name = std::string(bfd_dynsym[i]->name); sym->addr = bfd_asymbol_value(bfd_dynsym[i]); sym->ctype = bfd_dynsym[i]->flags; } else if(bfd_dynsym[i]->flags & BSF_LOCAL) { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->type = Symbol::SYM_TYPE_LOCAL; sym->name = std::string(bfd_dynsym[i]->name); sym->addr = bfd_asymbol_value(bfd_dynsym[i]); sym->ctype = bfd_dynsym[i]->flags; } /*else { bin->symbols.push_back(Symbol()); sym = &bin->symbols.back(); sym->ctype = bfd_dynsym[i]->flags; sym->name = std::string(bfd_dynsym[i]->name); sym->addr = bfd_asymbol_value(bfd_dynsym[i]); }*/ } } ret = 0; goto cleanup; fail: ret = -1; cleanup: if(bfd_dynsym) free(bfd_dynsym); return ret; } static int load_sections_bfd(bfd *bfd_h, Binary *bin) { int bfd_flags; uint64_t vma, size; const char *secname; asection* bfd_sec; Section *sec; Section::SectionType sectype; for(bfd_sec = bfd_h->sections; bfd_sec; bfd_sec = bfd_sec->next) { bfd_flags = bfd_get_section_flags(bfd_h, bfd_sec); sectype = Section::SEC_TYPE_NONE; if(bfd_flags & SEC_CODE) { sectype = Section::SEC_TYPE_CODE; } else if(bfd_flags & SEC_DATA) { sectype = Section::SEC_TYPE_DATA; } else { continue; } vma = bfd_section_vma(bfd_h, bfd_sec); size = bfd_section_size(bfd_h, bfd_sec); secname = bfd_section_name(bfd_h, bfd_sec); if(!secname) secname = "<unnamed>"; bin->sections.push_back(Section()); sec = &bin->sections.back(); sec->binary = bin; sec->name = std::string(secname); sec->type = sectype; sec->vma = vma; sec->size = size; sec->bytes = (uint8_t*)malloc(size); if(!sec->bytes) { fprintf(stderr, "out of memory\n"); return -1; } if(!bfd_get_section_contents(bfd_h, bfd_sec, sec->bytes, 0, size)) { fprintf(stderr, "failed to read section '%s' (%s)\n", secname, bfd_errmsg(bfd_get_error())); return -1; } } return 0; } static int load_binary_bfd(std::string &fname, Binary *bin, Binary::BinaryType type) { int ret; bfd *bfd_h; const bfd_arch_info_type *bfd_info; bfd_h = NULL; bfd_h = open_bfd(fname); if(!bfd_h) { goto fail; } bin->filename = std::string(fname); bin->entry = bfd_get_start_address(bfd_h); bin->type_str = std::string(bfd_h->xvec->name); switch(bfd_h->xvec->flavour) { case bfd_target_elf_flavour: bin->type = Binary::BIN_TYPE_ELF; break; case bfd_target_coff_flavour: bin->type = Binary::BIN_TYPE_PE; break; case bfd_target_unknown_flavour: default: fprintf(stderr, "unsupported binary type (%s)\n", bfd_h->xvec->name); goto fail; } bfd_info = bfd_get_arch_info(bfd_h); bin->arch_str = std::string(bfd_info->printable_name); switch(bfd_info->mach) { case bfd_mach_i386_i386: bin->arch = Binary::ARCH_X86; bin->bits = 32; break; case bfd_mach_x86_64: bin->arch = Binary::ARCH_X86; bin->bits = 64; break; default: fprintf(stderr, "unsupported architecture (%s)\n", bfd_info->printable_name); goto fail; } /* Symbol handling is best-effort only (they may not even be present) */ load_symbols_bfd(bfd_h, bin); load_dynsym_bfd(bfd_h, bin); if(load_sections_bfd(bfd_h, bin) < 0) goto fail; ret = 0; goto cleanup; fail: ret = -1; cleanup: if(bfd_h) bfd_close(bfd_h); return ret; } int load_binary(std::string &fname, Binary *bin, Binary::BinaryType type) { return load_binary_bfd(fname, bin, type); } void unload_binary(Binary *bin) { size_t i; Section *sec; for(i = 0; i < bin->sections.size(); i++) { sec = &bin->sections[i]; if(sec->bytes) { free(sec->bytes); } } }
C
복사
./inc/loader.h
#ifndef LOADER_H #define LOADER_H #include <stdint.h> #include <string> #include <vector> class Binary; class Section; class Symbol; class Symbol { public: enum SymbolType { SYM_TYPE_UKN = 0, SYM_TYPE_FUNC = 1, SYM_TYPE_WEAK = 2, SYM_TYPE_GLOBAL = 3, SYM_TYPE_LOCAL = 4 }; Symbol() : type(SYM_TYPE_UKN), name(), addr(0), ctype(0) {} SymbolType type; std::string name; uint64_t addr; unsigned int ctype; }; class Section { public: enum SectionType { SEC_TYPE_NONE = 0, SEC_TYPE_CODE = 1, SEC_TYPE_DATA = 2 }; Section() : binary(NULL), type(SEC_TYPE_NONE), vma(0), size(0), bytes(NULL) {} bool contains (uint64_t addr) { return (addr >= vma) && (addr-vma < size); } Binary *binary; std::string name; SectionType type; uint64_t vma; uint64_t size; uint8_t *bytes; }; class Binary { public: enum BinaryType { BIN_TYPE_AUTO = 0, BIN_TYPE_ELF = 1, BIN_TYPE_PE = 2 }; enum BinaryArch { ARCH_NONE = 0, ARCH_X86 = 1 }; Binary() : type(BIN_TYPE_AUTO), arch(ARCH_NONE), bits(0), entry(0) {} Section *get_text_section() { for(auto &s : sections) if(s.name == ".text") return &s; return NULL; } std::string filename; BinaryType type; std::string type_str; BinaryArch arch; std::string arch_str; unsigned bits; uint64_t entry; std::vector<Section> sections; std::vector<Symbol> symbols; }; int load_binary (std::string &fname, Binary *bin, Binary::BinaryType type); void unload_binary (Binary *bin); #endif /* LOADER_H */
C
복사
./chapter4loader_demo.cc
/* Demonstrate the binary loader from ../inc/loader.cc */ #include <stdio.h> #include <stdint.h> #include <string.h> #include "../inc/loader.h" int main(int argc, char *argv[]) { size_t i; Binary bin; Section *sec; Symbol *sym; std::string fname; if(argc < 2) { printf("Usage: %s <binary>\n", argv[0]); return 1; } fname.assign(argv[1]); if(load_binary(fname, &bin, Binary::BIN_TYPE_AUTO) < 0) { return 1; } printf("loaded binary '%s' %s/%s (%u bits) entry@0x%016jx\n", bin.filename.c_str(), bin.type_str.c_str(), bin.arch_str.c_str(), bin.bits, bin.entry); for(i = 0; i < bin.sections.size(); i++) { sec = &bin.sections[i]; if(argc == 3) { if(strcasecmp(argv[2],sec->name.c_str()) == 0) { int line = 0; printf(" 0x%016jx %-8ju %-20s %s\n", sec->vma, sec->size, sec->name.c_str(), sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA"); printf("Section Data\n offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n 000000 "); for(int bc = 0; bc < sec->size ; bc++) { printf("%02x ",sec->bytes[bc]); if((bc+1)%16 == 0 && bc != 0 && bc != sec->size-1) { line ++; printf("\n %05x0 ",line); } } printf("\n"); break; } } else { printf(" 0x%016jx %-8ju %-20s %s\n", sec->vma, sec->size, sec->name.c_str(), sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA"); } } if(bin.symbols.size() > 0) { printf("scanned symbol tables\n"); for(i = 0; i < bin.symbols.size(); i++) { sym = &bin.symbols[i]; printf(" %-40s 0x%016jx ",sym->name.c_str(), sym->addr); if(sym->type == Symbol::SYM_TYPE_FUNC)printf("FUNC "); if(sym->type == Symbol::SYM_TYPE_WEAK)printf("WEAK "); if(sym->type == Symbol::SYM_TYPE_GLOBAL)printf("GLOBAL "); if(sym->type == Symbol::SYM_TYPE_LOCAL)printf("LOCAL "); printf("0x%05x\n",sym->ctype); } } unload_binary(&bin); return 0; }
C
복사