LIEF allows you to modify (or create) PE resources at different levels:
pe: lief.PE.Binary
rsrc = pe.resources
print(rsrc)
std::unique_ptr<LIEF::PE::Binary> pe;
LIEF::PE::ResourceNode* rsrc = pe->resources();
std::cout << *rsrc << '\n';
let pe: &lief::pe::Binary = some_pe;
let rsrc = pe.resources().unwrap();
println!("{}", &rsrc as &dyn NodeBase);
pe: lief.PE.Binary
rsrc = pe.resources
assert isinstance(rsrc, lief.PE.ResourceNode)
dir_node = lief.PE.ResourceDirectory(100)
data_node = lief.PE.ResourceData([1, 2, 3])
rsrc.add_child(dir_node).add_child(data_node)
std::unique_ptr<LIEF::PE::Binary> pe;
LIEF::PE::ResourceNode* root = pe->resources();
LIEF::PE::ResourceDirectory dir_node(/*id=*/100);
LIEF::PE::ResourceData data_node(std::vector<uint8_t>{1, 2, 3});
(*root).add_child(dir_node).add_child(data_node);
pe->write("new.exe");
let pe: &mut lief::pe::Binary = some_pe;
let mut root = pe.resources().unwrap();
let mut dir_node = lief::pe::resources::Directory::with_id(100);
let data_node = lief::pe::resources::Data::with_buffer(&[1, 2, 3]);
dir_node.add_child(&Node::Data(data_node));
root.add_child(&Node::Directory(dir_node));
pe.write("new.exe");
This low-level API can be used to modify the tree or change the data of a specific node.
Pretty Printing
You can also print a node to get a formatted representation of the resource tree:
pe: lief.PE.Binary
tree = pe.resources
print(tree)
├── Directory ID: 0000 (0x0000)
│ ├── Directory ID: 0016 (0x0010) type: VERSION
│ │ └── Directory ID: 0001 (0x0001)
│ │ └── Data ID: 0000 (0x0000) Lang: 0x00 / Sublang: 0x00 length=772 (0x000304), offset: 0x1ca0
│ │ ├── Hex: 04:03:34:00:00:00:56:00:53:00:5f:00:56:00:45:00:52:00:53:00
│ │ └── Str: ..4...V.S._.V.E.R.S.
│ └── Directory ID: 0024 (0x0018) type: MANIFEST
│ └── Directory ID: 0001 (0x0001)
│ └── Data ID: 1033 (0x0409) Lang: 0x09 / Sublang: 0x01 length=1900 (0x00076c), offset: 0x1fa4
│ ├── Hex: 3c:61:73:73:65:6d:62:6c:79:20:78:6d:6c:6e:73:3d:22:75:72:6e
│ └── Str: <assembly xmlns="urn
pe: lief.PE.Binary
manager = pe.resources_manager
assert isinstance(manager, lief.PE.ResourcesManager)
manager.manifest = """
<?xml version="1.0" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo>
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false'/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"""
pe.write("new.exe")
std::unique_ptr<LIEF::PE::Binary> pe;
result<ResourcesManager> manager = pe->resources_manager();
manager->manifest(R"manifest(
<?xml version="1.0" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo>
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false'/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
)manifest");
pe->write("new.exe");
let pe: &mut lief::pe::Binary = some_pe;
let mut manager = pe.resources_manager().unwrap();
manager.set_manifest(
r#"
<?xml version="1.0" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0">
<trustInfo>
<security>
<requestedPrivileges>
<requestedExecutionLevel level='asInvoker' uiAccess='false'/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
"#,
);
pe.write("new.exe");
from_pe: lief.PE.Binary
to_pe: lief.PE.Binary
resources = from_pe.resources
assert isinstance(resources, lief.PE.ResourceNode)
to_pe.set_resources(resources)
to_pe.write("new.exe")
std::unique_ptr<LIEF::PE::Binary> from;
std::unique_ptr<LIEF::PE::Binary> to;
to->set_resources(*from->resources());
to->write("new.exe");
to_pe.set_resources(&from_pe.resources().unwrap());