Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Possible Bug] Fetch rip-based address failure with UC_ERR_FETCH_UNMAPPED #1906

Open
TommyJerryMairo opened this issue Nov 12, 2023 · 0 comments

Comments

@TommyJerryMairo
Copy link

TommyJerryMairo commented Nov 12, 2023

Describe the bug

When executing rip-based indirect call instruction, the emulated CPU attempts to fetch at an unrelated address, which is unexpected and raises a UC_ERR_FETCH_UNMAPPED error.

To Reproduce

  1. Download and save the proof-of-concept script unicorn-indircall.py to a local system
  2. Execute the script with python

Expected behaviour

The script exits succeed with the result printed

Actual output

$ python unicorn-indircall.py
>>> Tracing instruction at 0x0000000001000000, instruction size = 0x0000000000000006
>>> RIP is 0x0000000001000000
!!! Unicorn Engine Exception: Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)
!!! RIP is 0x7d894853e5894855

$

Environment

  • OS: ArchLinux w/ up-to-date upgrades
  • Python: 3.11.5
  • Unicorn Engine: 2.0.1

Proof-of-Concept: unicorn-indircall.py

#!/usr/bin/env python

from unicorn import *
from unicorn.x86_const import *
import os

#   0:   ff 15 3e 00 00 00       call   QWORD PTR [rip+0x3e]        # 0x44
#   6:   90                      nop
#   ......
#  43:   90                      nop
#  44:   55                      push   rbp
#  45:   48 89 e5                mov    rbp, rsp
#  48:   53                      push   rbx
#  49:   48 89 7d f0             mov    QWORD PTR [rbp-0x10], rdi
#  4d:   48 8b 5d f0             mov    rbx, QWORD PTR [rbp-0x10]
#  51:   eb 04                   jmp    0x57
#  53:   48 83 c3 01             add    rbx, 0x1
#  57:   0f b6 03                movzx  eax, BYTE PTR [rbx]
#  5a:   84 c0                   test   al, al
#  5c:   75 f5                   jne    0x53
#  5e:   48 89 d8                mov    rax, rbx
#  61:   48 2b 45 f0             sub    rax, QWORD PTR [rbp-0x10]
#  65:   48 8b 5d f8             mov    rbx, QWORD PTR [rbp-0x8]
#  69:   c9                      leave
#  6a:   c3                      ret
X86_CODE64 = b'\xff\x15\x3e\x00\x00\x00'+b'\x90'*62+b'\x55\x48\x89\xe5\x53\x48\x89\x7d\xf0\x48\x8b\x5d\xf0\xeb\x04\x48\x83\xc3\x01\x0f\xb6\x03\x84\xc0\x75\xf5\x48\x89\xd8\x48\x2b\x45\xf0\x48\x8b\x5d\xf8\xc9\xc3'

ADDRESS = 0x1000000
DATA_ADDR = ADDRESS+1024*1024
STACK_ADDR = ADDRESS+2*1024*1024-16

def hook_code64(uc, address, size, user_data):
    print(f">>> Tracing instruction at {address:#0{18}x}, instruction size = {size:#0{18}x}")
    rip = uc.reg_read(UC_X86_REG_RIP)
    print(f">>> RIP is {rip:#0{18}x}");


def main():
    data = os.urandom(4096)
    mu = Uc(UC_ARCH_X86, UC_MODE_64)
    mu.mem_map(ADDRESS, 144*1024*1024)
    mu.mem_write(ADDRESS, X86_CODE64)
    mu.mem_write(DATA_ADDR, data)
    mu.reg_write(UC_X86_REG_RSP, STACK_ADDR)
    mu.reg_write(UC_X86_REG_RDI, DATA_ADDR)
    mu.hook_add(UC_HOOK_CODE, hook_code64)
    try:
        mu.emu_start(ADDRESS,ADDRESS+8)
        print(f"Result={mu.reg_read(UC_X86_REG_RAX):#0{18}x}")
    except UcError as err:
        print(f"!!! Unicorn Engine Exception: {err}")
        print(f"!!! RIP is {mu.reg_read(UC_X86_REG_RIP):#0{18}x}")

if __name__ == '__main__':
    main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants