♧ 프로그램 실행에 필수적인 데이터를 파일에서 읽어 들여 이용할 때가 있다.
이 방법을 이용하면 손쉽게 데이터를 갱신할 수 있다는 이점이 있지만,
단일 실행 파일로 실행할 수 없고 데이터 파일을 분실하게 될 문제점도 있다.
여기서는 objcopy를 이용해서 실행파일에 데이터를 삽입하는 방법을 소개 한다.
[ 데이터 삽입 ]
적은 데이터를 소스코드에 삽입하는 것은 간단하다.
소스코드에 들어 있는 "Hello, world" 등의 메시지는 소스코드에 삽입된 데이터라 할 수 있다.
한편, 영화나 사전 등의 거대한 데이터를 소스코드에 삽입하기란 그리 간단하지 않다.
우선 데이터를 문자열 등으로 변환할 필요도 있고, 변환 후의 거대한 소스코드는 컴파일러가
처리할 수 있는 크기를 초과할 가능성이 높다.
[ objcopy ]
그래서 등장한 것이 GNU binutils에 포함되어 있는 objcopy 명령이다.
objcopy를 사용하면 임의의 파일을 링크 가능한 오브젝트 파일로 변환할 수 있다.
예) foo.jpg를 x86용 ELF32 형식의 오브젝트 파일 foo.o로 변환하려면 다음과 같다.
% objcopy -I binary -O elf32-i386 -B i386 foo.jpg foo.o |
▷ foo.o를 링크한 C 프로그램에서 foo.jpg 데이터는 다음과 같은 변수명을 이용해 참조.
extern char _binary_foo_jpg_start[]; extern char _binary_foo_jpg_end[]; extern char _binary_foo_jpg_size[]; |
▷ 이 변수들을 다음과 같이 사용한다.
const char *start = _binary_foo_jpg_start; // 데이터의 시작 주소 얻기 const char *end = _binary_foo_jpg_end; // 데이터의 끝 주소 +1 얻기 int size = (int) _binary_foo_jpg_size; // 데이터 크기 얻기 |
마지막의 _binary_foo_jpg_size 변수는 &_binary_foo_jpg_size[0]이 주소가 아닌
값(데이터 크기) 이므로 주의해야 한다.
[ 따라 해보자 ]
① jpg파일을 오브젝트 파일로 변환
② 간단한 test.c 작성
#include <stdio.h>
extern char _binary_foo_jpg_start[]; extern char _binary_foo_jpg_end[]; extern char _binary_foo_jpg_size[];
int main() { printf("start address : %p\n", _binary_foo_jpg_start); printf("end address : %p\n", _binary_foo_jpg_end); printf("size : %d\n", (int)_binary_foo_jpg_size);
return 0; } |
③ 변환된 .jpg 오브젝트 파일을 링크하여 컴파일 후 출력
[ 정리 ]
objcopy를 이용해 실행 파일에 데이터를 삽입하는 방법을 소개했다.
여기서 살펴본 예와 같은 일반 데이터뿐만 아니라 프로그램 자체의 소스코드나
다른 프로그램의 바이너리와 같이 특이한 데이터를 삽입하는 것과 같은 재미있는
경우도 있을 수 있다.
'컴퓨터 서적 정리 > Binary Hacks' 카테고리의 다른 글
[Hack #13] strings - 바이너리 파일에서 문자열 추출 (0) | 2011.07.03 |
---|---|
[Hack #12] nm - 오브젝트 파일에 포함된 심볼 확인 (0) | 2011.07.03 |
[Hack #10] objdump - (2) 오브젝트 파일 역어셈블 (0) | 2011.07.03 |
[Hack #9] objdump - (1) 오브젝트 파일 덤프 (0) | 2011.07.03 |
[Hack #8] readelf - ELF 파일 정보 보기 (0) | 2011.07.02 |