Files
unicorn/tests/regress/hang.py
@Antelox 9cfd5cfac3 - Improved the GitHub python binding workflow: (#2072)
- Added fullMode input in workflow_dispatch
    - Take decision whether to build either in debug or release mode and if to build for all python versions according to the commit message patterns
    - Set proper artifact names
    - Removed not needed steps
    - Compacted some steps in order to leverage more the matrix feature
    - Bumped cibuildwheel action to 2.22.0
    - Run actual regress tests in place of sample scripts
- Specify optional test install in pyproject.toml with proper requirements
- Derive package version from git tags
- Add GENERATORS env var support in setup.py to specify cmake generator and minor refactoring
- Minor cleanup/refactoring for the regress test suite
- Marked some regress tests with skipIf to skip them in case of old python versions
- Marked some failing regress tests to be checked with skipIf
2024-12-29 22:24:48 +08:00

87 lines
3.5 KiB
Python
Executable File

import binascii
import regress
from unicorn import *
from unicorn.x86_const import *
# callback for tracing instructions
def hook_code(uc, address, size, user_data):
# invalid instruction?
if size == 0xf1f1f1f1:
return
regress.logger.debug("[%#x] = %s", address, binascii.hexlify(uc.mem_read(address, size)))
# callback for tracing Linux interrupt
def hook_intr(uc, intno, user_data):
# only handle Linux syscall
rip = uc.reg_read(UC_X86_REG_RIP)
regress.logger.debug("[%#x]: got interrupt %#x", rip, intno)
regress.logger.debug(" EAX = %#010x", uc.reg_read(UC_X86_REG_EAX))
regress.logger.debug(" EBX = %#010x", uc.reg_read(UC_X86_REG_EBX))
regress.logger.debug(" ECX = %#010x", uc.reg_read(UC_X86_REG_ECX))
regress.logger.debug(" EDX = %#010x", uc.reg_read(UC_X86_REG_EDX))
uc.emu_stop()
class Hang(regress.RegressTest):
def runTest(self):
# self modifying shellcode execve('/bin/sh')
shellcode = (
b'\xeb\x1c' # 00: jmp 0x1e
b'\x5a' # 02: pop rdx
b'\x89\xd6' # 03: mov esi, edx
b'\x8b\x02' # 05: mov eax, [rdx]
b'\x66\x3d\xca\x7d' # 07: cmp ax, 0x7dca
b'\x75\x06' # 0b: jne 0x13
b'\x66\x05\x03\x03' # 0d: add ax,0x303
b'\x89\x02' # 11: mov [rdx], eax
b'\xfe\xc2' # 13: inc dl
b'\x3d\x41\x41\x41\x41' # 15: cmp eax, 0x41414141
b'\x75\xe9' # 1a: jne 0x5
b'\xff\xe6' # 1c: jmp rsi
b'\xe8\xdf\xff\xff\xff' # 1e: call 0x2
b'\x31\xd2' # 23: xor edx, edx
b'\x6a\x0b' # 25: push 0xb
b'\x58' # 27: pop rax
b'\x99' # 28: cdq
b'\x52' # 29: push rdx
b'\x68\x2f\x2f\x73\x68' # 2a: push 0x68732f2f
b'\x68\x2f\x62\x69\x6e' # 2f: push 0x6e69622f
b'\x89\xe3' # 34: mov ebx, esp
b'\x52' # 36: push rdx
b'\x53' # 37: push rbx
b'\x89\xe1' # 38: mov ecx, esp
b'\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41' # 3a: .db ca 7d 41 41 41 41 41 41 41 41
)
address = 0x00000000
mu = Uc(UC_ARCH_X86, UC_MODE_64)
mu.mem_map(address, 0x1000)
# tracing all instructions with customized callback
mu.hook_add(UC_HOOK_CODE, hook_code)
# handle interrupt ourself
mu.hook_add(UC_HOOK_INTR, hook_intr)
# setup stack
mu.reg_write(UC_X86_REG_RSP, 0x1000 - 8)
# write machine code to be emulated to memory
mu.mem_write(address, shellcode)
regress.logger.debug('Starting emulation')
mu.emu_start(address, address + len(shellcode))
if __name__ == '__main__':
regress.main()