0x01简介
之前学了一些但是后来没有跟进,慢慢忘了,最近找到一个比较好的学习github项目,系统地重新学一下
angr是一种模糊执行工具,不是太清楚怎么做的但是比直接爆破要好很多就对了。
并且angr提供了一个强大的功能,可以加载分析人以平台下的二进制文件。
原github项目地址
https://github.com/jakespringer/angr_ctf
下面的代码会给出两部分
1.官网给出的代码,但是需要填写一些内容。 我这里会填上之后放进来
2.我自己跟着写的。 这上面会加上我的理解
0x02环境搭建
需要pypy来运行generate.py 编译出来二进制文件。
需要给pypy安装pip 用来安装库 这东西好像跟python没多大区别
python2
需要安装angr python2 -m pip install angr
编译命令 pypy generate.py 1 1
0x00简单加载分析
github上并没有给地址,这里是我自己填上的,程序不同地址可能会不同
填上官网给的脚本的地址空缺
#coding=utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
# Before you begin, here are a few notes about these capture-the-flag
# challenges.
#
# Each binary, when run, will ask for a password, which can be entered via stdin
# (typing it into the console.) Many of the levels will accept many different
# passwords. Your goal is to find a single password that works for each binary.
#
# If you enter an incorrect password, the program will print "Try again." If you
# enter a correct password, the program will print "Good Job."
#
# Each challenge will be accompanied by a file like this one, named
# "scaffoldXX.py". It will offer guidance as well as the skeleton of a possible
# solution. You will have to edit each file. In some cases, you will have to
# edit it significantly. While use of these files is recommended, you can write
# a solution without them, if you find that they are too restrictive.
#
# Places in the scaffoldXX.py that require a simple substitution will be marked
# with three question marks (???). Places that require more code will be marked
# with an ellipsis (...). Comments will document any new concepts, but will be
# omitted for concepts that have already been covered (you will need to use
# previous scaffoldXX.py files as a reference to solve the challenges.) If a
# comment documents a part of the code that needs to be changed, it will be
# marked with an exclamation point at the end, on a separate line (!).
import angr
import sys
def main(argv):
# Create an Angr project.
# If you want to be able to point to the binary from the command line, you can
# use argv[1] as the parameter. Then, you can run the script from the command
# line as follows:
# python ./scaffold00.py [binary]
# (!)
path_to_binary = "1" # :string
project = angr.Project(path_to_binary)
# Tell Angr where to start executing (should it start from the main()
# function or somewhere else?) For now, use the entry_state function
# to instruct Angr to start from the main() function.
initial_state = project.factory.entry_state()
# Create a simulation manager initialized with the starting state. It provides
# a number of useful tools to search and execute the binary.
simulation = project.factory.simgr(initial_state)
# Explore the binary to attempt to find the address that prints "Good Job."
# You will have to find the address you want to find and insert it here.
# This function will keep executing until it either finds a solution or it
# has explored every possible path through the executable.
# (!)
print_good_address = 0x08048675 # :integer (probably in hexadecimal)
simulation.explore(find=print_good_address)
# Check that we have found a solution. The simulation.explore() method will
# set simulation.found to a list of the states that it could find that reach
# the instruction we asked it to search for. Remember, in Python, if a list
# is empty, it will be evaluated as false, otherwise true.
if simulation.found:
# The explore method stops after it finds a single state that arrives at the
# target address.
solution_state = simulation.found[0]
# Print the string that Angr wrote to stdin to follow solution_state. This
# is our solution.
print solution_state.posix.dumps(sys.stdin.fileno())
else:
# If Angr could not find a path that reaches print_good_address, throw an
# error. Perhaps you mistyped the print_good_address?
raise Exception('Could not find the solution')
if __name__ == '__main__':
main(sys.argv)
加上我的理解
# -*- coding:utf-8 -*-
#https://github.com/jakespringer/angr_ctf
"""
运行步骤:
1.创建project载入要分析的文件
2.告诉angr从哪里加载
3.告诉angr到哪里结束,angr会探索这些结果
4.判断是否有想要的结果然后输出
"""
import angr
import sys
reload(sys)
sys.setdefaultencoding('utf8')
def main(argv):
path_to_binary = "1" # :string
project = angr.Project(path_to_binary)#要分析的二进制文件
# 告诉ange从哪里开始执行entry_state() 表示从main函数开始
initial_state=project.factory.entry_state()
#创建一个使用起始状态初始化的模拟管理器。它提供
#一些有用的工具来搜索和执行二进制文件。
simulation=project.factory.simgr(initial_state)
#函数会一直运行直到运行到0x08048675这个地质处,或者探索了每条可能路径
print_good_address = 0x08048675 # :integer (probably in hexadecimal)
simulation.explore(find=print_good_address)
#找到的方案会存放到simulation.found列表里面(列表里面存放的是地址)
if simulation.found:
solution_state=simulation.found[0]
#用这种方式输出内容
print solution_state.posix.dumps(sys.stdin.fileno())
else:
raise Exception("Could not find the solution")
if __name__=="__main__":
main(sys.argv)
0x01这里添加了avoid用来排除错误的位置
git给出
import angr
import sys
reload(sys)
sys.setdefaultencoding('utf8')
def main(argv):
path_to_binary = "1"
project = angr.Project(path_to_binary)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)
# Explore the binary, but this time, instead of only looking for a state that
# reaches the print_good_address, also find a state that does not reach
# will_not_succeed_address. The binary is pretty large, to save you some time,
# everything you will need to look at is near the beginning of the address
# space.
# (!)
print_good_address = 0x080485E0
will_not_succeed_address = 0x080485F2
simulation.explore(find=print_good_address, avoid=will_not_succeed_address)
if simulation.found:
solution_state = simulation.found[0]
print solution_state.posix.dumps(sys.stdin.fileno())
else:
raise Exception('Could not find the solution')
if __name__ == '__main__':
main(sys.argv)
我的理解
# -*- coding:utf-8 -*-
import angr
import sys
reload(sys)
sys.setdefaultencoding("utf8")
def main(argv):
project=angr.Project("1")
initial_state=project.factory.entry_state()
simulation=project.factory.simgr(initial_state)
print_good_address=0x080485E0
will_not_succeed_address=0x080485F2
#这里除了找得到一个正确的地方还要找到一个不正确的地方,这样可以减少探索时间
simulation.explore(find=print_good_address,avoid=will_not_succeed_address)
if simulation.found:
solution_astate=simulation.found[0]
print solution_astate.posix.dumps(sys.stdin.fileno())
else:
raise Exception('Could not find the solution')
if __name__ == '__main__':
main(sys.argv)
0x02如何避免在代码里面写入地址
git给出
# It is very useful to be able to search for a state that reaches a certain
# instruction. However, in some cases, you may not know the address of the
# specific instruction you want to reach (or perhaps there is no single
# instruction goal.) In this challenge, you don't know which instruction
# grants you success. Instead, you just know that you want to find a state where
# the binary prints "Good Job."
#
# Angr is powerful in that it allows you to search for a states that meets an
# arbitrary condition that you specify in Python, using a predicate you define
# as a function that takes a state and returns True if you have found what you
# are looking for, and False otherwise.
import angr
import sys
reload(sys)
sys.setdefaultencoding('utf8')
def main(argv):
path_to_binary = argv[1]
project = angr.Project(path_to_binary)
initial_state = project.factory.entry_state()
simulation = project.factory.simgr(initial_state)
# Define a function that checks if you have found the state you are looking
# for.
def is_successful(state):
# Dump whatever has been printed out by the binary so far into a string.
stdout_output = state.posix.dumps(sys.stdout.fileno())
#print(stdout_output)
# Return whether 'Good Job.' has been printed yet.
# (!)
return 'Good Job.' in stdout_output# :boolean
# Same as above, but this time check if the state should abort. If you return
# False, Angr will continue to step the state. In this specific challenge, the
# only time at which you will know you should abort is when the program prints
# "Try again."
def should_abort(state):
stdout_output = state.posix.dumps(sys.stdout.fileno())
return 'Try again.' in stdout_output
# Tell Angr to explore the binary and find any state that is_successful identfies
# as a successful state by returning True.
simulation.explore(find=is_successful, avoid=should_abort)
if simulation.found:
solution_state = simulation.found[0]
print solution_state.posix.dumps(sys.stdin.fileno())
else:
raise Exception('Could not find the solution')
if __name__ == '__main__':
main(sys.argv)
我的理解
# -*- coding:utf-8 -*-
import angr
import sys
reload(sys)
sys.setdefaultencoding("utf8")
#和上一个不同这里用is_successful和should_abort两个bool型函数代替了原本的地址。
#也就是说simulation.explore()函数会接收find 和avoid的值,在find为True的时候结束探索。 在avoid为True的时候会重新开始新一轮探索
#使用条件是:有明确输出正确或错误。
#优势:省去了找两个地址的时间,也会兼容更多编译出来的代码
def main(argv):
project=angr.Project("1")
initial_state=project.factory.entry_state()
simulation=project.factory.simgr(initial_state)
def is_successful(state):
stdout_output=state.posix.dumps(sys.stdout.fileno())
return "Good Job." in stdout_output
def should_abort(state):
stdout_output=state.posix.dumps(sys.stdout.fileno())
return "Try agarn." in stdout_output
simulation.explore(find=is_successful,avoid=should_abort)
if simulation.found:
solution_state=simulation.found[0]
print solution_state.posix.dumps(sys.stdin.fileno())
else:
raise Exception("Could not find the solution")
if __name__=='__main__':
main(sys.argv)
接下来会持续更新这个再接再厉!