[BinaryHack#11] 실행 파일에 데이터 삽입하기 (64bits)

‘Binary Hacks’의 hack #11에는 objcopy를 이용해서 실행파일에 binary를 추가하는 방법이 나온다. 이것을 따라 64 bits machine에서 build하면 i386:x86-64 출력물과 i386 출력물이 incompatible 해서 link할 수 없다는 오류가 발생한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o
/usr/bin/ld: i386 architecture of input file 'binary.o' is incompatible with i386:x86-64 output
collect2: error: ld returned 1 exit status

gcc로 만들어진 main.o는 ELF-64 format인데 objcopy로 생성한 ELF-32 format이어서 함께 link할 수 없다는 것이다. 이 문제는 동일한 ELF format이 되도록 하면 해결된다. 즉, gcc로 compile한 결과물이 objcopy의 결과물인 ELF-32와 동일하게 되도록 하거나 objcopy의 결과 물이 main.o와 동일한 ELF-64가 되도록 해야한다.

첫번째 방법 – ELF-32 format으로 object를 compile
gcc에 -m32 option을 추가하면 ELF32로 compile된 object file을 얻을 수 있다. 이것을 objcopy의 결과 물과 link한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -m32 -c main.c
$> gcc -m32 -o program main.o binary.o

두번째 방법 – ELF-64 format으로 binary를 생성
objcopy가 ELF64를 생성하도록 하면 gcc로 compile한 다른 object file들과 link할 수 있다.

$> objcopy -I binary -O elf64-x86-64 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o

 

* objcopy로 생성된 ELF object에서 담고 있는 symbol의 목록은 nm 명령어나 readelf -s option으로 볼 수 있다.

$> nm binary.o
00000000002fd036 D _binary_binary_bmp_end
00000000002fd036 A _binary_binary_bmp_size
0000000000000000 D _binary_binary_bmp_start

$>readelf -s binary.o
Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_start
     3: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_end
     4: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT  ABS _binary_binary_bmp_size