Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need more examples #115

Closed
Pzixel opened this issue Dec 9, 2018 · 5 comments
Closed

Need more examples #115

Pzixel opened this issue Dec 9, 2018 · 5 comments

Comments

@Pzixel
Copy link
Contributor

Pzixel commented Dec 9, 2018

Hello guys.

I tried to use your library and it's api looks amazing. However, I don't see how to extract anything but very basic info.

I'm currently stuck getting CLI headers from PE executable file. I'm using ECMA335, section II.25.2.3.3 PE header data directories. I want to read CLI Header data so I'm writing following code:

use failure::{bail, Error, err_msg};
use goblin::pe::PE;
use goblin::pe::data_directories::DataDirectory;
use goblin::pe::section_table::SectionTable;

fn main() -> Result<(), Error> {
    let path = std::env::args()
        .skip(1)
        .next()
        .expect("Path to executable was not specified");
    let file = std::fs::read(path)?;
    let pe = PE::parse(&file)?;
    if pe.header.coff_header.machine != 0x14c {
        bail!("Is not a .Net executable");
    }
    let optional_header = pe.header.optional_header.ok_or_else(|| err_msg("No optional header"))?;
    let cli_header = optional_header.data_directories.data_directories[14].ok_or_else(|| err_msg("No CLI header"))?;
    let section = get_section(&pe, &cli_header)?;
    // what should I do here with section?
    Ok(())
}

fn get_section<'a>(pe: &'a PE, header: &DataDirectory) -> Result<&'a SectionTable, Error> {
    for section in pe.sections.iter() {
        if header.virtual_address >= section.virtual_address && header.virtual_address < section.virtual_address + header.size {
            return Ok(&section);
        }
    }
    bail!("Section for address {} was not found", header.virtual_address)
}

Being said, I don't see how it could be done.

OTOH, I have following working C code:

#define T_CALLOC(type) ((type*)calloc(1, sizeof(type)))
#define PTR(p, ofs) ((void*)((char*)(p) + (ofs)))
#define VAL(type, p, ofs) (*(type*)(PTR(p, ofs)))
void* RVA_FindData(tFile *pFile, int addr) {
	tRVA *pRVA = pFile->pRVAs;
	while (pRVA != NULL) {
		if (addr >= pRVA->baseAddress && addr < pRVA->baseAddress + pRVA->size) {
			return PTR(pRVA->pData, addr - pRVA->baseAddress);
		}
		pRVA = pRVA->pNext;
	}
	return NULL;
}
   ...

	for (int i = 0; i < numSections; i++) {
		void *pSection = PTR(pSectionHeaders, i * 40);
		tRVA *pRVA = T_CALLOC(tRVA);
		pRVA->baseAddress = VAL(int, pSection, 12);
		pRVA->size = VAL(int, pSection, 8);
		pRVA->pData = calloc(1, pRVA->size);
		int rvaOfs = VAL(int, pSection, 20);
		memcpy(pRVA->pData, PTR(pData, rvaOfs), min(pRVA->size, VAL(int, pSection, 16)));
		pRVA->pNext = pFile->pRVAs;
		pFile->pRVAs = pRVA;
	}
	printf("Loaded sections :)\n");
	// Load CLI header
	void *pCLIHeader = RVA_FindData(pFile, VAL(int, pPEOptionalHeader, 208));
	printf("Runtime version: %i.%i\n", VAL(short, pCLIHeader, 4), VAL(short, pCLIHeader, 6));
   ...

So the question is basically how can I analyze dynamic file structure? Maybe some more examples?

There should be some way to utilize pointer_to_raw_data, but it's just an index, but I don't havy any buffer to index on.

@Pzixel
Copy link
Contributor Author

Pzixel commented Dec 9, 2018

I ended up with copy-pasting utils module to make it work: Pzixel/dotnet-rs@d74b7d7

Seems completely broken to me. What is the intended way to perform such an operation?

@m4b
Copy link
Owner

m4b commented Dec 9, 2018

Hi thanks for the issue! So reading the linked dotnet-rs, your issue is that you need the find_offset from the utils mod? Seems that the mod is not pub, but the functions are otherwise pub; probably no one thought to export them before.

Otherwise, once you've mapped the rva into an offset, since you already have the bytes, that should get you on your way to accessing the raw data you want to analyze, yes? Or am I misunderstanding something?

@Pzixel
Copy link
Contributor Author

Pzixel commented Dec 9, 2018

I need to read data that is represented with DataDirectory entry. The problem is that it's not possible via current API, so I had to copy utils functions to duplicate internal API that makes it possible.

I firstly thinked that I don't understand examples of how to do it, but after reading source code I realised that it's just not exposed to public.

Functions are not pub because the whole module is imported (it's not listed as pub in mods.rs), so pub functions just means you can use it in same module, but they are hidden from outside.

@m4b
Copy link
Owner

m4b commented Dec 9, 2018

Yea got it, you just need utils pub right ? Should be easy enough; if you want to make a PR that would be great. While we’re at it, could also add some example using pe::utils

@Pzixel
Copy link
Contributor Author

Pzixel commented Dec 9, 2018

Hmm, last change 2 months ago... Okay, I'm gonna create a PR :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants