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:
parent
4eeeec32b4
commit
a6d3be739e
88
msi.c
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
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 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user