53ba5aaa85251692123e7828ff97a9da6927e46a
[ossec-hids.git] / src / win32 / extract-win-el.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2009 Trend Micro Inc.
4  * All right reserved.
5  *
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
9  * Foundation
10  */
11
12
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <time.h>
17
18 #include <windows.h>
19
20 #define BUFFER_SIZE 2048*64
21 #define DEFAULT_FILE    "C:\\ossec-extracted-evt.log"
22
23 FILE *fp;
24 char *file = DEFAULT_FILE;
25 char *name = "ossec-extract-evtlog.exe";
26
27 /* Event logging local structure */
28 typedef struct _os_el
29 {
30     int time_of_last;   
31     char *name;
32
33     EVENTLOGRECORD *er;
34     HANDLE h;
35
36     DWORD record;
37 }os_el;
38 os_el el[3];
39 int el_last = 0;
40
41
42 /** int startEL(char *app, os_el *el)
43  * Starts the event logging for each el 
44  */
45 int startEL(char *app, os_el *el)
46 {
47     /* Opening the event log */
48     el->h = OpenEventLog(NULL, app);
49     if(!el->h)
50     {
51         return(0);          
52     }
53
54     el->name = app;
55     GetOldestEventLogRecord(el->h, &el->record);
56
57     return(1);
58 }
59
60
61
62 /** char *el_getCategory(int category_id) 
63  * Returns a string related to the category id of the log.
64  */
65 char *el_getCategory(int category_id)
66 {
67     char *cat;
68     switch(category_id)
69     {
70         case EVENTLOG_ERROR_TYPE:
71             cat = "ERROR";
72             break;
73         case EVENTLOG_WARNING_TYPE:
74             cat = "WARNING";
75             break;
76         case EVENTLOG_INFORMATION_TYPE:
77             cat = "INFORMATION";
78             break;
79         case EVENTLOG_AUDIT_SUCCESS:
80             cat = "AUDIT_SUCCESS";
81             break;
82         case EVENTLOG_AUDIT_FAILURE:
83             cat = "AUDIT_FAILURE";
84             break;
85         default:
86             cat = "Unknown";
87             break;
88     }
89     return(cat);
90 }
91
92
93 /** int el_getEventDLL(char *evt_name, char *source, char *event)
94  * Returns the event.
95  */
96 int el_getEventDLL(char *evt_name, char *source, char *event) 
97 {
98     HKEY key;
99     DWORD ret;
100     char keyname[256];
101
102
103     keyname[255] = '\0';
104
105     snprintf(keyname, 254, 
106             "System\\CurrentControlSet\\Services\\EventLog\\%s\\%s", 
107             evt_name, 
108             source);
109
110     /* Opening registry */          
111     if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_ALL_ACCESS, &key)
112             != ERROR_SUCCESS)
113     {
114         return(0);    
115     }
116
117
118     ret = MAX_PATH -1;  
119     if (RegQueryValueEx(key, "EventMessageFile", NULL, 
120                 NULL, (LPBYTE)event, &ret) != ERROR_SUCCESS)
121     {
122         event[0] = '\0';        
123         return(0);
124     }
125
126     RegCloseKey(key);
127     return(1);
128 }
129
130
131
132 /** char *el_getmessage() 
133  * Returns a descriptive message of the event.
134  */
135 char *el_getMessage(EVENTLOGRECORD *er,  char *name, 
136                     char * source, LPTSTR *el_sstring) 
137 {
138     DWORD fm_flags = 0;
139     char tmp_str[257];
140     char event[MAX_PATH +1];
141     char *curr_str;
142     char *next_str;
143     LPSTR message = NULL;
144
145     HMODULE hevt;
146
147     /* Initializing variables */
148     event[MAX_PATH] = '\0';
149     tmp_str[256] = '\0';
150
151     /* Flags for format event */
152     fm_flags |= FORMAT_MESSAGE_FROM_HMODULE;
153     fm_flags |= FORMAT_MESSAGE_ALLOCATE_BUFFER;
154     fm_flags |= FORMAT_MESSAGE_ARGUMENT_ARRAY;
155
156     /* Get the file name from the registry (stored on event) */
157     if(!el_getEventDLL(name, source, event))
158     {
159         return(NULL);       
160     }       
161
162     curr_str = event;
163
164     /* If our event has multiple libraries, try each one of them */ 
165     while((next_str = strchr(curr_str, ';')))
166     {
167         *next_str = '\0';
168         next_str++;
169
170         ExpandEnvironmentStrings(curr_str, tmp_str, 255);
171         hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES);
172         if(hevt)
173         {
174             if(!FormatMessage(fm_flags, hevt, er->EventID, 
175                         0,
176                         (LPTSTR) &message, 0, el_sstring))
177             {
178                 message = NULL;           
179             }
180             FreeLibrary(hevt);
181
182             /* If we have a message, we can return it */
183             if(message)
184                 return(message);
185         }
186
187         curr_str = next_str;            
188     }
189
190     ExpandEnvironmentStrings(curr_str, tmp_str, 255);
191     hevt = LoadLibraryEx(tmp_str, NULL, DONT_RESOLVE_DLL_REFERENCES);
192     if(hevt)
193     {
194         int hr;    
195         if(!(hr = FormatMessage(fm_flags, hevt, er->EventID, 
196                         0,
197                         (LPTSTR) &message, 0, el_sstring)))
198         {
199             message = NULL;               
200         }
201         FreeLibrary(hevt);
202
203         /* If we have a message, we can return it */
204         if(message)
205             return(message);
206     }
207
208     return(NULL);
209 }
210
211
212
213 /** void readel(os_el *el)
214  * Reads the event log.
215  */ 
216 void readel(os_el *el, int printit)
217 {
218     DWORD nstr;
219     DWORD user_size;
220     DWORD domain_size;
221     DWORD read, needed;
222     int size_left;
223     int str_size;
224
225     char mbuffer[BUFFER_SIZE];
226     LPSTR sstr = NULL;
227
228     char *tmp_str = NULL;
229     char *category;
230     char *source;
231     char *computer_name;
232     char *descriptive_msg;
233
234     char el_user[257];
235     char el_domain[257];
236     char el_string[1025];
237     char final_msg[1024];
238     LPSTR el_sstring[57];
239
240     /* Er must point to the mbuffer */
241     el->er = (EVENTLOGRECORD *) &mbuffer; 
242
243     /* Zeroing the last values */
244     el_string[1024] = '\0';
245     el_user[256] = '\0';
246     el_domain[256] = '\0';
247     final_msg[1023] = '\0';
248     el_sstring[56] = NULL;
249
250     /* Reading the event log */     
251     while(ReadEventLog(el->h, 
252                 EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
253                 0,
254                 el->er, BUFFER_SIZE -1, &read, &needed))
255     {
256         while(read > 0)
257         {
258
259             /* We need to initialize every variable before the loop */
260             category = el_getCategory(el->er->EventType);
261             source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
262             computer_name = source + strlen(source) + 1;
263             descriptive_msg = NULL;
264
265
266             /* Initialing domain/user size */
267             user_size = 255; domain_size = 255;
268             el_domain[0] = '\0';
269             el_user[0] = '\0';
270
271
272             /* We must have some description */
273             if(el->er->NumStrings)
274             {   
275                 size_left = 1020;       
276
277                 sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
278                 el_string[0] = '\0';
279
280                 for (nstr = 0;nstr < el->er->NumStrings;nstr++)
281                 {
282                     str_size = strlen(sstr);    
283                     strncat(el_string, sstr, size_left);
284
285                     tmp_str= strchr(el_string, '\0');
286                     if(tmp_str)
287                     {
288                         *tmp_str = ' ';         
289                         tmp_str++; *tmp_str = '\0';
290                     }
291                     size_left-=str_size + 1;
292
293                     if(nstr <= 54)
294                         el_sstring[nstr] = (LPSTR)sstr;
295
296                     sstr = strchr( (LPSTR)sstr, '\0');
297                     sstr++; 
298                 }
299
300                 /* Get a more descriptive message (if available) */
301                 descriptive_msg = el_getMessage(el->er, el->name, source, 
302                                                         el_sstring);
303                 if(descriptive_msg != NULL)
304                 {
305                     /* Remove any \n or \r */
306                     tmp_str = descriptive_msg;    
307                     while((tmp_str = strchr(tmp_str, '\n')))
308                     {
309                         *tmp_str = ' ';
310                         tmp_str++;                  
311                     }                   
312
313                     tmp_str = descriptive_msg;    
314                     while((tmp_str = strchr(tmp_str, '\r')))
315                     {
316                         *tmp_str = ' ';
317                         tmp_str++;                  
318                     }                   
319                 }
320             }
321             else
322             {
323                 strncpy(el_string, "(no message)", 1020);       
324             }
325
326
327             /* Getting username */
328             if (el->er->UserSidLength)
329             {
330                 SID_NAME_USE account_type;
331                 if(!LookupAccountSid(NULL, (SID *)((LPSTR)el->er + el->er->UserSidOffset),
332                             el_user, &user_size, el_domain, &domain_size, &account_type))               
333                 {
334                     strncpy(el_user, "(no user)", 255);
335                     strncpy(el_domain, "no domain", 255);
336                 }
337
338             }
339
340             else
341             {
342                 strncpy(el_user, "(no user)", 255);     
343                 strncpy(el_domain, "no domain", 255);   
344             }
345
346
347             if(printit)
348             {
349                 DWORD _evtid = 65535;   
350                 int id = (int)el->er->EventID & _evtid;                  
351                 
352                 snprintf(final_msg, 1022, 
353                         "%d WinEvtLog: %s: %s(%d): %s: %s(%s): %s",
354                                 (int)el->er->TimeGenerated,     
355                         el->name,
356                         category, 
357                         id,
358                         source,
359                         el_user,
360                         el_domain,
361                         descriptive_msg != NULL?descriptive_msg:el_string);     
362                
363                 fprintf(fp, "%s\n", final_msg); 
364             }
365
366             if(descriptive_msg != NULL)
367                 LocalFree(descriptive_msg);
368
369             /* Changing the point to the er */
370             read -= el->er->Length;
371             el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
372         }               
373
374         /* Setting er to the beginning of the buffer */ 
375         el->er = (EVENTLOGRECORD *)&mbuffer;
376     }
377 }
378
379
380 /** void win_startel()
381  * Starts the event logging for windows
382  */
383 void win_startel(char *evt_log)
384 {
385     startEL(evt_log, &el[el_last]);
386     readel(&el[el_last],1);
387     el_last++;
388 }
389
390 void help()
391 {
392    printf(" OSSEC HIDS - Windows event log extract\n"); 
393    printf("%s -h                Shows this help message\n", name);      
394    printf("%s -e                Extract logs to '%s'\n", name, DEFAULT_FILE);
395    printf("%s -f        <file>  Extract logs to the file specified\n", name);   
396    exit(0);     
397 }
398 /** main **/
399 int main(int argc, char **argv)
400 {
401    name = argv[0];      
402    if((argc == 2)&&(strcmp(argv[1], "-e") == 0))
403    {
404    }
405    else if((argc == 3)&&(strcmp(argv[1], "-f") == 0))
406    {
407       file = argv[2];      
408    }  
409    else
410       help();
411    
412    fp = fopen(file, "w");
413    if(!fp)
414    {
415       printf("Unable to open file '%s'\n", file);
416       exit(1);
417    }
418    
419    win_startel("Application");  
420    win_startel("System");       
421    win_startel("Security");     
422
423    fclose(fp);
424    return(0);
425 }
426
427 /* EOF */