angr[2]--使用操作

这里将会写angr模拟寄存器,栈,bss段,模拟堆,模拟文件

补充:格式化是angr的弱点,需要尽量避开

0x03设置寄存器的值

# -*- coding:utf-8 -*-
import angr
import claripy
import sys
reload(sys)
sys.setdefaultencoding("utf8")

#设置寄存器值

"""
angr只支持一次scanf,多次scanf需要绕过。
因为是32位寄存器所以需要32位
initial_state.regs.eax = password0   可以设置寄存器的值
solution0 = solution_state.se.eval(password0)  可以获取解决方案,但是只有一个位向量的
加载程序,设置开始地址,设置寄存器值(设置初始状态)   设置正确和错误的结果探索   取出跑出来的结果    

"""

def main(argv):
    project=angr.Project("./1")

    #这个地址是从ida里面找出来的,读入了数据之后的值
    """
.text:08048911                 call    get_user_input
.text:08048916                 mov     [ebp+var_14], eax
.text:08048919                 mov     [ebp+var_10], ebx
.text:0804891C                 mov     [ebp+var_C], edx
    """
    start_address=0x08048916
    initial_state=project.factory.blank_state(addr=start_address) #用blank_state 来实现从某个地址处载入

    #因为32位程序寄存器最多放32位
    password0_size_in_bits=32
    #用来生成位向量   这个东西应该是类似列表之类的东西
    password0=claripy.BVS('password0',password0_size_in_bits)
    password1 = claripy.BVS('password1', password0_size_in_bits)
    password2 = claripy.BVS('password2', password0_size_in_bits)

    #给寄存器赋值   ida里面可以看到这三个寄存器是决定程序的值是否走到 good job的值
    initial_state.regs.eax=password0
    initial_state.regs.ebx = password1
    initial_state.regs.edx = password2

    simulation=project.factory.simgr(initial_state)

    def is_successful(state):
        stdout_output=state.posix.dumps(sys.stdout.fileno())
        return "Good" in stdout_output

    def should_abort(state):
        stdout_output=state.posix.dumps(sys.stdout.fileno())
        return "Try" in stdout_output

    simulation.explore(find=is_successful,avoid=should_abort)

    if simulation.found:
        solution_state=simulation.found[0]
        #找到了之后想要拿出来需要一个一个取  应该是字典之类的东东西
        solution0=solution_state.se.eval(password0)
        solution1=solution_state.se.eval(password1)
        solution2=solution_state.se.eval(password2)


        solution= str(solution0)+","+str(solution1)+","+str(solution2)
        print hex(solution0), hex(solution1), hex(solution2)
        print solution

    else:
        raise Exception("Could not find the solution")


if __name__ == '__main__':
    main(sys.argv)

0x04设置栈


import angr
import claripy
import sys

def main(argv):
  path_to_binary = "./04_angr_symbolic_stack"
  project = angr.Project(path_to_binary)    #设置加载路径

  start_address = 0x08048697
  initial_state = project.factory.blank_state(addr=start_address)      #设置开始地址



  initial_state.regs.ebp = initial_state.regs.esp                      #设置栈的开始数据
  password0 = claripy.BVS('password0', 32)
  password1 = claripy.BVS('password1', 32)

  padding_length_in_bytes = 8  # :integer
  initial_state.regs.esp -= padding_length_in_bytes                  #放入栈中
  initial_state.stack_push(password0)  # :bitvector (claripy.BVS, claripy.BVV, claripy.BV)
  initial_state.stack_push(password1)




  simulation = project.factory.simgr(initial_state)                #运行,找到地址

  def is_successful(state):
      stdout_output = state.posix.dumps(sys.stdout.fileno())
      return 'Good Job' in str(stdout_output)

  def should_abort(state):
      stdout_output = state.posix.dumps(sys.stdout.fileno())
      return 'Try again.' in str(stdout_output)

  simulation.explore(find=is_successful, avoid=should_abort)

  if simulation.found:                                          #处理结果
      solution_state = simulation.found[0]

      solution0 = solution_state.se.eval(password0)
      solution1 = solution_state.se.eval(password1)


      solution = ' '.join(map('{:x}'.format, [solution0, solution1]))
      print(solution)
  else:
      raise Exception('Could not find the solution')


if __name__ == '__main__':
    main(sys.argv)

