黑客大神告诉你:Angr_CTF从精通到弃坑( 三 )
SimProcedure 其实就是 Hook 机制 , 可以通过 proj.hook(addr,hook) 设置 , 其中 hook 是一个 SimProcedure 实例 。通过 .is_hooked / .unhook / .hook_by 进行管理 。 将 proj.hook(addr) 作为函数装饰器 , 可以编写自己的 hook 函数 。 还可以通过 proj.hook_symbol(name,hook) hook 函数
一个简单的例子:
>>> @project.hook(0x1234, length=5)... def set_rax(state):...state.regs.rax = 1
其中第一个参数即需要Hook的调用函数的地址 , 第二个参数length即指定执行引擎在完成挂钩后应跳过多少字节 。 具体多少字节由Hook处地址的指令长度确定 , 例如本题:
文章插图
文章插图
我们需要Hook地址的机器指令长度为5个字节 , 故最后的hook函数:
@project.hook(0x80486B3, length=5)
老样子先放最后EXP , 再逐一分析:
import angrimport sysimport claripydef Go():path_to_binary = "./09_angr_hooks"project = angr.Project(path_to_binary, auto_load_libs=False)initial_state = project.factory.entry_state()check_equals_called_address = 0x80486B3instruction_to_skip_length = 5@project.hook(check_equals_called_address, length=instruction_to_skip_length)def skip_check_equals_(state):user_input_buffer_address = 0x804A054user_input_buffer_length = 16user_input_string = state.memory.load(user_input_buffer_address,user_input_buffer_length)check_against_string = 'XKSPZSJKJYQCQXZV'register_size_bit = 32state.regs.eax = claripy.If(user_input_string == check_against_string,claripy.BVV(1, register_size_bit),claripy.BVV(0, register_size_bit))simulation = project.factory.simgr(initial_state)def is_successful(state):stdout_output = state.posix.dumps(1)if b'Good Job.\n' in stdout_output:return Trueelse:return Falsedef should_abort(state):stdout_output = state.posix.dumps(1)if b'Try again.\n' instdout_output:return Trueelse:return Falsesimulation.explore(find=is_successful, avoid=should_abort)if simulation.found:for i in simulation.found:solution_state = isolution = solution_state.posix.dumps(0)print("[+] Success! Solution is: {0}".format(solution.decode('utf-8')))#print(solution0)else:raise Exception('Could not find the solution')if __name__ == "__main__":Go()
运行一下查看结果:
文章插图
下面来逐步分析:
由于Angr可以处理对scanf的初始调用 , 因此我们可以从头开始
path_to_binary = "./09_angr_hooks" project = angr.Project(path_to_binary, auto_load_libs=False)initial_state = project.factory.entry_state()
如之前分析的而言 , 首先找到需要Hook的函数地址0x080486B3 , 然后设定指令长度
check_equals_called_address = 0x80486B3instruction_to_skip_length = 5
然后我们需要在在@project.hook语句之后书写我们的模拟函数 。 然后如上题一致 , 我们利用使用 state.memory 的 .load(addr, size)接口读出buffer处的内存数据 , 与答案进行比较
@project.hook(check_equals_called_address, length=instruction_to_skip_length)def skip_check_equals_(state):user_input_buffer_address = 0x804A054user_input_buffer_length = 16user_input_string = state.memory.load(user_input_buffer_address,user_input_buffer_length)check_against_string = 'XKSPZSJKJYQCQXZV'
然后这里的关键是 , 我们模拟一个函数就是把它视作一个黑盒 , 能成功模拟输入相对应的输出即可 , 所以我们需要处理check函数的返回值
文章插图
不难发现这个函数是利用EAX寄存器作为返回值 , 然后成功则返回1 , 不成功则返回0 , 还需要注意在构建符号位向量的时候EAX寄存器是32位寄存器
register_size_bit = 32state.regs.eax = claripy.If(user_input_string == check_against_string,claripy.BVV(1, register_size_bit),claripy.BVV(0, register_size_bit))
接下来同之前差不多 , 不再赘述
10_angr_simprocedures这题主要学习如何利用函数名进行hook , 而不是复杂的利用函数的调用地址
首先检查一下程序:
syc@ubuntu:~/Desktop/TEMP$ checksec 10_angr_simprocedures[*] '/home/syc/Desktop/TEMP/10_angr_simprocedures'Arch:i386-32-littleRELRO:Partial RELROStack:Canary foundNX:NX enabledPIE:No PIE (0x8048000)
用IDA打开看一下:
int __cdecl main(int argc, const char **argv, const char **envp){signed int i; // [esp+20h] [ebp-28h]char s[17]; // [esp+2Bh] [ebp-1Dh]unsigned int v6; // [esp+3Ch] [ebp-Ch]v6 = __readgsdword(0x14u);memcpy(memset(s, 0, 0x11u);printf("Enter the password: ");__isoc99_scanf("%16s", s);for ( i = 0; i <= 15; ++i )s[i] = complex_function(s[i], 18 - i);if ( check_equals_ORSDDWXHZURJRBDH(s, 16) )puts("Good Job.");elseputs("Try again.");return 0;}
- 化妆产品|直播带货年入百万,这8个行业告诉你:是真的
- 大神|研究完各路大神,终于知道互联网创业的你为何不赚钱
- 欺诈和滥用|美国最高法院审理黑客法及其限制的案件
- 美国|美国新“电影”,“谍战大片”打脸黑客帝国
- iQO|还不知道选?偷偷告诉你这些iQOO型号手机最值得买
- 告诉|阿里大佬告诉你如何一分钟利用Python在家告别会员看电影
- 捐赠|出乎意料——黑客勒索集团向慈善机构捐赠20000美金
- RTX 3090没啥性价比,破解密码倒挺厉害,黑客要大出血?
- 爆笑!Mate40只是曝光了一个侧脸,各路大神就玩起了骚操作
- Python大神用的贼溜,9个实用技巧分享给你