DOS header parser in Rust
up vote
1
down vote
favorite
Looking for feedback mostly on the from()
and printf()
implementations but I included everything for context. Please do not suggest crates, this was an exercise for me to better learn the primitives in Rust (including bitwise ops). Also, please do not suggest unsafe
Rust! I need the code to use only safe Rust constructs. I can't help but want to create a struct of Results and use it in place of all of the individual vars in the from()
func.
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::str;
use std::mem::size_of;
use std::convert::From;
use std::fmt::{Display, Formatter, Result};
// TODO: Parse LONG from vec of bytes
fn main() -> io::Result<()> {
let mut f = File::open("HashMyFiles.exe")?;
let mut reader = BufReader::new(f);
let read_result = parse_bytes::read_n(&mut reader, size_of::<IMAGE_DOS_HEADER>()); // Ok means Vec<u8>
match read_result
{
Ok(r) =>
{
let idh = IMAGE_DOS_HEADER::from(&r);
idh.printf();
},
Err(e) => println!("Error: {}", e)
}
Ok(())
}
/// Reads n bytes (arg1) from T: Read (arg2) and returns them in a u8 vector Result
/// Note: The number of bytes to read is controlled by the vector size for read_exact
fn read_n<T>(n: usize, reader: &mut T) -> io::Result<Vec<u8>>
where T: Read
{
let mut buf = vec![0; n];
let result = reader.read_exact(&mut buf);
match result
{
Ok(_) => return Ok(buf),
Err(e) => return Err(e)
}
}
type WORD = u16; // aka USHORT
type DWORD = u32;
type CHAR = u8;
type BYTE = u8;
type LONG = i32; // signed
///Size: First 64 bytes of valid PE file
#[derive(PartialEq, Debug)]
struct IMAGE_DOS_HEADER
{
e_magic: WORD,
e_cblp: WORD,
e_cp: WORD,
e_crlc: WORD,
e_cparhdr: WORD,
e_minalloc: WORD,
e_maxalloc: WORD,
e_ss: WORD,
e_sp: WORD,
e_csum: WORD,
e_ip: WORD,
e_cs: WORD,
e_lfarlc: WORD,
e_ovno: WORD,
e_res: [WORD; 4],
e_oemid: WORD,
e_oeminfo: WORD,
e_res2: [WORD; 10],
e_lfanew: LONG
}
impl IMAGE_DOS_HEADER
{
fn new<T>(br: T)
where T: BufRead
{
}
fn printf(&self)
{
println!("struct IMAGE_DOS_HEADER");
println!("te_magic: ");
parse_bytes::print_word(self.e_magic);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cp: {:X}", self.e_cp);
println!("te_crlc: {:X}", self.e_crlc);
println!("te_cparhdr: {:X}", self.e_cparhdr);
println!("te_minalloc: {:X}", self.e_minalloc);
println!("te_maxalloc: {:X}", self.e_maxalloc);
println!("te_ss: {:X}", self.e_ss);
println!("te_sp: {:X}", self.e_sp);
println!("te_csum: {:X}", self.e_csum);
println!("te_ip: {:X}", self.e_ip);
println!("te_cs: {:X}", self.e_cs);
println!("te_lfarlc: {:X}", self.e_lfarlc);
println!("te_ovno: {:X}", self.e_ovno);
println!("te_res: ");
for b in self.e_res.iter()
{
print!("{:X}", b);
}
println!("te_oemid: {:X}", self.e_oemid);
println!("te_oeminfo: {:X}", self.e_oeminfo);
println!("te_res2: ");
for b in self.e_res2.iter()
{
print!("{:X}", b);
}
println!("te_lfanew: {:X}", self.e_lfanew);
}
}
impl Display for IMAGE_DOS_HEADER
{
fn fmt(&self, f: &mut Formatter) -> Result
{
write!(f, "e_magic: {:X}n
e_cblp: {:X}n", self.e_magic, self.e_cblp)
}
}
impl<'a> From<&'a Vec<u8>> for IMAGE_DOS_HEADER
{
fn from(f: &'a Vec<u8>) -> Self
{
use std::io::Cursor;
let mut buf = Cursor::new(f);
//Not a fan of this below:
let e_magic = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cblp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_crlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cparhdr = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_minalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_maxalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ss = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_sp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_csum = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ip = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cs = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_lfarlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ovno = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 4]>());
let e_oemid = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_oeminfo = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res2 = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 10]>());
let e_lfanew = parse_bytes::read_n(&mut buf, std::mem::size_of::<LONG>());
IMAGE_DOS_HEADER
{
e_magic:
{
let v = e_magic.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cblp:
{
let v = e_cblp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cp:
{
let v = e_cp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_crlc:
{
let v = e_crlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cparhdr:
{
let v = e_cparhdr.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_minalloc:
{
let v = e_minalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_maxalloc:
{
let v = e_maxalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ss:
{
let v = e_ss.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_sp:
{
let v = e_sp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_csum:
{
let v = e_csum.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ip:
{
let v = e_ip.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cs:
{
let v = e_cs.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_lfarlc:
{
let v = e_lfarlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ovno:
{
let v = e_ovno.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res:
{
let v = e_res.unwrap();
let mut four_w: [WORD; 4]= [0; 4];
four_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
four_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
four_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
four_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
four_w
},
e_oemid:
{
let v = e_oemid.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_oeminfo:
{
let v = e_oeminfo.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res2:
{
let v = e_res2.unwrap();
let mut ten_w: [WORD;10]= [0; 10];
ten_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
ten_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
ten_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
ten_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
ten_w[4] = ((v[8] as u16) << 8) | v[9] as u16;
ten_w[5] = ((v[10] as u16) << 8) | v[11] as u16;
ten_w[6] = ((v[12] as u16) << 8) | v[13] as u16;
ten_w[7] = ((v[14] as u16) << 8) | v[15] as u16;
ten_w[8] = ((v[16] as u16) << 8) | v[17] as u16;
ten_w[9] = ((v[18] as u16) << 8) | v[19] as u16;
ten_w
},
e_lfanew:
{
let v = e_lfanew.unwrap();
let temp: i32 = (v[0] as i32)<< 24 as i32;
let temp2: i32 = (v[1] as i32)<< 16 as i32;
let temp3: i32 = (v[2] as i32)<< 8 as i32;
let result = temp | temp2 | temp3 | v[3] as i32;
result
}
}
}
}
mod parse_bytes
{
use std::io::Read;
use std::io::BufRead;
pub fn read_n<T>(br: &mut T, num_bytes: usize) -> Result<Vec<u8>, ::std::io::Error>
where T: BufRead
{
let mut buf = vec![0u8; num_bytes];
let result = br.read_exact(&mut buf);
match result
{
Ok(r) => return Ok(buf.to_vec()),
Err(e) => return Err(e)
}
}
pub fn u8_to_char(u: u8) -> char
{
u as char
}
pub fn print_word(w: u16)
{
let b1 = (w >> 8) as u8; // Grab high aka "first" byte
let b2 = w as u8; // Grab low aka "second" byte (right)
print!("{}{}", u8_to_char(b1), u8_to_char(b2));
}
pub fn be_to_le(be: &mut [u8]) -> Vec<u8>
{
let mut be2: Vec<u8> = vec!;
for i in be.len()..0
{
be2.push(be[i]);
}
be2
}
pub fn print_byte_vec_as_chars(bvec: &[u8])
{
for b in bvec.iter()
{
print!("{}", u8_to_char(*b));
}
}
}
parsing rust file-structure
add a comment |
up vote
1
down vote
favorite
Looking for feedback mostly on the from()
and printf()
implementations but I included everything for context. Please do not suggest crates, this was an exercise for me to better learn the primitives in Rust (including bitwise ops). Also, please do not suggest unsafe
Rust! I need the code to use only safe Rust constructs. I can't help but want to create a struct of Results and use it in place of all of the individual vars in the from()
func.
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::str;
use std::mem::size_of;
use std::convert::From;
use std::fmt::{Display, Formatter, Result};
// TODO: Parse LONG from vec of bytes
fn main() -> io::Result<()> {
let mut f = File::open("HashMyFiles.exe")?;
let mut reader = BufReader::new(f);
let read_result = parse_bytes::read_n(&mut reader, size_of::<IMAGE_DOS_HEADER>()); // Ok means Vec<u8>
match read_result
{
Ok(r) =>
{
let idh = IMAGE_DOS_HEADER::from(&r);
idh.printf();
},
Err(e) => println!("Error: {}", e)
}
Ok(())
}
/// Reads n bytes (arg1) from T: Read (arg2) and returns them in a u8 vector Result
/// Note: The number of bytes to read is controlled by the vector size for read_exact
fn read_n<T>(n: usize, reader: &mut T) -> io::Result<Vec<u8>>
where T: Read
{
let mut buf = vec![0; n];
let result = reader.read_exact(&mut buf);
match result
{
Ok(_) => return Ok(buf),
Err(e) => return Err(e)
}
}
type WORD = u16; // aka USHORT
type DWORD = u32;
type CHAR = u8;
type BYTE = u8;
type LONG = i32; // signed
///Size: First 64 bytes of valid PE file
#[derive(PartialEq, Debug)]
struct IMAGE_DOS_HEADER
{
e_magic: WORD,
e_cblp: WORD,
e_cp: WORD,
e_crlc: WORD,
e_cparhdr: WORD,
e_minalloc: WORD,
e_maxalloc: WORD,
e_ss: WORD,
e_sp: WORD,
e_csum: WORD,
e_ip: WORD,
e_cs: WORD,
e_lfarlc: WORD,
e_ovno: WORD,
e_res: [WORD; 4],
e_oemid: WORD,
e_oeminfo: WORD,
e_res2: [WORD; 10],
e_lfanew: LONG
}
impl IMAGE_DOS_HEADER
{
fn new<T>(br: T)
where T: BufRead
{
}
fn printf(&self)
{
println!("struct IMAGE_DOS_HEADER");
println!("te_magic: ");
parse_bytes::print_word(self.e_magic);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cp: {:X}", self.e_cp);
println!("te_crlc: {:X}", self.e_crlc);
println!("te_cparhdr: {:X}", self.e_cparhdr);
println!("te_minalloc: {:X}", self.e_minalloc);
println!("te_maxalloc: {:X}", self.e_maxalloc);
println!("te_ss: {:X}", self.e_ss);
println!("te_sp: {:X}", self.e_sp);
println!("te_csum: {:X}", self.e_csum);
println!("te_ip: {:X}", self.e_ip);
println!("te_cs: {:X}", self.e_cs);
println!("te_lfarlc: {:X}", self.e_lfarlc);
println!("te_ovno: {:X}", self.e_ovno);
println!("te_res: ");
for b in self.e_res.iter()
{
print!("{:X}", b);
}
println!("te_oemid: {:X}", self.e_oemid);
println!("te_oeminfo: {:X}", self.e_oeminfo);
println!("te_res2: ");
for b in self.e_res2.iter()
{
print!("{:X}", b);
}
println!("te_lfanew: {:X}", self.e_lfanew);
}
}
impl Display for IMAGE_DOS_HEADER
{
fn fmt(&self, f: &mut Formatter) -> Result
{
write!(f, "e_magic: {:X}n
e_cblp: {:X}n", self.e_magic, self.e_cblp)
}
}
impl<'a> From<&'a Vec<u8>> for IMAGE_DOS_HEADER
{
fn from(f: &'a Vec<u8>) -> Self
{
use std::io::Cursor;
let mut buf = Cursor::new(f);
//Not a fan of this below:
let e_magic = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cblp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_crlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cparhdr = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_minalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_maxalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ss = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_sp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_csum = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ip = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cs = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_lfarlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ovno = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 4]>());
let e_oemid = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_oeminfo = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res2 = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 10]>());
let e_lfanew = parse_bytes::read_n(&mut buf, std::mem::size_of::<LONG>());
IMAGE_DOS_HEADER
{
e_magic:
{
let v = e_magic.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cblp:
{
let v = e_cblp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cp:
{
let v = e_cp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_crlc:
{
let v = e_crlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cparhdr:
{
let v = e_cparhdr.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_minalloc:
{
let v = e_minalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_maxalloc:
{
let v = e_maxalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ss:
{
let v = e_ss.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_sp:
{
let v = e_sp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_csum:
{
let v = e_csum.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ip:
{
let v = e_ip.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cs:
{
let v = e_cs.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_lfarlc:
{
let v = e_lfarlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ovno:
{
let v = e_ovno.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res:
{
let v = e_res.unwrap();
let mut four_w: [WORD; 4]= [0; 4];
four_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
four_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
four_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
four_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
four_w
},
e_oemid:
{
let v = e_oemid.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_oeminfo:
{
let v = e_oeminfo.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res2:
{
let v = e_res2.unwrap();
let mut ten_w: [WORD;10]= [0; 10];
ten_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
ten_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
ten_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
ten_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
ten_w[4] = ((v[8] as u16) << 8) | v[9] as u16;
ten_w[5] = ((v[10] as u16) << 8) | v[11] as u16;
ten_w[6] = ((v[12] as u16) << 8) | v[13] as u16;
ten_w[7] = ((v[14] as u16) << 8) | v[15] as u16;
ten_w[8] = ((v[16] as u16) << 8) | v[17] as u16;
ten_w[9] = ((v[18] as u16) << 8) | v[19] as u16;
ten_w
},
e_lfanew:
{
let v = e_lfanew.unwrap();
let temp: i32 = (v[0] as i32)<< 24 as i32;
let temp2: i32 = (v[1] as i32)<< 16 as i32;
let temp3: i32 = (v[2] as i32)<< 8 as i32;
let result = temp | temp2 | temp3 | v[3] as i32;
result
}
}
}
}
mod parse_bytes
{
use std::io::Read;
use std::io::BufRead;
pub fn read_n<T>(br: &mut T, num_bytes: usize) -> Result<Vec<u8>, ::std::io::Error>
where T: BufRead
{
let mut buf = vec![0u8; num_bytes];
let result = br.read_exact(&mut buf);
match result
{
Ok(r) => return Ok(buf.to_vec()),
Err(e) => return Err(e)
}
}
pub fn u8_to_char(u: u8) -> char
{
u as char
}
pub fn print_word(w: u16)
{
let b1 = (w >> 8) as u8; // Grab high aka "first" byte
let b2 = w as u8; // Grab low aka "second" byte (right)
print!("{}{}", u8_to_char(b1), u8_to_char(b2));
}
pub fn be_to_le(be: &mut [u8]) -> Vec<u8>
{
let mut be2: Vec<u8> = vec!;
for i in be.len()..0
{
be2.push(be[i]);
}
be2
}
pub fn print_byte_vec_as_chars(bvec: &[u8])
{
for b in bvec.iter()
{
print!("{}", u8_to_char(*b));
}
}
}
parsing rust file-structure
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Looking for feedback mostly on the from()
and printf()
implementations but I included everything for context. Please do not suggest crates, this was an exercise for me to better learn the primitives in Rust (including bitwise ops). Also, please do not suggest unsafe
Rust! I need the code to use only safe Rust constructs. I can't help but want to create a struct of Results and use it in place of all of the individual vars in the from()
func.
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::str;
use std::mem::size_of;
use std::convert::From;
use std::fmt::{Display, Formatter, Result};
// TODO: Parse LONG from vec of bytes
fn main() -> io::Result<()> {
let mut f = File::open("HashMyFiles.exe")?;
let mut reader = BufReader::new(f);
let read_result = parse_bytes::read_n(&mut reader, size_of::<IMAGE_DOS_HEADER>()); // Ok means Vec<u8>
match read_result
{
Ok(r) =>
{
let idh = IMAGE_DOS_HEADER::from(&r);
idh.printf();
},
Err(e) => println!("Error: {}", e)
}
Ok(())
}
/// Reads n bytes (arg1) from T: Read (arg2) and returns them in a u8 vector Result
/// Note: The number of bytes to read is controlled by the vector size for read_exact
fn read_n<T>(n: usize, reader: &mut T) -> io::Result<Vec<u8>>
where T: Read
{
let mut buf = vec![0; n];
let result = reader.read_exact(&mut buf);
match result
{
Ok(_) => return Ok(buf),
Err(e) => return Err(e)
}
}
type WORD = u16; // aka USHORT
type DWORD = u32;
type CHAR = u8;
type BYTE = u8;
type LONG = i32; // signed
///Size: First 64 bytes of valid PE file
#[derive(PartialEq, Debug)]
struct IMAGE_DOS_HEADER
{
e_magic: WORD,
e_cblp: WORD,
e_cp: WORD,
e_crlc: WORD,
e_cparhdr: WORD,
e_minalloc: WORD,
e_maxalloc: WORD,
e_ss: WORD,
e_sp: WORD,
e_csum: WORD,
e_ip: WORD,
e_cs: WORD,
e_lfarlc: WORD,
e_ovno: WORD,
e_res: [WORD; 4],
e_oemid: WORD,
e_oeminfo: WORD,
e_res2: [WORD; 10],
e_lfanew: LONG
}
impl IMAGE_DOS_HEADER
{
fn new<T>(br: T)
where T: BufRead
{
}
fn printf(&self)
{
println!("struct IMAGE_DOS_HEADER");
println!("te_magic: ");
parse_bytes::print_word(self.e_magic);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cp: {:X}", self.e_cp);
println!("te_crlc: {:X}", self.e_crlc);
println!("te_cparhdr: {:X}", self.e_cparhdr);
println!("te_minalloc: {:X}", self.e_minalloc);
println!("te_maxalloc: {:X}", self.e_maxalloc);
println!("te_ss: {:X}", self.e_ss);
println!("te_sp: {:X}", self.e_sp);
println!("te_csum: {:X}", self.e_csum);
println!("te_ip: {:X}", self.e_ip);
println!("te_cs: {:X}", self.e_cs);
println!("te_lfarlc: {:X}", self.e_lfarlc);
println!("te_ovno: {:X}", self.e_ovno);
println!("te_res: ");
for b in self.e_res.iter()
{
print!("{:X}", b);
}
println!("te_oemid: {:X}", self.e_oemid);
println!("te_oeminfo: {:X}", self.e_oeminfo);
println!("te_res2: ");
for b in self.e_res2.iter()
{
print!("{:X}", b);
}
println!("te_lfanew: {:X}", self.e_lfanew);
}
}
impl Display for IMAGE_DOS_HEADER
{
fn fmt(&self, f: &mut Formatter) -> Result
{
write!(f, "e_magic: {:X}n
e_cblp: {:X}n", self.e_magic, self.e_cblp)
}
}
impl<'a> From<&'a Vec<u8>> for IMAGE_DOS_HEADER
{
fn from(f: &'a Vec<u8>) -> Self
{
use std::io::Cursor;
let mut buf = Cursor::new(f);
//Not a fan of this below:
let e_magic = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cblp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_crlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cparhdr = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_minalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_maxalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ss = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_sp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_csum = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ip = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cs = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_lfarlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ovno = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 4]>());
let e_oemid = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_oeminfo = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res2 = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 10]>());
let e_lfanew = parse_bytes::read_n(&mut buf, std::mem::size_of::<LONG>());
IMAGE_DOS_HEADER
{
e_magic:
{
let v = e_magic.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cblp:
{
let v = e_cblp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cp:
{
let v = e_cp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_crlc:
{
let v = e_crlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cparhdr:
{
let v = e_cparhdr.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_minalloc:
{
let v = e_minalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_maxalloc:
{
let v = e_maxalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ss:
{
let v = e_ss.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_sp:
{
let v = e_sp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_csum:
{
let v = e_csum.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ip:
{
let v = e_ip.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cs:
{
let v = e_cs.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_lfarlc:
{
let v = e_lfarlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ovno:
{
let v = e_ovno.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res:
{
let v = e_res.unwrap();
let mut four_w: [WORD; 4]= [0; 4];
four_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
four_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
four_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
four_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
four_w
},
e_oemid:
{
let v = e_oemid.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_oeminfo:
{
let v = e_oeminfo.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res2:
{
let v = e_res2.unwrap();
let mut ten_w: [WORD;10]= [0; 10];
ten_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
ten_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
ten_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
ten_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
ten_w[4] = ((v[8] as u16) << 8) | v[9] as u16;
ten_w[5] = ((v[10] as u16) << 8) | v[11] as u16;
ten_w[6] = ((v[12] as u16) << 8) | v[13] as u16;
ten_w[7] = ((v[14] as u16) << 8) | v[15] as u16;
ten_w[8] = ((v[16] as u16) << 8) | v[17] as u16;
ten_w[9] = ((v[18] as u16) << 8) | v[19] as u16;
ten_w
},
e_lfanew:
{
let v = e_lfanew.unwrap();
let temp: i32 = (v[0] as i32)<< 24 as i32;
let temp2: i32 = (v[1] as i32)<< 16 as i32;
let temp3: i32 = (v[2] as i32)<< 8 as i32;
let result = temp | temp2 | temp3 | v[3] as i32;
result
}
}
}
}
mod parse_bytes
{
use std::io::Read;
use std::io::BufRead;
pub fn read_n<T>(br: &mut T, num_bytes: usize) -> Result<Vec<u8>, ::std::io::Error>
where T: BufRead
{
let mut buf = vec![0u8; num_bytes];
let result = br.read_exact(&mut buf);
match result
{
Ok(r) => return Ok(buf.to_vec()),
Err(e) => return Err(e)
}
}
pub fn u8_to_char(u: u8) -> char
{
u as char
}
pub fn print_word(w: u16)
{
let b1 = (w >> 8) as u8; // Grab high aka "first" byte
let b2 = w as u8; // Grab low aka "second" byte (right)
print!("{}{}", u8_to_char(b1), u8_to_char(b2));
}
pub fn be_to_le(be: &mut [u8]) -> Vec<u8>
{
let mut be2: Vec<u8> = vec!;
for i in be.len()..0
{
be2.push(be[i]);
}
be2
}
pub fn print_byte_vec_as_chars(bvec: &[u8])
{
for b in bvec.iter()
{
print!("{}", u8_to_char(*b));
}
}
}
parsing rust file-structure
Looking for feedback mostly on the from()
and printf()
implementations but I included everything for context. Please do not suggest crates, this was an exercise for me to better learn the primitives in Rust (including bitwise ops). Also, please do not suggest unsafe
Rust! I need the code to use only safe Rust constructs. I can't help but want to create a struct of Results and use it in place of all of the individual vars in the from()
func.
use std::io;
use std::io::prelude::*;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
use std::str;
use std::mem::size_of;
use std::convert::From;
use std::fmt::{Display, Formatter, Result};
// TODO: Parse LONG from vec of bytes
fn main() -> io::Result<()> {
let mut f = File::open("HashMyFiles.exe")?;
let mut reader = BufReader::new(f);
let read_result = parse_bytes::read_n(&mut reader, size_of::<IMAGE_DOS_HEADER>()); // Ok means Vec<u8>
match read_result
{
Ok(r) =>
{
let idh = IMAGE_DOS_HEADER::from(&r);
idh.printf();
},
Err(e) => println!("Error: {}", e)
}
Ok(())
}
/// Reads n bytes (arg1) from T: Read (arg2) and returns them in a u8 vector Result
/// Note: The number of bytes to read is controlled by the vector size for read_exact
fn read_n<T>(n: usize, reader: &mut T) -> io::Result<Vec<u8>>
where T: Read
{
let mut buf = vec![0; n];
let result = reader.read_exact(&mut buf);
match result
{
Ok(_) => return Ok(buf),
Err(e) => return Err(e)
}
}
type WORD = u16; // aka USHORT
type DWORD = u32;
type CHAR = u8;
type BYTE = u8;
type LONG = i32; // signed
///Size: First 64 bytes of valid PE file
#[derive(PartialEq, Debug)]
struct IMAGE_DOS_HEADER
{
e_magic: WORD,
e_cblp: WORD,
e_cp: WORD,
e_crlc: WORD,
e_cparhdr: WORD,
e_minalloc: WORD,
e_maxalloc: WORD,
e_ss: WORD,
e_sp: WORD,
e_csum: WORD,
e_ip: WORD,
e_cs: WORD,
e_lfarlc: WORD,
e_ovno: WORD,
e_res: [WORD; 4],
e_oemid: WORD,
e_oeminfo: WORD,
e_res2: [WORD; 10],
e_lfanew: LONG
}
impl IMAGE_DOS_HEADER
{
fn new<T>(br: T)
where T: BufRead
{
}
fn printf(&self)
{
println!("struct IMAGE_DOS_HEADER");
println!("te_magic: ");
parse_bytes::print_word(self.e_magic);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cblp: {:X}", self.e_cblp);
println!("te_cp: {:X}", self.e_cp);
println!("te_crlc: {:X}", self.e_crlc);
println!("te_cparhdr: {:X}", self.e_cparhdr);
println!("te_minalloc: {:X}", self.e_minalloc);
println!("te_maxalloc: {:X}", self.e_maxalloc);
println!("te_ss: {:X}", self.e_ss);
println!("te_sp: {:X}", self.e_sp);
println!("te_csum: {:X}", self.e_csum);
println!("te_ip: {:X}", self.e_ip);
println!("te_cs: {:X}", self.e_cs);
println!("te_lfarlc: {:X}", self.e_lfarlc);
println!("te_ovno: {:X}", self.e_ovno);
println!("te_res: ");
for b in self.e_res.iter()
{
print!("{:X}", b);
}
println!("te_oemid: {:X}", self.e_oemid);
println!("te_oeminfo: {:X}", self.e_oeminfo);
println!("te_res2: ");
for b in self.e_res2.iter()
{
print!("{:X}", b);
}
println!("te_lfanew: {:X}", self.e_lfanew);
}
}
impl Display for IMAGE_DOS_HEADER
{
fn fmt(&self, f: &mut Formatter) -> Result
{
write!(f, "e_magic: {:X}n
e_cblp: {:X}n", self.e_magic, self.e_cblp)
}
}
impl<'a> From<&'a Vec<u8>> for IMAGE_DOS_HEADER
{
fn from(f: &'a Vec<u8>) -> Self
{
use std::io::Cursor;
let mut buf = Cursor::new(f);
//Not a fan of this below:
let e_magic = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cblp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_crlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cparhdr = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_minalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_maxalloc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ss = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_sp = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_csum = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ip = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_cs = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_lfarlc = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_ovno = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 4]>());
let e_oemid = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_oeminfo = parse_bytes::read_n(&mut buf, std::mem::size_of::<WORD>());
let e_res2 = parse_bytes::read_n(&mut buf, std::mem::size_of::<[WORD; 10]>());
let e_lfanew = parse_bytes::read_n(&mut buf, std::mem::size_of::<LONG>());
IMAGE_DOS_HEADER
{
e_magic:
{
let v = e_magic.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cblp:
{
let v = e_cblp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cp:
{
let v = e_cp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_crlc:
{
let v = e_crlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cparhdr:
{
let v = e_cparhdr.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_minalloc:
{
let v = e_minalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_maxalloc:
{
let v = e_maxalloc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ss:
{
let v = e_ss.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_sp:
{
let v = e_sp.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_csum:
{
let v = e_csum.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ip:
{
let v = e_ip.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_cs:
{
let v = e_cs.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_lfarlc:
{
let v = e_lfarlc.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_ovno:
{
let v = e_ovno.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res:
{
let v = e_res.unwrap();
let mut four_w: [WORD; 4]= [0; 4];
four_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
four_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
four_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
four_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
four_w
},
e_oemid:
{
let v = e_oemid.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_oeminfo:
{
let v = e_oeminfo.unwrap();
((v[0] as u16) << 8) | v[1] as u16
},
e_res2:
{
let v = e_res2.unwrap();
let mut ten_w: [WORD;10]= [0; 10];
ten_w[0] = ((v[0] as u16) << 8) | v[1] as u16;
ten_w[1] = ((v[2] as u16) << 8) | v[3] as u16;
ten_w[2] = ((v[4] as u16) << 8) | v[5] as u16;
ten_w[3] = ((v[6] as u16) << 8) | v[7] as u16;
ten_w[4] = ((v[8] as u16) << 8) | v[9] as u16;
ten_w[5] = ((v[10] as u16) << 8) | v[11] as u16;
ten_w[6] = ((v[12] as u16) << 8) | v[13] as u16;
ten_w[7] = ((v[14] as u16) << 8) | v[15] as u16;
ten_w[8] = ((v[16] as u16) << 8) | v[17] as u16;
ten_w[9] = ((v[18] as u16) << 8) | v[19] as u16;
ten_w
},
e_lfanew:
{
let v = e_lfanew.unwrap();
let temp: i32 = (v[0] as i32)<< 24 as i32;
let temp2: i32 = (v[1] as i32)<< 16 as i32;
let temp3: i32 = (v[2] as i32)<< 8 as i32;
let result = temp | temp2 | temp3 | v[3] as i32;
result
}
}
}
}
mod parse_bytes
{
use std::io::Read;
use std::io::BufRead;
pub fn read_n<T>(br: &mut T, num_bytes: usize) -> Result<Vec<u8>, ::std::io::Error>
where T: BufRead
{
let mut buf = vec![0u8; num_bytes];
let result = br.read_exact(&mut buf);
match result
{
Ok(r) => return Ok(buf.to_vec()),
Err(e) => return Err(e)
}
}
pub fn u8_to_char(u: u8) -> char
{
u as char
}
pub fn print_word(w: u16)
{
let b1 = (w >> 8) as u8; // Grab high aka "first" byte
let b2 = w as u8; // Grab low aka "second" byte (right)
print!("{}{}", u8_to_char(b1), u8_to_char(b2));
}
pub fn be_to_le(be: &mut [u8]) -> Vec<u8>
{
let mut be2: Vec<u8> = vec!;
for i in be.len()..0
{
be2.push(be[i]);
}
be2
}
pub fn print_byte_vec_as_chars(bvec: &[u8])
{
for b in bvec.iter()
{
print!("{}", u8_to_char(*b));
}
}
}
parsing rust file-structure
parsing rust file-structure
edited Nov 18 at 22:23
200_success
127k15148411
127k15148411
asked Nov 18 at 20:18
the_endian
381111
381111
add a comment |
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207938%2fdos-header-parser-in-rust%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown