/src/yara/libyara/modules/console/console.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2021. The YARA Authors. All Rights Reserved. |
3 | | |
4 | | Redistribution and use in source and binary forms, with or without modification, |
5 | | are permitted provided that the following conditions are met: |
6 | | |
7 | | 1. Redistributions of source code must retain the above copyright notice, this |
8 | | list of conditions and the following disclaimer. |
9 | | |
10 | | 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | this list of conditions and the following disclaimer in the documentation and/or |
12 | | other materials provided with the distribution. |
13 | | |
14 | | 3. Neither the name of the copyright holder nor the names of its contributors |
15 | | may be used to endorse or promote products derived from this software without |
16 | | specific prior written permission. |
17 | | |
18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
19 | | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
20 | | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
22 | | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
23 | | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
24 | | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
25 | | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | |
30 | | #include <stdio.h> |
31 | | |
32 | | #include <yara/mem.h> |
33 | | #include <yara/modules.h> |
34 | | #include <yara/strutils.h> |
35 | | |
36 | | #define MODULE_NAME console |
37 | | |
38 | | define_function(log_string) |
39 | 0 | { |
40 | | // We are intentionally using sized strings here as we may be needing to |
41 | | // output strings with a null character in the middle. |
42 | 0 | SIZED_STRING* s = sized_string_argument(1); |
43 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
44 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
45 | | |
46 | | // Assume the entire string is non-printable, so allocate 4 times the |
47 | | // space so that we can represent each byte as an escaped value. eg: \x00 |
48 | | // Add an extra byte for the NULL terminator. |
49 | 0 | char* msg = (char*) yr_calloc((s->length * 4) + 1, sizeof(char)); |
50 | 0 | if (msg == NULL) |
51 | 0 | return_integer(YR_UNDEFINED); |
52 | |
|
53 | 0 | char* p = msg; |
54 | 0 | for (size_t i = 0; i < s->length; i++) |
55 | 0 | { |
56 | 0 | if (isprint((unsigned char) s->c_string[i])) |
57 | 0 | { |
58 | 0 | *p++ = s->c_string[i]; |
59 | 0 | } |
60 | 0 | else |
61 | 0 | { |
62 | 0 | sprintf(p, "\\x%02x", (unsigned char) s->c_string[i]); |
63 | 0 | p += 4; |
64 | 0 | } |
65 | 0 | } |
66 | | |
67 | | // result is ignored, as we have no way to signal to the library that it |
68 | | // should abort or continue. |
69 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
70 | |
|
71 | 0 | yr_free(msg); |
72 | 0 | return_integer(1); |
73 | 0 | } |
74 | | |
75 | | define_function(log_string_msg) |
76 | 0 | { |
77 | 0 | char* m = string_argument(1); |
78 | | // We are intentionally using sized strings here as we may be needing to |
79 | | // output strings with a null character in the middle. |
80 | 0 | SIZED_STRING* s = sized_string_argument(2); |
81 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
82 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
83 | | |
84 | | // Assume the entire string is non-printable, so allocate 4 times the |
85 | | // space so that we can represent each byte as an escaped value. eg: \x00 |
86 | | // Add an extra byte for the NULL terminator. |
87 | 0 | size_t msg_len = strlen(m) + (s->length * 4) + 1; |
88 | 0 | char* msg = (char*) yr_calloc(msg_len, sizeof(char)); |
89 | 0 | if (msg == NULL) |
90 | 0 | return_integer(YR_UNDEFINED); |
91 | |
|
92 | 0 | char* p = msg; |
93 | 0 | strlcpy(msg, m, msg_len); |
94 | 0 | p += strlen(m); |
95 | 0 | for (size_t i = 0; i < s->length; i++) |
96 | 0 | { |
97 | 0 | if (isprint((unsigned char) s->c_string[i])) |
98 | 0 | { |
99 | 0 | *p++ = s->c_string[i]; |
100 | 0 | } |
101 | 0 | else |
102 | 0 | { |
103 | 0 | sprintf(p, "\\x%02x", (unsigned char) s->c_string[i]); |
104 | 0 | p += 4; |
105 | 0 | } |
106 | 0 | } |
107 | | |
108 | | // result is ignored, as we have no way to signal to the library that it |
109 | | // should abort or continue. |
110 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
111 | |
|
112 | 0 | yr_free(msg); |
113 | 0 | return_integer(1); |
114 | 0 | } |
115 | | |
116 | | define_function(log_integer) |
117 | 0 | { |
118 | 0 | char* msg = NULL; |
119 | 0 | int64_t i = integer_argument(1); |
120 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
121 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
122 | |
|
123 | 0 | yr_asprintf(&msg, "%lli", i); |
124 | |
|
125 | 0 | if (msg == NULL) |
126 | 0 | return_integer(YR_UNDEFINED); |
127 | | |
128 | | // result is ignored, as we have no way to signal to the library that it |
129 | | // should abort or continue. |
130 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
131 | |
|
132 | 0 | yr_free(msg); |
133 | 0 | return_integer(1); |
134 | 0 | } |
135 | | |
136 | | define_function(log_integer_msg) |
137 | 0 | { |
138 | 0 | char* msg = NULL; |
139 | 0 | char* s = string_argument(1); |
140 | 0 | int64_t i = integer_argument(2); |
141 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
142 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
143 | |
|
144 | 0 | yr_asprintf(&msg, "%s%lli", s, i); |
145 | |
|
146 | 0 | if (msg == NULL) |
147 | 0 | return_integer(YR_UNDEFINED); |
148 | | |
149 | | // result is ignored, as we have no way to signal to the library that it |
150 | | // should abort or continue. |
151 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
152 | |
|
153 | 0 | yr_free(msg); |
154 | 0 | return_integer(1); |
155 | 0 | } |
156 | | |
157 | | define_function(log_float) |
158 | 0 | { |
159 | 0 | char* msg = NULL; |
160 | 0 | double f = float_argument(1); |
161 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
162 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
163 | |
|
164 | 0 | yr_asprintf(&msg, "%f", f); |
165 | |
|
166 | 0 | if (msg == NULL) |
167 | 0 | return_integer(YR_UNDEFINED); |
168 | | |
169 | | // result is ignored, as we have no way to signal to the library that it |
170 | | // should abort or continue. |
171 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
172 | |
|
173 | 0 | yr_free(msg); |
174 | 0 | return_integer(1); |
175 | 0 | } |
176 | | |
177 | | define_function(log_float_msg) |
178 | 0 | { |
179 | 0 | char* msg = NULL; |
180 | 0 | char* s = string_argument(1); |
181 | 0 | double f = float_argument(2); |
182 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
183 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
184 | |
|
185 | 0 | yr_asprintf(&msg, "%s%f", s, f); |
186 | |
|
187 | 0 | if (msg == NULL) |
188 | 0 | return_integer(YR_UNDEFINED); |
189 | | |
190 | | // result is ignored, as we have no way to signal to the library that it |
191 | | // should abort or continue. |
192 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
193 | |
|
194 | 0 | yr_free(msg); |
195 | 0 | return_integer(1); |
196 | 0 | } |
197 | | |
198 | | define_function(hex_integer) |
199 | 0 | { |
200 | 0 | char* msg = NULL; |
201 | 0 | int64_t i = integer_argument(1); |
202 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
203 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
204 | |
|
205 | 0 | yr_asprintf(&msg, "0x%llx", i); |
206 | |
|
207 | 0 | if (msg == NULL) |
208 | 0 | return_integer(YR_UNDEFINED); |
209 | | |
210 | | // result is ignored, as we have no way to signal to the library that it |
211 | | // should abort or continue. |
212 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
213 | |
|
214 | 0 | yr_free(msg); |
215 | 0 | return_integer(1); |
216 | 0 | } |
217 | | |
218 | | define_function(hex_integer_msg) |
219 | 0 | { |
220 | 0 | char* msg = NULL; |
221 | 0 | char* s = string_argument(1); |
222 | 0 | int64_t i = integer_argument(2); |
223 | 0 | YR_SCAN_CONTEXT* ctx = yr_scan_context(); |
224 | 0 | YR_CALLBACK_FUNC callback = ctx->callback; |
225 | |
|
226 | 0 | yr_asprintf(&msg, "%s0x%llx", s, i); |
227 | |
|
228 | 0 | if (msg == NULL) |
229 | 0 | return_integer(YR_UNDEFINED); |
230 | | |
231 | | // result is ignored, as we have no way to signal to the library that it |
232 | | // should abort or continue. |
233 | 0 | callback(ctx, CALLBACK_MSG_CONSOLE_LOG, (void*) msg, ctx->user_data); |
234 | |
|
235 | 0 | yr_free(msg); |
236 | 0 | return_integer(1); |
237 | 0 | } |
238 | | |
239 | 0 | begin_declarations |
240 | 0 | declare_function("log", "s", "i", log_string); |
241 | 0 | declare_function("log", "ss", "i", log_string_msg); |
242 | 0 | declare_function("log", "i", "i", log_integer); |
243 | 0 | declare_function("log", "si", "i", log_integer_msg); |
244 | 0 | declare_function("log", "f", "i", log_float); |
245 | 0 | declare_function("log", "sf", "i", log_float_msg); |
246 | 0 | declare_function("hex", "i", "i", hex_integer); |
247 | 0 | declare_function("hex", "si", "i", hex_integer_msg); |
248 | 0 | end_declarations |
249 | | |
250 | | int module_initialize(YR_MODULE* module) |
251 | 2 | { |
252 | 2 | return ERROR_SUCCESS; |
253 | 2 | } |
254 | | |
255 | | int module_finalize(YR_MODULE* module) |
256 | 0 | { |
257 | 0 | return ERROR_SUCCESS; |
258 | 0 | } |
259 | | |
260 | | int module_load( |
261 | | YR_SCAN_CONTEXT* context, |
262 | | YR_OBJECT* module_object, |
263 | | void* module_data, |
264 | | size_t module_data_size) |
265 | 0 | { |
266 | 0 | return ERROR_SUCCESS; |
267 | 0 | } |
268 | | |
269 | | int module_unload(YR_OBJECT* module_object) |
270 | 0 | { |
271 | 0 | return ERROR_SUCCESS; |
272 | 0 | } |