2016-04-15 11 views
1

私はSIGQUITの後にコアダンプからプロセスを復活させようとしています。 私は本当にその仮想メモリを望んでいますが、マップしようとするとSIGSEGVを取得します。SIGSEGV、mmapping areaの後

編集:この領域は無料ではありません:0xf75d2000 - 0xf7774000、それでも私はそれを持っています。 enter image description here

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <string.h> 
#include <stdbool.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <ucontext.h> 
#include <elf.h> 
#include <sys/procfs.h> 
#include <sys/user.h> 
#include <linux/unistd.h> 
#include <linux/unistd.h> 
#include <asm/ldt.h> 
#include <signal.h> 
bool flag = false; 
int argc2; 
char ** argv2; 
int main2(){ 
    FILE * file = fopen("/proc/self/maps", "r"); 
    if (file) { 
     char c; 
     while ((c = getc(file)) != EOF) 
     putchar(c); 
     fclose(file); 
    } 
    fflush(stdout); 
    void* res = mmap((void*)(0xf75d2000), 0x001a5000, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); 
    return 0; 
} 
int main(int argc, char ** argv){ 
    argc2 = argc; 
    argv2 = argv; 
    ucontext_t cont; 
    getcontext (&cont); 
    if(!flag){ 
     void* a = mmap((void*)0x34B000, 81920, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); 
     if(a == MAP_FAILED){ 
     printf("mmapfail"); 
     return 1; 
     } 
     cont.uc_mcontext.gregs[REG_ESP] = 0x355000; 
     flag = true; 
     setcontext(&cont); 
    } else{ 
     exit(main2()); 
    } 
} 

私はそれをコンパイルしています:もちろん

gcc -static -Wl,-Ttext=0x4A9480,--build-idone,-Tdata=0x639480,--section-start=.plt=0x3B9480,--section-start=.rel.plt=0x3AF480,--section-start=.note.ABI-tag=0x39B480 main.c -o main -m32 

答えて

0

はあなたがSEGVを取得します。 MAP_FIXEDで物事をあなたに属していないいくつかのアドレスにマップし、あなたの足元からスタックを引っ張ります。あなたはこれをすることはできません。

アドレススペースはあなたの周りを混乱させるものではありません。MAP_FIXEDは、以前のマッピングを上書きする場合にのみ安全です。一回の実験でその中で遊んでも構わないが、後でそのプログラムを捨てることができるが、それ以外の用途はうまくいかない。

今すぐ返す場所がわからないため、setcontextへのお電話はクラッシュします。関数呼び出しとスタックがどのように相互作用するかを知っていますか? setcontextを呼び出すと、戻りアドレスがスタックに保存されます。その後、setcontextはスタックポインタを変更します。そして、戻りアドレスとして0を読み出すためにスタックポインタを返します。(または、setcontextは古いスタックポインタを他のレジスタに保存し、実際のスタックを上書きする別のmmapです)。しないでください。オペレーティングシステムでなくスタックを確実に変更する唯一の機会は、sigaltstackというシグナルハンドラを設定し、そのシグナルを捕捉し、シグナルハンドラから戻ってこないことです。

しかし、あなたの新しいスタックのメモリをMAP_FIXEDでいくつかのランダムなアドレスにマッピングするので、他の重要なデータ構造を上書きしてしまいますが、それでも動作しません。

+0

これは明らかに間違っています。プログラムはクラッシュしません。 mmapをprintfに置き換えると正常に動作します。関数内でespを印刷すると、スタックポインタが実際に変更されることがわかります。 – JKS

1

マップしようとしているアドレス(0xf75d2000)は、仮想メモリのユーザー空間/カーネル分割よりも上です。カーネルがCONFIG_VMSPLIT_3Gで構成されている場合、任意のアドレスを0xc0000000より上にマッピングすることはできません。

(システムコールを支援するために)既存のマッピングがvDSOスペースを公開するようにカーネルにセットアップされました。

+0

私は純粋なx86を持っていた場合は真実ですが、x64上で実行しています。niceを試してみました – JKS

+0

-m32でコンパイルすると、32ビット仮想アドレス空間で32ビット実行ファイルを作成できませんか? –

+0

x64でエミュレートされたx86だけです。すべてmmapできます – JKS