1. A great progress in RE of XuCode processing in ucode

2. Secure Enclave (SGX) SVN key generation is found
3. A Python module is implemented for the disassembler
4. Many other microarchitectural data are found and added
This commit is contained in:
Mark Ermolov
2022-07-26 00:27:54 +03:00
parent 82328ef568
commit 5b2b1f1246
8 changed files with 30054 additions and 30600 deletions

View File

@@ -0,0 +1,3 @@
from .glm_ucode_disasm import uop_disassemble
from .glm_ucode_disasm import process_seqword

View File

@@ -1,24 +1,38 @@
067: CORE_CR_CUR_RIP
068: CORE_CR_CUR_UIP
208: CTAP_CR_PPPE_DEBUG
285: CTAP_CR_DFX_CTL_STS
205: UCODE_CR_SE_SVN_KEY_0
206: UCODE_CR_SE_SVN_KEY_1
208: CTAP_CR_PPPE_TAP_STATUS
285: CTAP_CR_TAP_CONFIG
288: UCODE_CR_X2APIC_TPR
28b: UCODE_CR_X2APIC_EOI
29e: UCODE_CR_PPPE_EVENT_RESET
29f: UCODE_CR_PPPE_EVENT_STATUS
2c0: CTAP_CR_PDR_T0_LOW
2c1: CTAP_CR_PDR_T0_HIGH
2c4: ML3_CR_PIC_GLOBAL_EVENT_INHIBIT
2cd: CTAP_CR_PROBE_MODE
2b9: X86_CR_THREAD_ID
2df: ROB1_CR_ICECTLPMR
2e6: ML3_CR_PIC_DEBUG_MODES
51b: PMH_CR_BRAM_BASE
528: PMH_CR_CR3
555: PMH_CR_ELSRR_BASE
556: PMH_CR_ELSRR_MASK
557: PMH_CR_EPCM_BASE
562: PMH_CR_EMRR_BASE
563: PMH_CR_EMRR_MASK
564: PMH_CR_EMXRR_BASE
565: PMH_CR_EMXRR_MASK
572: PMH_CR_SMRR_BASE
573: PMH_CR_SMRR_MASK
574: PMH_CR_EMRR_BASE
575: PMH_CR_EMRR_MASK
574: PMH_CR_PRMRR_BASE
575: PMH_CR_PRMRR_MASK
692: MS_CR_DEBUG_DEFEATURE
752: UCODE_CR_XU_MACROINSTRUCTION_ALIAS
752: XU_CR_MACROINSTRUCTION_ALIAS
7c5: CORE_CR_CR4
78e: BAC_CR_CS_BASE
7c6: UCODE_CR_XU_USTATE_CTRL
7f6: CORE_CR_CR0
7f9: CORE_CR_DEBUGCTL
7fe: CORE_CR_EFLAGS

View File

@@ -1,4 +1,15 @@
0012: FSCP_CR_PDM_CTRL
0013: FSCP_CR_PROBE_MODE_PPPE_REDIRECTION_INFO
001b: FSCP_CR_EM_EXCEPTIONS_HANDLING_EIP
0020: FSCP_CR_WHO_AM_I_INFO
0034: FSCP_CR_PSMI_BASE
0035: FSCP_CR_CFG_FUSES0
0036: FSCP_CR_SMI_COUNT
0039: FSCP_CR_IO_MISC_INFO
003a: FSCP_CR_IA32_FEATURE_CTL
0050: FSCP_CR_ICECTLPMR_PRIOR_STATE
0058: FSCP_CR_TCS_PA
005b: FSCP_CR_XFEM_AND_XRSTOR_INFO
0071: FSCP_CR_SMBASE
0072: FSCP_CR_PROBE_MODE_PPPE_REDIRECTION
0077: FSCP_CR_CFG_FUSES1

View File

