深入浅出angr(四) | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

深入浅出angr(四)

申博_新闻事件 申博 211次浏览 已收录 0个评论

媒介

在逆向中,运用Hook来处置惩罚问题异常的罕见,在之前对angr的进修中,我并未关注到hook要领,如今有时候进修整顿一遍,我倍感快活,实在Hook也非常的简朴,而且能够将庞杂的问题简朴化

初识

一个对照简朴的例子defcamp_r100/r100

解题代码只需以下短短的几行:

import angr

project = angr.Project("angr-doc/examples/defcamp_r100/r100", auto_load_libs=False)

@project.hook(0x400844)
def print_flag(state):
    print("FLAG SHOULD BE:", state.posix.dumps(0))
    project.terminate_execution()

project.execute()

官方文档的引见以下:

深入浅出angr(四)

我们能够经由过程@proj.hook(proj.entry)的体式格局来Hook恣意一个地点。

例子中运用了project.execute()要领,此要领其实不经常使用,它每每和project.terminate_execution()结合起来运用,而且通经常使用在hook时

深入浅出angr(四)

因而代码也许的实行流程以下:

  1. 初始化proj
  2. hook指定地点的函数
  3. 挪用project.execute()
  4. 当碰到project.terminate_execution()标记实行完毕

此时angr会实行到0x400844并打印出flag的效果。

hook标记表

这里以tumctf2016_zwiebel作为例子举行申明。起首看官方文档的申明。

深入浅出angr(四)

hook_symbol函数能够依据所给出的标记名,在二进制文件中找寻对应的地点,而且hook该地点。

IDA载入问题

深入浅出angr(四)

这是一个smc的问题,关于angr来讲为了能在标记实行时举行自解密,须要增加support_selfmodifying_code=True参数

深入浅出angr(四)

很明显,我们没法运用sm.explore(find=xxx,avoid=xxx)的体式格局来运用angr,同时注意到顺序中涌现了ptrace想必肯定有反调试,让我们经由过程hook的要领来绕过反调试。

