1use std::{cmp, mem, ptr};
36use std::ops::Range;
37
38use crate::{Pod, pattern as pat};
39use crate::util::AlignTo;
40
41use super::{Align, Rva, Pe, image::*};
42
43const QS_BUF_LEN: usize = 16;
45
46#[derive(Copy, Clone)]
52pub struct Scanner<P> {
53 pe: P,
54}
55impl<'a, P: Pe<'a>> Scanner<P> {
56 pub(crate) fn new(pe: P) -> Scanner<P> {
57 Scanner { pe }
58 }
59 pub fn finds(&self, pat: &[pat::Atom], range: Range<Rva>, save: &mut [Rva]) -> bool {
71 let mut matches = self.matches(pat, range);
72 if !matches.next(save) {
73 return false;
74 }
75 !matches.next(&mut save[..0])
82 }
83 pub fn finds_code(&self, pat: &[pat::Atom], save: &mut [Rva]) -> bool {
87 self.finds(pat, self.pe.headers().code_range(), save)
88 }
89 pub fn matches<'pat>(&self, pat: &'pat [pat::Atom], range: Range<Rva>) -> Matches<'pat, P> {
91 Matches { scanner: *self, pat, range, hits: 0 }
92 }
93 pub fn matches_code<'pat>(&self, pat: &'pat [pat::Atom]) -> Matches<'pat, P> {
97 self.matches(pat, self.pe.headers().code_range())
98 }
99 pub fn exec(&self, cursor: Rva, pat: &[pat::Atom], save: &mut [Rva]) -> bool {
107 Exec { pe: self.pe, pat, cursor, pc: 0 }.exec(save)
108 }
109}
110
111trait Scan<'a>: Copy {
114 fn read<T: Copy + Pod>(self, rva: Rva) -> Option<T>;
115 fn pointer(self, va: Va) -> Option<Rva>;
116 fn slice(self, rva: Rva) -> Option<&'a [u8]>;
117}
118
119impl<'a, P: Pe<'a>> Scan<'a> for P {
120 fn read<T: Copy + Pod>(self, rva: Rva) -> Option<T> {
121 self.derva_copy(rva).ok()
122 }
123 fn pointer(self, va: Va) -> Option<Rva> {
124 self.va_to_rva(va).ok()
125 }
126 fn slice(self, rva: Rva) -> Option<&'a [u8]> {
127 self.slice_bytes(rva).ok()
128 }
129}
130
131impl<'a> Scan<'a> for &'a [u8] {
132 fn read<T: Copy + Pod>(self, rva: Rva) -> Option<T> {
133 let bytes = self.get(rva as usize..(rva as usize + mem::size_of::<T>()))?;
134 let ptr = bytes.as_ptr() as *const T;
135 Some(unsafe { ptr::read_unaligned(ptr) })
136 }
137 fn pointer(self, va: Va) -> Option<Rva> {
138 Some(va as Rva)
139 }
140 fn slice(self, rva: Rva) -> Option<&'a [u8]> {
141 self.get(rva as usize..)
142 }
143}
144
145#[derive(Clone)]
146struct Exec<'pat, P> {
147 pe: P,
148 pat: &'pat [pat::Atom],
149 cursor: Rva,
150 pc: usize,
151}
152impl<'a, 'pat, P: Scan<'a>> Exec<'pat, P> {
153 fn exec(&mut self, save: &mut [Rva]) -> bool {
154 const SKIP_VA: u32 = mem::size_of::<Va>() as u32;
155 let mut mask = 0xff;
156 let mut ext_range = 0u32;
157 while let Some(atom) = self.pat.get(self.pc).cloned() {
158 self.pc += 1;
159 match atom {
160 pat::Atom::Byte(pat_byte) => {
161 match self.pe.read::<u8>(self.cursor) {
162 Some(byte) if byte & mask == pat_byte & mask => (),
163 _ => return false,
164 }
165 mask = 0xff;
166 self.cursor += 1;
167 },
168 pat::Atom::Save(slot) => {
169 if let Some(slot) = save.get_mut(slot as usize) {
170 *slot = self.cursor;
171 }
172 },
173 pat::Atom::Push(skip) => {
174 let skip = ext_range + skip as u32;
175 let skip = if skip == 0 { SKIP_VA } else { skip };
176 let cursor = self.cursor.wrapping_add(skip);
177 if !self.exec(save) {
178 return false;
179 }
180 mask = 0xff;
181 ext_range = 0;
182 self.cursor = cursor;
183 },
184 pat::Atom::Pop => {
185 return true;
186 },
187 pat::Atom::Fuzzy(pat_mask) => {
188 mask = pat_mask;
189 },
190 pat::Atom::Skip(skip) => {
191 let skip = ext_range + skip as u32;
192 let skip = if skip == 0 { SKIP_VA } else { skip };
193 let cursor = self.cursor.wrapping_add(skip);
194 ext_range = 0;
195 self.cursor = cursor;
196 },
197 pat::Atom::Back(back) => {
198 let rewind = ext_range + back as u32;
199 let rewind = if rewind == 0 { SKIP_VA } else { rewind };
200 let cursor = self.cursor.wrapping_sub(rewind);
201 ext_range = 0;
202 self.cursor = cursor;
203 },
204 pat::Atom::Rangext(ext) => {
205 ext_range = ext as u32 * 256;
206 },
207 pat::Atom::Many(limit) => {
208 let limit = ext_range + limit as u32;
209 return self.exec_many(save, limit);
210 },
211 pat::Atom::Jump1 => {
212 if let Some(sbyte) = self.pe.read::<i8>(self.cursor) {
213 self.cursor = self.cursor.wrapping_add(sbyte as Rva).wrapping_add(1);
214 }
215 else {
216 return false;
217 }
218 },
219 pat::Atom::Jump4 => {
220 if let Some(sdword) = self.pe.read::<i32>(self.cursor) {
221 self.cursor = self.cursor.wrapping_add(sdword as Rva).wrapping_add(4);
222 }
223 else {
224 return false;
225 }
226 },
227 pat::Atom::Ptr => {
228 if let Some(rva) = self.pe.read::<Va>(self.cursor).and_then(|va| self.pe.pointer(va)) {
229 self.cursor = rva;
230 }
231 else {
232 return false;
233 }
234 },
235 pat::Atom::Pir(slot) => {
236 if let Some(sdword) = self.pe.read::<i32>(self.cursor) {
237 let base = save.get(slot as usize).cloned().unwrap_or(self.cursor);
238 self.cursor = base.wrapping_add(sdword as Rva);
239 }
240 else {
241 return false;
242 }
243 },
244 pat::Atom::VTypeName => {
245 branch! {
246 pe32 {
247 fn get<'a, S: Scan<'a>>(scan: S, cursor: u32) -> Option<u32> {
248 if (cursor & 3) != 0 { return None; }
249 let col_ptr = scan.read::<u32>(cursor.wrapping_sub(4))?;
250 let col_rva = scan.pointer(col_ptr)?;
251 let type_ptr = scan.read::<u32>(col_rva.wrapping_add(12))?;
252 let type_rva = scan.pointer(type_ptr)?;
253 Some(type_rva.wrapping_add(8))
254 }
255 }
256 pe64 {
257 fn get<'a, S: Scan<'a>>(scan: S, cursor: u32) -> Option<u32> {
258 if (cursor & 7) != 0 { return None; }
259 let col_ptr = scan.read::<u64>(cursor.wrapping_sub(8))?;
260 let col_rva = scan.pointer(col_ptr)?;
261 let type_rva = scan.read::<u32>(col_rva.wrapping_add(12))?;
262 Some(type_rva.wrapping_add(16))
263 }
264 }
265 }
266 if let Some(cursor) = get(self.pe, self.cursor) {
267 self.cursor = cursor;
268 }
269 else {
270 return false;
271 }
272 },
273 pat::Atom::Check(slot) => {
274 if let Some(&rva) = save.get(slot as usize) {
275 if rva != self.cursor {
276 return false;
277 }
278 }
279 },
280 pat::Atom::Aligned(align) => {
281 if !self.cursor.aligned_to(1 << align as u32) {
282 return false;
283 }
284 },
285 pat::Atom::ReadU8(slot) => {
286 if let Some(byte) = self.pe.read::<u8>(self.cursor) {
287 if let Some(slot) = save.get_mut(slot as usize) {
288 *slot = byte as Rva;
289 }
290 self.cursor = self.cursor.wrapping_add(1);
291 }
292 else {
293 return false;
294 }
295 },
296 pat::Atom::ReadI8(slot) => {
297 if let Some(sbyte) = self.pe.read::<i8>(self.cursor) {
298 if let Some(slot) = save.get_mut(slot as usize) {
299 *slot = sbyte as Rva;
300 }
301 self.cursor = self.cursor.wrapping_add(1);
302 }
303 else {
304 return false;
305 }
306 },
307 pat::Atom::ReadU16(slot) => {
308 if let Some(word) = self.pe.read::<u16>(self.cursor) {
309 if let Some(slot) = save.get_mut(slot as usize) {
310 *slot = word as Rva;
311 }
312 self.cursor = self.cursor.wrapping_add(2);
313 }
314 else {
315 return false;
316 }
317 },
318 pat::Atom::ReadI16(slot) => {
319 if let Some(sword) = self.pe.read::<i16>(self.cursor) {
320 if let Some(slot) = save.get_mut(slot as usize) {
321 *slot = sword as Rva;
322 }
323 self.cursor = self.cursor.wrapping_add(2);
324 }
325 else {
326 return false;
327 }
328 },
329 pat::Atom::ReadU32(slot) | pat::Atom::ReadI32(slot) => {
330 if let Some(dword) = self.pe.read::<Rva>(self.cursor) {
331 if let Some(slot) = save.get_mut(slot as usize) {
332 *slot = dword;
333 }
334 self.cursor = self.cursor.wrapping_add(4);
335 }
336 else {
337 return false;
338 }
339 },
340 pat::Atom::Zero(slot) => {
341 if let Some(slot) = save.get_mut(slot as usize) {
342 *slot = 0;
343 }
344 },
345 pat::Atom::Case(next) => {
346 let pc = self.pc;
347 let cursor = self.cursor;
348 if !self.exec(save) {
349 self.pc = pc + next as usize;
350 self.cursor = cursor;
351 }
352 },
353 pat::Atom::Break(next) => {
354 self.pc = self.pc + next as usize;
355 return true;
356 },
357 pat::Atom::Nop => {
358 },
359 }
360 }
361 return true;
362 }
363 fn exec_many(&mut self, save: &mut [Rva], limit: u32) -> bool {
364 let cursor = self.cursor;
366 let pc = self.pc;
367 let bytes = match self.pe.slice(cursor) {
369 Some(bytes) if limit == 0 => bytes,
370 Some(bytes) => &bytes[..cmp::min(limit as usize, bytes.len())],
371 None => return false,
372 };
373 let mut peek = None;
375 for &atom in &self.pat[pc..] {
376 match atom {
377 pat::Atom::Byte(byte) => {
378 peek = Some(byte);
379 break;
380 },
381 pat::Atom::Save(_) => (),
382 _ => break,
383 }
384 }
385 if let Some(byte) = peek {
387 for i in 0..bytes.len() as u32 {
388 if bytes[i as usize] == byte {
389 self.cursor = cursor.wrapping_add(i);
390 self.pc = pc;
391 if self.exec(save) {
392 return true;
393 }
394 }
395 }
396 }
397 else {
399 for i in 0..bytes.len() as u32 {
400 self.cursor = cursor.wrapping_add(i);
401 self.pc = pc;
402 if self.exec(save) {
403 return true;
404 }
405 }
406 }
407 return false;
409 }
410}
411
412#[derive(Clone)]
418pub struct Matches<'pat, P> {
419 scanner: Scanner<P>,
420 pat: &'pat [pat::Atom],
421 range: Range<Rva>,
422 hits: u32,
423}
424
425impl<'a, 'pat, P: Pe<'a>> Matches<'pat, P> {
426 pub fn scanner(&self) -> Scanner<P> {
428 self.scanner
429 }
430 pub fn pattern(&self) -> &'pat [pat::Atom] {
432 self.pat
433 }
434 pub fn range(&self) -> Range<Rva> {
436 self.range.clone()
437 }
438 pub fn hits(&self) -> u32 {
442 self.hits
443 }
444 fn setup<'b>(&self, qsbuf: &'b mut [u8; QS_BUF_LEN]) -> &'b [u8] {
446 let mut qslen = 0usize;
447 for &atom in self.pat {
448 match atom {
449 pat::Atom::Byte(byte) => {
450 if qslen >= QS_BUF_LEN {
451 break;
452 }
453 qsbuf[qslen] = byte;
454 qslen += 1;
455 },
456 pat::Atom::Save(_) => {},
458 pat::Atom::Aligned(_) => {},
459 pat::Atom::Nop => {},
460 _ => break,
462 }
463 }
464 &qsbuf[..qslen]
465 }
466 fn strategy(&mut self, qsbuf: &[u8], slice: &'a [u8], save: &mut [Rva]) -> bool {
468 if qsbuf.len() == 0 {
470 self.strategy0(qsbuf, slice, save)
471 }
472 else if qsbuf.len() < 4 {
473 self.strategy1(qsbuf, slice, save)
474 }
475 else {
476 self.strategy2(qsbuf, slice, save)
477 }
478 }
479 fn strategy0(&mut self, _qsbuf: &[u8], slice: &'a [u8], save: &mut [Rva]) -> bool {
482 let end = self.range.start + slice.len() as u32;
483 while self.range.start < end {
484 let cursor = self.range.start;
485 self.hits += 1;
486 self.range.start += 1;
487 if self.scanner.exec(cursor, self.pat, save) {
488 return true;
489 }
490 }
491 return false;
492 }
493 fn strategy1(&mut self, qsbuf: &[u8], slice: &'a [u8], save: &mut [Rva]) -> bool {
497 let byte = qsbuf[0];
498 for i in slice.iter().enumerate().filter_map(|(i, &a)| if a == byte { Some(i as u32) } else { None }) {
501 self.hits += 1;
502 let cursor = self.range.start + i;
503 if self.scanner.exec(cursor, self.pat, save) {
504 self.range.start = cursor + 1;
505 return true;
506 }
507 }
508 self.range.start += slice.len() as u32;
509 return false;
510 }
511 fn strategy2(&mut self, qsbuf: &[u8], slice: &'a [u8], save: &mut [Rva]) -> bool {
515 let qslen = qsbuf.len();
517 let mut jumps = [qslen as u8; 256];
518 for i in 0..qslen - 1 {
519 jumps[qsbuf[i] as usize] = qslen as u8 - i as u8 - 1;
520 }
521 let mut i = 0;
523 while i + qslen <= slice.len() {
524 let tbuf = &slice[i..i + qslen];
525 let last = tbuf[qslen - 1];
526 let jump = jumps[last as usize] as u32;
527 if qsbuf[qslen - 1] == last && tbuf == qsbuf {
528 self.hits += 1;
529 let cursor = self.range.start + i as u32;
530 if self.scanner.exec(cursor, self.pat, save) {
531 self.range.start = cursor + jump;
532 return true;
533 }
534 }
535 i += jump as usize;
536 }
537 self.range.start += slice.len() as u32;
542 return false;
543 }
544 pub fn next(&mut self, save: &mut [Rva]) -> bool {
546 let mut qsbuf = [0u8; QS_BUF_LEN];
548 let qsbuf = self.setup(&mut qsbuf);
549
550 let image = self.scanner.pe.image();
551 match self.scanner.pe.align() {
552 Align::File => {
553 for section in self.scanner.pe.section_headers() {
554 if section.VirtualAddress < self.range.end && u32::wrapping_add(section.VirtualAddress, section.VirtualSize) > self.range.start {
556 if let Some(slice) = image.get(section.PointerToRawData as usize..u32::wrapping_add(section.PointerToRawData, section.SizeOfRawData) as usize) {
558 if self.next_section(qsbuf, section.VirtualAddress, slice, save) {
559 return true;
560 }
561 }
562 }
563 }
564 false
565 },
566 Align::Section => {
567 self.next_section(qsbuf, 0, image, save)
568 },
569 }
570 }
571 fn next_section(&mut self, qsbuf: &[u8], base: Rva, slice: &'a [u8], save: &mut [Rva]) -> bool {
572 self.range.start = cmp::max(base, self.range.start);
583 let start = self.range.start - base;
584 let end = cmp::min(base + slice.len() as u32, self.range.end) - base;
585
586 self.strategy(qsbuf, &slice[start as usize..end as usize], save)
587 }
588}
589
590#[cfg(test)]
593pub(crate) fn test<'a, P: Pe<'a>>(pe: P) -> crate::Result<()> {
594 use crate::pattern::Atom::*;
595 let scanner = pe.scanner();
596 let mut save = [0; 4];
597
598 let mut matches = scanner.matches_code(&[Save(0), Byte(0xE8), Push(4), Jump4, Save(1), Pop, Save(2)]);
599 while matches.next(&mut save) {
600 assert_eq!(save[0] + 5, save[2]);
601 }
602
603 let mut matches = scanner.matches_code(&[Jump1, Save(1), Byte(0x0F), Byte(0x0D)]);
604 while matches.next(&mut save) {}
605
606 scanner.finds_code(&[Byte(0x8B), Byte(0x01), Byte(0x8B), Byte(0x10), Byte(0xFF), Byte(0xD2)], &mut save);
607
608 Ok(())
609}
610
611#[test]
613fn exec_tests_parse_docs() {
614 use crate::pattern::{Atom, parse};
615
616 fn exec(bytes: &[u8], pat: &[Atom], save: &mut [Rva]) -> bool {
617 Exec { pe: bytes, pat, cursor: 0, pc: 0 }.exec(save)
618 }
619
620 {
621 let bytes = [0x55, 0x89, 0xe5, 0x83, 0xff, 0xec];
622 let pat = parse("55 89 e5 83 ? ec").unwrap();
623 assert!(exec(&bytes, &pat, &mut []));
624 }{
625 let bytes = [0xb9, 0x37, 0x13, 0x00, 0x00];
626 let pat = parse("b9 '37 13 00 00").unwrap();
627 let mut save = [0; 2];
628 assert!(exec(&bytes, &pat, &mut save));
629 assert_eq!(save[1], 1);
630 }{
631 let mut bytes = [0; 64];
632 bytes[0] = 0xb8;
633 bytes[17] = 0x50;
634 bytes[41] = 0xff;
635 let pat = parse("b8 [16] 50 [13-42] 'ff").unwrap();
636 let mut save = [0; 2];
637 assert!(exec(&bytes, &pat, &mut save));
638 assert_eq!(save[1], 41);
639 }{
640 let bytes = [0x31, 0xc0, 0x74, (-3i8) as u8];
641 let pat = parse("31 c0 74 % 'c0").unwrap();
642 let mut save = [0; 2];
643 assert!(exec(&bytes, &pat, &mut save));
644 assert_eq!(save[1], 1);
645 }{
646 let bytes = [0xe8, 10, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0x31, 0xc0, 0xc3];
647 let pat = parse("e8 $ '31 c0 c3").unwrap();
648 let mut save = [0; 2];
649 assert!(exec(&bytes, &pat, &mut save));
650 assert_eq!(save[1], 15);
651 }{
652 let bytes = [0x68, 10, 0, 0, 0, 1, 2, 3, 4, 5, 0x31, 0xc0, 0xc3];
653 let pat = parse("68 * '31 c0 c3").unwrap();
654 let mut save = [0; 2];
655 assert!(exec(&bytes, &pat, &mut save));
656 assert_eq!(save[1], 10);
657 }{
658 let bytes = b"\xb8\x0a\x00\x00\x00\x01\x02\x03\x04\x05STRING\x00";
659 let pat = parse(r#"b8 * "STRING" 00"#).unwrap();
660 assert!(exec(bytes, &pat, &mut []));
661 }{
662 let bytes = [0xe8, 10, 0, 0, 0, 0x83, 0xf0, 0x5c, 0xc3, 5, 6, 7, 8, 9, 10];
663 let pat = parse("e8 $ { ' } 83 f0 5c c3").unwrap();
664 let mut save = [0; 2];
665 assert!(exec(&bytes, &pat, &mut save));
666 assert_eq!(save[1], 15);
667 }{
668 let bytes = [0xe8, 0xff, 0xa0, 0x78, 0x56, 0x34, 0x12];
669 let pat = parse("e8 i1 a0 u4").unwrap();
670 let mut save = [0; 3];
671 assert!(exec(&bytes, &pat, &mut save));
672 assert_eq!(save[1], (-1i8) as u32);
673 assert_eq!(save[2], 0x12345678);
674 }{
675 let bytes1 = [0x83, 0xc0, 0x2a, 0x6a, 0x00, 0xe8];
676 let bytes2 = [0x83, 0xc0, 0x2a, 0x68, 0x00, 0x00, 0x00, 0x10, 0xe8];
677 let pat = parse("83 c0 2a ( 6a ? | 68 ? ? ? ? ) e8").unwrap();
678 assert!(exec(&bytes1, &pat, &mut []));
679 assert!(exec(&bytes2, &pat, &mut []));
680 }
681}