2017-02-05 18 views
-2

私は有名な「スマッシュスタック」チュートリアルをやっていて、私は立ち往生しています。基本的には、スタックの戻りアドレスを指すポインタを操作します。その後、リターンアドレス自体を操作します。ですから、私の目標は命令x = 1を飛ばし過ぎることです。Cポインタ操作

私のコードを確認してください。私のコードで動作するはずです。私もASLRをオフにしていない...しかし、何の効果

しかし、最後に、私はまだ「1」を出力します...チュートリアルからなぜ:-(

コードを伝えることはできません:

void function(int a, int b, int c) { 
    char buffer1[5]; 
    char buffer2[10]; 
    int *ret; 

    ret = buffer1 + 12; 
    (*ret) += 8; 
} 

void main() { 
    int x; 

    x = 0; 
    function(1,2,3); 
    x = 1; 
    printf("%d\n",x); 
} 

マイコード(最初に試す):

void function(int a, int b, int c) { 

    // Dont really know if initiated arrays have a different address than non initiated... 
    char buffer1[5] = {1,2,3,4,5}; 
    char buffer2[10]; 
    int *ret; 

    ret = buffer1; 

    int i; 
    for(i=0;i<64;i++){ 
    printf("Added: %d, Address: %016x\n",i,(*ret)); 
    ret += i; 
    //Found out that adding 5 points to the return address on the stack 
    if(i == 5) break; 

    } 

    printf("stack address of ret: %p\n", ret); 
    printf("unchanged ret address: %016x\n", (*ret)); 

    //Just counted the bytes to pass the x = 1; movl $0x1,-0x4(%rbp) 
    (*ret) += 7; 
    printf("changed ret address: %016x\n", (*ret)); 
} 

void main() { 
    int x; 

    x = 0; 
    function(1,2,3); 
    x = 1; 
    printf("print x: %d\n",x); 
} 

更新:。 私のコードは、現在働いている(これは、x = 1をスキップ)誰もが興味を持っている場合、私はそのコードを投稿します。 ..

Greetz!

+0

それはもちろん、プリント1のみ –

+0

だからここで私のミスがあるのだろうか? – int80

+0

と-fno-stack-protectorでコンパイルすると、 – int80

答えて

0

これは動作します:

#include<stdio.h> 

void function(int a, int b, int c) { 
char buffer1[5] = {1,2,3,4,5}; 
char buffer2[10]; 
char *ret; 

ret = buffer1; 

ret += 0x18; 

printf("stack address of ret: %p\n", ret); 
printf("unchanged ret address: 0x%x%02x%x\n",ret[2],ret[1],ret[0]); 
printf("unchanged ret address: %p\n", *(void **)ret); 
printf("unchanged ret address: 0x%06x\n", *(unsigned int *)ret &  0x00FFFFFF); 
printf("unchanged ret address: 0x%03x\n", *(unsigned int *)ret); 

//Just counted the bytes to pass the x = 1; movl $0x1,-0x4(%rbp) 
(*ret) += 7; 
//printf("changed ret address: %p\n",(*ret)); 
printf("changed ret address: 0x%03x\n", *(unsigned int *)ret); 
} 

void main() { 
int x; 

x = 0; 
function(1,2,3); 
x = 1; 
printf("print x: %d\n",x); 
} 
0

あなたのコードにはいくつかの問題があります。あなたが何をしようとしているのか分かりません。 スタックを元に戻って、スタックの外観は何ですか?

あなたのポインタは8バイト(64ビット)で、あなたのintはそれぞれ4バイト(32ビット)で、次にそれぞれ5バイトの文字と10バイトの文字があります。 8バイト)に変数iを加えたものです。 だからあなたのスタックが次のようになります。あなたが学ぶためにこれをやっているので、あなたのポインタは、バッファ1には、バックアップに20バイトを必要なリターンアドレスを取得すると8 を読んで指している

<return address>  <8 bytes> 
<function parameters> <12 bytes> 
<buffer1>    <5 bytes> 
<buffer2>    <10 bytes> 
<ret>     <8 bytes> 
<i> 

、私はしませんあなたに答えを与えるが、ここでヒントです:

//Chars are 1 byte, ints are 4, char != int 
char buffer1[5] = {'a', 'b', 'c', 'd', 'e'}; 
char* currentAddress = &buffer1; 

printf("Value: %c, Address: %016x\n",(*currentAddress), currentAddress); 

//move 1 byte forward 
currentAddress++; 

//print a char 
printf("Value: %c, Address: %016x\n",(*currentAddress), currentAddress); 

//move back 
currentAddress--; 

//print a char 
printf("Value: %c, Address: %016x\n",(*currentAddress), currentAddress);  

//back up one int - safer than just saying back up 4 bytes 
currentAddress -= sizeof(int); 
//Print an int, notice the cast. 
printf("Value: %d, Address: %016x\n",(*(int*)currentAddress), currentAddress); 
+0

がうまくいきます。あなたの説明にはいくつかの誤りがあります。スタックはあなたが示したものとは異なって見えます(その関数のパラメータではなくEBP)。ローカル変数には実際には単語サイズがあります... – int80