mirror of
https://github.com/rizinorg/rizin.git
synced 2026-10-12 02:21:57 +00:00
librz/bin: add iH header structure support for Menuet format (#6189)
* librz/bin: add `iH` header structure for Menuet format * librz/bin: parse Menuet headers by version
This commit is contained in:
@@ -81,6 +81,133 @@ static ut64 menuetEntry(const ut8 *buf, int buf_size) {
|
||||
return UT64_MAX;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ut8 magic[8];
|
||||
ut8 version_char;
|
||||
ut32 header_version;
|
||||
ut32 program_start;
|
||||
ut32 image_size;
|
||||
ut32 memory_size;
|
||||
ut32 field_24;
|
||||
ut32 field_28;
|
||||
ut32 field_32;
|
||||
ut32 tls_map;
|
||||
ut32 import_start;
|
||||
ut32 import_end;
|
||||
ut32 entry_point;
|
||||
bool truncated_v2;
|
||||
} MenuetHeader;
|
||||
|
||||
static bool menuet_parse_header(RzBuffer *buf, MenuetHeader *hdr) {
|
||||
rz_return_val_if_fail(buf && hdr, false);
|
||||
const ut64 sz = rz_buf_size(buf);
|
||||
if (sz < 32) {
|
||||
return false;
|
||||
}
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
|
||||
ut64 off = 0;
|
||||
if (!rz_buf_read_offset(buf, &off, hdr->magic, sizeof(hdr->magic)) ||
|
||||
memcmp(hdr->magic, "MENUET0", 7) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->header_version) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->program_start) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->image_size) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->memory_size) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->field_24)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hdr->version_char = MENUET_VERSION(hdr->magic);
|
||||
if (hdr->version_char == '0') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!rz_buf_read_le32_offset(buf, &off, &hdr->field_28) ||
|
||||
!rz_buf_read_le32_offset(buf, &off, &hdr->field_32)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdr->version_char == '1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hdr->version_char != '2') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sz < 52) {
|
||||
hdr->truncated_v2 = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return rz_buf_read_le32_offset(buf, &off, &hdr->tls_map) &&
|
||||
rz_buf_read_le32_offset(buf, &off, &hdr->import_start) &&
|
||||
rz_buf_read_le32_offset(buf, &off, &hdr->import_end) &&
|
||||
rz_buf_read_le32_offset(buf, &off, &hdr->entry_point);
|
||||
}
|
||||
|
||||
static RzStructuredData *menuet_structure(RzBinFile *bf) {
|
||||
rz_return_val_if_fail(bf && bf->buf, NULL);
|
||||
|
||||
MenuetHeader hdr;
|
||||
if (!menuet_parse_header(bf->buf, &hdr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RzStructuredData *info = rz_structured_data_new_map();
|
||||
if (!info) {
|
||||
return NULL;
|
||||
}
|
||||
RzStructuredData *menuet = rz_structured_data_map_add_map(info, "menuet");
|
||||
if (!menuet) {
|
||||
rz_structured_data_free(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const ut8 version_char = hdr.version_char;
|
||||
const ut64 version = (version_char >= '0' && version_char <= '9') ? (ut64)(version_char - '0') : UT64_MAX;
|
||||
rz_structured_data_map_add_bytes(menuet, "magic", hdr.magic, sizeof(hdr.magic), RZ_STRUCTURED_DATA_FORMAT_HEXDUMP);
|
||||
if (version != UT64_MAX) {
|
||||
rz_structured_data_map_add_unsigned(menuet, "version", version, false);
|
||||
}
|
||||
|
||||
rz_structured_data_map_add_unsigned(menuet, "program_start", hdr.program_start, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "image_size", hdr.image_size, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "memory_size", hdr.memory_size, true);
|
||||
|
||||
switch (version_char) {
|
||||
case '0':
|
||||
rz_structured_data_map_add_unsigned(menuet, "required_os", hdr.header_version, false);
|
||||
rz_structured_data_map_add_unsigned(menuet, "reserved", hdr.field_24, true);
|
||||
break;
|
||||
case '1':
|
||||
rz_structured_data_map_add_unsigned(menuet, "header_version", hdr.header_version, false);
|
||||
rz_structured_data_map_add_unsigned(menuet, "stack_pointer", hdr.field_24, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "parameters", hdr.field_28, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "path", hdr.field_32, true);
|
||||
break;
|
||||
case '2':
|
||||
if (hdr.truncated_v2) {
|
||||
rz_structured_data_map_add_boolean(menuet, "truncated", true);
|
||||
break;
|
||||
}
|
||||
rz_structured_data_map_add_unsigned(menuet, "header_version", hdr.header_version, false);
|
||||
rz_structured_data_map_add_unsigned(menuet, "stack_pointer", hdr.field_24, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "cmdline", hdr.field_28, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "path", hdr.field_32, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "tls_map", hdr.tls_map, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "import_start", hdr.import_start, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "import_end", hdr.import_end, true);
|
||||
rz_structured_data_map_add_unsigned(menuet, "entry_point", hdr.entry_point, true);
|
||||
break;
|
||||
default:
|
||||
rz_structured_data_map_add_boolean(menuet, "unknown_version", true);
|
||||
break;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static RzPVector /*<RzBinAddr *>*/ *entries(RzBinFile *bf) {
|
||||
RzPVector *ret;
|
||||
ut8 buf[64] = { 0 };
|
||||
@@ -209,6 +336,7 @@ RzBinPlugin rz_bin_plugin_menuet = {
|
||||
.maps = &rz_bin_maps_of_file_sections,
|
||||
.sections = §ions,
|
||||
.info = &info,
|
||||
.bin_structure = &menuet_structure,
|
||||
.create = &create,
|
||||
};
|
||||
|
||||
|
||||
+16
-2
@@ -1,8 +1,22 @@
|
||||
NAME=Menuet: Open/iI
|
||||
NAME=Menuet: Open/iI/iH
|
||||
FILE=bins/menuet/dosbox
|
||||
CMDS=iI~?MenuetOS
|
||||
CMDS=<<EOF
|
||||
iI~?MenuetOS
|
||||
iH
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
1
|
||||
menuet:
|
||||
magic: "4d 45 4e 55 45 54 30 31 |MENUET01 |"
|
||||
version: 1
|
||||
program_start: 0x24
|
||||
image_size: 0x11b000
|
||||
memory_size: 0x1526000
|
||||
header_version: 1
|
||||
stack_pointer: 0x11f000
|
||||
parameters: 0x11f000
|
||||
path: 0x0
|
||||
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
||||
Reference in New Issue
Block a user