5static wchar_t *escape_for_powershell(
const wchar_t *input,
size_t n_chars) {
6 wchar_t *out =
nullptr;
7 if (input ==
nullptr || n_chars == 0) {
12 size_t new_n_chars = 0;
13 for (i = 0; i < n_chars; i++) {
16 if (input[i] == L
'\'') {
20 out = calloc(new_n_chars + 1, WL);
24 wmemset(out, L
'\0', new_n_chars + 1);
25 if (n_chars == new_n_chars) {
26 wmemcpy(out, input, new_n_chars + 1);
29 for (i = 0, j = 0; i < n_chars && j < new_n_chars; i++, j++) {
31 if (input[i] == L
'\'') {
38static wchar_t *convert_data_for_powershell(DWORD reg_type,
const char *data,
size_t data_len) {
39 wchar_t *out, *bin, *strings_nl, *escaped;
40 out = bin = strings_nl = escaped =
nullptr;
41 if (reg_type == REG_BINARY) {
44 size_t n_bin_chars = 5 * data_len;
45 size_t new_len = n_bin_chars + 1;
46 bin = calloc(new_len, WL);
50 wmemset(bin, L
'\0', new_len);
51 for (i = 0, j = 0; i < data_len; i++) {
52 if (i < (data_len - 1)) {
54 _snwprintf(conv, 6, L
"0x%02X,", data[i] & 0xFF);
56 wcsncat(bin + j, conv, 5);
60 _snwprintf(conv, 4, L
"0x%02X", data[i] & 0xFF);
62 wcsncat(bin + j, conv, 4);
66 size_t s_size = new_len + 10;
67 out = calloc(s_size, WL);
71 wmemset(out, L
'\0', s_size);
72 _snwprintf(out, s_size, L
"(byte[]](%ls))", bin);
75 if (reg_type == REG_EXPAND_SZ || reg_type == REG_SZ) {
76 escaped = escape_for_powershell((
wchar_t *)data, data_len == 0 ? 0 : data_len / WL);
80 size_t escaped_len = wcslen(escaped);
81 size_t total_size = escaped_len + 3;
82 out = calloc(total_size, WL);
86 wmemset(out, L
'\0', total_size);
87 _snwprintf(out, escaped_len + 2, L
"'%ls'", escaped);
90 if (reg_type == REG_MULTI_SZ) {
91 wchar_t *w_data = (
wchar_t *)data;
92 size_t w_data_len = (data_len % WL == 0) ? data_len / WL : (data_len / WL) + 1;
93 size_t real_len = determine_multi_sz_size(w_data, w_data_len);
95 size_t total_size = 9 + real_len;
96 out = calloc(total_size, WL);
100 wmemset(out, L
'\0', total_size);
101 strings_nl = calloc(w_data_len, WL);
105 wmemset(strings_nl, L
'\0', w_data_len);
107 for (i = 0; i < w_data_len - 2; i++) {
108 strings_nl[i] = w_data[i] == L
'\0' ? L
'\n' : w_data[i];
110 _snwprintf(out, total_size, L
"@\"\n%ls\n\"@", strings_nl);
113 debug_print(L
"Skipping incorrectly stored MultiString (length = %lu).\n", w_data_len);
116 if (reg_type == REG_DWORD) {
117 int req_size = _snwprintf(
nullptr, 0, L
"%lu", *(DWORD *)data);
118 out = calloc((
size_t)(req_size + 1), WL);
122 wmemset(out, L
'\0', (
size_t)(req_size + 1));
123 _snwprintf(out, (
size_t)req_size, L
"%lu", *(DWORD *)data);
126 if (reg_type == REG_QWORD) {
127 int req_size = _snwprintf(
nullptr, 0, L
"%llu", *(UINT64 *)data);
128 out = calloc((
size_t)(req_size + 1), WL);
132 wmemset(out, 0, (
size_t)req_size);
133 _snwprintf(out, (
size_t)req_size, L
"%llu", *(UINT64 *)data);
146static wchar_t *add_colon_if_required(
const wchar_t *path) {
147 wchar_t *escaped_reg_key, *full_path_ps, *top_key;
148 escaped_reg_key = full_path_ps = top_key =
nullptr;
149 size_t full_path_len = wcslen(path) + 2;
150 full_path_ps = calloc(full_path_len, WL);
154 wmemset(full_path_ps, L
'\0', full_path_len);
155 wchar_t *first_backslash = wcschr(path,
'\\');
156 if (!first_backslash) {
159 size_t top_key_len = (size_t)((first_backslash - path) + 1);
160 top_key = calloc(top_key_len, WL);
164 wmemset(top_key, L
'\0', top_key_len);
165 wmemcpy(top_key, path, top_key_len - 1);
166 _snwprintf(full_path_ps, full_path_len, L
"%ls:%ls", top_key, first_backslash);
167 full_path_ps[full_path_len - 1] = L
'\0';
168 escaped_reg_key = escape_for_powershell(full_path_ps, wcslen(full_path_ps));
171 escaped_reg_key =
nullptr;
175 return escaped_reg_key;
178bool do_write_powershell_reg_code(writer_t *writer,
179 const wchar_t *full_path,
183 unsigned long type) {
184 wchar_t *out =
nullptr;
185 wchar_t *escaped_d = convert_data_for_powershell(type, value, data_len);
186 wchar_t *escaped_reg_key = add_colon_if_required(full_path);
187 wchar_t *escaped_prop = escape_for_powershell(prop, wcslen(prop));
189 if (!escaped_reg_key) {
192 if (type == REG_MULTI_SZ && !escaped_d) {
195 wchar_t reg_type[14];
196 memset(reg_type, 0,
sizeof(reg_type));
199 wcsncpy(reg_type, L
"None", 4);
202 wcsncpy(reg_type, L
"Binary", 6);
205 wcsncpy(reg_type, L
"String", 6);
208 wcsncpy(reg_type, L
"ExpandString", 12);
211 wcsncpy(reg_type, L
"MultiString", 11);
214 wcsncpy(reg_type, L
"DWord", 5);
217 wcsncpy(reg_type, L
"Qword", 5);
223 int req_size = _snwprintf(
nullptr,
225 POWERSHELL_CODE_TEMPLATE,
229 escaped_prop ? escaped_prop : L
"",
231 escaped_d ? escaped_d : L
"$null");
232 if ((
size_t)req_size < POWERSHELL_MAX_COMMAND_LENGTH) {
233 out = calloc((
size_t)req_size + 1, WL);
237 wmemset(out, L
'\0', (
size_t)req_size + 1);
240 POWERSHELL_CODE_TEMPLATE,
244 escaped_prop ? escaped_prop : L
"",
246 escaped_d ? escaped_d : L
"$null");
247 ret = write_output(out,
false, writer);
249 debug_print(L
"%ls %ls: Skipping due to length of command.\n", full_path, prop);
257 free(escaped_reg_key);