Example 4: Filesystem Modification
This example collates previous examples, and additionally demonstrates the filesystem unpacking
capabilities of OFRAK.
The input to this example is a SquashFS filesystem which includes our boring old "Hello, World!"
program in it:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
The example unpacks the SquashFS input, and analyzes each of its contents including the "Hello,
World!" program. For that program it modifies the "Hello, World!" string, replacing it with
something even more fun and furry 😼😼. More Meow! Finally, the example modifies the executable's
permission bits and extended attributes as part of the SquashFS filesystem, before repacking it.
Example OFRAK script:
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | import argparse
import os
import stat
from ofrak import OFRAK, OFRAKContext
from ofrak.core import BinaryPatchConfig, BinaryPatchModifier
from ofrak.core.squashfs import SquashfsFilesystem
ASSETS_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "assets"))
SQUASHFS_FILE = os.path.join(ASSETS_DIR, "sample.sqsh")
async def main(ofrak_context: OFRAKContext, file_path: str, output_file_name: str):
# Create resource
root_resource = await ofrak_context.create_root_resource_from_file(file_path)
# Unpack resource
await root_resource.unpack_recursively()
# Get the program from inside the SquashFS filesystem
squashfs_view = await root_resource.view_as(SquashfsFilesystem)
hello_world_program_path = "src/program"
hello_world_program = await squashfs_view.get_entry(hello_world_program_path)
# Get the "Hello, World!" string location in the program and patch it with "More meow!"
program_data = await hello_world_program.resource.get_data()
hello_world_offset = program_data.find(b"Hello, World!")
new_string_config = BinaryPatchConfig(hello_world_offset, b"More meow!\0")
await hello_world_program.resource.run(BinaryPatchModifier, new_string_config)
# Modify the program permission bits and xattrs before repacking
print(f"Initial st_mode: {hello_world_program.stat.st_mode:o}")
print(f"Initial xattrs: {hello_world_program.xattrs}")
await hello_world_program.modify_stat_attribute(stat.ST_MODE, 0o100755)
await hello_world_program.modify_xattr_attribute("user.foo", b"bar")
print(f"Modified st_mode: {hello_world_program.stat.st_mode:o}")
print(f"Modified xattrs: {hello_world_program.xattrs}")
# Dump the repacked file to the disk
await root_resource.pack()
await root_resource.flush_data_to_disk(output_file_name)
print(f"Done! Output file written to {output_file_name}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--hello-world-file", default=SQUASHFS_FILE)
parser.add_argument("--output-file-name", default="./example_4_more_meow.sqsh")
args = parser.parse_args()
ofrak = OFRAK()
ofrak.run(main, args.hello_world_file, args.output_file_name)
|