1use crate::emu;
2use crate::emu::peb32;
3use crate::emu::peb64;
4use crate::emu::structures;
5use std::fs::File;
6use std::io::BufRead;
7use std::io::BufReader;
8use std::vec::Vec;
9
10pub struct Script {
11 code: Vec<String>,
12 result: u64,
13 skip: bool,
14 looped: u64,
15 trace: bool,
16}
17
18impl Script {
19 pub fn new() -> Script {
20 Script {
21 code: Vec::new(),
22 result: 0,
23 skip: false,
24 looped: 0,
25 trace: false,
26 }
27 }
28
29 pub fn load(&mut self, filename: &str) {
30 let file = File::open(filename).unwrap();
32 let buf = BufReader::new(file);
33
34 for line in buf.lines() {
35 if let Ok(line) = line {
36 self.code.push(line);
37 }
38 }
39 }
40
41 pub fn resolve(&self, arg: &str, i: usize, emu: &mut emu::Emu) -> u64 {
42 if arg == "result" {
43 return self.result;
44 } else if arg.starts_with("0x") {
45 let a = match self.to_hex(&arg) {
46 Some(v) => v,
47 None => {
48 panic!("error in line {}, bad hexa", i);
49 }
50 };
51 return a;
52 }
53 return emu.regs.get_by_name(arg);
54 }
55
56 pub fn to_int(&self, s: &str) -> Option<u64> {
57 let value: u64 = match u64::from_str_radix(s, 10) {
58 Ok(value) => value,
59 Err(_) => return None,
60 };
61
62 Some(value)
63 }
64
65 pub fn to_hex(&self, s: &str) -> Option<u64> {
66 let mut x = s.to_string();
67 if x.ends_with('h') {
68 x = x[0..x.len() - 1].to_string();
69 }
70 if x.starts_with("0x") {
71 x = x[2..x.len()].to_string();
72 }
73
74 let value: u64 = match u64::from_str_radix(x.as_str(), 16) {
75 Ok(value) => value,
76 Err(_) => return None,
77 };
78
79 Some(value)
80 }
81
82 pub fn run(&mut self, emu: &mut emu::Emu) {
83 emu.running_script = true;
84 let mut i = 0;
85
86 loop {
87 i += 1;
88
89 if i > self.code.len() {
90 break;
91 }
92 let line = &self.code[i - 1];
93 if line.len() == 0 || line.starts_with(";") {
94 continue;
95 }
96 let args: Vec<&str> = line.split_whitespace().collect();
97
98 if self.trace {
99 log::info!("==> {} {}", i, line);
100 }
101
102 if line == "endif" {
103 self.skip = false;
104 continue;
105 }
106
107 if self.skip {
108 continue;
109 }
110
111 match args[0] {
112 "pr" => {
113 log::info!("result: 0x{:x}", self.result);
114 }
115 "p" => {
116 if args.len() < 2 {
117 log::info!(
118 "error in line {}, `p` command needs a message to be printed",
119 i
120 );
121 return;
122 }
123 let msg = args
124 .iter()
125 .skip(1)
126 .map(|s| s.to_owned())
127 .collect::<Vec<_>>()
128 .join(" ");
129
130 log::info!("{}", msg);
131 }
132 "q" => std::process::exit(1),
133 "r" => {
134 if args.len() == 1 {
135 if emu.cfg.is_64bits {
136 emu.featured_regs64();
137 } else {
138 emu.featured_regs32();
139 }
140 } else {
141 self.result = emu.regs.get_by_name(&args[1]);
142
143 match args[1] {
144 "rax" => emu.regs.show_rax(&emu.maps, 0),
145 "rbx" => emu.regs.show_rbx(&emu.maps, 0),
146 "rcx" => emu.regs.show_rcx(&emu.maps, 0),
147 "rdx" => emu.regs.show_rdx(&emu.maps, 0),
148 "rsi" => emu.regs.show_rsi(&emu.maps, 0),
149 "rdi" => emu.regs.show_rdi(&emu.maps, 0),
150 "rbp" => log::info!("\trbp: 0x{:x}", emu.regs.rbp),
151 "rsp" => log::info!("\trsp: 0x{:x}", emu.regs.rsp),
152 "rip" => log::info!("\trip: 0x{:x}", emu.regs.rip),
153 "eax" => emu.regs.show_eax(&emu.maps, 0),
154 "ebx" => emu.regs.show_ebx(&emu.maps, 0),
155 "ecx" => emu.regs.show_ecx(&emu.maps, 0),
156 "edx" => emu.regs.show_edx(&emu.maps, 0),
157 "esi" => emu.regs.show_esi(&emu.maps, 0),
158 "edi" => emu.regs.show_edi(&emu.maps, 0),
159 "esp" => log::info!("\tesp: 0x{:x}", emu.regs.get_esp() as u32),
160 "ebp" => log::info!("\tebp: 0x{:x}", emu.regs.get_ebp() as u32),
161 "eip" => log::info!("\teip: 0x{:x}", emu.regs.get_eip() as u32),
162 "r8" => emu.regs.show_r8(&emu.maps, 0),
163 "r9" => emu.regs.show_r9(&emu.maps, 0),
164 "r10" => emu.regs.show_r10(&emu.maps, 0),
165 "r11" => emu.regs.show_r11(&emu.maps, 0),
166 "r12" => emu.regs.show_r12(&emu.maps, 0),
167 "r13" => emu.regs.show_r13(&emu.maps, 0),
168 "r14" => emu.regs.show_r14(&emu.maps, 0),
169 "r15" => emu.regs.show_r15(&emu.maps, 0),
170 "r8d" => emu.regs.show_r8d(&emu.maps, 0),
171 "r9d" => emu.regs.show_r9d(&emu.maps, 0),
172 "r10d" => emu.regs.show_r10d(&emu.maps, 0),
173 "r11d" => emu.regs.show_r11d(&emu.maps, 0),
174 "r12d" => emu.regs.show_r12d(&emu.maps, 0),
175 "r13d" => emu.regs.show_r13d(&emu.maps, 0),
176 "r14d" => emu.regs.show_r14d(&emu.maps, 0),
177 "r15d" => emu.regs.show_r15d(&emu.maps, 0),
178 "r8w" => emu.regs.show_r8w(&emu.maps, 0),
179 "r9w" => emu.regs.show_r9w(&emu.maps, 0),
180 "r10w" => emu.regs.show_r10w(&emu.maps, 0),
181 "r11w" => emu.regs.show_r11w(&emu.maps, 0),
182 "r12w" => emu.regs.show_r12w(&emu.maps, 0),
183 "r13w" => emu.regs.show_r13w(&emu.maps, 0),
184 "r14w" => emu.regs.show_r14w(&emu.maps, 0),
185 "r15w" => emu.regs.show_r15w(&emu.maps, 0),
186 "r8l" => emu.regs.show_r8l(&emu.maps, 0),
187 "r9l" => emu.regs.show_r9l(&emu.maps, 0),
188 "r10l" => emu.regs.show_r10l(&emu.maps, 0),
189 "r11l" => emu.regs.show_r11l(&emu.maps, 0),
190 "r12l" => emu.regs.show_r12l(&emu.maps, 0),
191 "r13l" => emu.regs.show_r13l(&emu.maps, 0),
192 "r14l" => emu.regs.show_r14l(&emu.maps, 0),
193 "r15l" => emu.regs.show_r15l(&emu.maps, 0),
194 "xmm0" => log::info!("\txmm0: 0x{:x}", emu.regs.xmm0),
195 "xmm1" => log::info!("\txmm1: 0x{:x}", emu.regs.xmm1),
196 "xmm2" => log::info!("\txmm2: 0x{:x}", emu.regs.xmm2),
197 "xmm3" => log::info!("\txmm3: 0x{:x}", emu.regs.xmm3),
198 "xmm4" => log::info!("\txmm4: 0x{:x}", emu.regs.xmm4),
199 "xmm5" => log::info!("\txmm5: 0x{:x}", emu.regs.xmm5),
200 "xmm6" => log::info!("\txmm6: 0x{:x}", emu.regs.xmm6),
201 "xmm7" => log::info!("\txmm7: 0x{:x}", emu.regs.xmm7),
202 "xmm8" => log::info!("\txmm8: 0x{:x}", emu.regs.xmm8),
203 "xmm9" => log::info!("\txmm9: 0x{:x}", emu.regs.xmm9),
204 "xmm10" => log::info!("\txmm10: 0x{:x}", emu.regs.xmm10),
205 "xmm11" => log::info!("\txmm11: 0x{:x}", emu.regs.xmm11),
206 "xmm12" => log::info!("\txmm12: 0x{:x}", emu.regs.xmm12),
207 "xmm13" => log::info!("\txmm13: 0x{:x}", emu.regs.xmm13),
208 "xmm14" => log::info!("\txmm14: 0x{:x}", emu.regs.xmm14),
209 "xmm15" => log::info!("\txmm15: 0x{:x}", emu.regs.xmm15),
210 _ => log::info!("unknown register r `{}` in line {}", args[1], i),
211 }
212 }
213 }
214 "rc" => {
215 if args.len() != 3 {
216 log::info!("expected: rc <register> <value>");
217 } else {
218 let value: u64 = self.resolve(args[2], i, emu);
219 emu.regs.set_by_name(args[1], value);
220 }
221 }
222 "mr" | "rm" => {
223 if args.len() < 2 {
224 log::info!("error in line {}, command `mr` without arguments", i);
225 return;
226 }
227
228 let ins = args
229 .iter()
230 .skip(1)
231 .map(|s| s.to_owned())
232 .collect::<Vec<_>>()
233 .join(" ");
234
235 let addr: u64 = emu.memory_operand_to_address(&ins);
236 let value = match emu.memory_read(&ins) {
237 Some(v) => v,
238 None => {
239 log::info!("error in line {}, bad address.", i);
240 return;
241 }
242 };
243 self.result = value;
244 log::info!("0x{:x}", value);
245 }
246 "mw" | "wm" => {
247 if args.len() < 3 {
250 log::info!("error in line {}, command `mw` without arguments", i);
251 return;
252 }
253
254 let ins = args
255 .iter()
256 .skip(2)
257 .map(|s| s.to_owned())
258 .collect::<Vec<_>>()
259 .join(" ");
260
261 let value = self.resolve(args[1], i, emu);
262
263 if !emu.memory_write(&ins, value) {
264 log::info!("error in line {}, cannot write on `{}`", i, args[1]);
265 return;
266 }
267 }
268 "mwb" => {
269 let addr = self.resolve(args[1], i, emu);
270 let bytes = args
271 .iter()
272 .skip(1)
273 .take(args.len() - 2)
274 .map(|s| s.to_owned())
275 .collect::<Vec<_>>()
276 .join(" ");
277
278 emu.maps.write_spaced_bytes(addr, &bytes);
279 }
280 "b" => {
281 emu.bp.show();
282 }
283 "ba" => {
284 if args.len() < 2 {
285 log::info!("error in line {}, address is missing", i);
286 return;
287 }
288 let addr = self.resolve(args[1], i, emu);
289 emu.bp.set_bp(addr);
290 }
291 "bmr" => {
292 if args.len() < 2 {
293 log::info!("error in line {}, address is missing", i);
294 return;
295 }
296 let addr = self.resolve(args[1], i, emu);
297
298 emu.bp.set_mem_read(addr);
299 }
300 "bmw" => {
301 if args.len() < 2 {
302 log::info!("error in line {}, address is missing", i);
303 return;
304 }
305 let addr = self.resolve(args[1], i, emu);
306 emu.bp.set_mem_write(addr);
307 }
308 "bi" => {
309 if args.len() < 2 {
310 log::info!("error in line {}, number is missing", i);
311 return;
312 }
313 let num = match self.to_int(args[1]) {
314 Some(v) => v,
315 None => {
316 log::info!("error in line {}, bad number", i);
317 return;
318 }
319 };
320 emu.bp.set_instruction(num);
321 emu.exp = num;
322 }
323 "bc" => {
324 emu.bp.clear_bp();
325 emu.exp = emu.pos + 1;
326 }
327 "bcmp" => {
328 emu.break_on_next_cmp = true;
329 }
330 "cls" => {
331 log::info!("{}", emu.colors.clear_screen);
332 }
333 "s" => {
334 if emu.cfg.is_64bits {
335 emu.maps.dump_qwords(emu.regs.rsp, 10);
336 } else {
337 emu.maps.dump_dwords(emu.regs.get_esp(), 10);
338 }
339 }
340 "v" => {
341 if emu.cfg.is_64bits {
342 emu.maps.dump_qwords(emu.regs.rbp - 0x100, 100);
343 } else {
344 emu.maps.dump_dwords(emu.regs.get_ebp() - 0x100, 100);
345 }
346 emu.maps
347 .get_mem("stack")
348 .print_dwords_from_to(emu.regs.get_ebp(), emu.regs.get_ebp() + 0x100);
349 }
350 "sv" => {
351 if args.len() < 2 {
352 log::info!("error in line {}, number is missing", i);
353 return;
354 }
355 let num = match self.to_int(args[1]) {
356 Some(v) => v,
357 None => {
358 log::info!("error in line {}, bad number", i);
359 return;
360 }
361 };
362 emu.cfg.verbose = num as u32;
363 }
364 "tr" => {
365 if args.len() < 2 {
366 log::info!("error in line {}, register is missing", i);
367 return;
368 }
369 emu.cfg.trace_reg = true;
370 emu.cfg.reg_names.push(args[1].to_string());
371 }
372 "trc" => {
373 emu.cfg.trace_reg = false;
374 emu.cfg.reg_names.clear();
375 }
376 "c" => {
377 emu.is_running
378 .store(1, std::sync::atomic::Ordering::Relaxed);
379 emu.run(None);
380 }
381 "cr" => {
382 emu.break_on_next_return = true;
383 emu.is_running
384 .store(1, std::sync::atomic::Ordering::Relaxed);
385 emu.run(None);
386 }
387 "f" => emu.flags.print(),
388 "fc" => emu.flags.clear(),
389 "fz" => emu.flags.f_zf = !emu.flags.f_zf,
390 "fs" => emu.flags.f_sf = !emu.flags.f_sf,
391 "mc" => {
392 if args.len() != 3 {
394 log::info!("error in line {}, mc <mapname> <size>", i);
395 return;
396 }
397 let sz = match self.to_int(&args[2]) {
398 Some(v) => v,
399 None => {
400 log::info!("error in line {}, bad size", i);
401 return;
402 }
403 };
404 let addr = match emu.maps.alloc(sz) {
405 Some(a) => a,
406 None => {
407 log::info!("error in line {}, memory full", i);
408 return;
409 }
410 };
411 emu.maps.create_map(&args[1], addr, sz);
412 log::info!("allocated {} at 0x{:x} sz: {}", &args[1], addr, sz);
413 self.result = addr;
414 }
415 "mca" => {
416 if args.len() != 4 {
418 log::info!("error in line {}, mc <mapname> <addr> <size>", i);
419 return;
420 }
421 let addr = self.resolve(args[2], i, emu);
422 let sz = match self.to_int(&args[3]) {
423 Some(v) => v,
424 None => {
425 log::info!("error in line {}, bad size", i);
426 return;
427 }
428 };
429 emu.maps.create_map(&args[1], addr, sz);
430 log::info!("allocated {} at 0x{:x} sz: {}", &args[1], addr, sz);
431 }
432 "ml" => {
433 if args.len() != 3 {
435 log::info!("error in line {}, `ml` needs mapname and a filename", i);
436 return;
437 }
438 emu.maps.get_mem(&args[1]).load(&args[2]);
439 }
440 "mn" => {
441 if args.len() != 2 {
443 log::info!("error in line {}, `mn` needs an address", i);
444 return;
445 }
446
447 let addr = self.resolve(args[1], i, emu);
448
449 let name = match emu.maps.get_addr_name(addr) {
450 Some(n) => n,
451 None => {
452 log::info!("error in line {}, address not found on any map", i);
453 return;
454 }
455 };
456
457 let mem = emu.maps.get_mem(&name);
458 if emu.cfg.is_64bits {
459 log::info!(
460 "map: {} 0x{:x}-0x{:x} ({})",
461 name,
462 mem.get_base(),
463 mem.get_bottom(),
464 mem.size()
465 );
466 } else {
467 log::info!(
468 "map: {} 0x{:x}-0x{:x} ({})",
469 name,
470 mem.get_base() as u32,
471 mem.get_bottom() as u32,
472 mem.size()
473 );
474 }
475 }
476 "ma" => {
477 emu.maps.show_allocs();
478 }
479 "md" => {
480 if args.len() != 2 {
482 log::info!("error in line {}, address missing", i);
483 return;
484 }
485
486 let addr = self.resolve(args[1], i, emu);
487
488 emu.maps.dump(addr);
489 }
490 "mrd" => {
491 if args.len() != 3 {
493 log::info!("error in line {}, address or number of dwords missing", i);
494 return;
495 }
496
497 let addr = self.resolve(args[1], i, emu);
498
499 let num = match self.to_int(&args[2]) {
500 Some(v) => v,
501 None => {
502 log::info!("error in line {}, bad number", i);
503 return;
504 }
505 };
506
507 emu.maps.dump_dwords(addr, num);
508 }
509 "mrq" => {
510 if args.len() != 3 {
512 log::info!("error in line {}, address or number of qwords missing", i);
513 return;
514 }
515
516 let addr = self.resolve(args[1], i, emu);
517
518 let num = match self.to_int(&args[2]) {
519 Some(v) => v,
520 None => {
521 log::info!("error in line {}, bad number", i);
522 return;
523 }
524 };
525
526 emu.maps.dump_qwords(addr, num);
527 }
528 "mds" => {
529 if args.len() != 2 {
531 log::info!("error in line {}, address is missing", i);
532 return;
533 }
534
535 let addr = self.resolve(args[1], i, emu);
536
537 if emu.cfg.is_64bits {
538 log::info!("0x{:x}: '{}'", addr, emu.maps.read_string(addr));
539 } else {
540 log::info!("0x{:x}: '{}'", addr as u32, emu.maps.read_string(addr));
541 }
542 }
543 "mdw" => {
544 if args.len() != 2 {
546 log::info!("error in line {}, address is missing", i);
547 return;
548 }
549
550 let addr = self.resolve(args[1], i, emu);
551
552 if emu.cfg.is_64bits {
553 log::info!("0x{:x}: '{}'", addr, emu.maps.read_wide_string(addr));
554 } else {
555 log::info!("0x{:x}: '{}'", addr as u32, emu.maps.read_wide_string(addr));
556 }
557 }
558 "mdd" => {
559 if args.len() != 4 {
561 log::info!("error in line {}, address, size or filename is missing", i);
562 return;
563 }
564
565 let addr = self.resolve(args[1], i, emu);
566
567 let sz = match self.to_int(&args[2]) {
568 Some(v) => v,
569 None => {
570 log::info!("error in line {}, bad size", i);
571 return;
572 }
573 };
574
575 if sz <= 0 {
576 log::info!("error in line {}, bad size", i);
577 return;
578 }
579 emu.maps.save(addr, sz, args[3].to_string());
580 }
581 "mdda" => {
582 if args.len() != 2 {
584 log::info!("error in line {}, foler is needed", i);
585 return;
586 }
587 emu.maps.save_all_allocs(args[1].to_string());
588 }
589 "mt" => {
590 if emu.maps.mem_test() {
591 log::info!("mem tests passed ok.");
592 } else {
593 log::info!("memory errors.");
594 }
595 }
596 "eip" => {
597 if args.len() != 2 {
599 log::info!("error in line {}, address is missing", i);
600 return;
601 }
602
603 let addr = self.resolve(args[1], i, emu);
604
605 emu.set_eip(addr, false);
606 }
607 "rip" => {
608 if args.len() != 2 {
610 log::info!("error in line {}, address is missing", i);
611 return;
612 }
613
614 let addr = self.resolve(args[1], i, emu);
615
616 emu.set_rip(addr, false);
617 }
618 "push" => {
619 if args.len() != 2 {
621 log::info!("error in line {}, hex value is missing", i);
622 return;
623 }
624
625 let value = self.resolve(args[1], i, emu);
626
627 if emu.cfg.is_64bits {
628 emu.stack_push64(value);
629 } else {
630 emu.stack_push32((value & 0xffffffff) as u32);
631 }
632 }
633 "pop" => {
634 if args.len() != 1 {
636 log::info!("error in line {}, no args required.", i);
637 return;
638 }
639
640 if emu.cfg.is_64bits {
641 let value = emu.stack_pop64(false).expect("pop failed");
642 log::info!("poped value 0x{:x}", value);
643 self.result = value;
644 } else {
645 let value = emu.stack_pop32(false).expect("pop failed");
646 log::info!("poped value 0x{:x}", value);
647 self.result = value as u64;
648 }
649 }
650 "fpu" => emu.fpu.print(),
651 "md5" => {
652 if args.len() != 2 {
654 log::info!("error in line {}, no args required.", i);
655 return;
656 }
657
658 let mem = emu.maps.get_mem(&args[1]);
659 let md5 = mem.md5();
660 log::info!("md5sum: {:x}", md5);
661 }
662 "ss" => {
663 if args.len() < 2 {
665 log::info!("error in line {}, need map name and string", i);
666 return;
667 }
668
669 let kw = args
670 .iter()
671 .skip(2)
672 .map(|s| s.to_owned())
673 .collect::<Vec<_>>()
674 .join(" ");
675
676 let result = match emu.maps.search_string(&kw, &args[1]) {
677 Some(v) => v,
678 None => {
679 log::info!("string not found");
680 return;
681 }
682 };
683
684 for addr in result.iter() {
685 if emu.cfg.is_64bits {
686 log::info!("found 0x{:x} '{}'", *addr, emu.maps.read_string(*addr));
687 } else {
688 log::info!(
689 "found 0x{:x} '{}'",
690 *addr as u32,
691 emu.maps.read_string(*addr)
692 );
693 }
694 }
695 }
696 "sb" => {
697 if args.len() < 2 {
699 log::info!("error in line {}, need map name and spaced bytes", i);
700 return;
701 }
702
703 let bytes = args
704 .iter()
705 .skip(2)
706 .map(|s| s.to_owned())
707 .collect::<Vec<_>>()
708 .join(" ");
709
710 if emu.maps.search_spaced_bytes(&bytes, &args[1]).len() == 0 {
711 log::info!("bytes not found.");
712 }
713 }
714 "sba" => {
715 let bytes = args
718 .iter()
719 .skip(1)
720 .map(|s| s.to_owned())
721 .collect::<Vec<_>>()
722 .join(" ");
723
724 let results = emu.maps.search_spaced_bytes_in_all(&bytes);
725 for addr in results.iter() {
726 log::info!("found at 0x{:x}", addr);
727 self.result = *addr;
728 }
729 }
730 "ssa" => {
731 let s = args
734 .iter()
735 .skip(1)
736 .map(|s| s.to_owned())
737 .collect::<Vec<_>>()
738 .join(" ");
739
740 emu.maps.search_string_in_all(s);
741 }
742 "seh" => {
743 log::info!("0x{:x}", emu.seh);
744 }
745 "veh" => {
746 log::info!("0x{:x}", emu.veh);
747 }
748 "ll" => {
749 let addr = self.resolve(args[1], i, emu);
751 let mut ptr = addr;
752 loop {
753 log::info!("- 0x{:x}", ptr);
754 ptr = match emu.maps.read_dword(ptr) {
755 Some(v) => v.into(),
756 None => break,
757 };
758 if ptr == 0 || ptr == addr {
759 break;
760 }
761 }
762 }
763 "n" => {
764 emu.step();
765 }
766 "m" => {
767 emu.maps.print_maps();
768 }
769 "ms" => {
770 if args.len() != 2 {
772 log::info!("error in line {}, `ms` command needs a keyword", i);
773 return;
774 }
775 emu.maps.print_maps_keyword(&args[1]);
776 }
777 "d" => {
778 if args.len() != 3 {
780 log::info!("error in line {}, `d` command needs an address to disasemble and amount of bytes", i);
781 return;
782 }
783
784 let addr = self.resolve(args[1], i, emu);
785
786 let sz = match self.to_int(&args[2]) {
787 Some(v) => v,
788 None => {
789 log::info!("error in line {}, bad size", i);
790 return;
791 }
792 };
793
794 emu.disassemble(addr, sz as u32);
795 }
796 "ldr" => {
797 if emu.cfg.is_64bits {
799 peb64::show_linked_modules(emu);
800 } else {
801 peb32::show_linked_modules(emu);
802 }
803 }
804 "iat" => {
805 if args.len() != 2 {
807 log::info!("error in line {}, keyword expected", i);
808 return;
809 }
810
811 let addr: u64;
812 let lib: String;
813 let name: String;
814 if emu.cfg.is_64bits {
815 (addr, lib, name) = emu::winapi64::kernel32::search_api_name(emu, &args[1]);
816 } else {
817 (addr, lib, name) = emu::winapi32::kernel32::search_api_name(emu, &args[1]);
818 }
819
820 if addr == 0 {
821 log::info!("api not found on iat.");
822 } else {
823 log::info!("found: 0x{:x} {}!{}", addr, lib, name);
824 }
825 }
826 "iatx" => {
827 if args.len() != 2 {
830 log::info!("error in line {}, api expected", i);
831 return;
832 }
833
834 let addr: u64;
835 let lib: String;
836 let name: String;
837 if emu.cfg.is_64bits {
838 (addr, lib, name) = emu::winapi64::kernel32::search_api_name(emu, &args[1]);
839 } else {
840 (addr, lib, name) = emu::winapi32::kernel32::search_api_name(emu, &args[1]);
841 }
842
843 if addr == 0 {
844 log::info!("api not found on iat.");
845 } else {
846 log::info!("found: 0x{:x} {}!{}", addr, lib, name);
847 }
848 }
849 "iatd" => {
850 if args.len() != 2 {
852 log::info!("error in line {}, module expected", i);
853 return;
854 }
855 if emu.cfg.is_64bits {
856 emu::winapi64::kernel32::dump_module_iat(emu, &args[1]);
857 } else {
858 emu::winapi32::kernel32::dump_module_iat(emu, &args[1]);
859 }
860 }
861 "dt" => {
862 if args.len() != 3 {
864 log::info!("error in line {}, structure and address expected", i);
865 return;
866 }
867
868 let addr = self.resolve(args[2], i, emu);
869
870 match args[1] {
871 "peb" => {
872 let s = structures::PEB::load(addr, &emu.maps);
873 s.print();
874 }
875 "teb" => {
876 let s = structures::TEB::load(addr, &emu.maps);
877 s.print();
878 }
879 "peb_ldr_data" => {
880 let s = structures::PebLdrData::load(addr, &emu.maps);
881 s.print();
882 }
883 "ldr_data_table_entry" => {
884 let s = structures::LdrDataTableEntry::load(addr, &emu.maps);
885 s.print();
886 }
887 "list_entry" => {
888 let s = structures::ListEntry::load(addr, &emu.maps);
889 s.print();
890 }
891 "cppeh_record" => {
892 let s = structures::CppEhRecord::load(addr, &emu.maps);
893 s.print();
894 }
895 "exception_pointers" => {
896 let s = structures::ExceptionPointers::load(addr, &emu.maps);
897 s.print();
898 }
899 "eh3_exception_registgration" => {
900 let s = structures::Eh3ExceptionRegistration::load(addr, &emu.maps);
901 s.print();
902 }
903 "memory_basic_information" => {
904 let s = structures::MemoryBasicInformation::load(addr, &emu.maps);
905 s.print();
906 }
907 "peb64" => {
908 let s = structures::PEB64::load(addr, &emu.maps);
909 s.print();
910 }
911 "teb64" => {
912 let s = structures::TEB64::load(addr, &emu.maps);
913 s.print();
914 }
915 "ldrdatatableentry64" => {
916 let s = structures::LdrDataTableEntry64::load(addr, &emu.maps);
917 s.print();
918 }
919 "image_export_directory" => {
920 let s = structures::ImageExportDirectory::load(addr, &emu.maps);
921 s.print();
922 }
923
924 _ => log::info!("unrecognized structure."),
925 }
926 }
927 "if" => {
928 if args.len() != 4 {
932 log::info!("error in line {}, incomplete `if`", i);
933 return;
934 }
935
936 let a: u64 = self.resolve(args[1], i, emu);
937 let b: u64 = self.resolve(args[3], i, emu);
938
939 if args[2] == "==" {
940 if a != b {
941 self.skip = true;
942 }
943 } else if args[2] == "!=" {
944 if a == b {
945 self.skip = true;
946 }
947 } else if args[2] == ">" {
948 if a <= b {
949 self.skip = true;
950 }
951 } else if args[2] == "<" {
952 if a >= b {
953 self.skip = true;
954 }
955 } else if args[2] == ">=" {
956 if a < b {
957 self.skip = true;
958 }
959 } else if args[2] == "<=" {
960 if a > b {
961 self.skip = true;
962 }
963 } else {
964 log::info!("error in line {}, if with worng operator", i);
965 return;
966 }
967 }
968 "console" => {
969 emu.spawn_console();
970 }
971 "call" => {
972 if args.len() < 2 {
974 panic!("error in line {}, call with no address", i);
975 }
976
977 let addr = self.resolve(args[1], i, emu);
978
979 for j in (2..args.len()).rev() {
981 let v = self.resolve(args[j], i, emu);
982 if emu.cfg.is_64bits {
983 emu.stack_push64(v);
984 } else {
985 emu.stack_push32(v as u32);
986 }
987 }
988
989 let retaddr: u64;
991 if emu.cfg.is_64bits {
992 retaddr = emu.regs.rip;
993 emu.stack_push64(emu.regs.rip);
994 } else {
995 retaddr = emu.regs.get_eip();
996 emu.stack_push32(emu.regs.get_eip() as u32);
997 }
998
999 if emu.cfg.is_64bits {
1000 emu.set_rip(addr, false);
1001 } else {
1002 emu.set_eip(addr, false);
1003 }
1004
1005 emu.is_running
1006 .store(1, std::sync::atomic::Ordering::Relaxed);
1007 emu.run(Some(retaddr));
1008 }
1009 "set" => {
1010 if args.len() < 2 {
1012 panic!("error in line {}, call with no value", i);
1013 }
1014
1015 let value = self.resolve(args[1], i, emu);
1016
1017 self.result = value;
1018 }
1019 "loop" => {
1020 self.looped = i as u64;
1021 }
1022 "endloop" => {
1023 if self.result <= 1 {
1024 self.looped = 0;
1025 continue;
1026 }
1027
1028 self.result -= 1;
1029 i = self.looped as usize;
1030 continue;
1031 }
1032 "trace" => {
1033 self.trace = true;
1034 }
1035
1036 _ => panic!("error in line {}, unknown command", i),
1037 }
1038 }
1039 }
1040}