update 18/2/2020
This commit is contained in:
122
src/main.rs
122
src/main.rs
@ -10,8 +10,9 @@ use pdb::PDB;
|
||||
use pdb::SymbolData;
|
||||
use pdb::TypeData;
|
||||
use pdb::ClassType;
|
||||
use pdb::FallibleIterator;
|
||||
use pdb::ModifierType;
|
||||
|
||||
use pdb::FallibleIterator;
|
||||
use pdb::TypeFinder;
|
||||
use pdb::TypeIndex;
|
||||
|
||||
@ -30,6 +31,78 @@ fn get_type_as_str(type_finder: &TypeFinder, typ: &TypeIndex) -> String {
|
||||
TypeData::Pointer(pt) => {
|
||||
format!("{}*", get_type_as_str(type_finder, &pt.underlying_type))
|
||||
},
|
||||
TypeData::StaticMember(st) => {
|
||||
format!("static {}", get_type_as_str(type_finder, &st.field_type))
|
||||
},
|
||||
TypeData::Array(at) => {
|
||||
format!("{}{:?}",
|
||||
get_type_as_str(type_finder, &at.element_type), /* get_type_as_str(type_finder, &at.indexing_type), */ at.dimensions)
|
||||
},
|
||||
// TypeData::Enumeration(et) => {
|
||||
// format!("enumeration")
|
||||
// },
|
||||
// TypeData::Enumerate(et) => {
|
||||
// format!("enumerate")
|
||||
// },
|
||||
// TypeData::MemberFunction(mft) => {
|
||||
// format!("member function")
|
||||
// },
|
||||
// TypeData::OverloadedMethod(ovmt) => {
|
||||
// format!("overloaded method")
|
||||
// },
|
||||
// TypeData::Nested(nt) => {
|
||||
// format!("nested")
|
||||
// },
|
||||
// TypeData::BaseClass(bct) => {
|
||||
// format!("base class")
|
||||
// },
|
||||
// TypeData::VirtualBaseClass(vbct) => {
|
||||
// format!("virtual base class")
|
||||
// },
|
||||
// TypeData::VirtualFunctionTablePointer(vftpt) => {
|
||||
// format!("virtual function table pointer")
|
||||
// },
|
||||
TypeData::Procedure(pt) => {
|
||||
let rettype = match pt.return_type {
|
||||
Some(rt) => get_type_as_str(type_finder, &rt),
|
||||
_ => "UNKNOWN".to_string()
|
||||
};
|
||||
format!("{}({})", rettype, get_type_as_str(type_finder, &pt.argument_list))
|
||||
},
|
||||
TypeData::Modifier(mt) => {
|
||||
match mt {
|
||||
ModifierType { constant: true, volatile: true, unaligned: true, .. } =>
|
||||
format!("const volatile unaligned {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: true, volatile: true, unaligned: false, .. } =>
|
||||
format!("const volatile {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: true, volatile: false, unaligned: true, .. } =>
|
||||
format!("const unaligned {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: false, volatile: true, unaligned: true, .. } =>
|
||||
format!("volatile unaligned {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: true, volatile: false, unaligned: false, .. } =>
|
||||
format!("const {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: false, volatile: true, unaligned: false, .. } =>
|
||||
format!("volatile {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
ModifierType { constant: false, volatile: false, unaligned: true, .. } =>
|
||||
format!("unaligned {}", get_type_as_str(type_finder, &mt.underlying_type)),
|
||||
_ => format!("modifier {}", get_type_as_str(type_finder, &mt.underlying_type))
|
||||
}
|
||||
},
|
||||
// TypeData::Union(ut) => {
|
||||
// format!("union")
|
||||
// },
|
||||
// TypeData::Bitfield(bft) => {
|
||||
// format!("bitfield")
|
||||
// },
|
||||
TypeData::FieldList(_flt) => {
|
||||
format!("fieldlist")
|
||||
},
|
||||
// TypeData::ArgumentList(alt) => {
|
||||
// format!("arglist")
|
||||
// },
|
||||
// TypeData::MethodList(mlt) => {
|
||||
// format!("methodlist")
|
||||
// },
|
||||
unk => {
|
||||
match unk.name() {
|
||||
Some(s) => format!("{}", s.to_string()),
|
||||
@ -48,13 +121,23 @@ fn parse_pdb() {
|
||||
println!("PDB for {}, guid: {}, age: {},", dbi.machine_type().unwrap(), info.guid, dbi.age().unwrap_or(0));
|
||||
println!("");
|
||||
|
||||
let type_information = pdb.type_information().expect("Cannot get type information");
|
||||
let mut type_finder = type_information.type_finder();
|
||||
let mut iter = type_information.iter();
|
||||
while let Some(_typ) = iter.next().unwrap() {
|
||||
type_finder.update(&iter);
|
||||
}
|
||||
|
||||
// find global symbols offset
|
||||
let addr_map = pdb.address_map().expect("Cannot get address map");
|
||||
let glosym = pdb.global_symbols().expect("Cannot get global symbols");
|
||||
let mut symbols = glosym.iter();
|
||||
let need_symbols = [
|
||||
"PsLoadedModuleList", "PsActiveProcessHead", "KeNumberNodes",
|
||||
// "PoolVector", "ExpNumberOfNonPagedPools",
|
||||
"KdDebuggerDataBlock", "MmNonPagedPoolStart", "MmNonPagedPoolEnd", // Windows XP
|
||||
"MiNonPagedPoolStartAligned", "MiNonPagedPoolEnd", "MiNonPagedPoolBitMap", // Windows 7, 8
|
||||
"MiNonPagedPoolBitMap", "MiNonPagedPoolVaBitMap",
|
||||
"MiState" // Windows 10
|
||||
];
|
||||
while let Some(symbol) = symbols.next().unwrap() {
|
||||
@ -64,7 +147,8 @@ fn parse_pdb() {
|
||||
for sym in need_symbols.iter() {
|
||||
if &name == sym {
|
||||
let rva = data.offset.to_rva(&addr_map).unwrap_or_default();
|
||||
println!("{} {} {}:{}", name, rva, data.offset.section, data.offset.offset);
|
||||
println!("{} {} {} {}:{}",
|
||||
get_type_as_str(&type_finder, &(symbol.raw_kind() as u32)), name, rva, data.offset.section, data.offset.offset);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -76,6 +160,10 @@ fn parse_pdb() {
|
||||
println!("");
|
||||
|
||||
let mut need_structs = HashMap::new();
|
||||
// need_structs.insert("_KLDR_DATA_TABLE_ENTRY", vec![]);
|
||||
need_structs.insert("_PEB", vec![]);
|
||||
need_structs.insert("_LIST_ENTRY", vec![]);
|
||||
need_structs.insert("_EPROCESS", vec![]);
|
||||
need_structs.insert("_KDDEBUGGER_DATA64", vec![
|
||||
"MmNonPagedPoolStart", "MmNonPagedPoolEnd", // Windows XP
|
||||
"MiNonPagedPoolStartAligned", "MiNonPagedPoolEnd", "MiNonPagedPoolBitMap", // Windows 7, 8 -- not sure, global symbols
|
||||
@ -84,26 +172,29 @@ fn parse_pdb() {
|
||||
|
||||
// these struct supports finding NonPagedPool{First,Last}Va in windows 10
|
||||
need_structs.insert("_MI_SYSTEM_INFORMATION", vec![
|
||||
"Hardware", // windows 10 2016+
|
||||
"SystemNodeInformation" // windows 10 2015
|
||||
"Hardware", // windows 10 2016+
|
||||
"SystemNodeInformation" // windows 10 2015
|
||||
]);
|
||||
need_structs.insert("_MI_HARDWARE_STATE", vec![
|
||||
"SystemNodeInformation", // till windows 10 1900
|
||||
"SystemNodeNonPagedPool" // windows insider, 2020
|
||||
"SystemNodeInformation", // till windows 10 1900
|
||||
"SystemNodeNonPagedPool" // windows insider, 2020
|
||||
]);
|
||||
need_structs.insert("_MI_SYSTEM_NODE_INFORMATION", vec![ // till windows 10 1900
|
||||
"NonPagedPoolFirstVa", "NonPagedPoolLastVa",
|
||||
"NonPagedBitMap" // missing on windows 10 1900+
|
||||
"NonPagedBitMap", // missing on windows 10 1900+
|
||||
"DynamicBitMapNonPagedPool" // some weird field
|
||||
]);
|
||||
need_structs.insert("_MI_SYSTEM_NODE_NONPAGED_POOL", vec![ // windows insider, 2020
|
||||
"NonPagedPoolFirstVa", "NonPagedPoolLastVa"
|
||||
"NonPagedPoolFirstVa", "NonPagedPoolLastVa",
|
||||
"DynamicBitMapNonPagedPool" // some weird field
|
||||
]);
|
||||
need_structs.insert("_MI_DYNAMIC_BITMAP", vec![]);
|
||||
need_structs.insert("_RTL_BITMAP", vec![]); // windows 10 until 2020
|
||||
need_structs.insert("_RTL_BITMAP_EX", vec![]); // windows insider, 2020
|
||||
|
||||
let type_information = pdb.type_information().expect("Cannot get type information");
|
||||
let mut type_finder = type_information.type_finder();
|
||||
let mut iter = type_information.iter();
|
||||
iter = type_information.iter();
|
||||
while let Some(typ) = iter.next().unwrap() {
|
||||
type_finder.update(&iter);
|
||||
// type_finder.update(&iter);
|
||||
match typ.parse() {
|
||||
Ok(TypeData::Class(ClassType {name, fields: Some(fields), ..})) => {
|
||||
let n = name.to_string();
|
||||
@ -111,22 +202,23 @@ fn parse_pdb() {
|
||||
if !need_structs.contains_key(&*n) {
|
||||
continue;
|
||||
}
|
||||
println!("struct {}", name);
|
||||
println!("beginstruct {}", name);
|
||||
match type_finder.find(fields).unwrap().parse().unwrap() {
|
||||
TypeData::FieldList(list) => {
|
||||
// `fields` is a Vec<TypeData>
|
||||
for field in list.fields {
|
||||
if let TypeData::Member(member) = field {
|
||||
let mem_typ = get_type_as_str(&type_finder, &member.field_type);
|
||||
println!(" - field {} {} at offset {:x}", mem_typ, member.name, member.offset);
|
||||
println!("\t0x{:x} {} {}", member.offset, mem_typ, member.name);
|
||||
} else {
|
||||
println!("\tmember_func");
|
||||
// handle member functions, nested types, etc.
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
println!("");
|
||||
println!("endstruct\n");
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
Reference in New Issue
Block a user