web-dev-qa-db-ja.com

Cプログラムのシェルコード

Execveシェルコードの謎を解く では、execveシェルコードを記述する方法が説明されています。

_#include<stdio.h>
#include<string.h>

unsigned char code[] = 
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

main()
{

    printf("Shellcode Length: %d\n", strlen(code));

    int (*ret)() = (int(*)())code;

    ret();
}
_

int (*ret)() = (int(*)())code;は何をしますか?

14
user720694
_  int (*ret)() = (int(*)())code;
  ~~~~~~~~~~~~   ~~~~~~~~~~~~~~
        1              2

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               3
_
  1. retを、パラメーター_()_を持たない関数へのポインターとして定義し、intを返します。したがって、これらの_()_は、関数のパラメーターの定義を示します。

  2. これは、codeを、パラメーター_()_を持たず、intを返す関数へのポインターにキャストするためのものです。

  3. codeを関数としてキャストし、それをretに割り当てます。その後、ret();を呼び出すことができます。

_unsigned char code[] =  "\x31\xc0\x50\x68\x6e\x2f\...
_

これは、16進値で表される一連のマシン命令です。関数としてコードに挿入されます。

17
deepmax
    (*(void(*)())shellcode)()

==

    p = (void(*)()) shellcode;
    (*p)();
1
Jeremy

この関数ポインタ部分をもっと簡単な形に書き直すことはできますか?

これがもっと簡単だと思うかどうかはわかりませんが、多分:

#include <stdio.h>
#include <string.h>

unsigned char code[] = 
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

typedef int(*shellcode_t)();

int main(int argc, char ** argv) {
    printf("Shellcode Length: %ld\n", strlen(code));

    shellcode_t ret = (shellcode_t)code;

    ret();
}
0
Robert Larsen

Int行は、code []配列を指すことにより、ret()関数を宣言します。つまり、関数はcode []バイナリ命令にマップされます。

\ x構文は、16進文字を文字列に埋め込むための安全な方法です。たとえば、「1」の文字コードは49、つまり16進数の31であるため、「\ x31」を「1」に置き換えることができます。

0