3 /* Copyright (C) 2009 Trend Micro Inc.
6 * This program is a free software; you can redistribute it
7 * and/or modify it under the terms of the GNU General Public
8 * License (version 2) as published by the FSF - Free Software
14 #include "rootcheck.h"
19 /** Registry checking values **/
21 /* Global variables */
25 #define MAX_KEY_LENGTH 255
27 #define MAX_VALUE_NAME 16383
32 * Check if file has NTFS ADS.
34 int os_check_ads(char *full_path)
40 char stream_name[MAX_PATH +1];
41 char final_name[MAX_PATH +1];
43 DWORD dwRead, shs, dw1, dw2;
47 file_h = CreateFile(full_path,
52 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
55 if (file_h == INVALID_HANDLE_VALUE)
62 ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));
64 /* Getting stream header size -- should be 20 bytes */
65 shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid+ sid.dwStreamNameSize;
70 if(BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead,
71 FALSE, FALSE, &context) == 0)
80 stream_name[0] = '\0';
81 stream_name[MAX_PATH] = '\0';
82 if(BackupRead(file_h, (LPBYTE)stream_name,
84 &dwRead, FALSE, FALSE, &context))
88 int i = 0, max_path_size = 0;
90 char op_msg[OS_SIZE_1024 +1];
92 snprintf(final_name, MAX_PATH, "%s", full_path);
94 max_path_size = strlen(final_name);
97 /* Copying from wide char to char. */
98 while((i < dwRead) && (max_path_size < MAX_PATH))
100 if(stream_name[i] != 0)
102 final_name[max_path_size] = stream_name[i];
104 final_name[max_path_size] = '\0';
110 tmp_pt = strrchr(final_name, ':');
116 snprintf(op_msg, OS_SIZE_1024, "NTFS Alternate data stream "
117 "found: '%s'. Possible hidden"
120 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
125 if(!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart,
126 &dw1, &dw2, &context))
138 /** char *__os_winreg_getkey(char *reg_entry)
139 * Gets registry high level key.
141 char *__os_winreg_getkey(char *reg_entry)
146 /* Getting only the sub tree first */
147 tmp_str = strchr(reg_entry, '\\');
154 /* Setting sub tree */
155 if((strcmp(reg_entry, "HKEY_LOCAL_MACHINE") == 0) ||
156 (strcmp(reg_entry, "HKLM") == 0))
158 rk_sub_tree = HKEY_LOCAL_MACHINE;
160 else if(strcmp(reg_entry, "HKEY_CLASSES_ROOT") == 0)
162 rk_sub_tree = HKEY_CLASSES_ROOT;
164 else if(strcmp(reg_entry, "HKEY_CURRENT_CONFIG") == 0)
166 rk_sub_tree = HKEY_CURRENT_CONFIG;
168 else if(strcmp(reg_entry, "HKEY_USERS") == 0)
170 rk_sub_tree = HKEY_USERS;
172 else if((strcmp(reg_entry, "HKCU") == 0) ||
173 (strcmp(reg_entry, "HKEY_CURRENT_USER") == 0))
175 rk_sub_tree = HKEY_CURRENT_USER;
179 /* Setting sub tree to null */
182 /* Returning tmp_str to the previous value */
183 if(tmp_str && (*tmp_str == '\0'))
188 /* Checking if ret has nothing else. */
189 if(ret && (*ret == '\0'))
192 /* fixing tmp_str and the real name of the registry */
193 if(tmp_str && (*tmp_str == '\0'))
201 /* int __os_winreg_querykey
202 * Query the key and get the value of a specific entry.
204 int __os_winreg_querykey(HKEY hKey, char *p_key, char *full_key_name,
205 char *reg_option, char *reg_value)
210 /* QueryInfo and EnumKey variables */
211 TCHAR sub_key_name_b[MAX_KEY_LENGTH +1];
212 TCHAR class_name_b[MAX_PATH +1];
213 DWORD class_name_s = MAX_PATH;
215 /* Number of sub keys */
216 DWORD subkey_count = 0;
218 /* Number of values */
221 /* Variables for RegEnumValue */
222 TCHAR value_buffer[MAX_VALUE_NAME +1];
223 TCHAR data_buffer[MAX_VALUE_NAME +1];
227 /* Data type for RegEnumValue */
232 char var_storage[MAX_VALUE_NAME +1];
235 /* Initializing the memory for some variables */
236 class_name_b[0] = '\0';
237 class_name_b[MAX_PATH] = '\0';
238 sub_key_name_b[0] = '\0';
239 sub_key_name_b[MAX_KEY_LENGTH] = '\0';
242 /* We use the class_name, subkey_count and the value count. */
243 rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL,
244 &subkey_count, NULL, NULL, &value_count,
245 NULL, NULL, NULL, NULL);
248 /* Check return code of QueryInfo */
249 if(rc != ERROR_SUCCESS)
256 /* Getting Values (if available) */
262 /* Clearing the values for value_size and data_size */
263 value_buffer[MAX_VALUE_NAME] = '\0';
264 data_buffer[MAX_VALUE_NAME] = '\0';
265 var_storage[MAX_VALUE_NAME] = '\0';
268 /* Getting each value */
269 for(i=0;i<value_count;i++)
271 value_size = MAX_VALUE_NAME;
272 data_size = MAX_VALUE_NAME;
274 value_buffer[0] = '\0';
275 data_buffer[0] = '\0';
276 var_storage[0] = '\0';
278 rc = RegEnumValue(hKey, i, value_buffer, &value_size,
279 NULL, &data_type, data_buffer, &data_size);
282 /* No more values available */
283 if(rc != ERROR_SUCCESS)
288 /* Checking if no value name is specified */
289 if(value_buffer[0] == '\0')
291 value_buffer[0] = '@';
292 value_buffer[1] = '\0';
296 /* Check if the entry name matches the reg_option */
297 if(strcasecmp(value_buffer, reg_option) != 0)
303 /* If a value is not present and the option matches,
313 /* Writing value into a string */
320 snprintf(var_storage, MAX_VALUE_NAME, "%s", data_buffer);
324 /* Printing multiple strings */
325 size_available = MAX_VALUE_NAME -3;
326 mt_data = data_buffer;
330 if(size_available > 2)
332 strncat(var_storage, mt_data, size_available);
333 strncat(var_storage, " ", 2);
334 size_available = MAX_VALUE_NAME -
335 (strlen(var_storage) +2);
337 mt_data += strlen(mt_data) +1;
342 snprintf(var_storage, MAX_VALUE_NAME,
343 "%x",(unsigned int)*data_buffer);
347 size_available = MAX_VALUE_NAME -2;
348 for(j = 0;j<data_size;j++)
352 snprintf(tmp_c, 12, "%02x",
353 (unsigned int)data_buffer[j]);
355 if(size_available > 2)
357 strncat(var_storage, tmp_c, size_available);
358 size_available = MAX_VALUE_NAME -
359 (strlen(var_storage) +2);
365 /* Checking if value matches */
366 if(pt_matches(var_storage, reg_value))
380 /* int __os_winreg_open_key(char *subkey)
381 * Open the registry key
383 int __os_winreg_open_key(char *subkey, char *full_key_name,
384 char *reg_option, char *reg_value)
390 if(RegOpenKeyEx(rk_sub_tree, subkey, 0, KEY_READ,&oshkey) != ERROR_SUCCESS)
396 /* If option is set, return the value of query key */
399 ret = __os_winreg_querykey(oshkey, subkey, full_key_name,
400 reg_option, reg_value);
410 /* is_registry: Check if the entry is present in the registry
412 int is_registry(char *entry_name, char *reg_option, char *reg_value)
417 rk = __os_winreg_getkey(entry_name);
418 if(rk_sub_tree == NULL || rk == NULL)
420 merror(SK_INV_REG, ARGV0, entry_name);
424 if(__os_winreg_open_key(rk, entry_name, reg_option, reg_value) == 0)
436 /* Non windows defs for them. */
437 int os_check_ads(char *full_path)
441 int is_registry(char *entry_name, char *reg_option, char *reg_value)