1
0
mirror of https://github.com/mtrojnar/osslsigncode.git synced 2025-04-09 18:48:05 -05:00

detect recursion loop

This commit is contained in:
Michał Trojnara 2022-02-18 22:33:03 +01:00
parent 4eeeec32b4
commit a6d3be739e
3 changed files with 56 additions and 39 deletions

88
msi.c

@ -404,9 +404,9 @@ MSI_FILE_HDR *msi_header_get(MSI_FILE *msi)
} }
/* Recursively parse MSI_DIRENT struct */ /* Recursively parse MSI_DIRENT struct */
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret, int verbose) int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT *prev, MSI_DIRENT **ret, int verbose)
{ {
MSI_DIRENT *dirent, *unused = NULL; MSI_DIRENT *dirent;
MSI_ENTRY *lnode = NULL, *rnode = NULL, *cnode = NULL; MSI_ENTRY *lnode = NULL, *rnode = NULL, *cnode = NULL;
if (!entry) { if (!entry) {
@ -416,12 +416,22 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
if (verbose) printf("Corrupted Directory Entry Name Length\n"); if (verbose) printf("Corrupted Directory Entry Name Length\n");
return 0; /* FAILED */ return 0; /* FAILED */
} }
/* detect loops in previously visited entries (parents, siblings) */
if (entry->childID != NOSTREAM) {
for (dirent = prev; dirent; dirent = dirent->prev) {
if (dirent->entry->childID == entry->childID) {
printf("Entry loop at ID: 0x%08X\n", entry->childID);
return 0; /* FAILED */
}
}
}
dirent = (MSI_DIRENT *)OPENSSL_malloc(sizeof(MSI_DIRENT)); dirent = (MSI_DIRENT *)OPENSSL_malloc(sizeof(MSI_DIRENT));
memcpy(dirent->name, entry->name, entry->nameLen); memcpy(dirent->name, entry->name, entry->nameLen);
dirent->nameLen = entry->nameLen; dirent->nameLen = entry->nameLen;
dirent->type = entry->type; dirent->type = entry->type;
dirent->entry = entry; dirent->entry = entry;
dirent->children = sk_MSI_DIRENT_new_null(); dirent->children = sk_MSI_DIRENT_new_null();
dirent->prev = prev;
if (parent && !sk_MSI_DIRENT_push(parent->children, dirent)) { if (parent && !sk_MSI_DIRENT_push(parent->children, dirent)) {
if (verbose) printf("Failed to insert MSI_DIRENT\n"); if (verbose) printf("Failed to insert MSI_DIRENT\n");
@ -430,45 +440,51 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
return 0; /* FAILED */ return 0; /* FAILED */
} }
/* NOTE : These links are a tree, not a linked list */ /* NOTE : These links are a tree, not a linked list */
if (!get_entry(msi, entry->leftSiblingID, FALSE, &lnode, verbose)) { /* The special value NOSTREAM (0xFFFFFFFF) is used as a terminator */
if (verbose) printf("Corrupted Left Sibling ID: 0x%08X\n", entry->leftSiblingID); if (entry->leftSiblingID != NOSTREAM) {
sk_MSI_DIRENT_free(dirent->children); if (!get_entry(msi, entry->leftSiblingID, FALSE, &lnode, verbose)) {
OPENSSL_free(dirent); if (verbose) printf("Corrupted Left Sibling ID: 0x%08X\n", entry->leftSiblingID);
return 0; /* FAILED */ sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent);
return 0; /* FAILED */
}
if (!msi_dirent_new(msi, lnode, parent, dirent, NULL, verbose)) {
OPENSSL_free(lnode);
sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent);
return 0; /* FAILED */
}
} }
if (!msi_dirent_new(msi, lnode, parent, &unused, verbose)) { if (entry->rightSiblingID != NOSTREAM) {
OPENSSL_free(lnode); if (!get_entry(msi, entry->rightSiblingID, FALSE, &rnode, verbose)) {
sk_MSI_DIRENT_free(dirent->children); if (verbose) printf("Corrupted Right Sibling ID: 0x%08X\n", entry->rightSiblingID);
OPENSSL_free(dirent); sk_MSI_DIRENT_free(dirent->children);
return 0; /* FAILED */ OPENSSL_free(dirent);
return 0; /* FAILED */
}
if (!msi_dirent_new(msi, rnode, parent, dirent, NULL, verbose)) {
OPENSSL_free(rnode);
sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent);
return 0; /* FAILED */
}
} }
if (!get_entry(msi, entry->rightSiblingID, FALSE, &rnode, verbose)) { if (entry->type != DIR_STREAM && entry->childID != NOSTREAM) {
if (verbose) printf("Corrupted Right Sibling ID: 0x%08X\n", entry->rightSiblingID);
sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent);
return 0; /* FAILED */
}
if (!msi_dirent_new(msi, rnode, parent, &unused, verbose)) {
OPENSSL_free(rnode);
sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent);
return 0; /* FAILED */
}
if (entry->type != DIR_STREAM) {
if (!get_entry(msi, entry->childID, FALSE, &cnode, verbose)) { if (!get_entry(msi, entry->childID, FALSE, &cnode, verbose)) {
if (verbose) printf("Corrupted Child ID: 0x%08X\n", entry->childID); if (verbose) printf("Corrupted Child ID: 0x%08X\n", entry->childID);
sk_MSI_DIRENT_free(dirent->children); sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent); OPENSSL_free(dirent);
return 0; /* FAILED */ return 0; /* FAILED */
} }
if (!msi_dirent_new(msi, cnode, dirent, &unused, verbose)) { if (!msi_dirent_new(msi, cnode, dirent, dirent, NULL, verbose)) {
OPENSSL_free(cnode); OPENSSL_free(cnode);
sk_MSI_DIRENT_free(dirent->children); sk_MSI_DIRENT_free(dirent->children);
OPENSSL_free(dirent); OPENSSL_free(dirent);
return 0; /* FAILED */ return 0; /* FAILED */
} }
} }
*ret = dirent; if (ret)
*ret = dirent;
return 1; /* OK */ return 1; /* OK */
} }
@ -845,7 +861,7 @@ static int stream_handle(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, int l
/* set the size of the user-defined data if this is a stream object */ /* set the size of the user-defined data if this is a stream object */
PUT_UINT32_LE(inlen, buf); PUT_UINT32_LE(inlen, buf);
memcpy(child->entry->size, buf, sizeof child->entry->size); memcpy(child->entry->size, buf, sizeof child->entry->size);
if (inlen < MINI_STREAM_CUTOFF_SIZE) { if (inlen < MINI_STREAM_CUTOFF_SIZE) {
/* set the index into the mini FAT to track the chain of sectors through the mini stream */ /* set the index into the mini FAT to track the chain of sectors through the mini stream */
child->entry->startSectorLocation = out->miniSectorNum; child->entry->startSectorLocation = out->miniSectorNum;
@ -926,7 +942,7 @@ static void minifat_save(BIO *outdata, MSI_OUT *out)
{ {
char buf[MAX_SECTOR_SIZE]; char buf[MAX_SECTOR_SIZE];
int i,remain; int i,remain;
/* set Mini FAT Starting Sector Location in the header */ /* set Mini FAT Starting Sector Location in the header */
if (out->minifatLen == 0) { if (out->minifatLen == 0) {
PUT_UINT32_LE(ENDOFCHAIN, buf); PUT_UINT32_LE(ENDOFCHAIN, buf);
@ -1029,7 +1045,7 @@ static int dirents_save(MSI_DIRENT *dirent, BIO *outdata, MSI_OUT *out, int *str
} else { /* DIR_ROOT */ } else { /* DIR_ROOT */
dirent->entry->rightSiblingID = NOSTREAM; dirent->entry->rightSiblingID = NOSTREAM;
} }
dirent->entry->childID = *streamId + 1; dirent->entry->childID = *streamId + 1;
entry = msi_dirent_get(dirent->entry); entry = msi_dirent_get(dirent->entry);
BIO_write(outdata, entry, DIRENT_SIZE); BIO_write(outdata, entry, DIRENT_SIZE);
OPENSSL_free(entry); OPENSSL_free(entry);
@ -1104,7 +1120,7 @@ static int fat_save(BIO *outdata, MSI_OUT *out)
{ {
char buf[MAX_SECTOR_SIZE]; char buf[MAX_SECTOR_SIZE];
int i, remain; int i, remain;
remain = (out->fatLen + out->sectorSize - 1) / out->sectorSize; remain = (out->fatLen + out->sectorSize - 1) / out->sectorSize;
out->fatSectorsCount = (out->fatLen + remain * 4 + out->sectorSize - 1) / out->sectorSize; out->fatSectorsCount = (out->fatLen + remain * 4 + out->sectorSize - 1) / out->sectorSize;
@ -1182,7 +1198,7 @@ static char *header_new(MSI_FILE_HDR *hdr, MSI_OUT *out)
} else { } else {
PUT_UINT16_LE(0x0003, buf); PUT_UINT16_LE(0x0003, buf);
} }
memcpy(data + HEADER_MAJOR_VER, buf, 2); memcpy(data + HEADER_MAJOR_VER, buf, 2);
PUT_UINT16_LE(hdr->byteOrder, buf); PUT_UINT16_LE(hdr->byteOrder, buf);
memcpy(data + HEADER_BYTE_ORDER, buf, 2); memcpy(data + HEADER_BYTE_ORDER, buf, 2);
PUT_UINT16_LE(hdr->sectorShift, buf); PUT_UINT16_LE(hdr->sectorShift, buf);
@ -1238,7 +1254,7 @@ static int msiout_set(MSI_FILE *msi, int len_msi, int len_msiex, MSI_OUT *out)
return 0;/* FAILED */ return 0;/* FAILED */
} }
out->header = header_new(hdr, out); out->header = header_new(hdr, out);
out->minifatMemallocCount = hdr->numMiniFATSector; out->minifatMemallocCount = hdr->numMiniFATSector;
out->fatMemallocCount = hdr->numFATSector; out->fatMemallocCount = hdr->numFATSector;
out->ministream = NULL; out->ministream = NULL;
out->minifat = OPENSSL_malloc(out->minifatMemallocCount * out->sectorSize); out->minifat = OPENSSL_malloc(out->minifatMemallocCount * out->sectorSize);
@ -1254,7 +1270,7 @@ int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p_msi, int len_msi
MSI_OUT out; MSI_OUT out;
int ret = 0; int ret = 0;
memset(&out, 0, sizeof(MSI_OUT)); memset(&out, 0, sizeof(MSI_OUT));
if (!msiout_set(msi, len_msi, len_msiex, &out)) { if (!msiout_set(msi, len_msi, len_msiex, &out)) {
goto out; /* FAILED */ goto out; /* FAILED */
} }

5
msi.h

@ -139,12 +139,13 @@ typedef struct {
u_char size[8]; u_char size[8];
} MSI_ENTRY; } MSI_ENTRY;
typedef struct { typedef struct msi_dirent_struct {
u_char name[DIRENT_MAX_NAME_SIZE]; u_char name[DIRENT_MAX_NAME_SIZE];
uint16_t nameLen; uint16_t nameLen;
uint8_t type; uint8_t type;
MSI_ENTRY *entry; MSI_ENTRY *entry;
STACK_OF(MSI_DIRENT) *children; STACK_OF(MSI_DIRENT) *children;
struct msi_dirent_struct *prev; /* detect loops */
} MSI_DIRENT; } MSI_DIRENT;
DEFINE_STACK_OF(MSI_DIRENT) DEFINE_STACK_OF(MSI_DIRENT)
@ -203,7 +204,7 @@ int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer
MSI_FILE *msi_file_new(char *buffer, uint32_t len, int verbose); MSI_FILE *msi_file_new(char *buffer, uint32_t len, int verbose);
void msi_file_free(MSI_FILE *msi); void msi_file_free(MSI_FILE *msi);
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi, int verbose); MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi, int verbose);
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret, int verbose); int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT *prev, MSI_DIRENT **ret, int verbose);
MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse); MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
void msi_dirent_free(MSI_DIRENT *dirent); void msi_dirent_free(MSI_DIRENT *dirent);
MSI_FILE_HDR *msi_header_get(MSI_FILE *msi); MSI_FILE_HDR *msi_header_get(MSI_FILE *msi);

@ -2919,7 +2919,7 @@ static int msi_verify_header(char *indata, uint32_t filesize, MSI_PARAMS *msipar
printf("Failed to get file entry\n"); printf("Failed to get file entry\n");
return 0; /* FAILED */ return 0; /* FAILED */
} }
if (!msi_dirent_new(msiparams->msi, root, NULL, &root_dir, verbose)) { if (!msi_dirent_new(msiparams->msi, root, NULL, NULL, &root_dir, verbose)) {
printf("Failed to parse MSI_DIRENT struct\n"); printf("Failed to parse MSI_DIRENT struct\n");
OPENSSL_free(root); OPENSSL_free(root);
return 0; /* FAILED */ return 0; /* FAILED */