吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2333|回复: 3
收起左侧

[Python 转载] 【笔记】多架构多平台CPU仿真器-Unicorn实用手册

[复制链接]
我已经蓝屏 发表于 2021-7-21 14:03
本帖最后由 我已经蓝屏 于 2021-7-21 14:07 编辑

前言

本文就是写写Unicorn咋用的
不涉及原理层面

地址

官方网站
https://www.unicorn-engine.org/
Github
https://github.com/unicorn-engine/unicorn
我的博客(欢迎来踩)
https://kdajv.com/2021/07/21/capstoneengine/

介绍

Unicorn是一个轻量级的多平台多架构CPU仿真器
高亮特点:

  • 多架构支持: Arm, Arm64 (Armv8), M68K, Mips, Sparc, & X86 (包括X86_64).
  • 干净/简单/轻量级/直观的API,同时不依赖任何架构。
  • 以C/C++实现,可在众多语言里使用:Pharo, Crystal, Clojure, Visual Basic, Perl, Rust, Haskell, Ruby, Python, Java, Go, .NET, Delphi/Pascal & MSVC。
  • 原生支持Windows和*nix系统(以下系统已确认支持:Mac OSX, Linux, *BSD & Solaris)。
  • 通过使用即时编译器技术以实现高性能。
  • 支持各种级别的细粒度检测。
  • 线程安全的设计。
  • 允许在开源软件许可 GPLv2 下分发。

使用

Input

from unicorn import *

# 要执行的字节码
# 可以使用Keystone引擎生成
binary = b'1\xc0Ph//shh/bin\x89\xe3PS\x89\xe1\xb0\x0b'

# 规定内存地址
ADDRESS = 0x400000

print("开始模拟-X86")

# 初始化仿真器,模式为X86-32
mu = Uc(UC_ARCH_X86, UC_MODE_32)

# 给仿真器映射2MB内存
mu.mem_map(ADDRESS, 2 * 1024 * 1024)

# 将指令写到内存
mu.mem_write(ADDRESS, binary)

# 初始化仿真器的寄存器,并赋值
# ESP给了内存的最后一个位置
mu.reg_write(x86_const.UC_X86_REG_EAX, 0x1000)
mu.reg_write(x86_const.UC_X86_REG_ESP, ADDRESS + 2 * 1024 * 1024 - 1)

# 这里创建一个钩子,每执行一条指令会先执行一次这里,如果有不想执行的语句可以跳过
# 跳过方法:EIP+size
def hook(emu: Uc, addr, size, userdata):
    # 反汇编当前语句的语义,详情请看Capstone篇
    from capstone import Cs, CS_ARCH_X86, CS_MODE_32
    CS = Cs(CS_ARCH_X86, CS_MODE_32)
    instruction = list(CS.disasm(emu.mem_read(addr, size), 0))[0]
    print(f"当前位置:{hex(addr)},指令长度:{size},指令:{instruction.mnemonic} {instruction.op_str}")
    userdata.Count += 1

# 这里可以传给钩子一个变量(注意不能是初始类型,否则就只传值而不是引用了),执行结束的时候可以读取到钩子里处理的数据
class InstCount:
    Count = 0

count = InstCount()

# 添加钩子,钩子类型为CODE,再传一个用户数据,别的暂时还不知道
mu.hook_add(UC_HOOK_CODE, hook, count)

# 开始仿真
mu.emu_start(ADDRESS, ADDRESS + len(binary))

# 仿真结束
print("仿真结束")
print(f"共执行{count.Count}条指令")

# 读寄存器
r_eax = mu.reg_read(x86_const.UC_X86_REG_EAX)
r_ebx = mu.reg_read(x86_const.UC_X86_REG_EBX)
r_ecx = mu.reg_read(x86_const.UC_X86_REG_ECX)
r_esp = mu.reg_read(x86_const.UC_X86_REG_ESP)
print(">>> EAX = 0x%x" % r_eax)
print(">>> EBX = 0x%x" % r_ebx)
print(">>> ECX = 0x%x" % r_ecx)
print(">>> ESP = 0x%x" % r_esp)

# 读栈内容
now = r_esp
while now != ADDRESS + 2 * 1024 * 1024 - 1:
    buf = mu.mem_read(now, 4)
    print(f"Stack > ESP - {hex(now)} - {buf}")
    now += 4

Output

开始模拟-X86
当前位置:0x400000,指令长度:2,指令:xor eax, eax
当前位置:0x400002,指令长度:1,指令:push eax
当前位置:0x400003,指令长度:5,指令:push 0x68732f2f
当前位置:0x400008,指令长度:5,指令:push 0x6e69622f
当前位置:0x40000d,指令长度:2,指令:mov ebx, esp
当前位置:0x40000f,指令长度:1,指令:push eax
当前位置:0x400010,指令长度:1,指令:push ebx
当前位置:0x400011,指令长度:2,指令:mov ecx, esp
当前位置:0x400013,指令长度:2,指令:mov al, 0xb
仿真结束
共执行9条指令
>>> EAX = 0xb
>>> EBX = 0x5ffff3
>>> ECX = 0x5fffeb
>>> ESP = 0x5fffeb
Stack > ESP - 0x5fffeb - bytearray(b'\xf3\xff_\x00')
Stack > ESP - 0x5fffef - bytearray(b'\x00\x00\x00\x00')
Stack > ESP - 0x5ffff3 - bytearray(b'/bin')
Stack > ESP - 0x5ffff7 - bytearray(b'//sh')
Stack > ESP - 0x5ffffb - bytearray(b'\x00\x00\x00\x00')

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

prospect2005 发表于 2021-7-21 14:26
虚拟机?支持sparc版的solaris系统吗?
 楼主| 我已经蓝屏 发表于 2021-7-21 14:38
prospect2005 发表于 2021-7-21 14:26
虚拟机?支持sparc版的solaris系统吗?

只是指令仿真器
我没接触过这两个
但是据官网上说时支持的
https://github.com/unicorn-engine/unicorn
星星之夜 发表于 2021-7-21 16:58
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 14:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表