核心代码

initial_state.regs.ebp = initial_state.regs.esp 
  password0 = claripy.BVS('password0', 32)
    padding_length_in_bytes = 8  # :integer       减8是因为两个数据,每个32bit也就是4个字节共8个字节
  initial_state.regs.esp -= padding_length_in_bytes                  #放入栈中
  initial_state.stack_push(password0) 

0x05模拟bass段

import angr
import claripy
import sys
import binascii

def main(argv):
  path_to_binary = "./05_angr_symbolic_memory"
  project = angr.Project(path_to_binary)

  start_address = 0x08048601
  initial_state = project.factory.blank_state(addr=start_address)

  # The binary is calling scanf("%8s %8s %8s %8s").
  # (!)
  password0 = claripy.BVS('password0', 8*8)      #设置数据个数,这里的数是bit数,一个字节是8个bit
  password1 = claripy.BVS('password1', 8 * 8)
  password2 = claripy.BVS('password2', 8 * 8)
  password3 = claripy.BVS('password3', 8 * 8)


  # Determine the address of the global variable to which scanf writes the user
  # input. The function 'initial_state.memory.store(address, value)' will write
  # 'value' (a bitvector) to 'address' (a memory location, as an integer.) The
  # 'address' parameter can also be a bitvector (and can be symbolic!).
  # (!)
  password0_address = 0x09FD92A0                       #把数据放到
  initial_state.memory.store(password0_address, password0)
  password0_address = 0x09FD92A8
  initial_state.memory.store(password0_address, password1)
  password0_address = 0x09FD92B0
  initial_state.memory.store(password0_address, password2)
  password0_address = 0x09FD92B8
  initial_state.memory.store(password0_address, password3)


  simulation = project.factory.simgr(initial_state)

  def is_successful(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Good Job' in str(stdout_output)

  def should_abort(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Try again.' in str(stdout_output)

  simulation.explore(find=is_successful, avoid=should_abort)

  if simulation.found:
    solution_state = simulation.found[0]

    # Solve for the symbolic values. We are trying to solve for a string.
    # Therefore, we will use eval, with named parameter cast_to=str
    # which returns a string instead of an integer.
    # (!)
    solution0 = solution_state.se.eval(password0)
    solution1 = solution_state.se.eval(password1)
    solution2 = solution_state.se.eval(password2)
    solution3 = solution_state.se.eval(password3)

    solution = ''.join(map('{:x}'.format, [solution0, solution1,solution2,solution3]))

    print (binascii.a2b_hex(solution))       #16进制数转字符串
  else:
    raise Exception('Could not find the solution')

if __name__ == '__main__':
  main(sys.argv)

设置数据的内容

password0_address = 0x09FD92A0                       #把数据放到
initial_state.memory.store(password0_address, password0)

0x06模拟堆

import angr
import claripy
import sys
import binascii

def main(argv):
  path_to_binary = "./06_angr_symbolic_dynamic_memory"
  project = angr.Project(path_to_binary)

  start_address = 0x08048699
  initial_state = project.factory.blank_state(addr=start_address)

  # The binary is calling scanf("%8s %8s").
  # (!)
  password0 = claripy.BVS('password0', 8*8) #buffer0
  password1 = claripy.BVS('password1', 8*8) #buffer1


  # Instead of telling the binary to write to the address of the memory
  # allocated with malloc, we can simply fake an address to any unused block of
  # memory and overwrite the pointer to the data. This will point the pointer
  # with the address of pointer_to_malloc_memory_address0 to fake_heap_address.
  # Be aware, there is more than one pointer! Analyze the binary to determine
  # global location of each pointer.
  # Note: by default, Angr stores integers in memory with big-endianness. To
  # specify to use the endianness of your architecture, use the parameter
  # endness=project.arch.memory_endness. On x86, this is little-endian.
  # (!)
  fake_heap_address0 = 0x40000
  pointer_to_malloc_memory_address0 =0x09FD92AC
  initial_state.memory.store(pointer_to_malloc_memory_address0, fake_heap_address0, endness=project.arch.memory_endness)
  #buffer0    把数据放入内存堆地址(数据具体存到哪随意) 这个地址的指针,也就是变量的具体值要准确
  fake_heap_address1 = 0x40010
  pointer_to_malloc_memory_address1 = 0x09FD92B4
  initial_state.memory.store(pointer_to_malloc_memory_address1, fake_heap_address1, endness=project.arch.memory_endness) #buffer1


  # Store our symbolic values at our fake_heap_address. Look at the binary to
  # determine the offsets from the fake_heap_address where scanf writes.
  # (!)
  initial_state.memory.store(fake_heap_address0, password0)
  initial_state.memory.store(fake_heap_address1, password1)


  simulation = project.factory.simgr(initial_state)

  def is_successful(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Good Job' in str(stdout_output)

  def should_abort(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Try again.' in str(stdout_output)
  simulation.explore(find=is_successful, avoid=should_abort)

  if simulation.found:
    solution_state = simulation.found[0]

    solution0 = solution_state.se.eval(password0)
    solution1 = solution_state.se.eval(password1)

    solution = ''.join(map("{:x}".format,[solution0,solution1]))
    # print(solution)
    print (binascii.a2b_hex(solution.strip()))
  else:
    raise Exception('Could not find the solution')

if __name__ == '__main__':
  main(sys.argv)

一组数据进行两次写入,第一次把数据写入到具体位置也就是申请的空间
第二次把第一次写入的地址写入到程序的变量位置(这里是bss段)
其实就是写入内存和0x01没有本质区别

 fake_heap_address0 = 0x40000
  pointer_to_malloc_memory_address0 =0x09FD92AC
  initial_state.memory.store(pointer_to_malloc_memory_address0, fake_heap_address0, endness=project.arch.memory_endness)
  #buffer0    把数据放入内存堆地址(数据具体存到哪随意) 这个地址的指针,也就是变量的具体值要准确
  initial_state.memory.store(fake_heap_address0, password0)

0x07angr 模拟文件

# This challenge could, in theory, be solved in multiple ways. However, for the
# sake of learning how to simulate an alternate filesystem, please solve this
# challenge according to structure provided below. As a challenge, once you have
# an initial solution, try solving this in an alternate way.
#
# Problem description and general solution strategy:
# The binary loads the password from a file using the fread function. If the
# password is correct, it prints "Good Job." In order to keep consistency with
# the other challenges, the input from the console is written to a file in the 
# ignore_me function. As the name suggests, ignore it, as it only exists to
# maintain consistency with other challenges.
# We want to:
# 1. Determine the file from which fread reads.
# 2. Use Angr to simulate a filesystem where that file is replaced with our own
#    simulated file.
# 3. Initialize the file with a symbolic value, which will be read with fread
#    and propogated through the program.
# 4. Solve for the symbolic input to determine the password.
import binascii
import angr
import claripy
import sys

def main(argv):
  path_to_binary = "./07_angr_symbolic_file"
  project = angr.Project(path_to_binary)

  start_address = 0x80488D6
  initial_state = project.factory.blank_state(addr=start_address)     #开始地址需要在打开文件之前,这里模拟了文件


  filename = "MRXJKZYR.txt" # :string     设置文件名
  symbolic_file_size_bytes = 0x40


  password = claripy.BVS('password', symbolic_file_size_bytes * 8)       #生成符号



  password_file = angr.storage.SimFile(filename, content=password)       #把内容放入文件
  initial_state.fs.insert(filename, password_file)
  simulation = project.factory.simgr(initial_state)                       #运行


  def is_successful(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Good Job' in str(stdout_output)

  def should_abort(state):
    stdout_output = state.posix.dumps(sys.stdout.fileno())
    return 'Try again.' in str(stdout_output)

  simulation.explore(find=is_successful, avoid=should_abort)

  if simulation.found:
    solution_state = simulation.found[0]

    solution = solution_state.se.eval(password)
    solution="".join(map("{:x}".format,[solution]))

    print (binascii.a2b_hex(solution))
  else:
    raise Exception('Could not find the solution')

if __name__ == '__main__':
  main(sys.argv)

核心内容

  filename = "MRXJKZYR.txt" # :string     设置文件名
  symbolic_file_size_bytes = 0x40                         #  设置文件长度
  password = claripy.BVS('password', symbolic_file_size_bytes * 8)       #生成符号
  password_file = angr.storage.SimFile(filename, content=password)       #把内容放入文件
  initial_state.fs.insert(filename, password_file)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值