@@ -114,7 +114,26 @@ g_uop_cregs = {}
g_uop_fscp_regs = {}
g_uop_ioregs = {}
def glm_ucode_disasm_init():
def load_id_names_str_data(file_name):
id_names = {}
fi = open(file_name, "r")
str_id_names = fi.read()
fi.close()
str_id_name_lines = str_id_names.split("\n")
for id_name in str_id_name_lines:
id_name_seq = id_name.split(":")
if len(id_name_seq) != 2:
continue
str_id, str_name = id_name_seq
if str_id == "" or str_name == "":
continue
id = int(str_id, 16)
if id not in id_names:
id_names[id] = str_name.strip()
return id_names
def glm_ucode_disasm_init(init_udata):
global g_opcodes
g_opcodes = {}
fi = open("opcodes.txt", "r")
@@ -137,6 +156,16 @@ def glm_ucode_disasm_init():
str_hard_imm = str_hard_imm.strip()
if len(str_hard_imm):
g_hard_imms.append(int(str_hard_imm, 16))
if init_udata:
global g_uop_cregs
global g_uop_lables
global g_uop_fscp_regs
global g_uop_ioregs
g_uop_lables = load_id_names_str_data("lables.txt")
g_uop_cregs = load_id_names_str_data("cregs.txt")
g_uop_fscp_regs = load_id_names_str_data("fscp.txt")
g_uop_ioregs = load_id_names_str_data("ioregs.txt")
def get_uop_opcode(uop):
return (uop >> 32) & 0xfff
@@ -256,12 +285,12 @@ def is_uop_creg_move_fromto(uop):
opcode = get_uop_opcode(uop)
return opcode in creg_move_fromto_opcodes
def is_uop_creg_xxx(uop):
def is_uop_creg_uram_xxx(uop):
opcode = get_uop_opcode(uop)
return opcode >= 0x800 and opcode <= 0xb00 and opcode & 0xff == opcode & 0xe2
return opcode >= 0x800 and opcode <= 0xb00 and opcode & 0xff == opcode & 0xe3
def is_uop_xxx_uip_regovr(uop):
xxx_uip_flgs_opcodes = [0x00c, 0x00d, 0x04c, 0x08c, 0x0cc, 0x108]
xxx_uip_flgs_opcodes = [0x00c, 0x00d, 0x04c, 0x04d, 0x08c, 0x0cc, 0x108]
opcode = get_uop_opcode(uop)
return opcode in xxx_uip_flgs_opcodes
@@ -423,7 +452,7 @@ def get_str_uop_creg_move_fromto_special_imms(uop, uaddr):
return str_special_imms
def get_str_uop_creg_xxx_special_imms(uop, uaddr):
def get_str_uop_creg_uram_xxx_special_imms(uop, uaddr):
src1_sel = get_src1_sel(uop)
if src1_sel == 0x10:
@@ -518,7 +547,8 @@ g_str_ustates = {
g_str_ustate_bits = (
{
0x0001: "UST_MSLOOPCTR_NONZERO" \
0x0001: "UST_MSLOOPCTR_NONZERO", \
0x0800: "UST_SMM" \
}, \
{
0x0001: "UST_VMX_DIS", \
@@ -526,8 +556,8 @@ g_str_ustate_bits = (
0x0004: "UST_8086_MODE", \
0x0008: "UST_OP_SIZE_32BIT", \
0x0010: "UST_ADDR_SIZE_64BIT", \
0x0020: "UST_SMM", \
0x0040: "UST_VMX_DUAL_MON", \
0x0020: "UST_XUCODE", \
0x0040: "UST_SE_INIT_DONE", \
0x0080: "UST_VMX_GUEST", \
0x0100: "UST_VMX_OP_DIS" \
}, \
@@ -716,7 +746,7 @@ g_uop_special_imms_process_funcs = ( \
(is_uop_log_ldstad, get_str_uop_log_ldstad_special_imms), \
(is_uop_cmpujcc, get_str_uop_cmpujcc_special_imms), \
(is_uop_creg_move_fromto, get_str_uop_creg_move_fromto_special_imms), \
(is_uop_creg_xxx, get_str_uop_creg_xxx_special_imms), \
(is_uop_creg_uram_xxx, get_str_uop_creg_uram_xxx_special_imms), \
(is_uop_xxx_uip_regovr, get_str_uop_xxx_uip_regovr_special_imms), \
(is_uop_uram_rw, get_str_uop_uram_rw_special_imms), \
(is_uop_xxx_ustate, get_str_uop_xxx_ustate_special_imms), \
@@ -806,7 +836,7 @@ def get_idq_src_dst_mnem(sel, is_xmm):
def is_uop_mmxmm(uop):
opcode = get_uop_opcode(uop)
non_mmxmm_opcodes = [0x52b, 0x608, 0x646, 0x685, 0x68a, 0x6a0, 0x6ed,
non_mmxmm_opcodes = [0x608, 0x646, 0x685, 0x68a, 0x6a0, 0x6ed,
0x720, 0x722, 0x723, 0x7b8, 0x7ed]
mmxmm_opcodes = [0xcfe, 0xeae, 0xeee]
if opcode in non_mmxmm_opcodes:
@@ -818,13 +848,13 @@ def is_uop_mmxmm(uop):
def is_mmxmm_uop_src_mmxmm(uop):
assert(is_uop_mmxmm(uop))
opcode = get_uop_opcode(uop)
non_mmxmm_src_opcodes = [0x705, 0x716, 0x745]
non_mmxmm_src_opcodes = [0x705, 0x716, 0x745, 0x746, 0x747]
return opcode not in non_mmxmm_src_opcodes
def is_mmxmm_uop_dst_mmxmm(uop):
assert(is_uop_mmxmm(uop))
opcode = get_uop_opcode(uop)
non_mmxmm_dst_opcodes = [0x72c, 0x72d]
non_mmxmm_dst_opcodes = [0x72c, 0x72d, 0x72f]
return (opcode & 0xfbf) not in non_mmxmm_dst_opcodes
def is_uop_two_src(uop):
@@ -894,7 +924,7 @@ def uop_disassemble(uop, uaddr):
if is_src0 and not is_src0_imm:
str_src0 = get_src_mnem(src0_sel, is_src_xmm)
if is_src1 and not is_src1_imm:
str_src1 = get_src_mnem(src1_sel, is_src_xmm)
str_src1 = get_src_mnem(src1_sel, is_uop_mmxmm(uop))
if is_src2:
str_src2 = get_dst_mnem(dst_sel, is_dst_xmm) if dst_sel else "0x%08x" % 0
elif is_dst:
@@ -1024,25 +1054,6 @@ def load_ms_array_str_data(file_name):
array_vals.append(int(val, 16))
return array_vals
def load_id_names_str_data(file_name):
id_names = {}
fi = open(file_name, "r")
str_id_names = fi.read()
fi.close()
str_id_name_lines = str_id_names.split("\n")
for id_name in str_id_name_lines:
id_name_seq = id_name.split(":")
if len(id_name_seq) != 2:
continue
str_id, str_name = id_name_seq
if str_id == "" or str_name == "":
continue
id = int(str_id, 16)
if id not in id_names:
id_names[id] = str_name.strip()
return id_names
def process_seqword(uaddr, uop, seqword, before_uop):
uop_ctrl = (seqword & 0x3c) >> 2
uop_ctrl_uidx = seqword & 0x03
@@ -1121,6 +1132,30 @@ def process_seqword(uaddr, uop, seqword, before_uop):
return (res, exec_flow_stop) if after_uop else res
def process_match_patch_regs(match_patch_regs):
match_patch_data = {}
patch_match_data = {}
for match_patch_reg in match_patch_regs:
if not (match_patch_reg & 0x1):
continue
match_addr = match_patch_reg & 0xfffe
patch_addr = ((match_patch_reg & 0x7fff0000) >> 16) << 1
assert(match_addr not in match_patch_data)
assert(patch_addr not in patch_match_data)
match_patch_data[match_addr] = patch_addr
patch_match_data[patch_addr] = match_addr
return match_patch_data, patch_match_data
def process_msram_uops(msram):
assert(len(msram) == 0x200)
msram_ucode = []
for i in range(0x80):
msram_ucode.append(msram[i])
msram_ucode.append(msram[0x80 + i])
msram_ucode.append(msram[0x100 + i])
msram_ucode.append(msram[0x180 + i])
return msram_ucode
def idq_test():
fi = open("idq_test_uops.txt", "r")
str_idq_uops = fi.read()
@@ -1136,25 +1171,27 @@ def idq_test():
for str_idq_uop, str_idq_imm in zip(str_idq_uops, str_idq_imms))
def msrom_disasm(arrays_dump_dir):
global g_uop_cregs
global g_uop_lables
global g_uop_fscp_regs
global g_uop_ioregs
g_uop_lables = load_id_names_str_data("lables.txt")
g_uop_cregs = load_id_names_str_data("cregs.txt")
g_uop_fscp_regs = load_id_names_str_data("fscp.txt")
g_uop_ioregs = load_id_names_str_data("ioregs.txt")
ucode = load_ms_array_str_data(arrays_dump_dir + "\\ms_array0.txt")
msrom_seqwords = load_ms_array_str_data(arrays_dump_dir + "\\ms_array1.txt")
assert(len(ucode) == len(msrom_seqwords))
msram_seqwords = load_ms_array_str_data(arrays_dump_dir + "\\ms_array2.txt")
match_patch_regs = load_ms_array_str_data(arrays_dump_dir + "\\ms_array3.txt")
match_patch_data, patch_match_data = process_match_patch_regs(match_patch_regs)
msram = load_ms_array_str_data(arrays_dump_dir + "\\ms_array4.txt")
msram_ucode = process_msram_uops(msram)
if len(ucode) > 0x7c00:
ucode = ucode[0: 0x7c00]
msrom_seqwords = msrom_seqwords[0: 0x7c00]
ucode += msram_ucode
str_exec_flow_delim = "------------------------------------------------------------------------------------"
str_disasm = ""
for uaddr, uop in enumerate(ucode):
seqword = msrom_seqwords[uaddr // 4 * 4]
if uaddr >= 0x7c00:
msram_addr = uaddr - (0x7e00 if uaddr >= 0x7e00 else 0x7c00)
if uaddr < 0x7c00:
seqword = msrom_seqwords[uaddr // 4 * 4]
else:
msram_addr = uaddr - 0x7c00
seqword = msram_seqwords[msram_addr // 4]
if uaddr & 3 == 3:
@@ -1166,17 +1203,24 @@ def msrom_disasm(arrays_dump_dir):
str_disasm += "\n"
str_disasm += g_uop_lables[uaddr] + ":\n"
str_disasm += "U%04x: " % uaddr + "%012x" % uop
str_match_patch_addr = ""
if uaddr in match_patch_data or uaddr in patch_match_data:
str_match_patch_addr = "U%04x: " % (match_patch_data[uaddr] if uaddr in match_patch_data else \
patch_match_data[uaddr])
str_disasm += "U%04x: " % uaddr + str_match_patch_addr + "%012x " % uop
seqword_prefix = process_seqword(uaddr, uop, seqword, True)
str_seqw_prefix_format = "%" + ("%d" % (15 - len(str_match_patch_addr))) + "s "
if seqword_prefix != "":
str_disasm += "%15s " % seqword_prefix
str_disasm += str_seqw_prefix_format % seqword_prefix
else:
str_disasm += "%16s" % ""
str_disasm += str_seqw_prefix_format % ""
str_disasm += uop_disassemble(uop, uaddr) + "\n"
seqword_sentences, exec_flow_stop = process_seqword(uaddr, uop, seqword, False)
if len(seqword_sentences):
for idx, seqword_sentence in enumerate(seqword_sentences):
str_prefix = "%19s" % ("%08x" % seqword if idx == 0 else "") + "%16s" % ""
str_prefix = "%19s" % ("%08x" % seqword if idx == 0 else "") + "%17s" % ""
str_disasm += str_prefix + seqword_sentence + "\n"
if exec_flow_stop:
str_disasm += str_exec_flow_delim + "\n"
@@ -1195,16 +1239,25 @@ def main():
print("Usage: glm_ucode_disasm <ms_array0_file_path>")
return -1
glm_ucode_disasm_init()
glm_ucode_disasm_init(True)
msrom_disasm(os.path.split(sys.argv[1])[0])
def main_ipc():
cur_dir = os.getcwd()
os.chdir("c:\\Work\\E\\UCode\\scripts\\glm_ucode_disasm")
glm_ucode_disasm_init()
glm_ucode_disasm_init(False)
os.chdir(cur_dir)
if "ipccli" not in sys.modules:
main()
def main_package():
cur_dir = os.getcwd()
os.chdir(os.path.split(__file__)[0])
glm_ucode_disasm_init(True)
os.chdir(cur_dir)
if __name__ == "__main__":
if "ipccli" not in sys.modules:
main()
else:
main_ipc()
else:
main_ipc()
main_package()

View File

@@ -1,7 +1,23 @@
d4: PCU_CR_PCODE_UCODE_Mailbox_Interface
d8: PCU_CR_PCODE_UCODE_Mailbox_Data
000c: FUNNYIO_CR_SGX_DEBUG_MODE
0010: FUNNYIO_CR_IPC_DATA
0018: FUNNYIO_CR_IPC_CMD
0020: FUNNYIO_CR_SCP_PPIN_CTL
003c: FUNNYIO_CR_SCP_SE_ENABLE
0040: FUNNYIO_CR_UNCORE_MUTEX
004c: FUNNYIO_CR_IPC_MUTEX
00d4: PCU_CR_PCODE_UCODE_Mailbox_Interface
00d8: PCU_CR_PCODE_UCODE_Mailbox_Data
46f0: PCU_CR_UCODE_CFG_FUSES0
46f8: PCU_CR_UCODE_CFG_FUSES1
4718: PCU_CR_PLATFORM_INFO
4730: PCU_CR_FUSE_KEY1_0
4738: PCU_CR_FUSE_KEY1_1
4900: PCU_CR_MICROCONTROLLER_CONFIGURATION
4cd8: B_CR_EMRR_BASE
4ce0: B_CR_EMRR_MASK
50a0: FUNNYIO_CR_SCP_SE_OWNER_EPOCH_0
50a8: FUNNYIO_CR_SCP_SE_OWNER_EPOCH_1
50d4: FUNNYIO_CR_SCP_SMM_FEATURE_CONTROL
50d8: FUNNYIO_CR_SCP_SE_STATE
8404: DFXAGG_CR_CONSENT
8408: DFXAGG_CR_STATUS

View File

@@ -1,18 +1,25 @@
0002: clear_physical_regsiter_file
0011: sha256_ret
008e: lfence_wait_uend0
02b2: acquire_uncore_mutex
02d8: sidt_xlat
0320: vmresume_xlat
0328: vmlaunch_xlat
0330: vmwrite_r64_mem_xlat
035a: call_x86_reset_vector
0428: rdrand_xlat
0430: rdseed_xlat
04ae: set_carry_uend
0660: udbgwr_xlat
06be: jump_tmp3
06c6: uret1
06ce: gen_se_svn_key
0720: sldt_m16_xlat
0738: sysexit_xlat
0788: rdtscp_xlat
0794: clear_aflags_uend0
079d: generate_#MC0
079e: generate_#MC
07b5: send_op_pcu_mailbox
0818: hlt_xlat
0858: pcommit_xlat
@@ -20,6 +27,7 @@
08c0: rsm_xlat
08c8: vmxoff_xlat
08d0: encls_xlat
09f8: monitor_xlat
0a68: sldt_r16_xlat
0ae0: rdmsr_xlat
0ae8: vmxon_xlat
@@ -27,14 +35,16 @@
0af8: vmclear_xlat
0b08: vmcall_xlat
0b10: enclu_xlat
0b50: mcheckret_xlat
0b58: udbgrd_xlat
0b90: lidt_xlat
0ba0: str_m16_xlat
0bc9: write_port_4c
0bc9: acquire_ipc_mutex
0bd0: wmptrst_xlat
0be0: cpuid_xlat
0bf0: pause_xlat
0c10: sgdt_xlat
0c52: ipc_cmd_handler_loop
0c70: mov_r64_cr8_xlat
0c80: wrmsr_xlat
0ca8: rdtsc_xlat
@@ -45,11 +55,15 @@
1cbe: uret1
1d8d: check_rdrand_vmexits
1ea6: patch_runs_load_loop
1f90: do_smm_vmexit
1f91: do_smm_vmexit_ovr_enter_rip
1f90: call_xucode
1f91: call_xucode_vmexit_qual
2050: pppe_event_vmx_timer
2088: pppe_event_smi_psmi
25ad: iosfsb_write
2711: generate_#GP
2769: generate_#UD
2771: generate_#NM
2799: clear_se_svn_key
27b4: patch_load_error
27c1: uarch_bufs_ldat_init
27dc: skip_patch_processing
@@ -57,6 +71,7 @@
2d72: check_rsa_padding_signature
2b15: lbsync_full
304e: uret0
318e: save_cpu_arch_state
3210: uend0
327c: apply_ucode_patch
334d: ith_trace_pdm
@@ -67,8 +82,9 @@
4000: reset_flow
4644: check_rsa_pub_key_hash
465c: gen_rc4_key
4859: aes128_key_expansion
4e81: do_vmexit
4e82: do_vmexit_ovr_enter_rip
4e82: do_vmexit_qual
50c4: calc_sha256_start
50da: calc_sha256_update
556a: calc_fast_sha256_start
@@ -76,8 +92,11 @@
5c01: probe_mode_force_smm_xlat
5c62: send_op_data_pcu_mailbox
5e68: fit_process_error
5ee8: send_ipc_cmd_resp
5ed5: rc4_decrypt
608a: fit_load_end
60aa: send_ipc_cmd
60fe: iosfsb_read
64ea: ucode_fit_xlat_found
6bfd: pdm_trace_uacrh_state
6e16: fit_load_start
@@ -86,3 +105,4 @@
6f3d: process_plain_patch
735c: rsa_decrypt
75c6: enclu_impl
7661: aes128_encrypt

View File

@@ -43,6 +43,7 @@
049: MOVE_DSZ64
04a: TESTUSTATE
04c: SAVEUIP
04d: SAVEUIP_REGOVR
050: UJMPCC_DIRECT_NOTTAKEN_CONDO
051: UJMPCC_DIRECT_NOTTAKEN_CONDNO
052: UJMPCC_DIRECT_NOTTAKEN_CONDB
@@ -125,8 +126,8 @@
108: READUIP_REGOVR
120: SUBR_DSZ32
122: RCXBTCNTMSK_DSZ32
130: SELECTCC_DSZ32_CONDZ
131: SELECTCC_DSZ32_CONDNZ
130: SELECTCC_DSZ32_CONDNZ
131: SELECTCC_DSZ32_CONDZ
132: SELECTCC_DSZ32_CONDBE
133: SELECTCC_DSZ32_CONDNBE
134: CMOVCC_DSZ32_CONDZ
@@ -149,8 +150,8 @@
15f: UJMPCC_DIRECT_TAKEN_CONDZ
160: SUBR_DSZ64
162: RCXBTCNTMSK_DSZ64
170: SELECTCC_DSZ64_CONDZ
171: SELECTCC_DSZ64_CONDNZ
170: SELECTCC_DSZ64_CONDNZ
171: SELECTCC_DSZ64_CONDZ
172: SELECTCC_DSZ64_CONDBE
173: SELECTCC_DSZ64_CONDNBE
174: CMOVCC_DSZ64_CONDZ
@@ -313,11 +314,13 @@
470: MOVLPD
471: MOVHPD
472: MOVDQU
477: PINTSLLDQQ
4b4: FMOV
4c3: ORPD
4c7: XORPD
4c7: PINTPXORD
4e3: ANDPD
4e7: ANDNPD
4ec: PINTSRLDQ
4ef: MOVHLPS
508: PUNPCKLDQ
50a: PSRLQ
@@ -364,6 +367,7 @@
655: PMULHW
685: FILD
68a: FCOM2
6e2: AESKEYGENASSIST
6f1: MULPD
6f5: SQRTPD
6f6: DIVPD
@@ -380,12 +384,17 @@
72c: PINTMOVDTMM2I_DSZ32
72d: PINTMOVDMM2I_DSZ32
745: PINTMOVDI2MM_DSZ64
746: PINTMOVQI2XMMHQ_DSZ64
747: PINTMOVQI2XMMLQ_DSZ64
769: PMOVMSKB
76c: PINTMOVDTMM2I_DSZ64
76d: PINTMOVDMM2I_DSZ64
76f: PINTMOVQXMMLQ2I_DSZ64
785: PINSRW
7ad: PEXTRW
7b8: RSQRTPS
7c8: AESENC
7c9: AESENCLAST
7ed: FCMOVNE
7f8: MOVMSKPD
81f: LA2LIN_DSZ32

File diff suppressed because it is too large Load Diff