1 /* Copyright (C) 2009 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
11 #include "rootcheck.h"
15 /* Global variables */
19 #define MAX_KEY_LENGTH 255
21 #define MAX_VALUE_NAME 16383
24 /* Check if file has NTFS ADS */
25 int os_check_ads(const char *full_path)
30 char stream_name[MAX_PATH + 1];
31 char final_name[MAX_PATH + 1];
32 DWORD dwRead, shs, dw1, dw2;
35 file_h = CreateFile(full_path,
40 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
43 if (file_h == INVALID_HANDLE_VALUE) {
48 ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));
50 /* Get stream header size -- should be 20 bytes */
51 shs = (LPBYTE)&sid.cStreamName - (LPBYTE)&sid + sid.dwStreamNameSize;
54 if (BackupRead(file_h, (LPBYTE) &sid, shs, &dwRead,
55 FALSE, FALSE, &context) == 0) {
62 stream_name[0] = '\0';
63 stream_name[MAX_PATH] = '\0';
64 if (BackupRead(file_h, (LPBYTE)stream_name,
66 &dwRead, FALSE, FALSE, &context)) {
69 int max_path_size = 0;
71 char op_msg[OS_SIZE_1024 + 1];
73 snprintf(final_name, MAX_PATH, "%s", full_path);
74 max_path_size = strlen(final_name);
76 /* Copy from wide char to char */
77 while ((i < dwRead) && (max_path_size < MAX_PATH)) {
78 if (stream_name[i] != 0) {
79 final_name[max_path_size] = stream_name[i];
81 final_name[max_path_size] = '\0';
86 tmp_pt = strrchr(final_name, ':');
91 snprintf(op_msg, OS_SIZE_1024, "NTFS Alternate data stream "
92 "found: '%s'. Possible hidden"
95 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
100 if (!BackupSeek(file_h, sid.Size.LowPart, sid.Size.HighPart,
101 &dw1, &dw2, &context)) {
110 /* Get registry high level key */
111 char *__os_winreg_getkey(char *reg_entry)
116 /* Get only the sub tree first */
117 tmp_str = strchr(reg_entry, '\\');
124 if ((strcmp(reg_entry, "HKEY_LOCAL_MACHINE") == 0) ||
125 (strcmp(reg_entry, "HKLM") == 0)) {
126 rk_sub_tree = HKEY_LOCAL_MACHINE;
127 } else if (strcmp(reg_entry, "HKEY_CLASSES_ROOT") == 0) {
128 rk_sub_tree = HKEY_CLASSES_ROOT;
129 } else if (strcmp(reg_entry, "HKEY_CURRENT_CONFIG") == 0) {
130 rk_sub_tree = HKEY_CURRENT_CONFIG;
131 } else if (strcmp(reg_entry, "HKEY_USERS") == 0) {
132 rk_sub_tree = HKEY_USERS;
133 } else if ((strcmp(reg_entry, "HKCU") == 0) ||
134 (strcmp(reg_entry, "HKEY_CURRENT_USER") == 0)) {
135 rk_sub_tree = HKEY_CURRENT_USER;
137 /* Set sub tree to null */
140 /* Return tmp_str to the previous value */
141 if (tmp_str && (*tmp_str == '\0')) {
147 /* Check if ret has nothing else */
148 if (ret && (*ret == '\0')) {
152 /* Fixing tmp_str and the real name of the registry */
153 if (tmp_str && (*tmp_str == '\0')) {
160 /* Query the key and get the value of a specific entry */
161 int __os_winreg_querykey(HKEY hKey,
162 __attribute__((unused))char *p_key,
163 __attribute__((unused)) char *full_key_name,
164 char *reg_option, char *reg_value)
169 /* QueryInfo and EnumKey variables */
170 TCHAR class_name_b[MAX_PATH + 1];
171 DWORD class_name_s = MAX_PATH;
173 /* Number of sub keys */
174 DWORD subkey_count = 0;
176 /* Number of values */
179 /* Variables for RegEnumValue */
180 TCHAR value_buffer[MAX_VALUE_NAME + 1];
181 TCHAR data_buffer[MAX_VALUE_NAME + 1];
185 /* Data type for RegEnumValue */
189 char var_storage[MAX_VALUE_NAME + 1];
191 /* Initialize the memory for some variables */
192 class_name_b[0] = '\0';
193 class_name_b[MAX_PATH] = '\0';
195 /* We use the class_name, subkey_count and the value count */
196 rc = RegQueryInfoKey(hKey, class_name_b, &class_name_s, NULL,
197 &subkey_count, NULL, NULL, &value_count,
198 NULL, NULL, NULL, NULL);
199 if (rc != ERROR_SUCCESS) {
203 /* Get values (if available) */
207 /* Clear the values for value_size and data_size */
208 value_buffer[MAX_VALUE_NAME] = '\0';
209 data_buffer[MAX_VALUE_NAME] = '\0';
210 var_storage[MAX_VALUE_NAME] = '\0';
213 for (i = 0; i < value_count; i++) {
214 value_size = MAX_VALUE_NAME;
215 data_size = MAX_VALUE_NAME;
217 value_buffer[0] = '\0';
218 data_buffer[0] = '\0';
219 var_storage[0] = '\0';
221 rc = RegEnumValue(hKey, i, value_buffer, &value_size,
222 NULL, &data_type, (LPBYTE)data_buffer, &data_size);
224 /* No more values available */
225 if (rc != ERROR_SUCCESS) {
229 /* Check if no value name is specified */
230 if (value_buffer[0] == '\0') {
231 value_buffer[0] = '@';
232 value_buffer[1] = '\0';
235 /* Check if the entry name matches the reg_option */
236 if (strcasecmp(value_buffer, reg_option) != 0) {
240 /* If a value is not present and the option matches,
247 /* Write value into a string */
253 snprintf(var_storage, MAX_VALUE_NAME, "%s", data_buffer);
256 /* Printing multiple strings */
257 size_available = MAX_VALUE_NAME - 3;
258 mt_data = data_buffer;
261 if (size_available > 2) {
262 strncat(var_storage, mt_data, size_available);
263 strncat(var_storage, " ", 2);
264 size_available = MAX_VALUE_NAME -
265 (strlen(var_storage) + 2);
267 mt_data += strlen(mt_data) + 1;
272 snprintf(var_storage, MAX_VALUE_NAME,
273 "%x", (unsigned int)*data_buffer);
276 size_available = MAX_VALUE_NAME - 2;
277 for (j = 0; j < data_size; j++) {
280 snprintf(tmp_c, 12, "%02x",
281 (unsigned int)data_buffer[j]);
283 if (size_available > 2) {
284 strncat(var_storage, tmp_c, size_available);
285 size_available = MAX_VALUE_NAME -
286 (strlen(var_storage) + 2);
292 /* Check if value matches */
293 if (pt_matches(var_storage, reg_value)) {
304 /* Open the registry key */
305 int __os_winreg_open_key(char *subkey, char *full_key_name,
306 char *reg_option, char *reg_value)
311 int REG64MASK = (KEY_READ | KEY_WOW64_64KEY);
312 int REG32MASK = (KEY_READ | KEY_WOW64_32KEY);
314 if((RegOpenKeyEx(rk_sub_tree, subkey, 0, REG64MASK, &oshkey) ||
315 (RegOpenKeyEx(rk_sub_tree, subkey, 0, REG32MASK, &oshkey))
321 /* If option is set, return the value of query key */
323 ret = __os_winreg_querykey(oshkey, subkey, full_key_name,
324 reg_option, reg_value);
331 /* Check if the entry is present in the registry */
332 int is_registry(char *entry_name, char *reg_option, char *reg_value)
336 rk = __os_winreg_getkey(entry_name);
337 if (rk_sub_tree == NULL || rk == NULL) {
338 merror(SK_INV_REG, ARGV0, entry_name);
342 if (__os_winreg_open_key(rk, entry_name, reg_option, reg_value) == 0) {
351 /* Non-Windows defs */
352 int os_check_ads(__attribute__((unused)) const char *full_path)
356 int is_registry(__attribute__((unused)) char *entry_name,
357 __attribute__((unused)) char *reg_option,
358 __attribute__((unused)) char *reg_value)