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)
發佈了130 篇原創文章 · 獲贊 35 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章