「メモリ破壊」の版間の差分

提供: セキュリティ
移動: 案内検索
(ページの作成:「メモリ破壊 (memory corruption, メモリコラプション)とは、不正なメモリの書き換え・操作によって、データを破壊してしまうこ...」)
(相違点なし)

2015年3月22日 (日) 12:16時点における版

メモリ破壊 (memory corruption, メモリコラプション)とは、不正なメモリの書き換え・操作によって、データを破壊してしまうことです。

読み方

メモリ破壊
めもりはかい
memory corruption
めもり こらぷしょん

概要

メモリ破壊は、メモリの操作を誤ったときに発生します。

  • ポインタ操作、誤ったアドレスの計算などにより、割り当てられた領域をこえて、参照、書き込みを行う(バッファオーバーラン
  • すでに解放済みのメモリ領域に参照、書き込みを行う (Use After Free)
  • 動的に確保したメモリを解放したあとに、再び解放してしまう

メモリ破壊脆弱性がある場合、サービス妨害攻撃によりDoS状態に陥ったり、任意のコードを実行させられてしまう可能性があります。

二重解放の例

ファイルポインタ

double_fp_free.c

/*
 * double_fp_free.c
 * Copyright (C) 2015 kaoru <kaoru@bsd>
 */
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
        FILE *fp = fopen ("/etc/services", "r");
        if ( fclose(fp) != 0) { perror("fclose 1"); } ;
        if ( fclose(fp) != 0) { perror("fclose 2"); } ;
        exit(EXIT_SUCCESS);
}

実行結果

$ ./a.out
*** Error in `./a.out': double free or corruption (top): 0x000000000216a010 ***
[1]    7304 abort (core dumped)  ./a.out

gdb

(gdb) b main
Breakpoint 1 at 0x40061c: file double_fp_free.c, line 12.
(gdb) run
Starting program: /tmp/a.out 
 
Breakpoint 1, main (argc=1, argv=0x7fffffffc608) at double_fp_free.c:12
12		FILE *fp = fopen ("/etc/services", "r");
(gdb) n
13		if ( fclose(fp) != 0) { perror("fclose 1"); } ;
(gdb) n
14		if ( fclose(fp) != 0) { perror("fclose 2"); } ;
(gdb) n
*** Error in `/tmp/a.out': double free or
corruption (top): 0x0000000000602010 ***
 
Program received signal SIGABRT, Aborted.
0x00007ffff7a4bcc9 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56	../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) strace 
warning: Couldn't determine the static tracepoint marker to probe
Static tracepoint 2 at 0x7ffff7a4bcc9: file
../nptl/sysdeps/unix/sysv/linux/raise.c, line 56.

strace

straceの結果

$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 85 vars */]) = 0
brk(0)                                  = 0xdbd000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7fa6fe72d000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=96509, ...}) = 0
mmap(NULL, 96509, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa6fe715000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3,
"\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) =
832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) =
0x7fa6fe148000
mprotect(0x7fa6fe303000, 2093056, PROT_NONE) = 0
mmap(0x7fa6fe502000, 24576, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7fa6fe502000
mmap(0x7fa6fe508000, 17088, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa6fe508000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7fa6fe714000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7fa6fe712000
arch_prctl(ARCH_SET_FS, 0x7fa6fe712740) = 0
mprotect(0x7fa6fe502000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ)     = 0
mprotect(0x7fa6fe72f000, 4096, PROT_READ) = 0
munmap(0x7fa6fe715000, 96509)           = 0
brk(0)                                  = 0xdbd000
brk(0xdde000)                           = 0xdde000
open("/etc/services", O_RDONLY)         = 3
close(3)                                = 0
open("/dev/tty", O_RDWR|O_NOCTTY|O_NONBLOCK) = 3
writev(3, [{"*** Error in `", 14}, {"./a.out", 7}, {"': ", 3}, {"double free
or corruption (top)", 31}, {": 0x", 4}, {"0000000000dbd010", 16}, {" ***\n",
5}], 7*** Error in `./a.out': double free or corruption (top):
0x0000000000dbd010 ***
) = 80
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7fa6fe72c000
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
gettid()                                = 7277
tgkill(7277, 7277, SIGABRT)             = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=7277, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++
[1]    7274 abort (core dumped)  strace ./a.out

関連項目