1mod command;
2mod error;
3mod predicates;
4mod script_result;
5mod stream_message;
6mod token;
7mod value;
8mod variables;
9
10use std::collections::HashMap;
11
12pub(crate) use command::CommandError;
13use command::{Command, CommandElem};
14pub(crate) use stream_message::StreamMessage;
15use value::{RuntimeObject, ScriptBlock, ValResult};
16use variables::Scope;
17type ParserResult<T> = core::result::Result<T, ParserError>;
18use error::ParserError;
19type PestError = pest::error::Error<Rule>;
20use pest::Parser;
21use pest_derive::Parser;
22use predicates::{ArithmeticPred, BitwisePred, LogicalPred, StringPred};
23pub use script_result::{PsValue, ScriptResult};
24pub use token::{Token, Tokens};
25pub(crate) use value::{Val, ValType};
26pub use variables::Variables;
27use variables::{VarName, VariableError};
28
29use crate::parser::command::CommandOutput;
30
31type Pair<'i> = ::pest::iterators::Pair<'i, Rule>;
32type Pairs<'i> = ::pest::iterators::Pairs<'i, Rule>;
33
34pub(crate) const NEWLINE: &str = "\n";
35
36macro_rules! check_rule {
37 ($pair:expr, $rule:pat) => {
38 if !matches!($pair.as_rule(), $rule) {
39 panic!("rule: {:?}", $pair.as_rule());
40 }
41 };
42}
43
44#[derive(Parser)]
45#[grammar = "powershell.pest"]
46pub struct PowerShellSession {
47 variables: Variables,
48 tokens: Tokens,
49 errors: Vec<ParserError>,
50 output: Vec<StreamMessage>,
51 deobfuscated_statements: Vec<String>,
52}
53
54impl Default for PowerShellSession {
55 fn default() -> Self {
56 Self::new()
57 }
58}
59
60impl<'a> PowerShellSession {
61 pub fn new() -> Self {
81 Self {
82 variables: Variables::new(),
83 tokens: Tokens::new(),
84 errors: Vec::new(),
85 output: Vec::new(),
86 deobfuscated_statements: Vec::new(),
87 }
88 }
89
90 pub fn with_variables(mut self, variables: Variables) -> Self {
115 self.variables = variables;
116 self
117 }
118
119 pub fn safe_eval(&mut self, script: &str) -> Result<String, ParserError> {
151 Ok(self.parse_input(script)?.result().to_string())
152 }
153
154 pub fn parse_input(&mut self, input: &str) -> Result<ScriptResult, ParserError> {
186 let mut pairs = PowerShellSession::parse(Rule::program, input)?;
187 let program_token = pairs.next().expect("");
188
189 let mut script_last_output = Val::default();
191
192 if let Rule::program = program_token.as_rule() {
193 let pairs = program_token.into_inner();
194
195 for token in pairs {
198 let token_str = token.as_str();
199 let result = match token.as_rule() {
200 Rule::pipeline => {
201 let mut pairs = token.into_inner();
204 let token = pairs.next().unwrap();
205
206 match token.as_rule() {
207 Rule::assignment_exp => {
208 let result = self.eval_assigment_exp(token);
209 result.map(|_| Val::Null)
212 }
213 Rule::pipeline_with_tail => self.eval_pipeline_with_tail(token),
214 _ => panic!("not possible: {:?}", token.as_rule()),
215 }
216 }
217 Rule::statement_terminator => continue,
218 Rule::EOI => break,
219 _ => {
220 log::error!("parse_input not implemented: {:?}", token.as_rule());
221 Err(ParserError::NotImplemented(format!(
222 "Not implemented: {:?}",
223 token.as_rule()
224 )))
225 }
226 };
227
228 self.variables.set_status(result.is_ok());
229
230 script_last_output = match result {
231 Ok(val) => {
232 if val != Val::Null {
233 self.output.push(val.display().into());
234 }
235
236 val
237 }
238 Err(e) => {
239 self.errors.push(e);
240 self.deobfuscated_statements.push(token_str.into());
241 Val::Null
242 }
243 };
244 }
245 }
246
247 Ok(ScriptResult::new(
248 script_last_output,
249 std::mem::take(&mut self.output),
250 std::mem::take(&mut self.deobfuscated_statements),
251 std::mem::take(&mut self.tokens),
252 std::mem::take(&mut self.errors),
253 ))
254 }
255
256 pub(crate) fn eval_script_block(
257 &mut self,
258 input: &ScriptBlock,
259 ps_item: &Val,
260 ) -> ParserResult<bool> {
261 self.variables.set_ps_item(ps_item.clone());
262 let mut new_session = PowerShellSession::new().with_variables(self.variables.clone());
263 let res = new_session
264 .parse_input(input.0.as_str())?
265 .result()
266 .is_true();
267 self.variables.reset_ps_item();
268 Ok(res)
269 }
270
271 fn eval_statement(&mut self, token: Pair<'a>) -> ParserResult<Val> {
272 match token.as_rule() {
273 Rule::pipeline => self.eval_pipeline(token),
274 _ => Err(ParserError::NotImplemented(format!(
275 "Not implemented: {:?}",
276 token.as_rule()
277 )))?,
278 }
279 }
280
281 fn safe_eval_sub_expr(&mut self, token: Pair<'a>) -> ParserResult<Val> {
282 match self.eval_statements(token.clone()) {
283 Ok(vals) => Ok(Val::Array(vals)),
284 Err(err) => {
285 self.errors.push(err);
286 Ok(Val::ScriptText(token.as_str().to_string()))
287 }
288 }
289 }
290
291 fn eval_statements(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
292 let pairs = token.into_inner();
294 let mut statements = vec![];
295
296 for token in pairs {
297 let s = self.eval_statement(token)?;
298 statements.push(s);
299 }
300 Ok(statements)
301 }
302
303 fn parse_dq(&mut self, token: Pair<'a>) -> ParserResult<String> {
304 let mut res_str = String::new();
305 let pairs = token.into_inner();
306 for token in pairs {
307 let token = token.into_inner().next().unwrap();
308 let s = match token.as_rule() {
309 Rule::variable => self.get_variable(token)?.cast_to_string(),
310 Rule::sub_expression => self.safe_eval_sub_expr(token)?.cast_to_string(),
311 Rule::backtick_escape => token
312 .as_str()
313 .strip_prefix("`")
314 .unwrap_or_default()
315 .to_string(),
316 _ => token.as_str().to_string(),
317 };
318 res_str.push_str(s.as_str());
319 }
320 Ok(res_str)
321 }
322
323 fn eval_string_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
324 check_rule!(token, Rule::string_literal);
325 let mut pair = token.into_inner();
326 let token = pair.next().unwrap();
327 let cloned_token = token.clone();
328
329 let mut is_expandable = false;
330 let res = match token.as_rule() {
331 Rule::doublequoted_string_literal | Rule::doublequoted_multiline_string_literal => {
332 is_expandable = true;
333 self.parse_dq(token)?
334 }
335 Rule::singlequoted_string_literal => {
336 if let Some(stripped_prefix) = token.as_str().to_string().strip_prefix("'") {
337 if let Some(stripped_suffix) = stripped_prefix.to_string().strip_suffix("'") {
338 stripped_suffix.to_string()
339 } else {
340 panic!("no suffix")
341 }
342 } else {
343 panic!("no prefix")
344 }
345 }
346 Rule::singlequoted_multiline_string_literal => {
347 let mut res_str = String::new();
348 let pairs = token.into_inner();
349 for token in pairs {
350 res_str.push_str(token.as_str());
351 }
352 res_str
353 }
354 _ => {
355 panic!("eval_string_literal - token.rule(): {:?}", token.as_rule());
356 }
357 };
358 let ps_token = if is_expandable {
359 Token::StringExpandable(cloned_token.as_str().to_string(), res.clone())
360 } else {
361 Token::String(cloned_token.as_str().to_string())
362 };
363 self.tokens.push(ps_token);
364
365 Ok(Val::String(res.into()))
366 }
367
368 fn get_variable(&mut self, token: Pair<'a>) -> ParserResult<Val> {
369 check_rule!(token, Rule::variable);
370 let var_name = Self::parse_variable(token)?;
371 let Some(var) = self.variables.get(&var_name) else {
372 return Err(ParserError::VariableError(VariableError::NotDefined(
373 var_name.name,
374 )));
375 };
376 Ok(var)
377 }
378
379 fn parse_variable(token: Pair<'a>) -> ParserResult<VarName> {
380 check_rule!(token, Rule::variable);
381 let mut pair = token.into_inner();
382 let token = pair.next().unwrap();
383
384 Ok(match token.as_rule() {
385 Rule::special_variable => VarName::new(Scope::Special, token.as_str().to_string()),
386 Rule::parenthesized_variable => {
387 Self::parse_variable(token.into_inner().next().unwrap())?
388 }
389 Rule::braced_variable => {
390 let token = token.into_inner().next().unwrap();
391 let var = token.as_str().to_ascii_lowercase();
392 let splits: Vec<&str> = var.split(":").collect();
393 if splits.len() == 2 {
394 VarName::new(Scope::from(splits[0]), splits[1].to_string())
395 } else {
396 VarName::new(Scope::Global, var)
397 }
398 }
399 Rule::scoped_variable => {
400 let mut pairs = token.into_inner();
401 let mut token = pairs.next().unwrap();
402
403 let scope = if token.as_rule() == Rule::scope_keyword {
404 let scope = token.as_str().to_ascii_lowercase();
405 token = pairs.next().unwrap();
406 check_rule!(token, Rule::var_name);
407 Scope::from(scope.as_str())
408 } else {
409 Scope::Global
410 };
411 VarName::new(scope, token.as_str().to_ascii_lowercase())
412 }
413 _ => {
414 panic!("token.rule(): {:?}", token.as_rule());
415 }
416 })
417 }
418
419 fn eval_expression_with_unary_operator(&mut self, token: Pair<'a>) -> ParserResult<Val> {
420 check_rule!(token, Rule::expression_with_unary_operator);
421 let mut pair = token.into_inner();
422 let token = pair.next().unwrap();
423
424 let res = match token.as_rule() {
425 Rule::pre_inc_expression => {
426 let variable_token = token.into_inner().next().unwrap();
427 let var_name = Self::parse_variable(variable_token)?;
428 let mut var = self.variables.get(&var_name).unwrap_or_default();
429 var.inc()?;
430
431 self.variables.set(&var_name, var.clone())?;
432 var
433 }
434 Rule::pre_dec_expression => {
435 let variable_token = token.into_inner().next().unwrap();
436 let var_name = Self::parse_variable(variable_token)?;
437 let mut var = self.variables.get(&var_name).unwrap_or_default();
438 var.dec()?;
439
440 self.variables.set(&var_name, var.clone())?;
441 var
442 }
443 Rule::cast_expression => self.eval_cast_expression(token)?,
444 Rule::negate_op => {
445 let unary_token = pair.next().unwrap();
446 let unary = self.eval_unary_exp(unary_token)?;
447 Val::Bool(!unary.cast_to_bool())
448 }
449 Rule::bitwise_negate_op => {
450 let unary_token = pair.next().unwrap();
451 let unary = self.eval_unary_exp(unary_token)?;
452 Val::Int(!unary.cast_to_int()?)
453 }
454 _ => {
455 panic!("token.rule(): {:?}", token.as_rule());
456 }
457 };
458
459 Ok(res)
460 }
461
462 fn eval_argument_list(&mut self, token: Pair<'a>) -> ParserResult<Vec<Val>> {
463 check_rule!(token, Rule::argument_list);
464 let pairs = token.into_inner();
465
466 let mut args = Vec::new();
467 for token in pairs {
468 args.push(self.eval_expression(token)?);
469 }
470
471 Ok(args)
472 }
473
474 fn eval_member_access(&mut self, token: Pair<'a>) -> ParserResult<String> {
475 let member_name_token = token.into_inner().next().unwrap();
477 let member_name = member_name_token.as_str().to_ascii_lowercase();
478
479 Ok(member_name)
480 }
481
482 fn method_is_static(&mut self, token: Pair<'a>) -> bool {
483 check_rule!(token, Rule::method_invocation);
484 let mut pairs = token.into_inner();
485
486 let access = pairs.next().unwrap();
487 match access.as_rule() {
488 Rule::member_access => false,
489 Rule::static_access => true,
490 _ => todo!(),
491 }
492 }
493
494 fn eval_method_invokation(&mut self, token: Pair<'a>) -> ParserResult<(String, Vec<Val>)> {
495 check_rule!(token, Rule::method_invocation);
496 let token_string = token.as_str().to_string();
497
498 let mut pairs = token.into_inner();
499
500 let access = pairs.next().unwrap();
501 let method_name = self.eval_member_access(access)?;
503
504 let args = if let Some(token) = pairs.next() {
505 check_rule!(token, Rule::argument_list);
506 self.eval_argument_list(token)?
507 } else {
508 Vec::new()
509 };
510
511 self.tokens.push(Token::Function(
512 token_string,
513 method_name.clone(),
514 args.clone().iter().map(|arg| arg.clone().into()).collect(),
515 ));
516 Ok((method_name, args))
517 }
518
519 fn eval_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
520 fn get_member_name(token: Pair<'_>) -> &'_ str {
521 token.into_inner().next().unwrap().as_str()
522 }
523 check_rule!(token, Rule::access);
524 let mut pairs = token.into_inner();
525 let token = pairs.next().unwrap();
526
527 let mut object = self.eval_value(token)?;
528
529 for token in pairs {
530 match token.as_rule() {
531 Rule::static_access => {
532 object = object.get_static_member(get_member_name(token))?;
533 }
534 Rule::member_access => {
535 object = object.get_member(get_member_name(token))?;
536 }
537 Rule::method_invocation => {
538 let static_method = self.method_is_static(token.clone());
539 let (function_name, args) = self.eval_method_invokation(token)?;
540 log::trace!("Method: {:?} {:?}", &function_name, &args);
541 object = if static_method {
542 let call = object.get_static_fn(function_name.as_str())?;
543 call(args)?
544 } else {
545 let call = object.get_method(function_name.as_str())?;
546 call(object, args)?
547 };
548 }
549 Rule::element_access => {
550 let mut pairs = token.into_inner();
551 let index_token = pairs.next().unwrap();
552 check_rule!(index_token, Rule::expression);
553 let index = self.eval_expression(index_token)?;
554 object = object.get_index(index)?;
555 }
556 _ => {
557 panic!("token.rule(): {:?}", token.as_rule());
558 }
559 }
560 }
561 log::debug!("Success eval_access: {:?}", object);
562 Ok(object)
563 }
564
565 fn parse_access(&mut self, token: Pair<'a>) -> ParserResult<Val> {
566 check_rule!(token, Rule::access);
567 let mut pairs = token.into_inner();
568 let token = pairs.next().unwrap();
569
570 let mut object = token.as_str().to_string();
571
572 for token in pairs {
573 match token.as_rule() {
574 Rule::static_access => {
575 object.push_str("::");
576 object.push_str(token.as_str());
577 }
578 Rule::member_access => {
579 object.push_str(token.as_str());
581 }
582 Rule::method_invocation => {
583 let static_method = self.method_is_static(token.clone());
584 let (method_name, args) = self.eval_method_invokation(token)?;
585
586 let separator = if static_method { "::" } else { "." };
587 object = format!(
588 "{}{separator}{}({:?})",
589 object,
590 method_name.to_ascii_lowercase(),
591 args
592 )
593 }
594 Rule::element_access => {
595 let mut pairs = token.into_inner();
596 let index_token = pairs.next().unwrap();
597 check_rule!(index_token, Rule::expression);
598 let index = self.eval_expression(index_token)?;
599 object = format!("{}[{}]", object, index);
600 }
601 _ => {
602 panic!("parse_access token.rule(): {:?}", token.as_rule());
603 }
604 }
605 }
606 Ok(Val::String(object.into()))
607 }
608
609 fn eval_primary_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
610 check_rule!(token, Rule::primary_expression);
611 let mut pair = token.into_inner();
612 let token = pair.next().unwrap();
613 let res = match token.as_rule() {
614 Rule::access => match self.eval_access(token.clone()) {
615 Ok(res) => res,
616 Err(err) => {
617 log::info!("eval_access error: {:?}", err);
618 self.errors.push(err);
619 self.parse_access(token)?
620 }
621 },
622 Rule::value => self.eval_value(token)?,
623 Rule::post_inc_expression => {
624 let variable_token = token.into_inner().next().unwrap();
625 let var_name = Self::parse_variable(variable_token)?;
626 let mut var = self.variables.get(&var_name).unwrap_or_default();
627 let var_to_return = var.clone();
628
629 var.inc()?;
630 self.variables.set(&var_name, var.clone())?;
631
632 var_to_return
634 }
635 Rule::post_dec_expression => {
636 let variable_token = token.into_inner().next().unwrap();
637 let var_name = Self::parse_variable(variable_token)?;
638 let mut var = self.variables.get(&var_name).unwrap_or_default();
639 let var_to_return = var.clone();
640
641 var.dec()?;
642 self.variables.set(&var_name, var.clone())?;
643
644 var_to_return
645 }
646 _ => {
647 panic!(
648 "eval_primary_expression: rule: {:?} str: {}",
649 token.as_rule(),
650 token.as_str()
651 );
652 }
653 };
654
655 Ok(res)
656 }
657
658 fn eval_type_literal(&mut self, token: Pair<'a>) -> ParserResult<ValType> {
659 check_rule!(token, Rule::type_literal);
660
661 let token = token.into_inner().next().unwrap();
662 check_rule!(token, Rule::type_spec);
663 Ok(ValType::cast(token.as_str())?)
664 }
665
666 fn parse_script_block_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
667 check_rule!(token, Rule::script_block_expression);
668
669 let mut pairs = token.into_inner();
670 let token = pairs.next().unwrap();
671
672 Ok(Val::ScriptBlock(ScriptBlock(token.as_str().to_string())))
673 }
674
675 fn eval_hash_key(&mut self, token: Pair<'a>) -> ParserResult<String> {
676 check_rule!(token, Rule::key_expression);
677 let mut pairs = token.into_inner();
678 let key_token = pairs.next().unwrap();
679
680 Ok(match key_token.as_rule() {
681 Rule::simple_name => key_token.as_str().to_ascii_lowercase(),
682 Rule::unary_exp => self
683 .eval_unary_exp(key_token)?
684 .cast_to_string()
685 .to_ascii_lowercase(),
686 _ => {
687 panic!("key_token.rule(): {:?}", key_token.as_rule());
688 }
689 })
690 }
691
692 fn eval_hash_entry(&mut self, token: Pair<'a>) -> ParserResult<(String, Val)> {
693 check_rule!(token, Rule::hash_entry);
694
695 let mut pairs = token.into_inner();
696 let token_key = pairs.next().unwrap();
697 let token_value = pairs.next().unwrap();
698
699 Ok((
700 self.eval_hash_key(token_key)?,
701 self.eval_statement(token_value)?,
702 ))
703 }
704
705 fn eval_hash_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
706 check_rule!(token, Rule::hash_literal_expression);
707 let pairs = token.into_inner();
708 let mut hash = HashMap::new();
709 for token in pairs {
710 let (key, value) = self.eval_hash_entry(token)?;
711 hash.insert(key, value);
712 }
713 Ok(Val::HashTable(hash))
714 }
715
716 fn eval_value(&mut self, token: Pair<'a>) -> ParserResult<Val> {
717 check_rule!(token, Rule::value);
718 let mut pair = token.into_inner();
719 let token = pair.next().unwrap();
720
721 let res = match token.as_rule() {
722 Rule::parenthesized_expression => {
723 let token = token.into_inner().next().unwrap();
724 self.safe_eval_pipeline(token)?
725 }
726 Rule::sub_expression | Rule::array_expression => {
727 let statements = self.eval_statements(token)?;
728 if statements.len() == 1 && statements[0].ttype() == ValType::Array {
729 statements[0].clone()
730 } else {
731 Val::Array(statements)
732 }
733 }
734 Rule::script_block_expression => self.parse_script_block_expression(token)?,
735 Rule::hash_literal_expression => self.eval_hash_literal(token)?,
736 Rule::string_literal => self.eval_string_literal(token)?,
737 Rule::number_literal => self.eval_number_literal(token)?,
738 Rule::type_literal => Val::init(self.eval_type_literal(token)?)?,
739 Rule::variable => self.get_variable(token)?,
740 _ => {
741 panic!("token.rule(): {:?}", token.as_rule());
742 }
743 };
744 log::debug!("eval_value - res: {:?}", res);
745 Ok(res)
746 }
747
748 fn eval_number_literal(&mut self, token: Pair<'a>) -> ParserResult<Val> {
749 check_rule!(token, Rule::number_literal);
750 let mut negate = false;
751 let mut pairs = token.into_inner();
752 let mut token = pairs.next().unwrap();
753
754 if token.as_rule() == Rule::minus {
756 negate = true;
757 token = pairs.next().unwrap();
758 } else if token.as_rule() == Rule::plus {
759 token = pairs.next().unwrap();
760 }
761
762 let mut val = self.eval_number(token)?;
763
764 if negate {
765 val.neg()?;
766 }
767
768 if let Some(unit) = pairs.next() {
769 let unit = unit.as_str().to_ascii_lowercase();
770 let unit_int = match unit.as_str() {
771 "k" => 1024,
772 "m" => 1024 * 1024,
773 "g" => 1024 * 1024 * 1024,
774 "t" => 1024 * 1024 * 1024 * 1024,
775 "p" => 1024 * 1024 * 1024 * 1024 * 1024,
776 _ => 1,
777 };
778 val.mul(Val::Int(unit_int))?;
779 }
780 Ok(val)
781 }
782
783 fn eval_number(&mut self, token: Pair<'a>) -> ParserResult<Val> {
784 check_rule!(token, Rule::number);
785 let mut pairs = token.into_inner();
786 let token = pairs.next().unwrap();
787 let v = match token.as_rule() {
788 Rule::decimal_integer => {
789 let int_val = token.into_inner().next().unwrap();
790 Val::Int(int_val.as_str().parse::<i64>().unwrap())
791 }
792 Rule::hex_integer => {
793 let int_val = token.into_inner().next().unwrap();
794 Val::Int(i64::from_str_radix(int_val.as_str(), 16).unwrap())
795 }
796 Rule::float => {
798 let float_str = token.as_str().trim();
799
800 match float_str.parse::<f64>() {
801 Ok(float_val) => Val::Float(float_val),
802 Err(err) => {
803 println!("eval_number - invalid float: {}: asd {}", float_str, err);
804 panic!("eval_number - invalid float: {}: {}", float_str, err);
805 }
806 }
807 }
808 _ => {
809 panic!("eval_number - token.rule(): {:?}", token.as_rule());
810 }
811 };
812 Ok(v)
813 }
814
815 fn eval_unary_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
816 check_rule!(token, Rule::unary_exp);
817 let token = token.into_inner().next().unwrap();
818 match token.as_rule() {
819 Rule::expression_with_unary_operator => self.eval_expression_with_unary_operator(token),
820 Rule::primary_expression => self.eval_primary_expression(token),
821 _ => {
822 panic!("eval_unary_exp token.rule(): {:?}", token.as_rule());
823 }
824 }
825 }
826
827 fn eval_array_literal_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
828 check_rule!(token, Rule::array_literal_exp);
829 let mut arr = Vec::new();
830 let mut pairs = token.into_inner();
831 arr.push(self.eval_unary_exp(pairs.next().unwrap())?);
832 for token in pairs {
833 arr.push(self.eval_unary_exp(token)?);
834 }
835
836 Ok(if arr.len() == 1 {
837 arr[0].clone()
838 } else {
839 Val::Array(arr)
840 })
841 }
842
843 fn eval_range_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
844 fn range(left: i64, right: i64) -> Vec<Val> {
845 if left < right {
846 (left..=right).collect::<Vec<i64>>()
847 } else {
848 let mut v = (right..=left).collect::<Vec<i64>>();
849 v.reverse();
850 v
851 }
852 .into_iter()
853 .map(Val::Int)
854 .collect::<Vec<Val>>()
855 }
856 check_rule!(token, Rule::range_exp);
857 let mut pairs = token.into_inner();
858 let token = pairs.next().unwrap();
859 let res = match token.as_rule() {
860 Rule::decimal_integer => {
861 let int_val = token.into_inner().next().unwrap();
862 let left = int_val.as_str().parse::<i64>().unwrap();
863 let token = pairs.next().unwrap();
864 let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
865 Val::Array(range(left, right))
866 }
867 Rule::array_literal_exp => {
868 let res = self.eval_array_literal_exp(token)?;
869 if let Some(token) = pairs.next() {
870 let left = res.cast_to_int()?;
871 let right = self.eval_array_literal_exp(token)?.cast_to_int()?;
872 Val::Array(range(left, right))
873 } else {
874 res
875 }
876 }
877 _ => {
878 panic!("eval_range_exp not implemented: {:?}", token.as_rule());
879 }
880 };
881
882 Ok(res)
883 }
884
885 fn eval_format_impl(&mut self, format: Val, mut pairs: Pairs<'a>) -> ParserResult<Val> {
886 fn format_with_vec(fmt: &str, args: Vec<Val>) -> ParserResult<String> {
887 fn strange_special_case(fmt: &str, n: i64) -> String {
888 fn split_digits(n: i64) -> Vec<u8> {
889 n.abs() .to_string()
891 .chars()
892 .filter_map(|c| c.to_digit(10).map(|opt| opt as u8))
893 .collect()
894 }
895
896 let mut digits = split_digits(n);
898 digits.reverse();
899 let mut fmt_vec = fmt.as_bytes().to_vec();
900 fmt_vec.reverse();
901
902 let mut i = 0;
903 for digit in digits {
904 while i < fmt_vec.len() {
905 if fmt_vec[i] != b'0' {
906 i += 1
907 } else {
908 fmt_vec[i] = digit + b'0';
909 break;
910 }
911 }
912 }
913 fmt_vec.reverse();
914 String::from_utf8(fmt_vec).unwrap_or_default()
915 }
916
917 let mut output = String::new();
918 let mut i = 0;
919
920 while i < fmt.len() {
921 if fmt[i..].starts_with('{') {
922 if let Some(end) = fmt[i..].find('}') {
923 let token = &fmt[i + 1..i + end];
924 let formatted = if token.contains(':') {
925 let mut parts = token.split(':');
926 let index: usize = if let Some(p) = parts.next() {
927 p.parse().unwrap_or(0)
928 } else {
929 0
930 };
931
932 let spec = parts.next();
933 match args.get(index) {
934 Some(val) => match spec {
935 Some(s) if s.starts_with('N') => {
936 let precision = s[1..].parse::<usize>().unwrap_or(2);
937 if let Ok(f) = val.cast_to_float() {
938 format!("{:.1$}", f, precision)
939 } else {
940 val.cast_to_string().to_string()
941 }
942 }
943 Some(s) => strange_special_case(s, val.cast_to_int()?),
944 None => val.cast_to_string().to_string(),
945 },
946 None => format!("{{{}}}", token), }
949 } else if token.contains(',') {
950 let mut parts = token.split(',');
951 let index: usize = parts.next().unwrap().parse().unwrap_or(0);
952 let spec = parts.next();
953 match args.get(index) {
954 Some(val) => match spec {
955 Some(s) => {
956 let spaces = s.parse::<usize>().unwrap_or(0);
957 let spaces_str = " ".repeat(spaces);
958 format!("{spaces_str}{}", val.cast_to_string())
959 }
960 _ => val.cast_to_string().to_string(),
961 },
962 None => format!("{{{}}}", token), }
965 } else {
966 let index: usize =
967 Val::String(token.to_string().into()).cast_to_int()? as usize;
968 match args.get(index) {
969 Some(val) => val.cast_to_string().to_string(),
970 None => format!("{{{}}}", token), }
973 };
974
975 output.push_str(&formatted);
976 i += end + 1;
977 } else {
978 output.push('{');
979 i += 1;
980 }
981 } else {
982 output.push(fmt[i..].chars().next().unwrap());
983 i += 1;
984 }
985 }
986
987 Ok(output)
988 }
989
990 Ok(if let Some(token) = pairs.next() {
991 let first_fmt = format.cast_to_string();
992
993 let second_fmt = self.eval_range_exp(token)?;
994 let res = self.eval_format_impl(second_fmt, pairs)?;
995 Val::String(format_with_vec(first_fmt.as_str(), res.cast_to_array())?.into())
996 } else {
997 format
998 })
999 }
1000
1001 fn eval_format_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1002 check_rule!(token, Rule::format_exp);
1003 let mut pairs = token.into_inner();
1004 let format = self.eval_range_exp(pairs.next().unwrap())?;
1005 self.eval_format_impl(format, pairs)
1006 }
1007
1008 fn eval_mult(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1009 check_rule!(token, Rule::multiplicative_exp);
1010 let mut pairs = token.into_inner();
1011 let mut res = self.eval_format_exp(pairs.next().unwrap())?;
1012 while let Some(op) = pairs.next() {
1013 let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1014 panic!(
1015 "can't find arithmetic function for operator: {}",
1016 op.as_str()
1017 )
1018 };
1019
1020 let postfix = pairs.next().unwrap();
1021 let right_op = self.eval_format_exp(postfix)?;
1022 res = fun(res, right_op)?;
1023 }
1024
1025 Ok(res)
1026 }
1027
1028 fn eval_additive(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1029 check_rule!(token, Rule::additive_exp);
1030
1031 let mut pairs = token.into_inner();
1032 let mut res = self.eval_mult(pairs.next().unwrap())?;
1033 while let Some(op) = pairs.next() {
1034 let Some(fun) = ArithmeticPred::get(op.as_str()) else {
1036 panic!()
1037 };
1038
1039 let mult = pairs.next().unwrap();
1040 let right_op = self.eval_mult(mult)?;
1041 res = fun(res, right_op)?;
1042 }
1043
1044 Ok(res)
1045 }
1046
1047 fn eval_split_special_case(
1048 &mut self,
1049 token: Pair<'a>,
1050 input: Val,
1051 ) -> ParserResult<Vec<String>> {
1052 let mut res_vec = vec![];
1053 let mut parts = String::new();
1054 let input_str = input.cast_to_string();
1055 let characters = input_str.chars();
1056
1057 for ch in characters {
1059 self.variables
1060 .set_ps_item(Val::String(ch.to_string().into()));
1061
1062 let b = match self.eval_script_block(
1063 &ScriptBlock(token.as_str().to_string()),
1064 &Val::String(ch.to_string().into()),
1065 ) {
1066 Err(er) => {
1067 self.errors.push(er);
1068 false
1069 }
1070 Ok(b) => b,
1071 };
1072
1073 if b {
1074 res_vec.push(parts);
1075 parts = String::new();
1076 } else {
1077 parts.push(ch);
1078 }
1079 }
1080 self.variables.reset_ps_item();
1081 Ok(res_vec)
1082 }
1083 fn eval_comparison_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1084 check_rule!(token, Rule::comparison_exp);
1085 let mut pairs = token.into_inner();
1086 let token = pairs.next().unwrap();
1087
1088 let mut res = if token.as_rule() == Rule::additive_exp {
1091 self.eval_additive(token)?
1092 } else {
1093 Val::Null
1094 };
1095
1096 while let Some(op) = pairs.next() {
1097 let Some(fun) = StringPred::get(op.as_str()) else {
1098 panic!("no operator: {}", op.as_str())
1099 };
1100
1101 let token = pairs.next().unwrap();
1102 let right_op = match token.as_rule() {
1103 Rule::script_block_expression => {
1104 let mut pairs = token.into_inner();
1105 let token = pairs.next().unwrap();
1106 check_rule!(token, Rule::script_block_inner);
1107
1108 let mut pairs = token.into_inner();
1109 let mut token = pairs.next().unwrap();
1110 if token.as_rule() == Rule::param_block {
1111 token = pairs.next().unwrap();
1113 }
1114 check_rule!(token, Rule::script_block);
1115 return Ok(Val::Array(
1116 self.eval_split_special_case(token, res)?
1117 .into_iter()
1118 .map(|s| Val::String(s.into()))
1119 .collect::<Vec<_>>(),
1120 ));
1121 }
1122 Rule::additive_exp => self.eval_additive(token)?,
1123 _ => {
1124 panic!("eval_comparison_exp not implemented: {:?}", token.as_rule());
1125 }
1126 };
1127 log::trace!("res: {:?}, right_op: {:?}", &res, &right_op);
1128 res = fun(res, right_op)?;
1129 log::trace!("res: {:?}", &res);
1130 }
1131
1132 Ok(res)
1133 }
1134
1135 fn eval_bitwise_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1136 check_rule!(token, Rule::bitwise_exp);
1137
1138 let mut pairs = token.into_inner();
1139 let mut res = self.eval_comparison_exp(pairs.next().unwrap())?;
1140 while let Some(op) = pairs.next() {
1141 check_rule!(op, Rule::bitwise_operator);
1142 let Some(fun) = BitwisePred::get(op.as_str()) else {
1143 panic!()
1144 };
1145
1146 let mult = pairs.next().unwrap();
1147 let right_op = self.eval_comparison_exp(mult)?;
1148 res = fun(res, right_op);
1149 }
1150
1151 Ok(res)
1152 }
1153
1154 fn parse_long_command(&mut self, token: Pair<'a>) -> ParserResult<(String, Vec<CommandElem>)> {
1155 check_rule!(token, Rule::long_command);
1156
1157 let mut pairs = token.into_inner();
1158 let command_name_token = pairs.next().unwrap();
1159 let command_name = command_name_token.as_str();
1160
1161 let mut args = vec![];
1162 for command_element_token in pairs {
1163 let token_string = command_element_token.as_str().to_string();
1164 match command_element_token.as_rule() {
1165 Rule::command_argument => {
1166 let arg_token = command_element_token.into_inner().next().unwrap();
1167 let arg = match arg_token.as_rule() {
1168 Rule::array_literal_exp => self.eval_array_literal_exp(arg_token)?,
1169 Rule::parenthesized_expression => {
1170 let token = arg_token.into_inner().next().unwrap();
1171 self.eval_pipeline(token)?
1172 }
1173 _ => Val::String(arg_token.as_str().to_string().into()),
1174 };
1175 args.push(CommandElem::Argument(arg));
1176 }
1177 Rule::command_parameter => args.push(CommandElem::Parameter(token_string)),
1178 Rule::argument_list => args.push(CommandElem::ArgList(token_string)),
1179 Rule::redirection => { }
1181 Rule::stop_parsing => { }
1183 Rule::script_block_expression => args.push(CommandElem::Argument(
1184 self.parse_script_block_expression(command_element_token)?,
1185 )),
1186 _ => panic!(
1187 "eval_command not implemented: {:?}",
1188 command_element_token.as_rule()
1189 ),
1190 }
1191 }
1192 Ok((command_name.to_string(), args))
1193 }
1194
1195 fn parse_script_block_command(
1196 &mut self,
1197 token: Pair<'a>,
1198 ) -> ParserResult<(String, Vec<CommandElem>)> {
1199 check_rule!(token, Rule::script_block_command);
1200
1201 let mut pairs = token.into_inner();
1202 let command_name_token = pairs.next().unwrap();
1203 let command_name = command_name_token.as_str();
1204 let command_element_token = pairs.next().unwrap();
1205
1206 check_rule!(command_element_token, Rule::script_block_expression);
1207 let script_block = self.parse_script_block_expression(command_element_token)?;
1208 Ok((
1209 command_name.to_string(),
1210 vec![CommandElem::Argument(script_block)],
1211 ))
1212 }
1213
1214 fn eval_command(&mut self, token: Pair<'a>, input: Option<Val>) -> ParserResult<Val> {
1215 check_rule!(token, Rule::command);
1216
1217 let mut pairs = token.into_inner();
1218 let mut args = if let Some(v) = input {
1221 vec![CommandElem::Argument(v)]
1222 } else {
1223 Vec::new()
1224 };
1225
1226 let command = pairs.next().unwrap();
1227 let (command_name, mut command_args) = match command.as_rule() {
1228 Rule::script_block_command => self.parse_script_block_command(command)?,
1229 Rule::foreach_command => Err(ParserError::NotImplemented("foreach_command".into()))?,
1230 Rule::long_command => self.parse_long_command(command)?,
1231 Rule::invocation_command => {
1232 Err(ParserError::NotImplemented("invocation_command".into()))?
1233 }
1234 _ => panic!("eval_command not implemented: {:?}", command.as_rule()),
1235 };
1236 args.append(&mut command_args);
1237
1238 let CommandOutput {
1239 val,
1240 deobfuscated,
1241 stream,
1242 } = Command::execute(self, command_name.as_str(), args)?;
1243
1244 if let Some(msg) = deobfuscated {
1245 self.deobfuscated_statements.push(msg);
1246 }
1247
1248 if let Some(msg) = stream {
1249 self.output.push(msg);
1250 }
1251
1252 Ok(val.unwrap_or_default())
1253 }
1254
1255 fn eval_redirected_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1256 check_rule!(token, Rule::redirected_expression);
1257
1258 let expression_token = token.into_inner().next().unwrap();
1259 self.eval_expression(expression_token)
1262 }
1263
1264 fn eval_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1265 check_rule!(token, Rule::expression);
1266 let token_string = token.as_str().trim().to_string();
1267
1268 let mut pairs = token.into_inner();
1269 let mut res = self.eval_bitwise_exp(pairs.next().unwrap())?;
1270 while let Some(op) = pairs.next() {
1271 check_rule!(op, Rule::logical_operator);
1272 let Some(fun) = LogicalPred::get(op.as_str()) else {
1273 panic!()
1274 };
1275
1276 let mult = pairs.next().unwrap();
1277 let right_op = self.eval_bitwise_exp(mult)?;
1278 res = Val::Bool(fun(res, right_op));
1279 }
1280 self.tokens
1281 .push(Token::Expression(token_string, res.clone().into()));
1282
1283 Ok(res)
1284 }
1285
1286 fn eval_pipeline_tail(&mut self, token: Pair<'a>, input: Val) -> ParserResult<Val> {
1287 check_rule!(token, Rule::pipeline_tail);
1288 let mut arg = input;
1289 let mut pairs = token.into_inner();
1290
1291 while let Some(token) = pairs.next() {
1292 arg = self.eval_command(token, Some(arg))?;
1293 }
1294
1295 Ok(arg)
1296 }
1297
1298 fn eval_pipeline_with_tail(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1299 check_rule!(token, Rule::pipeline_with_tail);
1300 let mut pairs = token.into_inner();
1301 let token = pairs.next().unwrap();
1302
1303 let result: Val = match token.as_rule() {
1304 Rule::redirected_expression => self.eval_redirected_expression(token)?,
1305 Rule::command => self.eval_command(token, None)?,
1306 _ => {
1307 panic!("eval_pipeline not implemented: {:?}", token.as_rule());
1308 }
1309 };
1310
1311 if let Some(token) = pairs.next() {
1312 match token.as_rule() {
1313 Rule::pipeline_tail => Ok(self.eval_pipeline_tail(token, result)?),
1314 _ => {
1315 panic!("eval_pipeline not implemented: {:?}", token.as_rule());
1316 }
1317 }
1318 } else {
1319 Ok(result)
1320 }
1321 }
1322
1323 fn eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1324 check_rule!(token, Rule::pipeline);
1325 let mut pairs = token.into_inner();
1326 let token = pairs.next().unwrap();
1327
1328 match token.as_rule() {
1329 Rule::assignment_exp => return self.eval_assigment_exp(token),
1330 Rule::pipeline_with_tail => return self.eval_pipeline_with_tail(token),
1331 _ => panic!("not possible: {:?}", token.as_rule()),
1332 }
1333 }
1334
1335 fn safe_eval_pipeline(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1336 let res = self.eval_pipeline(token.clone());
1337
1338 let v = match res {
1339 Ok(val) => val,
1340 Err(err) => {
1341 self.errors.push(err);
1342 Val::ScriptText(token.as_str().to_string())
1343 }
1344 };
1345
1346 Ok(v)
1347 }
1348
1349 fn eval_cast_expression(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1350 check_rule!(token, Rule::cast_expression);
1351
1352 let mut pairs = token.into_inner();
1353 let type_token = pairs.next().unwrap();
1354 let val_type = self.eval_type_literal(type_token)?;
1355
1356 let token = pairs.next().unwrap();
1357 let mut res = match token.as_rule() {
1358 Rule::parenthesized_expression => {
1359 let token = token.into_inner().next().unwrap();
1360 self.safe_eval_pipeline(token)?
1361 }
1362 Rule::range_exp => self.eval_range_exp(token)?,
1363 Rule::unary_exp => self.eval_unary_exp(token)?,
1364 _ => {
1365 panic!(
1366 "eval_cast_expression not implemented: {:?}",
1367 token.as_rule()
1368 );
1369 }
1370 };
1371
1372 Ok(res.cast(val_type)?)
1373 }
1374
1375 fn eval_assigment_exp(&mut self, token: Pair<'a>) -> ParserResult<Val> {
1376 check_rule!(token, Rule::assignment_exp);
1377
1378 let mut pairs = token.into_inner();
1379 let variable_token = pairs.next().unwrap();
1380 let var_name = Self::parse_variable(variable_token)?;
1381 let var = self.variables.get(&var_name).unwrap_or_default();
1382
1383 let assignement_op = pairs.next().unwrap();
1384
1385 let op = assignement_op.into_inner().next().unwrap();
1387 let pred = ArithmeticPred::get(op.as_str());
1388
1389 let right_token = pairs.next().unwrap();
1390 let right_op = self.eval_pipeline(right_token.clone())?;
1391
1392 let Some(pred) = pred else { panic!() };
1393 let op_result = pred(var, right_op)?;
1394 self.variables.set(&var_name, op_result.clone())?;
1395
1396 self.deobfuscated_statements
1398 .push(format!("{} = {}", var_name, op_result.cast_to_script()));
1399 Ok(op_result)
1400 }
1401}
1402
1403#[cfg(test)]
1404mod tests {
1405 use pest::Parser;
1406
1407 use super::*;
1408
1409 #[test]
1410 fn comment_and_semicolon() {
1411 let input = r#"
1412# This is a single line comment
1413$a = 1; $b = 2; Write-Output $a
1414
1415Write-Output "Hello" # Another comment
1416
1417<#
1418 This is a
1419 multi-line block comment
1420#>
1421"#;
1422
1423 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1424 }
1425
1426 #[test]
1427 fn while_loop() {
1428 let input = r#"
1429while ($true) {
1430 if ($someCondition) {
1431 break
1432 }
1433 # other code
1434}
1435"#;
1436
1437 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1438 }
1439
1440 #[test]
1441 fn foreach_loop() {
1442 let input = r#"
1443foreach ($n in $numbers) {
1444 Write-Output $n
1445}
1446"#;
1447
1448 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1449 }
1450
1451 #[test]
1452 fn for_loop() {
1453 let input = r#"
1454# Comma separated assignment expressions enclosed in parentheses.
1455for (($i = 0), ($j = 0); $i -lt 10; $i++)
1456{
1457 "`$i:$i"
1458 "`$j:$j"
1459}
1460"#;
1461
1462 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1463 }
1464
1465 #[test]
1466 fn switch() {
1467 let input = r#"
1468switch ($var) {
1469 "a" { Write-Output "A" }
1470 1 { Write-Output "One" }
1471 default { Write-Output "Other" }
1472}
1473"#;
1474
1475 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1476 }
1477
1478 #[test]
1479 fn functions() {
1480 let input = r#"
1481function Get-Square {
1482 param($x)
1483 return $x * $x
1484}
1485
1486function Say-Hello {
1487 Write-Output "Hello"
1488}
1489"#;
1490
1491 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1492 }
1493
1494 #[test]
1495 fn if_expression() {
1496 let input = r#"
1497$x="hello"
1498 Write-Host $x
1499 $y = 42
1500 Start-Process "notepad.exe"
1501
1502 $x = 42
1503if ($x -eq 1) {
1504 Write-Output "One"
1505} elseif ($x -eq 2) {
1506 Write-Output "Two"
1507} else {
1508 Write-Output "Other"
1509}
1510"#;
1511
1512 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1513 }
1514
1515 #[test]
1516 fn command() {
1517 let input = r#"
1518Get-Process | Where-Object { $_.CPU -gt 100 }
1519"#;
1520
1521 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1522 }
1523
1524 #[test]
1525 fn range() {
1526 let input = r#"
1527$numbers = 1..5
1528"#;
1529
1530 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1531 }
1532
1533 #[test]
1534 fn literals() {
1535 let input = r#"
1536$hex = 0xFF
1537
1538$name = "Alice"
1539$msg = "Hello, $name. Today is $day."
1540$escaped = "She said: `"Hi`""
1541$literal = 'Hello, $name'
1542"#;
1543
1544 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1545 }
1546
1547 #[test]
1548 fn floats() {
1549 let input = r#"
1550 $pi = 3.1415
1551$half = .5
1552"#;
1553
1554 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1555 }
1556
1557 #[test]
1558 fn arrays() {
1559 let input = r#"
1560$a = 1, 2, 3
1561$b = @("one", "two", "three")
1562$c = @(1, 2, @(3, 4))
1563"#;
1564
1565 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1566 }
1567
1568 #[test]
1569 fn static_method_call() {
1570 let input = r#"
1571[Threading.Thread]::Sleep(399)
1572"#;
1573
1574 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1575 }
1576
1577 #[test]
1578 fn neg_pipeline() {
1579 let input = r#"
1580-not $input | Where-Object { $_ -gt 5 }
1581"#;
1582
1583 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1584 }
1585
1586 #[test]
1587 fn amsi_fail() {
1588 let input = r#"
1589#Matt Graebers second Reflection method
1590$VMRviwsbtehQfPtxbt=$null;
1591$ilryNQSTt="System.$([cHAR]([ByTE]0x4d)+[ChAR]([byte]0x61)+[chAr](110)+[cHar]([byTE]0x61)+[cHaR](103)+[cHar](101*64/64)+[chaR]([byTE]0x6d)+[cHAr](101)+[CHAr]([byTE]0x6e)+[Char](116*103/103)).$([Char]([ByTe]0x41)+[Char](117+70-70)+[CHAr]([ByTE]0x74)+[CHar]([bYte]0x6f)+[CHar]([bytE]0x6d)+[ChaR]([ByTe]0x61)+[CHar]([bYte]0x74)+[CHAR]([byte]0x69)+[Char](111*26/26)+[chAr]([BYTe]0x6e)).$(('Âmsí'+'Ùtìl'+'s').NORmalizE([ChAR](44+26)+[chAR](111*9/9)+[cHar](82+32)+[ChaR](109*34/34)+[cHaR](68+24-24)) -replace [ChAr](92)+[CHaR]([BYTe]0x70)+[Char]([BytE]0x7b)+[CHaR]([BYTe]0x4d)+[chAR](110)+[ChAr](15+110))"
1592
1593"#;
1594
1595 let _ = PowerShellSession::parse(Rule::program, input).unwrap();
1596 }
1597}