p.hook_symbol('ptrace', angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'](return_value=0))

由于angr完成了大批的标记化函数,以此来替换顺序中对库函数的外部挪用,个中angr.SIM_PROCEDURESangr对标记化函数的字典挪用,我们能够接纳angr.SIM_PROCEDURES['模块名']['库函数名']()举行hook

————————————-

申博网络安全巴士站

申博-网络安全巴士站是一个专注于网络安全、系统安全、互联网安全、信息安全,全新视界的互联网安全新媒体。

————————————-

然后便能够经由过程simulation_manager举行实行了。

state = p.factory.full_init_state(cadd_options=angr.options.unicorn)
    sm = p.factory.simulation_manager(state)

这里只能接纳相似step的要领举行处置惩罚,效力很低,例子中供应的代码是如许的。

while sm.active:
        # in order to save memory, we only keep the recent 20 deadended or
        # errored states
        #print(len(sm.active))
        sm.run(n=20)
        if 'deadended' in sm.stashes and sm.deadended:
            sm.stashes['deadended'] = sm.deadended[-20:]
        if sm.errored:
            sm.errored = sm.errored[-20:]

    assert sm.deadended
    flag = sm.deadended[-1].posix.dumps(0).split(b"\n")[0]
    import ipdb; ipdb.set_trace()
    return flag

我以为有点多此一举了,他这段代码的目标就是实行完sm.run()此时准确的输入应当保存在末了一个deadended节点的posix.dumps(0)傍边,末了跑了两个小时,我也是醉了。不外最少知道了angr是怎样hook,并绕过反调试的。

典范例题defcon2016quals_baby-re

这道题作为例子可能会更好一点。

这题实在不消hook也能顺遂的解出,只是我们须要对效果举行处置惩罚一下,能力获得我们想要的flag。

深入浅出angr(四)

IDA载入

深入浅出angr(四)

实在之前我们碰到过相似的问题,不外当时我们接纳的要领是:跳过输入局部,直接对内存举行存储,从而举行输入,这里固然也能这么做,只需对[rbp+var_60]内存举行操纵便可

ps:正本只想简朴实验一下,没想到花了几分钟随意写的代码竟然跑出效果了,因而这里特地贴一下代码。

深入浅出angr(四)

import angr
import claripy

# 最简朴的要领,不外须要对效果举行转变
def main():
    proj = angr.Project('./baby-re', auto_load_libs=False)
    state = proj.factory.entry_state(add_options={angr.options.LAZY_SOLVES})
    sm = proj.factory.simulation_manager(state)
    sm.explore(find=0x4028E9, avoid=0x402941)

# 跳过顺序自身的输入,经由过程内存掌握输入
def main2():
    proj = angr.Project('./baby-re', auto_load_libs=False)
    flag_chars = [claripy.BVS('flag_%d' % i, 32) for i in range(13)]

    state = proj.factory.blank_state(addr=0x4028E0,add_options={angr.options.LAZY_SOLVES})
    for i in range:
        state.memory.store(state.regs.rbp-0x60+i*4,flag_chars[i])
    state.regs.rdi = state.regs.rbp-0x60
    sm = proj.factory.simulation_manager(state)
    sm.explore(find=0x4028E9, avoid=0x402941)
if __name__ == '__main__':
    main2()

固然说了这么多,这里最主要照样想说一下怎样运用Hook手艺,来掌握输入,从而轻易我们的输出。

我们能够经由过程如许的体式格局举行Hook

proj.hook_symbol('__isoc99_scanf', my_scanf(), replace=True)

我们用自身的my_scanf()来替代__isoc99_scanf,我们在连结scanf功用稳定的情况下,将我们的标记变量存储进去。

class my_scanf(angr.SimProcedure):
        def run(self, fmt, ptr): # pylint: disable=arguments-differ,unused-argument
            self.state.mem[ptr].dword = flag_chars[self.state.globals['scanf_count']]
            self.state.globals['scanf_count'] += 1

如许顺序每次挪用scanf时,实在就是在实行my_scanf就会将flag_chars[i]存储到self.state.mem[ptr]傍边,这个中ptr参数,实在就是自身scanf函数通报进来的rdi也就是[rbp+var_60]+i*4,为了掌握下标,我们设置了一个全局标记变量scanf_count,置信智慧的你肯定不难理解。

如此一来,只需angr实行到我们想要抵达的分支,那末我们就能够经由过程solver.eval()的体式格局将其打印出来

代码以下:

import angr
import claripy

def main():
    proj = angr.Project('./baby-re', auto_load_libs=False)

    # let's provide the exact variables received through the scanf so we don't have to worry about parsing stdin into a bunch of ints.
    flag_chars = [claripy.BVS('flag_%d' % i, 32) for i in range(13)]
    class my_scanf(angr.SimProcedure):
        def run(self, fmt, ptr): # pylint: disable=arguments-differ,unused-argument
            self.state.mem[ptr].dword = flag_chars[self.state.globals['scanf_count']]
            self.state.globals['scanf_count'] += 1

    proj.hook_symbol('__isoc99_scanf', my_scanf(), replace=True)

    sm = proj.factory.simulation_manager()
    sm.one_active.options.add(angr.options.LAZY_SOLVES)
    sm.one_active.globals['scanf_count'] = 0

    # search for just before the printf("%c%c...")
    # If we get to 0x402941, "Wrong" is going to be printed out, so definitely avoid that.
    sm.explore(find=0x4028E9, avoid=0x402941)

    # evaluate each of the flag chars against the constraints on the found state to construct the flag
    flag = ''.join(chr(sm.one_found.solver.eval(c)) for c in flag_chars)
    return flag

def test():
    assert main() == 'Math is hard!'

if __name__ == '__main__':
    print(main())

总结

我觉得Hook的代码照样对照难写的,不外若是学会了,确切能够省下我们写剧本剖析的时候,又是一个进步效力的要领。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明深入浅出angr(四)
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址