Support additional API on Python 3 bindings (#2016)

* Styling and commets fixes

* Add errno API support

* Improve OOP approach by adjusting the way reg types are selected

* Leverage new approach to deduplicate reg_read and reg_write code

* Adjust reg_read_batch

* Add support for reg_write_batch

* Adjust x86 MSR accessors

* Turn asserts into descriptive exceptions

* Improve comments and styling

* Fix ARM memcpy neon regression test

* Modify canonicals import

* Introduce ARM CP reg accessors
This commit is contained in:
Eli
2024-10-06 18:14:03 +03:00
committed by GitHub
parent 05e29b4507
commit ac4872be4c
6 changed files with 404 additions and 225 deletions

View File

@@ -1,52 +1,68 @@
from unicorn import *
from unicorn.arm_const import *
# .text:0001F894 ADD PC, PC, R3
# .text:0001F898 ; ---------------------------------------------------------------------------
# .text:0001F898 VLD1.8 {D0}, [R1]!
# .text:0001F89C VST1.8 {D0}, [R12]!
# .text:0001F8A0 VLD1.8 {D0}, [R1]!
# .text:0001F8A4 VST1.8 {D0}, [R12]!
# .text:0001F8A8 VLD1.8 {D0}, [R1]!
# .text:0001F8AC VST1.8 {D0}, [R12]!
# .text:0001F8B0 VLD1.8 {D0}, [R1]!
# .text:0001F8B4 VST1.8 {D0}, [R12]!
# .text:0001F8B8 VLD1.8 {D0}, [R1]!
# .text:0001F8BC VST1.8 {D0}, [R12]!
# .text:0001F8C0 VLD1.8 {D0}, [R1]!
# .text:0001F8C4 VST1.8 {D0}, [R12]!
# .text:0001F8C8 VLD1.8 {D0}, [R1]!
# .text:0001F8CC VST1.8 {D0}, [R12]!
# .text:0001F8D0 TST R2, #4
# .text:0001F8D4 LDRNE R3, [R1],#4
# .text:0001F8D8 STRNE R3, [R12],#4
# .text:0001F8DC MOVS R2, R2,LSL#31
# .text:0001F8E0 LDRHCS R3, [R1],#2
# .text:0001F8E4 LDRBNE R1, [R1]
# .text:0001F8E8 STRHCS R3, [R12],#2
# .text:0001F8EC STRBNE R1, [R12]
shellcode = [0x3, 0xf0, 0x8f, 0xe0, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0xd, 0x7, 0x21, 0xf4, 0xd, 0x7, 0xc, 0xf4, 0x4, 0x0, 0x12, 0xe3, 0x4, 0x30, 0x91, 0x14, 0x4, 0x30, 0x8c, 0x14, 0x82, 0x2f, 0xb0, 0xe1, 0xb2, 0x30, 0xd1, 0x20, 0x0, 0x10, 0xd1, 0x15, 0xb2, 0x30, 0xcc, 0x20, 0x0, 0x10, 0xcc, 0x15]
base = 0x1F894
from_address = 0x1000
to_address = 0x2000
cplen = 8
bs = b"c8"*cplen
SHELLCODE = bytes.fromhex(
'03 f0 8f e0' # 0001F894 ADD PC, PC, R3
'0d 07 21 f4' # 0001F898 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F89C VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8A0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8A4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8A8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8AC VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8B0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8B4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8B8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8BC VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8C0 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8C4 VST1.8 {D0}, [R12]!
'0d 07 21 f4' # 0001F8C8 VLD1.8 {D0}, [R1]!
'0d 07 0c f4' # 0001F8CC VST1.8 {D0}, [R12]!
'04 00 12 e3' # 0001F8D0 TST R2, #4
'04 30 91 14' # 0001F8D4 LDRNE R3, [R1],#4
'04 30 8c 14' # 0001F8D8 STRNE R3, [R12],#4
'82 2f b0 e1' # 0001F8DC MOVS R2, R2,LSL#31
'b2 30 d1 20' # 0001F8E0 LDRHCS R3, [R1],#2
'00 10 d1 15' # 0001F8E4 LDRBNE R1, [R1]
'b2 30 cc 20' # 0001F8E8 STRHCS R3, [R12],#2
'00 10 cc 15' # 0001F8EC STRBNE R1, [R12]
)
BASE = 0x1F894
COPY_SRC = 0x1000
COPY_DST = 0x2000
COPY_LEN = 8
bs = b'c8' * COPY_LEN
uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
uc.mem_map(from_address, 0x1000)
uc.mem_map(to_address, 0x1000)
uc.mem_map(0x1F000, 0x1000)
uc.mem_write(from_address, bs)
uc.mem_write(base, bytes(shellcode))
uc.reg_write(UC_ARM_REG_R12, to_address)
uc.reg_write(UC_ARM_REG_R1, from_address)
uc.reg_write(UC_ARM_REG_R2, cplen)
uc.reg_write(UC_ARM_REG_R3, 0x24)
# enable_vfp
uc.reg_write(UC_ARM_REG_C1_C0_2, uc.reg_read(UC_ARM_REG_C1_C0_2) | (0xf << 20))
uc.reg_write(UC_ARM_REG_FPEXC, 0x40000000)
uc.emu_start(base, base+len(shellcode))
fr = uc.mem_read(from_address, len(bs))
to = uc.mem_read(to_address, len(bs))
print(f"memcpy result:\nfrom: {bytes(fr)}\nto: {bytes(to)}")
uc.mem_map(COPY_SRC, 0x1000)
uc.mem_map(COPY_DST, 0x1000)
uc.mem_map(BASE & ~(0x1000 - 1), 0x1000)
uc.mem_write(COPY_SRC, bs)
uc.mem_write(BASE, bytes(SHELLCODE))
uc.reg_write_batch((
(UC_ARM_REG_R12, COPY_DST),
(UC_ARM_REG_R1, COPY_SRC),
(UC_ARM_REG_R2, COPY_LEN),
(UC_ARM_REG_R3, 0x24)
))
# enable_vfp
# coproc=15, is64=0, sec=0, CRn=1, CRm=0, opc1=0, opc2=2
CPACR = (15, 0, 0, 1, 0, 0, 2)
cpacr = uc.reg_read(UC_ARM_REG_CP_REG, CPACR)
uc.reg_write(UC_ARM_REG_CP_REG, CPACR + (cpacr | (0b11 << 20) | (0b11 << 22),))
uc.reg_write(UC_ARM_REG_FPEXC, (0b1 << 30))
uc.emu_start(BASE, BASE + len(SHELLCODE))
src = uc.mem_read(COPY_SRC, len(bs))
dst = uc.mem_read(COPY_DST, len(bs))
print(f'''memcpy result:
from: {bytes(src)}
to: {bytes(dst)}
''')