1 /* @(#) $Id: ./src/rootcheck/win-common.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
7 * This program is a free software; you can redistribute it
8 * and/or modify it under the terms of the GNU General Public
9 * License (version 2) as published by the FSF - Free Software
15 #include "rootcheck.h"
20 /** Registry checking values **/
22 /* Global variables */
26 #define MAX_KEY_LENGTH 255
28 #define MAX_VALUE_NAME 16383
33 * Check if file has NTFS ADS.
35 int os_check_ads(char *full_path)
41 char stream_name[MAX_PATH +1];
42 char final_name[MAX_PATH +1];
44 DWORD dwRead, shs, dw1, dw2;
48 file_h = CreateFile(full_path,
53 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
56 if (file_h == INVALID_HANDLE_VALUE)
63 ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));
65 /* Getting stream header size -- should be 20 bytes */
66 shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid+ sid.dwStreamNameSize;
71 if(BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead,
72 FALSE, FALSE, &context) == 0)
81 stream_name[0] = '\0';
82 stream_name[MAX_PATH] = '\0';
83 if(BackupRead(file_h, (LPBYTE)stream_name,
85 &dwRead, FALSE, FALSE, &context))
89 int i = 0, max_path_size = 0;
91 char op_msg[OS_SIZE_1024 +1];
93 snprintf(final_name, MAX_PATH, "%s", full_path);
95 max_path_size = strlen(final_name);
98 /* Copying from wide char to char. */
99 while((i < dwRead) && (max_path_size < MAX_PATH))
101 if(stream_name[i] != 0)
103 final_name[max_path_size] = stream_name[i];
105 final_name[max_path_size] = '\0';
111 tmp_pt = strrchr(final_name, ':');
117 snprintf(op_msg, OS_SIZE_1024, "NTFS Alternate data stream "
118 "found: '%s'. Possible hidden"
121 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
126 if(!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart,
127 &dw1, &dw2, &context))
139 /** char *__os_winreg_getkey(char *reg_entry)
140 * Gets registry high level key.
142 char *__os_winreg_getkey(char *reg_entry)
147 /* Getting only the sub tree first */
148 tmp_str = strchr(reg_entry, '\\');
155 /* Setting sub tree */
156 if((strcmp(reg_entry, "HKEY_LOCAL_MACHINE") == 0) ||
157 (strcmp(reg_entry, "HKLM") == 0))
159 rk_sub_tree = HKEY_LOCAL_MACHINE;
161 else if(strcmp(reg_entry, "HKEY_CLASSES_ROOT") == 0)
163 rk_sub_tree = HKEY_CLASSES_ROOT;
165 else if(strcmp(reg_entry, "HKEY_CURRENT_CONFIG") == 0)
167 rk_sub_tree = HKEY_CURRENT_CONFIG;
169 else if(strcmp(reg_entry, "HKEY_USERS") == 0)
171 rk_sub_tree = HKEY_USERS;
173 else if((strcmp(reg_entry, "HKCU") == 0) ||
174 (strcmp(reg_entry, "HKEY_CURRENT_USER") == 0))
176 rk_sub_tree = HKEY_CURRENT_USER;
180 /* Setting sub tree to null */
183 /* Returning tmp_str to the previous value */
184 if(tmp_str && (*tmp_str == '\0'))
189 /* Checking if ret has nothing else. */
190 if(ret && (*ret == '\0'))
193 /* fixing tmp_str and the real name of the registry */
194 if(tmp_str && (*tmp_str == '\0'))
202 /* int __os_winreg_querykey
203 * Query the key and get the value of a specific entry.
205 int __os_winreg_querykey(HKEY hKey, char *p_key, char *full_key_name,
206 char *reg_option, char *reg_value)
211 /* QueryInfo and EnumKey variables */
212 TCHAR sub_key_name_b[MAX_KEY_LENGTH +1];
213 TCHAR class_name_b[MAX_PATH +1];
214 DWORD class_name_s = MAX_PATH;
216 /* Number of sub keys */
217 DWORD subkey_count = 0;
219 /* Number of values */
222 /* Variables for RegEnumValue */
223 TCHAR value_buffer[MAX_VALUE_NAME +1];
224 TCHAR data_buffer[MAX_VALUE_NAME +1];
228 /* Data type for RegEnumValue */
233 char var_storage[MAX_VALUE_NAME +1];
236 /* Initializing the memory for some variables */
237 class_name_b[0] = '\0';
238 class_name_b[MAX_PATH] = '\0';
239 sub_key_name_b[0] = '\0';
240 sub_key_name_b[MAX_KEY_LENGTH] = '\0';
243 /* We use the class_name, subkey_count and the value count. */
244 rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL,
245 &subkey_count, NULL, NULL, &value_count,
246 NULL, NULL, NULL, NULL);
249 /* Check return code of QueryInfo */
250 if(rc != ERROR_SUCCESS)
257 /* Getting Values (if available) */
263 /* Clearing the values for value_size and data_size */
264 value_buffer[MAX_VALUE_NAME] = '\0';
265 data_buffer[MAX_VALUE_NAME] = '\0';
266 var_storage[MAX_VALUE_NAME] = '\0';
269 /* Getting each value */
270 for(i=0;i<value_count;i++)
272 value_size = MAX_VALUE_NAME;
273 data_size = MAX_VALUE_NAME;
275 value_buffer[0] = '\0';
276 data_buffer[0] = '\0';
277 var_storage[0] = '\0';
279 rc = RegEnumValue(hKey, i, value_buffer, &value_size,
280 NULL, &data_type, (LPBYTE)data_buffer, &data_size);
283 /* No more values available */
284 if(rc != ERROR_SUCCESS)
289 /* Checking if no value name is specified */
290 if(value_buffer[0] == '\0')
292 value_buffer[0] = '@';
293 value_buffer[1] = '\0';
297 /* Check if the entry name matches the reg_option */
298 if(strcasecmp(value_buffer, reg_option) != 0)
304 /* If a value is not present and the option matches,
314 /* Writing value into a string */
321 snprintf(var_storage, MAX_VALUE_NAME, "%s", data_buffer);
325 /* Printing multiple strings */
326 size_available = MAX_VALUE_NAME -3;
327 mt_data = data_buffer;
331 if(size_available > 2)
333 strncat(var_storage, mt_data, size_available);
334 strncat(var_storage, " ", 2);
335 size_available = MAX_VALUE_NAME -
336 (strlen(var_storage) +2);
338 mt_data += strlen(mt_data) +1;
343 snprintf(var_storage, MAX_VALUE_NAME,
344 "%x",(unsigned int)*data_buffer);
348 size_available = MAX_VALUE_NAME -2;
349 for(j = 0;j<data_size;j++)
353 snprintf(tmp_c, 12, "%02x",
354 (unsigned int)data_buffer[j]);
356 if(size_available > 2)
358 strncat(var_storage, tmp_c, size_available);
359 size_available = MAX_VALUE_NAME -
360 (strlen(var_storage) +2);
366 /* Checking if value matches */
367 if(pt_matches(var_storage, reg_value))
381 /* int __os_winreg_open_key(char *subkey)
382 * Open the registry key
384 int __os_winreg_open_key(char *subkey, char *full_key_name,
385 char *reg_option, char *reg_value)
391 if(RegOpenKeyEx(rk_sub_tree, subkey, 0, KEY_READ,&oshkey) != ERROR_SUCCESS)
397 /* If option is set, return the value of query key */
400 ret = __os_winreg_querykey(oshkey, subkey, full_key_name,
401 reg_option, reg_value);
411 /* is_registry: Check if the entry is present in the registry
413 int is_registry(char *entry_name, char *reg_option, char *reg_value)
418 rk = __os_winreg_getkey(entry_name);
419 if(rk_sub_tree == NULL || rk == NULL)
421 merror(SK_INV_REG, ARGV0, entry_name);
425 if(__os_winreg_open_key(rk, entry_name, reg_option, reg_value) == 0)
437 /* Non windows defs for them. */
438 int os_check_ads(char *full_path)
442 int is_registry(char *entry_name, char *reg_option, char *reg_value)