LoginSignup
3
2

C言語 (GCC) で配列の配置先を切り替えて実行可能にする

Posted at

実行できない配列

例として、x86_64 で第1引数と第2引数の値の和を返すプログラムを用意する。

89 f8    mov eax, edi
01 f0    add eax, esi
c3       ret

これを呼び出すプログラムを用意する。

このようにデータへのポインタを関数ポインタに変換するのはC言語の規格には違反するみたいだけど、目をつぶってね…

#include <stdio.h>

unsigned char program[] = {0x89, 0xf8, 0x01, 0xf0, 0xc3};

int main(void) {
	int (*add)(int, int) = (void*)program;
	printf("%d\n", add(40, 2));
	return 0;
}

しかし、これを実行するとエラーになってしまった。

yUZ7Mw - Online C Compiler & Debugging Tool - Ideone.com

これは、メモリ上でデータを格納する領域とプログラムを格納する領域が分かれており、データを格納する領域にあるデータをプログラムとして実行しようとするとエラーとして落とす設定になっているからであると考えられる。

実行できる配列

GCC では、section 属性を用いることで、変数を配置するセクションを指定できる。

Common Variable Attributes (Using the GNU Compiler Collection (GCC))

これを用いてプログラムを格納した配列をプログラムを格納する領域 (.text セクション) に配置することで、配列に格納したプログラムを実行できるようになる (ことがある)。

#include <stdio.h>

__attribute__ ((section (".text")))
unsigned char program[] = {0x89, 0xf8, 0x01, 0xf0, 0xc3};

int main(void) {
	int (*add)(int, int) = (void*)program;
	printf("%d\n", add(40, 2));
	return 0;
}

XUDB3j - Online C Compiler & Debugging Tool - Ideone.com

ただし、プログラムを格納する領域への書き込みは許可されておらず、プログラムを格納する領域に配置した配列の要素への代入はエラーの原因となる。

#include <stdio.h>

__attribute__ ((section (".text")))
unsigned char program[] = {0x89, 0xf8, 0x01, 0xf0, 0x83, 0xc0, 0x01, 0xc3};

int main(void) {
	int (*add)(int, int) = (void*)program;
	program[6] = 0x2; /* エラー */
	printf("%d\n", add(40, 2));
	return 0;
}

さらに、この方法を応用し、main 関数を配列として記述することも可能である。

__attribute__ ((section (".text")))
char main[] = "H\xb8orld\n\0\0\0PH\xb8hello, wP\xb8\x01\0\0\0\x89\xc7H\x89\xe6\xba\r\0\0\0\x0f\x05H\x83\xc4\0201\xc0\xc3";

L54eSJ - Online C Compiler & Debugging Tool - Ideone.com

アセンブリソース
bits 64

	mov rax, 0x0a646c726f
	push rax
	mov rax, 0x77202c6f6c6c6568
	push rax
	mov eax, 1
	mov edi, eax
	mov rsi, rsp
	mov edx, 13
	syscall
	add rsp, 16
	xor eax, eax
	ret
3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2