Filza 27.2 worse_query: public and developer builds

This commit is contained in:
admin committed 2026-11-11 03:40:37 +08:00
commit 91a6adf723
267 files changed
+42015

No files matched your search

+523
View File
@@ -0,0 +1,523 @@
#include "CSBlob.h"
#include "CodeDirectory.h"
#include "MachO.h"
#include "MachOByteOrder.h"
#include "BufferedStream.h"
#include "MemoryStream.h"
#include "Util.h"
#include <mach-o/loader.h>
#include <stddef.h>
#include <stdint.h>
const char *cs_blob_magic_to_string(uint32_t magic)
{
switch (magic) {
case CSMAGIC_REQUIREMENT:
return "Requirement blob";
case CSMAGIC_REQUIREMENTS:
return "Requirements blob";
case CSMAGIC_CODEDIRECTORY:
return "Code directory blob";
case CSMAGIC_EMBEDDED_SIGNATURE:
return "Embedded signature blob";
case CSMAGIC_EMBEDDED_SIGNATURE_OLD:
return "Embedded signature blob (old)";
case CSMAGIC_EMBEDDED_ENTITLEMENTS:
return "Entitlements blob";
case CSMAGIC_EMBEDDED_DER_ENTITLEMENTS:
return "DER entitlements blob";
case CSMAGIC_DETACHED_SIGNATURE:
return "Detached signature blob";
case CSMAGIC_BLOBWRAPPER:
return "Signature blob";
case CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT:
return "Launchd contraint blob";
default:
return "Unknown blob type";
}
}
const char *cs_slot_type_to_string(uint32_t slotType)
{
if (slotType & CSSLOT_ALTERNATE_CODEDIRECTORIES) {
int num = slotType & 0xfff;
switch (num) {
case 0:
return "Alternate code directory slot (1)";
case 1:
return "Alternate code directory slot (2)";
case 2:
return "Alternate code directory slot (3)";
case 3:
return "Alternate code directory slot (4)";
case 4:
return "Alternate code directory slot (5)";
default:
return "Alternate code directory slot (invalid)";
}
}
switch (slotType) {
case CSSLOT_CODEDIRECTORY:
return "Code directory slot";
case CSSLOT_INFOSLOT:
return "Info slot";
case CSSLOT_REQUIREMENTS:
return "Requirements slot";
case CSSLOT_RESOURCEDIR:
return "Resource Dir slot";
case CSSLOT_APPLICATION:
return "Application slot";
case CSSLOT_ENTITLEMENTS:
return "Entitlements slot";
case CSSLOT_DER_ENTITLEMENTS:
return "DER entitlements slot";
case CSSLOT_LAUNCH_CONSTRAINT_SELF:
return "Launch constraint slot (self)";
case CSSLOT_LAUNCH_CONSTRAINT_PARENT:
return "Launch constraint slot (parent)";
case CSSLOT_LAUNCH_CONSTRAINT_RESPONSIBLE:
return "Launch constraint slot (responsible)";
case CSSLOT_LIBRARY_CONSTRAINT:
return "Library constraint slot";
case CSSLOT_SIGNATURESLOT:
return "Signature slot";
case CSSLOT_IDENTIFICATIONSLOT:
return "Identification slot";
case CSSLOT_TICKETSLOT:
return "Ticket slot";
default:
return "Unknown blob type";
}
}
int macho_parse_signature_blob_to_der_encoded_data(MachO *macho, uint32_t signatureBlobOffset, uint32_t signatureBlobLength, void *outputDER)
{
return macho_read_at_offset(macho, signatureBlobOffset + 8, signatureBlobLength - 8, outputDER);
}
int macho_find_code_signature_bounds(MachO *macho, uint32_t *offsetOut, uint32_t *sizeOut)
{
__block int r = -1;
macho_enumerate_load_commands(macho, ^(struct load_command loadCommand, uint64_t offset, void *cmd, bool *stop) {
if (loadCommand.cmd == LC_CODE_SIGNATURE) {
struct linkedit_data_command *csLoadCommand = ((struct linkedit_data_command *)cmd);
LINKEDIT_DATA_COMMAND_APPLY_BYTE_ORDER(csLoadCommand, LITTLE_TO_HOST_APPLIER);
if (offsetOut) *offsetOut = csLoadCommand->dataoff;
if (sizeOut) *sizeOut = csLoadCommand->datasize;
*stop = true;
r = 0;
}
});
return r;
}
CS_SuperBlob *macho_read_code_signature(MachO *macho)
{
uint32_t offset = 0, size = 0;
if (macho_find_code_signature_bounds(macho, &offset, &size) == 0) {
CS_SuperBlob *dataOut = malloc(size);
if (macho_read_at_offset(macho, offset, size, dataOut) == 0) {
return dataOut;
}
else {
free(dataOut);
}
}
return NULL;
}
int macho_replace_code_signature(MachO *macho, CS_SuperBlob *superblob)
{
uint32_t csSegmentOffset = 0, csSegmentSize = 0;
macho_find_code_signature_bounds(macho, &csSegmentOffset, &csSegmentSize);
uint32_t sizeOfCodeSignature = 0;
memory_stream_read(macho->stream, csSegmentOffset + offsetof(CS_SuperBlob, length), sizeof(sizeOfCodeSignature), &sizeOfCodeSignature);
sizeOfCodeSignature = BIG_TO_HOST(sizeOfCodeSignature);
uint64_t newCodeSignatureSize = BIG_TO_HOST(superblob->length);
// See how much space we have to write the new code signature
uint64_t entireFileSize = memory_stream_get_size(macho->stream);
uint64_t freeSpace = entireFileSize - csSegmentOffset;
uint64_t paddingSize = freeSpace - sizeOfCodeSignature;
if (newCodeSignatureSize >= freeSpace) {
macho_write_at_offset(macho, csSegmentOffset, newCodeSignatureSize, superblob);
uint8_t padding[paddingSize];
memset(padding, 0, paddingSize);
macho_write_at_offset(macho, csSegmentOffset + newCodeSignatureSize, paddingSize, padding);
} else if (newCodeSignatureSize < freeSpace) {
memory_stream_trim(macho_get_stream(macho), 0, entireFileSize - csSegmentOffset);
macho_write_at_offset(macho, csSegmentOffset, newCodeSignatureSize, superblob);
uint8_t padding[paddingSize];
memset(padding, 0, paddingSize);
macho_write_at_offset(macho, csSegmentOffset + newCodeSignatureSize, paddingSize, padding);
}
return 0;
}
int macho_extract_cs_to_file(MachO *macho, CS_SuperBlob *superblob)
{
FILE *csDataFile = fopen("Code_Signature-Data", "wb+");
fwrite(superblob, BIG_TO_HOST(superblob->length), 1, csDataFile);
fclose(csDataFile);
return 0;
}
CS_DecodedBlob *csd_blob_init(uint32_t type, CS_GenericBlob *blobData)
{
CS_DecodedBlob *blob = malloc(sizeof(CS_DecodedBlob));
if (!blob) return NULL;
memset(blob, 0, sizeof(CS_DecodedBlob));
blob->type = type;
blob->stream = buffered_stream_init_from_buffer(blobData, BIG_TO_HOST(blobData->length), BUFFERED_STREAM_FLAG_AUTO_EXPAND);
return blob;
}
int csd_blob_read(CS_DecodedBlob *blob, uint64_t offset, size_t size, void *outBuf)
{
return memory_stream_read(blob->stream, offset, size, outBuf);
}
static void _csd_blob_fix_length(CS_DecodedBlob *blob)
{
uint32_t curSize = HOST_TO_BIG((uint32_t)memory_stream_get_size(blob->stream));
memory_stream_write(blob->stream, offsetof(CS_GenericBlob, length), sizeof(curSize), &curSize);
}
int csd_blob_write(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf)
{
int r = memory_stream_write(blob->stream, offset, size, inBuf);
if (r == 0) _csd_blob_fix_length(blob);
return r;
}
int csd_blob_insert(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf)
{
int r = memory_stream_insert(blob->stream, offset, size, inBuf);
if (r == 0) _csd_blob_fix_length(blob);
return r;
}
int csd_blob_delete(CS_DecodedBlob *blob, uint64_t offset, size_t size)
{
int r = memory_stream_delete(blob->stream, offset, size);
if (r == 0) _csd_blob_fix_length(blob);
return r;
}
int csd_blob_read_string(CS_DecodedBlob *blob, uint64_t offset, char **outString)
{
return memory_stream_read_string(blob->stream, offset, outString);
}
int csd_blob_write_string(CS_DecodedBlob *blob, uint64_t offset, const char *string)
{
int r = memory_stream_write_string(blob->stream, offset, string);
if (r == 0) _csd_blob_fix_length(blob);
return r;
}
size_t csd_blob_get_size(CS_DecodedBlob *blob)
{
return memory_stream_get_size(blob->stream);
}
uint32_t csd_blob_get_type(CS_DecodedBlob *blob)
{
return blob->type;
}
void csd_blob_set_type(CS_DecodedBlob *blob, uint32_t type)
{
blob->type = type;
}
void csd_blob_free(CS_DecodedBlob *blob)
{
if (blob->stream) {
memory_stream_free(blob->stream);
}
free(blob);
}
CS_DecodedSuperBlob *csd_superblob_init(void)
{
CS_DecodedSuperBlob *decodedSuperblob = malloc(sizeof(CS_DecodedSuperBlob));
if (!decodedSuperblob) return NULL;
memset(decodedSuperblob, 0, sizeof(CS_DecodedSuperBlob));
return decodedSuperblob;
}
CS_DecodedSuperBlob *csd_superblob_decode(CS_SuperBlob *superblob)
{
uint32_t magic = BIG_TO_HOST(superblob->magic);
if (magic != CSMAGIC_EMBEDDED_SIGNATURE && magic != CSMAGIC_DETACHED_SIGNATURE) return NULL;
CS_DecodedSuperBlob *decodedSuperblob = csd_superblob_init();
if (!decodedSuperblob) return NULL;
CS_DecodedBlob **nextBlob = &decodedSuperblob->firstBlob;
decodedSuperblob->magic = magic;
for (uint32_t i = 0; i < BIG_TO_HOST(superblob->count); i++) {
CS_BlobIndex curIndex = superblob->index[i];
BLOB_INDEX_APPLY_BYTE_ORDER(&curIndex, BIG_TO_HOST_APPLIER);
//printf("decoding %u (type: %x, offset: 0x%x)\n", i, curIndex.type, curIndex.offset);
CS_GenericBlob *curBlobData = (CS_GenericBlob *)(((uint8_t*)superblob) + curIndex.offset);
*nextBlob = csd_blob_init(curIndex.type, curBlobData);
nextBlob = &(*nextBlob)->next;
}
return decodedSuperblob;
}
CS_SuperBlob *csd_superblob_encode(CS_DecodedSuperBlob *decodedSuperblob)
{
uint32_t blobCount = 0, blobSize = 0;
// Determine amount and size of contained blobs
CS_DecodedBlob *nextBlob = decodedSuperblob->firstBlob;
while (nextBlob) {
blobCount++;
blobSize += csd_blob_get_size(nextBlob);
nextBlob = nextBlob->next;
}
uint32_t superblobLength = sizeof(CS_SuperBlob) + (sizeof(CS_BlobIndex) * blobCount) + blobSize;
CS_SuperBlob *superblob = malloc(superblobLength);
// Populate superblob fields
superblob->count = blobCount;
superblob->length = superblobLength;
superblob->magic = decodedSuperblob->magic;
SUPERBLOB_APPLY_BYTE_ORDER(superblob, HOST_TO_BIG_APPLIER)
// Populate indexes and write actual backing data
uint32_t idx = 0;
uint32_t dataStartOffset = sizeof(CS_SuperBlob) + (sizeof(CS_BlobIndex) * blobCount);
uint8_t *superblobData = ((uint8_t*)superblob) + dataStartOffset;
uint8_t *superblobDataCur = superblobData;
nextBlob = decodedSuperblob->firstBlob;
while (nextBlob) {
// Populate blob data
uint32_t curSize = csd_blob_get_size(nextBlob);
csd_blob_read(nextBlob, 0, curSize, superblobDataCur);
// Populate index
CS_BlobIndex *curIndex = &superblob->index[idx];
curIndex->offset = dataStartOffset + (superblobDataCur - superblobData);
curIndex->type = nextBlob->type;
BLOB_INDEX_APPLY_BYTE_ORDER(curIndex, HOST_TO_BIG_APPLIER);
superblobDataCur += curSize;
idx++;
nextBlob = nextBlob->next;
}
return superblob;
}
CS_DecodedBlob *csd_superblob_find_blob(CS_DecodedSuperBlob *superblob, uint32_t type, uint32_t *indexOut)
{
CS_DecodedBlob *blob = superblob->firstBlob;
uint32_t i = 0;
while (blob) {
if (blob->type == type) {
if (indexOut) *indexOut = i;
return blob;
}
blob = blob->next;
i++;
}
return NULL;
}
CS_DecodedBlob *csd_superblob_find_blob_by_magic(CS_DecodedSuperBlob *superblob, uint32_t magic, uint32_t *indexOut)
{
CS_DecodedBlob *blob = superblob->firstBlob;
uint32_t i = 0;
while (blob) {
uint32_t blobMagic = 0;
memory_stream_read(blob->stream, 0, sizeof(uint32_t), &blobMagic);
if (BIG_TO_HOST(blobMagic) == magic) {
if (indexOut) *indexOut = i;
return blob;
}
blob = blob->next;
i++;
}
return NULL;
}
int csd_superblob_insert_blob_after_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToInsert, CS_DecodedBlob *afterBlob)
{
blobToInsert->next = afterBlob->next;
afterBlob->next = blobToInsert;
return 0;
}
int csd_superblob_insert_blob_at_index(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToInsert, uint32_t atIndex)
{
if (atIndex == 0) {
blobToInsert->next = superblob->firstBlob;
superblob->firstBlob = blobToInsert;
return 0;
}
else {
uint32_t i = 0;
CS_DecodedBlob *blobAtIndex = superblob->firstBlob;
while (blobAtIndex && i < atIndex) {
blobAtIndex = blobAtIndex->next;
i++;
}
if (blobAtIndex) {
return csd_superblob_insert_blob_after_blob(superblob, blobToInsert, blobAtIndex);
}
return -1;
}
}
int csd_superblob_append_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToAppend)
{
if (!superblob->firstBlob) {
superblob->firstBlob = blobToAppend;
return 0;
}
CS_DecodedBlob *lastBlob = superblob->firstBlob;
while (lastBlob->next) {
lastBlob = lastBlob->next;
}
return csd_superblob_insert_blob_after_blob(superblob, blobToAppend, lastBlob);
}
int csd_superblob_replace_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *newBlob)
{
uint32_t index = 0;
CS_DecodedBlob *blob = csd_superblob_find_blob(superblob, newBlob->type, &index);
if (blob) {
csd_superblob_remove_blob_at_index(superblob, index);
csd_superblob_insert_blob_at_index(superblob, newBlob, index);
} else {
csd_superblob_append_blob(superblob, newBlob);
}
return 0;
}
int csd_superblob_remove_blob(CS_DecodedSuperBlob *superblob, CS_DecodedBlob *blobToRemove)
{
CS_DecodedBlob *blob = superblob->firstBlob;
if (blob == blobToRemove) {
superblob->firstBlob = blobToRemove->next;
return 0;
}
while (blob) {
if (blob->next == blobToRemove) {
blob->next = blobToRemove->next;
return 0;
}
blob = blob->next;
}
return -1;
}
int csd_superblob_remove_blob_at_index(CS_DecodedSuperBlob *superblob, uint32_t atIndex)
{
if (atIndex == 0) {
return csd_superblob_remove_blob(superblob, superblob->firstBlob);
}
else {
uint32_t i = 0;
CS_DecodedBlob *blobAtIndex = superblob->firstBlob;
while (blobAtIndex && i < atIndex) {
blobAtIndex = blobAtIndex->next;
i++;
}
if (blobAtIndex) {
int r = csd_superblob_remove_blob(superblob, blobAtIndex);
if (r == 0) csd_blob_free(blobAtIndex);
return r;
}
return -1;
}
return 0;
}
CS_DecodedBlob *csd_superblob_find_best_code_directory(CS_DecodedSuperBlob *decodedSuperblob)
{
CS_DecodedBlob *bestCDBlob = NULL;
unsigned bestCDBlobRank = 0;
CS_DecodedBlob *blob = decodedSuperblob->firstBlob;
while (blob) {
if (blob->type == CSSLOT_CODEDIRECTORY || ((CSSLOT_ALTERNATE_CODEDIRECTORIES <= blob->type && blob->type < CSSLOT_ALTERNATE_CODEDIRECTORY_LIMIT))) {
unsigned CDBlobRank = csd_code_directory_calculate_rank(blob);
if (CDBlobRank > bestCDBlobRank) {
bestCDBlob = blob;
bestCDBlobRank = CDBlobRank;
}
}
blob = blob->next;
}
return bestCDBlob;
}
int csd_superblob_calculate_best_cdhash(CS_DecodedSuperBlob *decodedSuperblob, void *cdhashOut, int *cdhashTypeOut)
{
if (!cdhashOut) return -1;
CS_DecodedBlob *bestCDBlob = csd_superblob_find_best_code_directory(decodedSuperblob);
if (cdhashTypeOut) *cdhashTypeOut = csd_code_directory_get_hash_type(bestCDBlob);
return csd_code_directory_calculate_hash(bestCDBlob, cdhashOut);
}
int csd_superblob_print_content(CS_DecodedSuperBlob *decodedSuperblob, MachO *macho, bool printAllSlots, bool verifySlots)
{
CS_DecodedBlob *currentBlob = decodedSuperblob->firstBlob;
int count = 0;
uint32_t offset = 0;
while (currentBlob) {
uint32_t blobType = currentBlob->type;
printf("Slot %d: %s (offset 0x%x, type: 0x%x).\n", count++, cs_slot_type_to_string(blobType), offset, blobType);
if (blobType == CSSLOT_CODEDIRECTORY || blobType == CSSLOT_ALTERNATE_CODEDIRECTORIES) {
csd_code_directory_print_content(currentBlob, macho, printAllSlots, verifySlots);
}
else if (blobType == CSSLOT_SIGNATURESLOT) {
CS_GenericBlob *cms_blob = malloc(sizeof(CS_GenericBlob));
memset(cms_blob, 0, sizeof(CS_GenericBlob));
memory_stream_read(currentBlob->stream, 0, sizeof(CS_GenericBlob), cms_blob);
GENERIC_BLOB_APPLY_BYTE_ORDER(cms_blob, BIG_TO_HOST_APPLIER);
printf("This is the %s, magic %#x.\n", cs_blob_magic_to_string(cms_blob->magic), cms_blob->magic);
}
else {
CS_GenericBlob *generic_blob = malloc(sizeof(CS_GenericBlob));
memset(generic_blob, 0, sizeof(CS_GenericBlob));
memory_stream_read(currentBlob->stream, 0, sizeof(CS_GenericBlob), generic_blob);
GENERIC_BLOB_APPLY_BYTE_ORDER(generic_blob, BIG_TO_HOST_APPLIER);
printf("This is the %s, magic %#x.\n", cs_blob_magic_to_string(generic_blob->magic), generic_blob->magic);
}
offset += csd_blob_get_size(currentBlob);
currentBlob = currentBlob->next;
}
return 0;
}
void csd_superblob_free(CS_DecodedSuperBlob *decodedSuperblob)
{
CS_DecodedBlob *nextBlob = decodedSuperblob->firstBlob;
while (nextBlob) {
CS_DecodedBlob *prevBlob = nextBlob;
nextBlob = nextBlob->next;
csd_blob_free(prevBlob);
}
free(decodedSuperblob);
}