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