Update ChOma (yes this sucks)

This commit is contained in:
opa334 2024-01-12 15:40:20 +01:00
parent 2587c320d0
commit 206541d9f0
22 changed files with 446 additions and 72 deletions

View File

@ -31,7 +31,7 @@ typedef struct __GenericBlob {
} CS_GenericBlob;
// CMS blob magic types
enum {
typedef enum {
CSMAGIC_REQUIREMENT = 0xfade0c00,
CSMAGIC_REQUIREMENTS = 0xfade0c01,
CSMAGIC_CODEDIRECTORY = 0xfade0c02,
@ -44,7 +44,7 @@ enum {
CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT = 0xfade8181,
} CS_BlobMagic;
enum {
typedef enum {
CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2,
@ -90,8 +90,6 @@ CS_SuperBlob *macho_read_code_signature(MachO *macho);
int macho_replace_code_signature(MachO *macho, CS_SuperBlob *superblob);
int update_load_commands(MachO *macho, CS_SuperBlob *superblob, uint64_t originalSize);
CS_DecodedBlob *csd_blob_init(uint32_t type, CS_GenericBlob *blobData);
int csd_blob_read(CS_DecodedBlob *blob, uint64_t offset, size_t size, void *outBuf);
int csd_blob_write(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf);
@ -104,6 +102,7 @@ uint32_t csd_blob_get_type(CS_DecodedBlob *blob);
void csd_blob_set_type(CS_DecodedBlob *blob, uint32_t type);
void csd_blob_free(CS_DecodedBlob *blob);
CS_DecodedSuperBlob *csd_superblob_init(void);
CS_DecodedSuperBlob *csd_superblob_decode(CS_SuperBlob *superblob);
CS_SuperBlob *csd_superblob_encode(CS_DecodedSuperBlob *decodedSuperblob);
CS_DecodedBlob *csd_superblob_find_blob(CS_DecodedSuperBlob *superblob, uint32_t type, uint32_t *indexOut);

View File

@ -12,7 +12,6 @@
#include "MachOLoadCommand.h"
#include "MemoryStream.h"
// Code directory blob header
typedef struct __CodeDirectory {
uint32_t magic;
@ -26,12 +25,15 @@ typedef struct __CodeDirectory {
uint32_t codeLimit;
uint8_t hashSize;
uint8_t hashType;
uint8_t spare1;
uint8_t platform;
uint8_t pageSize;
uint32_t spare2;
/* Version 0x20100 */
uint32_t scatterOffset;
uint32_t teamOffset;
} CS_CodeDirectory;
} CS_CodeDirectory
__attribute__ ((aligned(1)));
enum CS_HashType {
CS_HASHTYPE_SHA160_160 = 1,
@ -40,7 +42,7 @@ enum CS_HashType {
CS_HASHTYPE_SHA384_384 = 4,
};
char *csd_code_directory_copy_identity(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
char *csd_code_directory_copy_identifier(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
char *csd_code_directory_copy_team_id(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
int csd_code_directory_set_team_id(CS_DecodedBlob *codeDirBlob, char *newTeamID);
uint32_t csd_code_directory_get_flags(CS_DecodedBlob *codeDirBlob);

View File

@ -131,7 +131,7 @@
applier(cd, codeLimit); \
applier(cd, hashSize); \
applier(cd, hashType); \
applier(cd, spare1); \
applier(cd, platform); \
applier(cd, pageSize); \
applier(cd, spare2); \
applier(cd, scatterOffset); \

View File

@ -3,9 +3,9 @@
#include <mach-o/loader.h>
#include "MachO.h"
#include "CSBlob.h"
#include "FileStream.h"
#include "MachOByteOrder.h"
#include "CSBlob.h"
// Convert load command to load command name
char *load_command_to_string(int loadCommand);

View File

@ -55,6 +55,6 @@ int memory_stream_expand(MemoryStream *stream, size_t expandAtStart, size_t expa
void memory_stream_free(MemoryStream *stream);
int memory_stream_copy_data(MemoryStream *originStream, uint64_t originOffset, MemoryStream *targetStream, uint64_t targetOffset, size_t size);
int memory_stream_find_memory(MemoryStream *stream, uint64_t searchOffset, size_t searchSize, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut);
int memory_stream_find_memory(MemoryStream *stream, uint64_t searchStartOffset, uint64_t searchEndOffset, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut);
#endif // MEMORY_STREAM_H

View File

@ -1,11 +1,16 @@
#ifndef PATCHFINDER_H
#define PATCHFINDER_H
#include <stdint.h>
#include "MachO.h"
#define METRIC_TYPE_PATTERN 1
#define METRIC_TYPE_STRING_XREF 2
#define METRIC_TYPE_FUNCTION_XREF 3
enum {
PF_METRIC_TYPE_PATTERN,
PF_METRIC_TYPE_STRING,
PF_METRIC_TYPE_XREF,
};
typedef struct PFSection {
typedef struct s_PFSection {
MachO *macho;
uint64_t fileoff;
uint64_t vmaddr;
@ -14,34 +19,57 @@ typedef struct PFSection {
bool ownsCache;
} PFSection;
PFSection *pf_section_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int pf_section_read_at_relative_offset(PFSection *section, uint64_t rel, size_t size, void *outBuf);
int pf_section_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pf_section_read32(PFSection *section, uint64_t vmaddr);
int pf_section_set_cached(PFSection *section, bool cached);
void pf_section_free(PFSection *section);
PFSection *pfsec_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int pfsec_read_reloff(PFSection *section, uint64_t rel, size_t size, void *outBuf);
uint32_t pfsec_read32_reloff(PFSection *section, uint64_t rel);
int pfsec_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pfsec_read32(PFSection *section, uint64_t vmaddr);
uint64_t pfsec_read64(PFSection *section, uint64_t vmaddr);
int pfsec_read_string(PFSection *section, uint64_t vmaddr, char **outString);
int pfsec_set_cached(PFSection *section, bool cached);
uint64_t pfsec_find_prev_inst(PFSection *section, uint64_t startAddr, uint32_t searchCount, uint32_t inst, uint32_t mask);
uint64_t pfsec_find_next_inst(PFSection *section, uint64_t startAddr, uint32_t searchCount, uint32_t inst, uint32_t mask);
uint64_t pfsec_find_function_start(PFSection *section, uint64_t midAddr);
void pfsec_free(PFSection *section);
typedef struct MetricShared {
typedef struct s_MetricShared {
uint32_t type;
} MetricShared;
typedef enum {
BYTE_PATTERN_ALIGN_8_BIT,
BYTE_PATTERN_ALIGN_16_BIT,
BYTE_PATTERN_ALIGN_32_BIT,
BYTE_PATTERN_ALIGN_64_BIT,
} BytePatternAlignment;
typedef struct BytePatternMetric {
typedef struct s_PFPatternMetric {
MetricShared shared;
void *bytes;
void *mask;
size_t nbytes;
BytePatternAlignment alignment;
} BytePatternMetric;
uint16_t alignment;
} PFPatternMetric;
BytePatternMetric *pf_create_byte_pattern_metric(void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment);
void pf_section_run_metric(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
typedef struct s_PFStringMetric {
MetricShared shared;
char *string;
} PFStringMetric;
typedef enum {
XREF_TYPE_MASK_CALL = (1 << 0),
XREF_TYPE_MASK_REFERENCE = (1 << 1),
XREF_TYPE_MASK_ALL = (XREF_TYPE_MASK_CALL | XREF_TYPE_MASK_REFERENCE),
} PFXrefTypeMask;
typedef struct s_PFXrefMetric {
MetricShared shared;
uint64_t address;
PFXrefTypeMask typeMask;
} PFXrefMetric;
PFPatternMetric *pfmetric_pattern_init(void *bytes, void *mask, size_t nbytes, uint16_t alignment);
PFStringMetric *pfmetric_string_init(const char *string);
PFXrefMetric *pfmetric_xref_init(uint64_t address, PFXrefTypeMask types);
void pfmetric_free(void *metric);
void pfmetric_run_in_range(PFSection *section, uint64_t startAddr, uint64_t endAddr, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
void pfmetric_run(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
#endif

View File

@ -0,0 +1,33 @@
#ifndef PATCHFINDER_ARM64_H
#define PATCHFINDER_ARM64_H
#include "PatchFinder.h"
typedef enum {
ARM64_XREF_TYPE_B = 0,
ARM64_XREF_TYPE_BL = 1,
ARM64_XREF_TYPE_ADR = 2,
ARM64_XREF_TYPE_ADRP_ADD = 3,
ARM64_XREF_TYPE_ADRP_LDR = 4,
ARM64_XREF_TYPE_ADRP_STR = 5,
} Arm64XrefType;
typedef enum {
ARM64_XREF_TYPE_MASK_B = (1 << ARM64_XREF_TYPE_B),
ARM64_XREF_TYPE_MASK_BL = (1 << ARM64_XREF_TYPE_BL),
ARM64_XREF_TYPE_MASK_CALL = (ARM64_XREF_TYPE_MASK_B | ARM64_XREF_TYPE_MASK_BL),
ARM64_XREF_TYPE_MASK_ADR = (1 << ARM64_XREF_TYPE_ADR),
ARM64_XREF_TYPE_MASK_ADRP_ADD = (1 << ARM64_XREF_TYPE_ADRP_ADD),
ARM64_XREF_TYPE_MASK_ADRP_LDR = (1 << ARM64_XREF_TYPE_ADRP_LDR),
ARM64_XREF_TYPE_MASK_ADRP_STR = (1 << ARM64_XREF_TYPE_ADRP_STR),
ARM64_XREF_TYPE_MASK_REFERENCE = (ARM64_XREF_TYPE_MASK_ADR | ARM64_XREF_TYPE_MASK_ADRP_ADD | ARM64_XREF_TYPE_MASK_ADRP_LDR | ARM64_XREF_TYPE_MASK_ADRP_STR),
ARM64_XREF_TYPE_ALL = (ARM64_XREF_TYPE_MASK_CALL | ARM64_XREF_TYPE_MASK_REFERENCE),
} Arm64XrefTypeMask;
uint64_t pfsec_arm64_resolve_adrp_ldr_str_add_reference(PFSection *section, uint64_t adrpAddr, uint64_t ldrStrAddAddr);
uint64_t pfsec_arm64_resolve_adrp_ldr_str_add_reference_auto(PFSection *section, uint64_t ldrStrAddAddr);
uint64_t pfsec_arm64_resolve_stub(PFSection *section, uint64_t stubAddr);
void pfsec_arm64_enumerate_xrefs(PFSection *section, Arm64XrefTypeMask types, void (^xrefBlock)(Arm64XrefType type, uint64_t source, uint64_t target, bool *stop));
#endif

View File

@ -1,6 +1,8 @@
#ifndef SIGN_OSSL_H
#define SIGN_OSSL_H
#ifndef DISABLE_SIGNING
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -11,6 +13,8 @@
unsigned char *signWithRSA(unsigned char *inputData, size_t inputDataLength, unsigned char *key, size_t key_len, size_t *outputDataLength);
#endif
#endif // SIGN_OSSL_H
// 0xA422

View File

@ -1,7 +1,34 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct s_optional_uint64 {
bool isSet;
uint64_t value;
} optional_uint64_t;
#define OPT_UINT64_IS_SET(x) (x.isSet)
#define OPT_UINT64_GET_VAL(x) (x.value)
#define OPT_UINT64_NONE (optional_uint64_t){.isSet = false, .value = 0}
#define OPT_UINT64(x) (optional_uint64_t){.isSet = true, .value = x}
typedef struct s_optional_bool {
bool isSet;
bool value;
} optional_bool;
#define OPT_BOOL_IS_SET(x) (x.isSet)
#define OPT_BOOL_GET_VAL(x) (x.value)
#define OPT_BOOL_NONE (optional_bool){.isSet = false, .value = false}
#define OPT_BOOL(x) (optional_bool){.isSet = true, .value = x}
int64_t sxt64(int64_t value, uint8_t bits);
int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n);
uint64_t align_to_size(int size, int alignment);
int count_digits(int64_t num);
void print_hash(uint8_t *hash, size_t size);
void enumerate_range(uint64_t start, uint64_t end, uint16_t alignment, size_t nbytes, bool (^enumerator)(uint64_t cur));
#endif

View File

@ -0,0 +1,94 @@
#ifndef ARM64_H
#define ARM64_H
#include "Util.h"
typedef enum {
// registers
ARM64_REG_TYPE_X,
ARM64_REG_TYPE_W,
// vector shit
ARM64_REG_TYPE_Q,
ARM64_REG_TYPE_D,
ARM64_REG_TYPE_S,
ARM64_REG_TYPE_H,
ARM64_REG_TYPE_B,
} arm64_register_type;
enum {
ARM64_REG_MASK_ANY_FLAG = (1 << 0),
ARM64_REG_MASK_X_W = (1 << 1),
ARM64_REG_MASK_VECTOR = (1 << 2),
ARM64_REG_MASK_ALL = (ARM64_REG_MASK_X_W | ARM64_REG_MASK_VECTOR),
ARM64_REG_MASK_ANY_X_W = (ARM64_REG_MASK_X_W | ARM64_REG_MASK_ANY_FLAG),
ARM64_REG_MASK_ANY_VECTOR = (ARM64_REG_MASK_VECTOR | ARM64_REG_MASK_ANY_FLAG),
ARM64_REG_MASK_ANY_ALL = (ARM64_REG_MASK_ALL | ARM64_REG_MASK_ANY_FLAG),
};
typedef enum {
LDR_STR_TYPE_ANY, // NOTE: "ANY" will inevitably also match STUR and LDUR instructions
LDR_STR_TYPE_POST_INDEX,
LDR_STR_TYPE_PRE_INDEX,
LDR_STR_TYPE_UNSIGNED,
} arm64_ldr_str_type;
typedef struct s_arm64_register {
uint8_t mask;
arm64_register_type type;
uint8_t num;
} arm64_register;
#define ARM64_REG(type_, num_) (arm64_register){.mask = ARM64_REG_MASK_ALL, .type = type_, .num = num_}
#define ARM64_REG_X(x) ARM64_REG(ARM64_REG_TYPE_X, x)
#define ARM64_REG_W(x) ARM64_REG(ARM64_REG_TYPE_W, x)
#define ARM64_REG_Q(x) ARM64_REG(ARM64_REG_TYPE_Q, x)
#define ARM64_REG_S(x) ARM64_REG(ARM64_REG_TYPE_S, x)
#define ARM64_REG_H(x) ARM64_REG(ARM64_REG_TYPE_H, x)
#define ARM64_REG_B(x) ARM64_REG(ARM64_REG_TYPE_B, x)
#define ARM64_REG_ANY (arm64_register){.mask = ARM64_REG_MASK_ANY_ALL, .type = 0, .num = 0}
#define ARM64_REG_ANY_X_W (arm64_register){.mask = ARM64_REG_MASK_ANY_X_W, .type = 0, .num = 0}
#define ARM64_REG_ANY_VECTOR (arm64_register){.mask = ARM64_REG_MASK_ANY_VECTOR, .type = 0, .num = 0}
#define ARM64_REG_GET_TYPE(x) (x.type)
#define ARM64_REG_IS_X(x) (x.type == ARM64_REG_TYPE_X)
#define ARM64_REG_IS_W(x) (x.type == ARM64_REG_TYPE_W)
#define ARM64_REG_IS_VECTOR(x) (x.type == ARM64_REG_TYPE_Q || x.type == ARM64_REG_TYPE_D || x.type == ARM64_REG_TYPE_S || x.type == ARM64_REG_TYPE_H || x.type == ARM64_REG_TYPE_B)
#define ARM64_REG_GET_NUM(x) (x.num & 0x1f)
#define ARM64_REG_IS_ANY(x) (x.mask == ARM64_REG_MASK_ANY_ALL)
#define ARM64_REG_IS_ANY_X_W(x) (x.mask == ARM64_REG_MASK_ANY_X_W)
#define ARM64_REG_IS_ANY_VECTOR(x) (x.mask == ARM64_REG_MASK_ANY_VECTOR)
uint8_t arm64_reg_type_get_width(arm64_register_type type);
const char *arm64_reg_type_get_string(arm64_register_type type);
const char *arm64_reg_get_type_string(arm64_register reg);
#define ARM64_REG_NUM_SP 31
typedef struct s_arm64_cond {
bool isSet;
uint8_t value;
} arm64_cond;
#define ARM64_COND(x) (arm64_cond){.isSet = true, .value = x}
#define ARM64_COND_ANY (arm64_cond){.isSet = false, .value = 0}
#define ARM64_COND_GET_VAL(x) (x.value & 0xf)
#define ARM64_COND_IS_SET(x) x.isSet
int arm64_gen_b_l(optional_bool optIsBl, optional_uint64_t optOrigin, optional_uint64_t optTarget, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_b_l(uint32_t inst, uint64_t origin, uint64_t *targetOut, bool *isBlOut);
int arm64_gen_b_c_cond(optional_bool optIsBc, optional_uint64_t optOrigin, optional_uint64_t optTarget, arm64_cond optCond, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_b_c_cond(uint32_t inst, uint64_t origin, uint64_t *targetOut, arm64_cond *condOut, bool *isBcOut);
int arm64_gen_adr_p(optional_bool optIsAdrp, optional_uint64_t optOrigin, optional_uint64_t optTarget, arm64_register reg, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_adr_p(uint32_t inst, uint64_t origin, uint64_t *targetOut, arm64_register *registerOut, bool *isAdrpOut);
int arm64_gen_mov_imm(char type, arm64_register destinationReg, optional_uint64_t optImm, optional_uint64_t optShift, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_mov_imm(uint32_t inst, arm64_register *destinationRegOut, uint64_t *immOut, uint64_t *shiftOut, char *typeOut);
int arm64_gen_add_imm(arm64_register destinationReg, arm64_register sourceReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_add_imm(uint32_t inst, arm64_register *destinationRegOut, arm64_register *sourceRegOut, uint16_t *immOut);
int arm64_gen_ldr_imm(char type, arm64_ldr_str_type instType, arm64_register destinationReg, arm64_register addrReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_ldr_imm(uint32_t inst, arm64_register *destinationReg, arm64_register *addrReg, uint64_t *immOut, char *typeOut, arm64_ldr_str_type *instTypeOut);
int arm64_gen_str_imm(char type, arm64_ldr_str_type instType, arm64_register sourceReg, arm64_register addrReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_str_imm(uint32_t inst, arm64_register *sourceRegOut, arm64_register *addrRegOut, uint64_t *immOut, char *typeOut, arm64_ldr_str_type *instTypeOut);
int arm64_gen_ldr_lit(arm64_register destinationReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_ldr_lit(uint32_t inst, arm64_register *destinationReg, int64_t *immOut);
int arm64_gen_cb_n_z(optional_bool isCbnz, arm64_register reg, optional_uint64_t optTarget, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_cb_n_z(uint32_t inst, uint64_t origin, bool *isCbnzOut, arm64_register *regOut, uint64_t *targetOut);
#endif

Binary file not shown.

View File

@ -31,7 +31,7 @@ typedef struct __GenericBlob {
} CS_GenericBlob;
// CMS blob magic types
enum {
typedef enum {
CSMAGIC_REQUIREMENT = 0xfade0c00,
CSMAGIC_REQUIREMENTS = 0xfade0c01,
CSMAGIC_CODEDIRECTORY = 0xfade0c02,
@ -44,7 +44,7 @@ enum {
CSMAGIC_EMBEDDED_LAUNCH_CONSTRAINT = 0xfade8181,
} CS_BlobMagic;
enum {
typedef enum {
CSSLOT_CODEDIRECTORY = 0,
CSSLOT_INFOSLOT = 1,
CSSLOT_REQUIREMENTS = 2,
@ -90,8 +90,6 @@ CS_SuperBlob *macho_read_code_signature(MachO *macho);
int macho_replace_code_signature(MachO *macho, CS_SuperBlob *superblob);
int update_load_commands(MachO *macho, CS_SuperBlob *superblob, uint64_t originalSize);
CS_DecodedBlob *csd_blob_init(uint32_t type, CS_GenericBlob *blobData);
int csd_blob_read(CS_DecodedBlob *blob, uint64_t offset, size_t size, void *outBuf);
int csd_blob_write(CS_DecodedBlob *blob, uint64_t offset, size_t size, const void *inBuf);
@ -104,6 +102,7 @@ uint32_t csd_blob_get_type(CS_DecodedBlob *blob);
void csd_blob_set_type(CS_DecodedBlob *blob, uint32_t type);
void csd_blob_free(CS_DecodedBlob *blob);
CS_DecodedSuperBlob *csd_superblob_init(void);
CS_DecodedSuperBlob *csd_superblob_decode(CS_SuperBlob *superblob);
CS_SuperBlob *csd_superblob_encode(CS_DecodedSuperBlob *decodedSuperblob);
CS_DecodedBlob *csd_superblob_find_blob(CS_DecodedSuperBlob *superblob, uint32_t type, uint32_t *indexOut);

View File

@ -12,7 +12,6 @@
#include "MachOLoadCommand.h"
#include "MemoryStream.h"
// Code directory blob header
typedef struct __CodeDirectory {
uint32_t magic;
@ -26,12 +25,15 @@ typedef struct __CodeDirectory {
uint32_t codeLimit;
uint8_t hashSize;
uint8_t hashType;
uint8_t spare1;
uint8_t platform;
uint8_t pageSize;
uint32_t spare2;
/* Version 0x20100 */
uint32_t scatterOffset;
uint32_t teamOffset;
} CS_CodeDirectory;
} CS_CodeDirectory
__attribute__ ((aligned(1)));
enum CS_HashType {
CS_HASHTYPE_SHA160_160 = 1,
@ -40,7 +42,7 @@ enum CS_HashType {
CS_HASHTYPE_SHA384_384 = 4,
};
char *csd_code_directory_copy_identity(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
char *csd_code_directory_copy_identifier(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
char *csd_code_directory_copy_team_id(CS_DecodedBlob *codeDirBlob, uint32_t *offsetOut);
int csd_code_directory_set_team_id(CS_DecodedBlob *codeDirBlob, char *newTeamID);
uint32_t csd_code_directory_get_flags(CS_DecodedBlob *codeDirBlob);

View File

@ -131,7 +131,7 @@
applier(cd, codeLimit); \
applier(cd, hashSize); \
applier(cd, hashType); \
applier(cd, spare1); \
applier(cd, platform); \
applier(cd, pageSize); \
applier(cd, spare2); \
applier(cd, scatterOffset); \

View File

@ -3,9 +3,9 @@
#include <mach-o/loader.h>
#include "MachO.h"
#include "CSBlob.h"
#include "FileStream.h"
#include "MachOByteOrder.h"
#include "CSBlob.h"
// Convert load command to load command name
char *load_command_to_string(int loadCommand);

View File

@ -55,6 +55,6 @@ int memory_stream_expand(MemoryStream *stream, size_t expandAtStart, size_t expa
void memory_stream_free(MemoryStream *stream);
int memory_stream_copy_data(MemoryStream *originStream, uint64_t originOffset, MemoryStream *targetStream, uint64_t targetOffset, size_t size);
int memory_stream_find_memory(MemoryStream *stream, uint64_t searchOffset, size_t searchSize, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut);
int memory_stream_find_memory(MemoryStream *stream, uint64_t searchStartOffset, uint64_t searchEndOffset, void *bytes, void *mask, size_t nbytes, uint16_t alignment, uint64_t *foundOffsetOut);
#endif // MEMORY_STREAM_H

View File

@ -1,11 +1,16 @@
#ifndef PATCHFINDER_H
#define PATCHFINDER_H
#include <stdint.h>
#include "MachO.h"
#define METRIC_TYPE_PATTERN 1
#define METRIC_TYPE_STRING_XREF 2
#define METRIC_TYPE_FUNCTION_XREF 3
enum {
PF_METRIC_TYPE_PATTERN,
PF_METRIC_TYPE_STRING,
PF_METRIC_TYPE_XREF,
};
typedef struct PFSection {
typedef struct s_PFSection {
MachO *macho;
uint64_t fileoff;
uint64_t vmaddr;
@ -14,34 +19,57 @@ typedef struct PFSection {
bool ownsCache;
} PFSection;
PFSection *pf_section_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int pf_section_read_at_relative_offset(PFSection *section, uint64_t rel, size_t size, void *outBuf);
int pf_section_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pf_section_read32(PFSection *section, uint64_t vmaddr);
int pf_section_set_cached(PFSection *section, bool cached);
void pf_section_free(PFSection *section);
PFSection *pfsec_init_from_macho(MachO *macho, const char *filesetEntryId, const char *segName, const char *sectName);
int pfsec_read_reloff(PFSection *section, uint64_t rel, size_t size, void *outBuf);
uint32_t pfsec_read32_reloff(PFSection *section, uint64_t rel);
int pfsec_read_at_address(PFSection *section, uint64_t vmaddr, void *outBuf, size_t size);
uint32_t pfsec_read32(PFSection *section, uint64_t vmaddr);
uint64_t pfsec_read64(PFSection *section, uint64_t vmaddr);
int pfsec_read_string(PFSection *section, uint64_t vmaddr, char **outString);
int pfsec_set_cached(PFSection *section, bool cached);
uint64_t pfsec_find_prev_inst(PFSection *section, uint64_t startAddr, uint32_t searchCount, uint32_t inst, uint32_t mask);
uint64_t pfsec_find_next_inst(PFSection *section, uint64_t startAddr, uint32_t searchCount, uint32_t inst, uint32_t mask);
uint64_t pfsec_find_function_start(PFSection *section, uint64_t midAddr);
void pfsec_free(PFSection *section);
typedef struct MetricShared {
typedef struct s_MetricShared {
uint32_t type;
} MetricShared;
typedef enum {
BYTE_PATTERN_ALIGN_8_BIT,
BYTE_PATTERN_ALIGN_16_BIT,
BYTE_PATTERN_ALIGN_32_BIT,
BYTE_PATTERN_ALIGN_64_BIT,
} BytePatternAlignment;
typedef struct BytePatternMetric {
typedef struct s_PFPatternMetric {
MetricShared shared;
void *bytes;
void *mask;
size_t nbytes;
BytePatternAlignment alignment;
} BytePatternMetric;
uint16_t alignment;
} PFPatternMetric;
BytePatternMetric *pf_create_byte_pattern_metric(void *bytes, void *mask, size_t nbytes, BytePatternAlignment alignment);
void pf_section_run_metric(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
typedef struct s_PFStringMetric {
MetricShared shared;
char *string;
} PFStringMetric;
typedef enum {
XREF_TYPE_MASK_CALL = (1 << 0),
XREF_TYPE_MASK_REFERENCE = (1 << 1),
XREF_TYPE_MASK_ALL = (XREF_TYPE_MASK_CALL | XREF_TYPE_MASK_REFERENCE),
} PFXrefTypeMask;
typedef struct s_PFXrefMetric {
MetricShared shared;
uint64_t address;
PFXrefTypeMask typeMask;
} PFXrefMetric;
PFPatternMetric *pfmetric_pattern_init(void *bytes, void *mask, size_t nbytes, uint16_t alignment);
PFStringMetric *pfmetric_string_init(const char *string);
PFXrefMetric *pfmetric_xref_init(uint64_t address, PFXrefTypeMask types);
void pfmetric_free(void *metric);
void pfmetric_run_in_range(PFSection *section, uint64_t startAddr, uint64_t endAddr, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
void pfmetric_run(PFSection *section, void *metric, void (^matchBlock)(uint64_t vmaddr, bool *stop));
#endif

View File

@ -0,0 +1,33 @@
#ifndef PATCHFINDER_ARM64_H
#define PATCHFINDER_ARM64_H
#include "PatchFinder.h"
typedef enum {
ARM64_XREF_TYPE_B = 0,
ARM64_XREF_TYPE_BL = 1,
ARM64_XREF_TYPE_ADR = 2,
ARM64_XREF_TYPE_ADRP_ADD = 3,
ARM64_XREF_TYPE_ADRP_LDR = 4,
ARM64_XREF_TYPE_ADRP_STR = 5,
} Arm64XrefType;
typedef enum {
ARM64_XREF_TYPE_MASK_B = (1 << ARM64_XREF_TYPE_B),
ARM64_XREF_TYPE_MASK_BL = (1 << ARM64_XREF_TYPE_BL),
ARM64_XREF_TYPE_MASK_CALL = (ARM64_XREF_TYPE_MASK_B | ARM64_XREF_TYPE_MASK_BL),
ARM64_XREF_TYPE_MASK_ADR = (1 << ARM64_XREF_TYPE_ADR),
ARM64_XREF_TYPE_MASK_ADRP_ADD = (1 << ARM64_XREF_TYPE_ADRP_ADD),
ARM64_XREF_TYPE_MASK_ADRP_LDR = (1 << ARM64_XREF_TYPE_ADRP_LDR),
ARM64_XREF_TYPE_MASK_ADRP_STR = (1 << ARM64_XREF_TYPE_ADRP_STR),
ARM64_XREF_TYPE_MASK_REFERENCE = (ARM64_XREF_TYPE_MASK_ADR | ARM64_XREF_TYPE_MASK_ADRP_ADD | ARM64_XREF_TYPE_MASK_ADRP_LDR | ARM64_XREF_TYPE_MASK_ADRP_STR),
ARM64_XREF_TYPE_ALL = (ARM64_XREF_TYPE_MASK_CALL | ARM64_XREF_TYPE_MASK_REFERENCE),
} Arm64XrefTypeMask;
uint64_t pfsec_arm64_resolve_adrp_ldr_str_add_reference(PFSection *section, uint64_t adrpAddr, uint64_t ldrStrAddAddr);
uint64_t pfsec_arm64_resolve_adrp_ldr_str_add_reference_auto(PFSection *section, uint64_t ldrStrAddAddr);
uint64_t pfsec_arm64_resolve_stub(PFSection *section, uint64_t stubAddr);
void pfsec_arm64_enumerate_xrefs(PFSection *section, Arm64XrefTypeMask types, void (^xrefBlock)(Arm64XrefType type, uint64_t source, uint64_t target, bool *stop));
#endif

View File

@ -1,6 +1,8 @@
#ifndef SIGN_OSSL_H
#define SIGN_OSSL_H
#ifndef DISABLE_SIGNING
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -11,6 +13,8 @@
unsigned char *signWithRSA(unsigned char *inputData, size_t inputDataLength, unsigned char *key, size_t key_len, size_t *outputDataLength);
#endif
#endif // SIGN_OSSL_H
// 0xA422

View File

@ -1,7 +1,34 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct s_optional_uint64 {
bool isSet;
uint64_t value;
} optional_uint64_t;
#define OPT_UINT64_IS_SET(x) (x.isSet)
#define OPT_UINT64_GET_VAL(x) (x.value)
#define OPT_UINT64_NONE (optional_uint64_t){.isSet = false, .value = 0}
#define OPT_UINT64(x) (optional_uint64_t){.isSet = true, .value = x}
typedef struct s_optional_bool {
bool isSet;
bool value;
} optional_bool;
#define OPT_BOOL_IS_SET(x) (x.isSet)
#define OPT_BOOL_GET_VAL(x) (x.value)
#define OPT_BOOL_NONE (optional_bool){.isSet = false, .value = false}
#define OPT_BOOL(x) (optional_bool){.isSet = true, .value = x}
int64_t sxt64(int64_t value, uint8_t bits);
int memcmp_masked(const void *str1, const void *str2, unsigned char* mask, size_t n);
uint64_t align_to_size(int size, int alignment);
int count_digits(int64_t num);
void print_hash(uint8_t *hash, size_t size);
void enumerate_range(uint64_t start, uint64_t end, uint16_t alignment, size_t nbytes, bool (^enumerator)(uint64_t cur));
#endif

View File

@ -0,0 +1,94 @@
#ifndef ARM64_H
#define ARM64_H
#include "Util.h"
typedef enum {
// registers
ARM64_REG_TYPE_X,
ARM64_REG_TYPE_W,
// vector shit
ARM64_REG_TYPE_Q,
ARM64_REG_TYPE_D,
ARM64_REG_TYPE_S,
ARM64_REG_TYPE_H,
ARM64_REG_TYPE_B,
} arm64_register_type;
enum {
ARM64_REG_MASK_ANY_FLAG = (1 << 0),
ARM64_REG_MASK_X_W = (1 << 1),
ARM64_REG_MASK_VECTOR = (1 << 2),
ARM64_REG_MASK_ALL = (ARM64_REG_MASK_X_W | ARM64_REG_MASK_VECTOR),
ARM64_REG_MASK_ANY_X_W = (ARM64_REG_MASK_X_W | ARM64_REG_MASK_ANY_FLAG),
ARM64_REG_MASK_ANY_VECTOR = (ARM64_REG_MASK_VECTOR | ARM64_REG_MASK_ANY_FLAG),
ARM64_REG_MASK_ANY_ALL = (ARM64_REG_MASK_ALL | ARM64_REG_MASK_ANY_FLAG),
};
typedef enum {
LDR_STR_TYPE_ANY, // NOTE: "ANY" will inevitably also match STUR and LDUR instructions
LDR_STR_TYPE_POST_INDEX,
LDR_STR_TYPE_PRE_INDEX,
LDR_STR_TYPE_UNSIGNED,
} arm64_ldr_str_type;
typedef struct s_arm64_register {
uint8_t mask;
arm64_register_type type;
uint8_t num;
} arm64_register;
#define ARM64_REG(type_, num_) (arm64_register){.mask = ARM64_REG_MASK_ALL, .type = type_, .num = num_}
#define ARM64_REG_X(x) ARM64_REG(ARM64_REG_TYPE_X, x)
#define ARM64_REG_W(x) ARM64_REG(ARM64_REG_TYPE_W, x)
#define ARM64_REG_Q(x) ARM64_REG(ARM64_REG_TYPE_Q, x)
#define ARM64_REG_S(x) ARM64_REG(ARM64_REG_TYPE_S, x)
#define ARM64_REG_H(x) ARM64_REG(ARM64_REG_TYPE_H, x)
#define ARM64_REG_B(x) ARM64_REG(ARM64_REG_TYPE_B, x)
#define ARM64_REG_ANY (arm64_register){.mask = ARM64_REG_MASK_ANY_ALL, .type = 0, .num = 0}
#define ARM64_REG_ANY_X_W (arm64_register){.mask = ARM64_REG_MASK_ANY_X_W, .type = 0, .num = 0}
#define ARM64_REG_ANY_VECTOR (arm64_register){.mask = ARM64_REG_MASK_ANY_VECTOR, .type = 0, .num = 0}
#define ARM64_REG_GET_TYPE(x) (x.type)
#define ARM64_REG_IS_X(x) (x.type == ARM64_REG_TYPE_X)
#define ARM64_REG_IS_W(x) (x.type == ARM64_REG_TYPE_W)
#define ARM64_REG_IS_VECTOR(x) (x.type == ARM64_REG_TYPE_Q || x.type == ARM64_REG_TYPE_D || x.type == ARM64_REG_TYPE_S || x.type == ARM64_REG_TYPE_H || x.type == ARM64_REG_TYPE_B)
#define ARM64_REG_GET_NUM(x) (x.num & 0x1f)
#define ARM64_REG_IS_ANY(x) (x.mask == ARM64_REG_MASK_ANY_ALL)
#define ARM64_REG_IS_ANY_X_W(x) (x.mask == ARM64_REG_MASK_ANY_X_W)
#define ARM64_REG_IS_ANY_VECTOR(x) (x.mask == ARM64_REG_MASK_ANY_VECTOR)
uint8_t arm64_reg_type_get_width(arm64_register_type type);
const char *arm64_reg_type_get_string(arm64_register_type type);
const char *arm64_reg_get_type_string(arm64_register reg);
#define ARM64_REG_NUM_SP 31
typedef struct s_arm64_cond {
bool isSet;
uint8_t value;
} arm64_cond;
#define ARM64_COND(x) (arm64_cond){.isSet = true, .value = x}
#define ARM64_COND_ANY (arm64_cond){.isSet = false, .value = 0}
#define ARM64_COND_GET_VAL(x) (x.value & 0xf)
#define ARM64_COND_IS_SET(x) x.isSet
int arm64_gen_b_l(optional_bool optIsBl, optional_uint64_t optOrigin, optional_uint64_t optTarget, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_b_l(uint32_t inst, uint64_t origin, uint64_t *targetOut, bool *isBlOut);
int arm64_gen_b_c_cond(optional_bool optIsBc, optional_uint64_t optOrigin, optional_uint64_t optTarget, arm64_cond optCond, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_b_c_cond(uint32_t inst, uint64_t origin, uint64_t *targetOut, arm64_cond *condOut, bool *isBcOut);
int arm64_gen_adr_p(optional_bool optIsAdrp, optional_uint64_t optOrigin, optional_uint64_t optTarget, arm64_register reg, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_adr_p(uint32_t inst, uint64_t origin, uint64_t *targetOut, arm64_register *registerOut, bool *isAdrpOut);
int arm64_gen_mov_imm(char type, arm64_register destinationReg, optional_uint64_t optImm, optional_uint64_t optShift, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_mov_imm(uint32_t inst, arm64_register *destinationRegOut, uint64_t *immOut, uint64_t *shiftOut, char *typeOut);
int arm64_gen_add_imm(arm64_register destinationReg, arm64_register sourceReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_add_imm(uint32_t inst, arm64_register *destinationRegOut, arm64_register *sourceRegOut, uint16_t *immOut);
int arm64_gen_ldr_imm(char type, arm64_ldr_str_type instType, arm64_register destinationReg, arm64_register addrReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_ldr_imm(uint32_t inst, arm64_register *destinationReg, arm64_register *addrReg, uint64_t *immOut, char *typeOut, arm64_ldr_str_type *instTypeOut);
int arm64_gen_str_imm(char type, arm64_ldr_str_type instType, arm64_register sourceReg, arm64_register addrReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_str_imm(uint32_t inst, arm64_register *sourceRegOut, arm64_register *addrRegOut, uint64_t *immOut, char *typeOut, arm64_ldr_str_type *instTypeOut);
int arm64_gen_ldr_lit(arm64_register destinationReg, optional_uint64_t optImm, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_ldr_lit(uint32_t inst, arm64_register *destinationReg, int64_t *immOut);
int arm64_gen_cb_n_z(optional_bool isCbnz, arm64_register reg, optional_uint64_t optTarget, uint32_t *bytesOut, uint32_t *maskOut);
int arm64_dec_cb_n_z(uint32_t inst, uint64_t origin, bool *isCbnzOut, arm64_register *regOut, uint64_t *targetOut);
#endif

Binary file not shown.