macro: fix 0E decode

binnvecs! for str arg
This commit is contained in:
Dmitry Belyaev 2022-08-27 22:28:51 +03:00
parent 4c8ce5c648
commit 46526d7c27
Signed by: b4tman
GPG Key ID: 41A00BF15EA7E5F3
2 changed files with 117 additions and 97 deletions

View File

@ -2,7 +2,6 @@ extern crate binnpatch;
extern crate data_encoding; extern crate data_encoding;
extern crate memmap; extern crate memmap;
extern crate binnpatch_macro; extern crate binnpatch_macro;
use data_encoding::HEXUPPER; use data_encoding::HEXUPPER;
@ -11,15 +10,15 @@ use std::fs;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use binnpatch::{BytesPattern, FindPattern, ApplyPatch}; use binnpatch::{ApplyPatch, BytesPattern, FindPattern};
use binnpatch_macro::binnvec; use binnpatch_macro::binnvecs;
fn main() { fn main() {
let src_file = "Some.dll"; let src_file = "Some.dll";
let dst_file = "Some.dll.patched"; let dst_file = "Some.dll.patched";
let src_pattern = let src_pattern = "40 3E 1D ?? ?? 12 1C 7C 48 ?? 73 6F 02 22 ?? 61 19 4E 13 60 48 45 19 27 5B";
"40 3E 1D ?? ?? 12 1C 7C 48 ?? 73 6F 02 22 ?? 61 19 4E 13 60 48 45 19 27 5B"; let replacement =
let replacement = binnvec!(06 5A 18 74 2D 62 12 6A 13 4A 2B 0E 6F 0F 36 7A 28 0A 37 67 0A 4B 01 73 0x14); binnvecs!("06 5A 18 74 2D 62 12 6A 13 4A 2B 0E 6F 0F 36 7A 28 0A 37 67 0A 4B 01 73 14");
let pattern = BytesPattern::from(src_pattern); let pattern = BytesPattern::from(src_pattern);

View File

@ -1,91 +1,112 @@
extern crate proc_macro; extern crate proc_macro;
use proc_macro::{TokenStream, TokenTree}; use proc_macro::{TokenStream, TokenTree};
use proc_macro::{Punct, Literal, Spacing, Span, Ident, Group, Delimiter}; use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span};
fn parse_str(s: &str) -> TokenStream { macro_rules! forest {
s.parse().unwrap() ($($x:expr),+) => {[$( TokenTree::from($x), )+]};
} }
#[proc_macro] fn parse_hex_values(items: TokenStream) -> TokenStream {
pub fn binnvec(_item: TokenStream) -> TokenStream { let mut new_tokens: Vec<TokenTree> = vec![];
println!("- - - - -"); let comma: Punct = Punct::new(',', Spacing::Alone);
println!("{}", _item.to_string()); let zero = Literal::u8_suffixed(0);
println!("- - - - -"); let mut prev_separated: bool = true;
println!("{:?}", _item); let mut prev_is_mask: bool = false;
println!("- - - - -");
for token in items {
let mut new_tokens: Vec<TokenTree> = vec![]; match token {
let comma: Punct = Punct::new(',', Spacing::Alone); TokenTree::Punct(ref x) if x.as_char() == ',' => {
let zero = Literal::u8_suffixed(0); new_tokens.push(token);
let mut prev_separated: bool = true; prev_separated = true;
let mut prev_is_mask: bool = false; continue;
}
for token in _item { TokenTree::Punct(ref x) if x.as_char() == '?' => {
match token { if prev_is_mask {
TokenTree::Punct(ref x) if x.as_char() == ',' => { if !prev_separated {
new_tokens.push(token.into()); new_tokens.push(comma.clone().into());
prev_separated = true; }
continue; let mut val = zero.clone();
} val.set_span(x.span());
TokenTree::Punct(ref x) if x.as_char() == '?' => { new_tokens.push(zero.clone().into());
if prev_is_mask { prev_is_mask = false;
if !prev_separated { prev_separated = false;
new_tokens.push(comma.clone().into()); } else if !prev_is_mask {
} prev_is_mask = true;
let mut val = zero.clone(); }
val.set_span(x.span()); continue;
new_tokens.push(zero.clone().into()); }
prev_is_mask = false; TokenTree::Ident(ref x) if x.to_string().len() == 2 => {
prev_separated = false; if !prev_separated {
} else if !prev_is_mask { new_tokens.push(comma.clone().into());
prev_is_mask = true; }
} let lit_str = format!("0x{}u8", x);
continue; let mut val: Literal = lit_str.as_str().parse().expect("parse literal from ident");
} val.set_span(x.span());
TokenTree::Ident(ref x) if x.to_string().len() == 2 => { new_tokens.push(val.into());
if !prev_separated { }
new_tokens.push(comma.clone().into()); TokenTree::Literal(ref x) => {
} if !prev_separated {
let lit_str = format!("0x{}u8", x.to_string()); new_tokens.push(comma.clone().into());
let mut val:Literal = lit_str.as_str().parse().expect("parse literal from ident"); }
val.set_span(x.span());
new_tokens.push(val.into()); let in_str = x.to_string();
} if in_str.starts_with("0x") {
TokenTree::Literal(ref x) => { new_tokens.push(token);
if !prev_separated { } else {
new_tokens.push(comma.clone().into()); let lit_str = format!("0x{}u8", in_str);
} let mut val: Literal = lit_str.as_str().parse().expect("parse literal");
val.set_span(x.span());
let in_str = x.to_string(); new_tokens.push(val.into());
if in_str.starts_with("0x") { }
new_tokens.push(token.into()); }
} else { _ => {}
let lit_str = format!("0x{}u8", in_str); }
let mut val:Literal = lit_str.as_str().parse().expect("parse literal"); prev_separated = false;
val.set_span(x.span()); }
new_tokens.push(val.into()); let mut new_stream = TokenStream::new();
} new_stream.extend(new_tokens);
} new_stream
_ => { }
} #[proc_macro]
} pub fn binnvec(_item: TokenStream) -> TokenStream {
prev_separated = false; let group_elements = parse_hex_values(_item);
}
let group = Group::new(Delimiter::Bracket, group_elements);
let mut ts_new = TokenStream::new(); let mut result = TokenStream::new();
ts_new.extend(new_tokens); let vec_ident = Ident::new("vec", Span::call_site());
let macro_marc = Punct::new('!', Spacing::Joint);
let group = Group::new(Delimiter::Bracket, ts_new); result.extend(forest!(vec_ident, macro_marc, group));
let mut result = TokenStream::new();
let vec_ident = Ident::new("vec", Span::call_site()); result
let macro_marc = Punct::new('!', Spacing::Joint); }
result.extend([TokenTree::from(vec_ident), TokenTree::from(macro_marc)]);
result.extend([TokenTree::from(group)]); #[proc_macro]
pub fn binnvecs(_item: TokenStream) -> TokenStream {
println!("result: \"{}\"", result.to_string()); let first = _item.clone().into_iter().next();
result match first {
} Some(TokenTree::Literal(lit)) => {
let mut lit_str = lit.to_string();
if !(lit_str.starts_with('\"') && lit_str.ends_with('\"')) {
panic!("unexpected literal: \"{}\"", lit_str);
}
lit_str = lit_str.trim_matches('"').to_string();
let lit_str_copy = lit_str.clone();
(0u8..=9)
.map(|i| i.to_string())
.filter(|x| lit_str_copy.contains(format!("{}E", x).as_str()))
.for_each(|x| {
lit_str =
lit_str.replace(format!("{}E", x).as_str(), format!("0x{}E", x).as_str());
});
let stream: TokenStream = lit_str.parse().unwrap();
binnvec(stream)
}
_ => {
panic!("invalid item: \"{}\"", _item);
}
}
}