... | ... |
@@ -30,6 +30,7 @@ |
30 | 30 |
#include <stdlib.h> |
31 | 31 |
#include <fcntl.h> |
32 | 32 |
#include <errno.h> |
33 |
+#include <string.h> |
|
33 | 34 |
#include "cltypes.h" |
34 | 35 |
#include "clambc.h" |
35 | 36 |
#include "bytecode.h" |
... | ... |
@@ -252,3 +253,60 @@ uint32_t cli_bcapi_pe_rawaddr(struct cli_bc_ctx *ctx, uint32_t rva, uint32_t dum |
252 | 252 |
return PE_INVALID_RVA; |
253 | 253 |
return ret; |
254 | 254 |
} |
255 |
+ |
|
256 |
+static inline const char* cli_memmem(const char *haystack, unsigned hlen, |
|
257 |
+ const unsigned char *needle, unsigned nlen) |
|
258 |
+{ |
|
259 |
+ const char *p; |
|
260 |
+ unsigned char c; |
|
261 |
+ if (!needle || !haystack) |
|
262 |
+ return NULL; |
|
263 |
+ c = *needle++; |
|
264 |
+ if (nlen == 1) |
|
265 |
+ return memchr(haystack, c, hlen); |
|
266 |
+ |
|
267 |
+ while (hlen >= nlen) { |
|
268 |
+ p = haystack; |
|
269 |
+ haystack = memchr(haystack, c, hlen - nlen + 1); |
|
270 |
+ if (!haystack) |
|
271 |
+ return NULL; |
|
272 |
+ p = haystack + 1; |
|
273 |
+ if (!memcmp(p, needle, nlen-1)) |
|
274 |
+ return haystack; |
|
275 |
+ hlen -= p - haystack; |
|
276 |
+ haystack = p; |
|
277 |
+ } |
|
278 |
+ return NULL; |
|
279 |
+} |
|
280 |
+ |
|
281 |
+int32_t cli_bcapi_file_find(struct cli_bc_ctx *ctx, const uint8_t* data, uint32_t len) |
|
282 |
+{ |
|
283 |
+ char buf[4096]; |
|
284 |
+ fmap_t *map = ctx->fmap; |
|
285 |
+ uint32_t off = ctx->off, newoff; |
|
286 |
+ int n; |
|
287 |
+ |
|
288 |
+ if (!map || len > sizeof(buf)/4 || len <= 0) |
|
289 |
+ return -1; |
|
290 |
+ for (;;) { |
|
291 |
+ const char *p; |
|
292 |
+ n = fmap_readn(map, buf, off, sizeof(buf)); |
|
293 |
+ if ((unsigned)n < len) |
|
294 |
+ return -1; |
|
295 |
+ p = cli_memmem(buf, n, data, len); |
|
296 |
+ if (p) |
|
297 |
+ return off + p - buf; |
|
298 |
+ off += n-len; |
|
299 |
+ } |
|
300 |
+ return -1; |
|
301 |
+} |
|
302 |
+ |
|
303 |
+int32_t cli_bcapi_file_byteat(struct cli_bc_ctx *ctx, uint32_t off, uint32_t dummy) |
|
304 |
+{ |
|
305 |
+ unsigned char c; |
|
306 |
+ if (!ctx->fmap) |
|
307 |
+ return -1; |
|
308 |
+ if (fmap_readn(ctx->fmap, &c, off, 1) != 1) |
|
309 |
+ return -1; |
|
310 |
+ return c; |
|
311 |
+} |
... | ... |
@@ -178,5 +178,17 @@ uint32_t trace_ptr(const uint8_t* ptr, uint32_t dummy); |
178 | 178 |
*/ |
179 | 179 |
uint32_t pe_rawaddr(uint32_t rva, uint32_t dummy); |
180 | 180 |
|
181 |
+/** Looks for the specified sequence of bytes in the current file. |
|
182 |
+ * @param[in] data the sequence of bytes to look for |
|
183 |
+ * @param len length of \p data, cannot be more than 1024 |
|
184 |
+ * @return offset in the current file if match is found, -1 otherwise */ |
|
185 |
+int32_t file_find(const uint8_t* data, uint32_t len); |
|
186 |
+ |
|
187 |
+/** Read a single byte from current file |
|
188 |
+ * @param offset file offset |
|
189 |
+ * @return byte at offset \p off in the current file, or -1 if offset is |
|
190 |
+ * invalid */ |
|
191 |
+int32_t file_byteat(uint32_t offset, uint32_t dummy); |
|
192 |
+ |
|
181 | 193 |
#endif |
182 | 194 |
#endif |
... | ... |
@@ -49,6 +49,8 @@ uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32 |
49 | 49 |
uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
50 | 50 |
uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
51 | 51 |
uint32_t cli_bcapi_pe_rawaddr(struct cli_bc_ctx *ctx, uint32_t, uint32_t); |
52 |
+int32_t cli_bcapi_file_find(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
|
53 |
+int32_t cli_bcapi_file_byteat(struct cli_bc_ctx *ctx, uint32_t, uint32_t); |
|
52 | 54 |
|
53 | 55 |
const struct cli_apiglobal cli_globals[] = { |
54 | 56 |
/* Bytecode globals BEGIN */ |
... | ... |
@@ -141,14 +143,17 @@ const struct cli_apicall cli_apicalls[]={ |
141 | 141 |
{"trace_op", 17, 9, 1}, |
142 | 142 |
{"trace_value", 17, 10, 1}, |
143 | 143 |
{"trace_ptr", 17, 11, 1}, |
144 |
- {"pe_rawaddr", 16, 3, 0} |
|
144 |
+ {"pe_rawaddr", 16, 3, 0}, |
|
145 |
+ {"file_find", 17, 12, 1}, |
|
146 |
+ {"file_byteat", 16, 4, 0} |
|
145 | 147 |
/* Bytecode APIcalls END */ |
146 | 148 |
}; |
147 | 149 |
const cli_apicall_int2 cli_apicalls0[] = { |
148 | 150 |
(cli_apicall_int2)cli_bcapi_test1, |
149 | 151 |
(cli_apicall_int2)cli_bcapi_seek, |
150 | 152 |
(cli_apicall_int2)cli_bcapi_debug_print_uint, |
151 |
- (cli_apicall_int2)cli_bcapi_pe_rawaddr |
|
153 |
+ (cli_apicall_int2)cli_bcapi_pe_rawaddr, |
|
154 |
+ (cli_apicall_int2)cli_bcapi_file_byteat |
|
152 | 155 |
}; |
153 | 156 |
const cli_apicall_pointer cli_apicalls1[] = { |
154 | 157 |
(cli_apicall_pointer)cli_bcapi_test0, |
... | ... |
@@ -162,6 +167,7 @@ const cli_apicall_pointer cli_apicalls1[] = { |
162 | 162 |
(cli_apicall_pointer)cli_bcapi_trace_source, |
163 | 163 |
(cli_apicall_pointer)cli_bcapi_trace_op, |
164 | 164 |
(cli_apicall_pointer)cli_bcapi_trace_value, |
165 |
- (cli_apicall_pointer)cli_bcapi_trace_ptr |
|
165 |
+ (cli_apicall_pointer)cli_bcapi_trace_ptr, |
|
166 |
+ (cli_apicall_pointer)cli_bcapi_file_find |
|
166 | 167 |
}; |
167 | 168 |
const unsigned cli_apicall_maxapi = sizeof(cli_apicalls)/sizeof(cli_apicalls[0]); |
... | ... |
@@ -46,5 +46,7 @@ uint32_t cli_bcapi_trace_op(struct cli_bc_ctx *ctx, const const uint8_t*, uint32 |
46 | 46 |
uint32_t cli_bcapi_trace_value(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
47 | 47 |
uint32_t cli_bcapi_trace_ptr(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
48 | 48 |
uint32_t cli_bcapi_pe_rawaddr(struct cli_bc_ctx *ctx, uint32_t, uint32_t); |
49 |
+int32_t cli_bcapi_file_find(struct cli_bc_ctx *ctx, const const uint8_t*, uint32_t); |
|
50 |
+int32_t cli_bcapi_file_byteat(struct cli_bc_ctx *ctx, uint32_t, uint32_t); |
|
49 | 51 |
|
50 | 52 |
#endif |