Post

Peristence-Windows-Registry

Peristence-Windows-Registry

Peristence-Windows-Registry

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 Run / RunOnce registry keys are well known to be used by legitimate software.
    - Run registry     -> Executes everytime the user logs on
    - RunOnce registry -> Executes a single time and are removed by the system after successful execution
 */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>

#define VALUE_NAME   L"N0xshell"
#define COMMAND_LINE L"cmd.exe /k ping 127.0.0.1 -n 3"

#define REG_PATH_RUN     L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"
#define REG_PATH_RUNONCE L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce"

/*
 Creates the specified registry subkey (creates it if it does not exist)
 
 hRootKey   -> Defines root registry hive to be used
 pszSubKey  -> Defines subkey path
 pszSubName -> Defines value name
 pszRegData -> Defines the data stored inside the value
 */
BOOL SetRegistryKey(_In_ HKEY hRootKey, _In_ LPCWSTR pszSubKey, _In_ LPCWSTR pszSubName, _In_ LPCWSTR pszRegData) {
    HKEY hKey = NULL;
    DWORD dwDataLength = 0;
    LSTATUS STATUS = ERROR_SUCCESS;

    // Check if parameters are filled
    if (!hRootKey || !pszSubKey || !pszSubName || !pszRegData)
        return FALSE;

    // Setup buffer for command
    dwDataLength = (lstrlenW(pszRegData) + 1) * sizeof(WCHAR);

    // Open / create registry key
    STATUS = RegCreateKeyExW(hRootKey, pszSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL);
    if (STATUS != ERROR_SUCCESS) {
        printf("[!] RegCreateKeyExW Failed: 0x%0.8X\n", STATUS);
        goto _CleanUp;
    }

    // Set registry value with our ping command
    STATUS = RegSetValueExW(hKey, pszSubName, 0, REG_SZ, (PBYTE)pszRegData, dwDataLength);
    if (STATUS != ERROR_SUCCESS) {
        printf("[!] RegSetValueExW Failed: 0x%0.8X\n", STATUS);
        goto _CleanUp;
    }

_CleanUp:
    if (hKey)
        RegCloseKey(hKey);

    return (STATUS == ERROR_SUCCESS) ? TRUE : FALSE;
}

int wmain(void) {
    int choice = 0;

    printf("1. Write to Run key\n");
    printf("2. Write to RunOnce key\n");
    printf("0. Exit\n");
    printf("=============================================\n");
    printf("Select option: ");

    if (scanf_s("%d", &choice) != 1) {
        printf("[-] Invalid input.\n");
        return 1;
    }

    switch (choice) {
    case 1:
        printf("\n[*] Writing benign Run key (HKCU)...\n");
        if (SetRegistryKey(HKEY_CURRENT_USER, REG_PATH_RUN, VALUE_NAME, COMMAND_LINE)) {
            printf("[+] Run key written successfully.\n");
        }
        else {
            printf("[-] Failed to write Run key.\n");
        }
        break;

    case 2:
        printf("\n[*] Writing benign RunOnce key (HKCU)...\n");
        if (SetRegistryKey(HKEY_CURRENT_USER, REG_PATH_RUNONCE, VALUE_NAME, COMMAND_LINE)) {
            printf("[+] RunOnce key written successfully.\n");
        }
        else {
            printf("[-] Failed to write RunOnce key.\n");
        }
        break;

    case 0:
        printf("[*] Exiting...\n");
        break;

    default:
        printf("[-] Invalid choice.\n");
        return 1;
    }

    return 0;
}
This post is licensed under CC BY 4.0 by the author.