2
\$\begingroup\$

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));
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Running cargo clippy will give you a very good hint what to do. When you resolved them, edit your question and ping me. \$\endgroup\$ – hellow Nov 26 '18 at 17:04
  • \$\begingroup\$ Also please make sure, that you run rustfmt on your code before posting it, so it will be nicely formatted. \$\endgroup\$ – hellow Nov 26 '18 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.