check Root Directory Entry's Name

This commit is contained in:
olszomal 2022-02-24 15:19:45 +01:00 committed by Michał Trojnara
parent e0d652b987
commit 77b2b30d1f
3 changed files with 28 additions and 5 deletions

19
msi.c
View File

@ -302,7 +302,7 @@ static MSI_FILE_HDR *parse_header(char *data)
}
/* Parse MSI_ENTRY struct */
static MSI_ENTRY *parse_entry(MSI_FILE *msi, const u_char *data)
static MSI_ENTRY *parse_entry(MSI_FILE *msi, const u_char *data, int is_root)
{
uint32_t inlen;
MSI_ENTRY *entry = (MSI_ENTRY *)OPENSSL_malloc(sizeof(MSI_ENTRY));
@ -317,6 +317,13 @@ static MSI_ENTRY *parse_entry(MSI_FILE *msi, const u_char *data)
return NULL; /* FAILED */
}
memcpy(entry->name, data + DIRENT_NAME, entry->nameLen);
/* The root directory entry's Name field MUST contain the null-terminated
* string "Root Entry" in Unicode UTF-16. */
if (is_root && memcmp(entry->name, root_entry, entry->nameLen)) {
printf("Corrupted Root Directory Entry's Name\n");
OPENSSL_free(entry);
return NULL; /* FAILED */
}
entry->type = GET_UINT8_LE(data + DIRENT_TYPE);
entry->colorFlag = GET_UINT8_LE(data + DIRENT_COLOUR);
entry->leftSiblingID = GET_UINT32_LE(data + DIRENT_LEFT_SIBLING_ID);
@ -325,6 +332,13 @@ static MSI_ENTRY *parse_entry(MSI_FILE *msi, const u_char *data)
memcpy(entry->clsid, data + DIRENT_CLSID, 16);
memcpy(entry->stateBits, data + DIRENT_STATE_BITS, 4);
memcpy(entry->creationTime, data + DIRENT_CREATE_TIME, 8);
/* The Creation Time field in the root storage directory entry MUST be all zeroes
but the Modified Time field in the root storage directory entry MAY be all zeroes */
if (is_root && memcmp(entry->creationTime, zeroes, 8)) {
printf("Corrupted Root Directory Entry's Creation Time\n");
OPENSSL_free(entry);
return NULL; /* FAILED */
}
memcpy(entry->modifiedTime, data + DIRENT_MODIFY_TIME, 8);
entry->startSectorLocation = GET_UINT32_LE(data + DIRENT_START_SECTOR_LOC);
memcpy(entry->size, data + DIRENT_FILE_SIZE, 8);
@ -376,7 +390,7 @@ static MSI_ENTRY *get_entry(MSI_FILE *msi, uint32_t entryID, int is_root)
printf("Failed to get a final address\n");
return NULL; /* FAILED */
}
return parse_entry(msi, address);
return parse_entry(msi, address, is_root);
}
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi)
@ -446,7 +460,6 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
printf("Corrupted Directory Entry Name Length\n");
return 0; /* FAILED */
}
/* detect cycles in previously visited entries (parents, siblings) */
if (!ret) { /* initialized (non-root entry) */
if ((entry->leftSiblingID != NOSTREAM && tortoise->entry->leftSiblingID == entry->leftSiblingID)

10
msi.h
View File

@ -200,6 +200,16 @@ static const u_char digital_signature_ex[] = {
0x45, 0x00, 0x78, 0x00, 0x00, 0x00
};
static const u_char root_entry[] = {
0x52, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x74, 0x00,
0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x74, 0x00,
0x72, 0x00, 0x79, 0x00, 0x00, 0x00
};
static const u_char zeroes[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer, uint32_t len);
MSI_FILE *msi_file_new(char *buffer, uint32_t len);
void msi_file_free(MSI_FILE *msi);

View File

@ -2905,7 +2905,6 @@ static int verify_signature(SIGNATURE *signature, GLOBAL_OPTIONS *options)
static int msi_verify_header(char *indata, uint32_t filesize, MSI_PARAMS *msiparams)
{
int ret = 1;
MSI_ENTRY *root;
MSI_DIRENT *root_dir = NULL;
@ -2925,7 +2924,8 @@ static int msi_verify_header(char *indata, uint32_t filesize, MSI_PARAMS *msipar
return 0; /* FAILED */
}
msiparams->dirent = root_dir;
return ret;
return 1; /* OK */
}
static int msi_verify_pkcs7(SIGNATURE *signature, MSI_FILE *msi, MSI_DIRENT *dirent,