The Shellcoder's Handbook の Format String セクションを勉強しています。本のアドバイスとして、私は次のようなコードを使用してテストを行います。
[フォーマット文字列.c]
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc>1) {
if(argc>2) {
printf("Push a key to continue...\n");
getc(stdin);
}
printf("Sortie format string => ");
printf( argv[1] );
printf("\n");
}
printf("\n");
}
したがって、オフセットを使用してスタック上で引数 (formatstring に渡し、後で printf によって使用されるチェーン) を見つけることがトリックであることがわかりました。
./formatstring "aaaa%$offset\$x"
(オフセットが一定のままになるように、kernel.randomize_va_space を 0 に設定します)。このオフセットを見つけるために、彼らは小さなバッチ スクリプトを使用します。
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%$i\$x"; done | grep 4141
私はこれを手に入れました(ここではオフセット= 137)
137 Sortie format string => AAAAAAAA41414141
138 Sortie format string => AAAAAAAA25414141
最初に、私の「AAAAAAAA」はスタック上で「整列」されていません (ここでは 7 つの 41 しか数えられませんが、formatstring に 8 つの「A」を送信しました)。 bash スクリプト (for) を起動すると、2 時間後に「A」の「アライメント」が変更されている可能性があります。
さらに厄介なことに、./formatstring に送信する引数にバイトを追加すると、オフセットが変化するようです。私が走れば
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%32x%$i\$x"; done | grep 4141
私は得る
136 Sortie format string => AAAAAAAA b7ff103041414141
137 Sortie format string => AAAAAAAA b7ff103025414141
または実行
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%320x%$i\$x"; done | grep 4141
私は得る
139 Sortie format string => AAAAAAAA b7ff103041410067
140 Sortie format string => AAAAAAAA b7ff103041414141
141 Sortie format string => AAAAAAAA b7ff103033254141
ご覧のとおり、オフセットが変化し、理解できないロジックに従います。本によると、これは起こらないはずです。それがどこから来たか知っていますか?一種のスタック保護メカニズムですか? formatstring.c を gcc するときに削除できますか?