1

C バス エラー 10 からのシェルコードのテスト

上記は、シェルコードがソース内にある場合に、ac プログラム内からシェルコードを実行することに関する私の以前の質問でした。これは Carl Norum によって解決され、メモリ保護が原因でした。私は別の問題を抱えていますが、似ています。シェル コードを同じファイルに格納する代わりに、.txt ファイルからシェル コードを読み取って実行したいと考えています。以下では、メモリのセクションを PROT_EXEC としてマークし、.txt ファイルの内容を読み込んで実行しようとしました。しかし、うまくいきません。同じエラー KERN_PROTECTION_FAILURE が表示されます。mprotect と mmap を使用して、メモリのセクションを PROT_EXEC としてマークしようとしました。

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

int (*ret)();

unsigned char* buf;

int main()
{
    FILE* file;
    file = fopen("text.txt", "rb");

    fseek(file, 0, SEEK_END);
    unsigned int len = ftell(file);
    fseek(file, 0, SEEK_SET);

    buf = valloc(len);
    fread(buf, 1, len, file);

    fclose(file);

    mprotect(buf, len, PROT_EXEC);

   // I also tried mmap, but same error.
   /* void *ptr = mmap(0, 1024, PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);

    if (ptr == MAP_FAILED)
    {
        perror("mmap");
        exit(-1);
    }

    memcpy(ptr, buf, 1024);*/

    ret = buf;

    ret();

    return 0;
}

これは私が読んでいる text.txt ファイルで、前の質問と同じ Hello World コードです。

\x55\x48\x89\xe5\xeb\x33\x48\x31\xff\x66\xbf\x01\x00\x5e\x48\x31\xd2\xb2\x0e\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x04\x4c\x89\xc0\x0f\x05\x31\xff\x41\xb0\x02\x49\xc1\xe0\x18\x49\x83\xc8\x01\x4c\x89\xc0\x0f\x05\x48\x89\xec\x5d\xe8\xc8\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0a

txt ファイルの内容を PROC_EXEC メモリにコピーしているため、KERN_PROTECTION_FAILURE が発生する理由がわかりません。

4

1 に答える 1

5

あなたの前の質問に対する私の答えに基づいて、ここに解決策があります:

#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>

int main(void)
{
    FILE *file = fopen("text.txt", "r");
    unsigned char *buf;
    int length = 0;
    struct stat st;
    int v;

    // get file size and allocate. We're going to convert to bytes 
    // from text, so this allocation will be safely large enough
    fstat(fileno(file), &st);
    buf = valloc(st.st_size);
    while (fscanf(file, "\\x%02x", &v) == 1)
    {
        buf[length++] = v;
    }

    fclose(file);

    mprotect(buf, length, PROT_EXEC);

    int (*ret)() = (int (*)())buf;
    ret();

    return 0;
}

プログラムから実際に変更する必要があったのは、ASCII テキストをバイナリ データに変換するループだけです。便宜上使用fscanfしましたが、それはかなり壊れやすいです。

于 2013-07-24T18:54:56.277 に答える