.dataセグメントにある構造体のメンバの値を書き換えることはできるか
悩んでいます。→とりあえずできました。
オイラ的な最近の話題の一つとして、MySQLの文字コードのとある制御用フラグ(escape_with_backslash_is_dangerous)があるんですが、
CHARSET_INFO my_charset_sjis_japanese_ci= { 13,0,0, /* number */ MY_CS_COMPILED|MY_CS_PRIMARY|MY_CS_STRNXFRM, /* state */ "sjis", /* cs name */ "sjis_japanese_ci", /* name */ "", /* comment */ NULL, /* tailoring */ ctype_sjis, to_lower_sjis, to_upper_sjis, sort_order_sjis, NULL, /* contractions */ NULL, /* sort_order_big*/ NULL, /* tab_to_uni */ NULL, /* tab_from_uni */ my_unicase_default, /* caseinfo */ NULL, /* state_map */ NULL, /* ident_map */ 1, /* strxfrm_multiply */ 1, /* caseup_multiply */ 1, /* casedn_multiply */ 1, /* mbminlen */ 2, /* mbmaxlen */ 0, /* min_sort_char */ 255, /* max_sort_char */ ' ', /* pad char */ 0, /* escape_with_backslash_is_dangerous */ &my_charset_handler, &my_collation_ci_handler };
このescape_with_backslash_is_dangerousをbinary hack的に0から1に書き換える方法はないかと思案しています。
nm+grepでmy_charset_sjis_japanese_ciがデータセクションに入っているのを確認できます。
mir@t43:~/tritonn/show/install/bin$ nm --demangl mysqld | grep my_charset_sjis_japanese_ci 085b4aa0 D my_charset_sjis_japanese_ci
アドレスが0x085b4aa0となっていて、sizeof(my_charset_sjis_japanese_ci) = 108なので、
mir@t43:~/tritonn/show/install/bin$ objdump -s --start-address=0x085b4aa0 --stop-address=0x085b4b0c mysqld mysqld: ファイル形式 elf32-i386 セクション .data の内容: 85b4aa0 0d000000 00000000 00000000 61000000 ............a... 85b4ab0 32494e08 37494e08 48494e08 00000000 2IN.7IN.HIN..... 85b4ac0 60495a08 804a5a08 804b5a08 804c5a08 `IZ..JZ..KZ..LZ. 85b4ad0 00000000 00000000 00000000 00000000 ................ 85b4ae0 605c5d08 00000000 00000000 01000000 `\]............. 85b4af0 01010000 01000000 02000000 0000ff00 ................ 85b4b00 20000000 204a5b08 e0495b08 ... J[..I[.
たぶんこれがmy_charset_sjis_japanese_ciなんだと思うのですが、これを、
85b4aa0 0d000000 00000000 00000000 61000000 ............a... 85b4ab0 32494e08 37494e08 48494e08 00000000 2IN.7IN.HIN..... 85b4ac0 60495a08 804a5a08 804b5a08 804c5a08 `IZ..JZ..KZ..LZ. 85b4ad0 00000000 00000000 00000000 00000000 ................ 85b4ae0 605c5d08 00000000 00000000 01000000 `\]............. 85b4af0 01010000 01000000 02000000 0000ff00 ................ 85b4b00 20010000 204a5b08 e0495b08 ... J[..I[.
こうしたい訳です。何か良い方法はないですかね。
readelfによれば、.dataセクションはファイルオフセット0x49e580からのようです。
mir@t43:~/tritonn/show/install/bin$ readelf -S mysqld 37 個のセクションヘッダ、始点オフセット 0x130e71c: Section Headers: [番] 名前 タイプ アドレス Off サイズ ES Flg Lk Inf Al [23] .data PROGBITS 084e6580 49e580 113e0c 00 WA 0 0 32
書き換えたいバイトのアドレスは、0x085b4b01で、.dataの先頭が0x084e6580だから、差し引き、、、
0x085b4b01 - 0x084e6580 = 0xCE581
となって、ファイルオフセットでいうと、
0x49e580 + 0xCE581 = 0x56CB01
ということで、hexdump -Cした内容で見ると、、、
0056caa0 0d 00 00 00 00 00 00 00 00 00 00 00 61 00 00 00 |............a...| 0056cab0 32 49 4e 08 37 49 4e 08 48 49 4e 08 00 00 00 00 |2IN.7IN.HIN.....| 0056cac0 60 49 5a 08 80 4a 5a 08 80 4b 5a 08 80 4c 5a 08 |`IZ..JZ..KZ..LZ.| 0056cad0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 0056cae0 60 5c 5d 08 00 00 00 00 00 00 00 00 01 00 00 00 |`\].............| 0056caf0 01 01 00 00 01 00 00 00 02 00 00 00 00 00 ff 00 |................| 0056cb00 20 00 00 00 20 4a 5b 08 e0 49 5b 08 00 00 00 00 | ... J[..I[.....|
ここですね。
ここで、my ubuntuにバイナリエディタが入っていないことに気づくw 適当にいくつか入れる(bbe, beav, biew, bvi)。
あと「バイナリファイル 書き換え」でぐぐったら楽しそうな資料を発見したので載せておきます。
http://gotom.jp/~gotom/pub/2005-12-binary-2.0/Binary2.0Conf-presen/gotom.pdf
# 良くみたら、これbinary2.0カンファレンスで講演した方の資料ですな。
bviで0x0056CB01に飛んで00を01に書き換え。確認すると書き換わってた。
セクション .data の内容: 85b4aa0 0d000000 00000000 00000000 61000000 ............a... 85b4ab0 32494e08 37494e08 48494e08 00000000 2IN.7IN.HIN..... 85b4ac0 60495a08 804a5a08 804b5a08 804c5a08 `IZ..JZ..KZ..LZ. 85b4ad0 00000000 00000000 00000000 00000000 ................ 85b4ae0 605c5d08 00000000 00000000 01000000 `\]............. 85b4af0 01010000 01000000 02000000 0000ff00 ................ 85b4b00 20010000 204a5b08 e0495b08 ... J[..I[.
で、この「任意のファイルアドレスの値を書き換える」ってのをエディタ上でなくコマンドライン上でやるにはどーしたらいいんだろう。それができれば、ここまでの作業をスクリプト化して、フラグ書き換えパッチとかできそーなんですが。
bvi -s 0x0056CB01 -e 0x0056CB01 -f hoge mysqld
hogeに上手いこと書いたらいけそーな気がするが、hogeが上手くかけず、、、今日はここで撃沈。
改変したいバイナリとまったく同じバイナリを用意できるなら、bsdiff/bspatchでいいね。というか用意できるならそもそもreadelfとかいらねーかw
http://x68000.q-e-d.net/~68user/unix/pickup?bsdiff