黑客大神告诉你:Angr_CTF从精通到弃坑( 五 )


首先检测一下程序:
syc@ubuntu:~/Desktop/TEMP$ checksec 11_angr_sim_scanf[*] '/home/syc/Desktop/TEMP/11_angr_sim_scanf'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){_BOOL4 v3; // eaxint i; // [esp+20h] [ebp-28h]char s[4]; // [esp+28h] [ebp-20h]int v7; // [esp+2Ch] [ebp-1Ch]unsigned int v8; // [esp+3Ch] [ebp-Ch]v8 = __readgsdword(0x14u);print_msg();memset(s, 0, 0x14u);qmemcpy(s, "DCLUESMR", 8);for ( i = 0; i <= 7; ++i )s[i] = complex_function(s[i], i);printf("Enter the password: ");__isoc99_scanf("%u %u", buffer0, buffer1);v3 = !strncmp(buffer0, s, 4u)if ( v3 )puts("Good Job.");elseputs("Try again.");return 0;}int __cdecl complex_function(signed int a1, int a2){if ( a1 <= 64 || a1 > 90 ){puts("Try again.");exit(1);}return (a1 - 65 + 29 * a2) % 26 + 65;}还记得之前我们有一题也是scanf函数的复杂格式化字符串处理吗?没错 , 就是03_angr_simbolic_registers , 那一题我们是利用符号化寄存器实现了scanf函数的多参数处理 。 而在这一题中 , 我们采用的是Hook重写库函数scnaf实现复杂格式化字符串的支持
客官新鲜的二辆EXP这就奉上
import angrimport claripyimport sysdef Go():path_to_binary = "./11_angr_sim_scanf"project = angr.Project(path_to_binary, auto_load_libs=False)initial_state = project.factory.entry_state()class ReplacementScanf(angr.SimProcedure):def run(self, format_string, param0, param1):scanf0 = claripy.BVS('scanf0', 32)scanf1 = claripy.BVS('scanf1', 32)scanf0_address = param0self.state.memory.store(scanf0_address, scanf0, endness=project.arch.memory_endness)scanf1_address = param1self.state.memory.store(scanf1_address, scanf1, endness=project.arch.memory_endness)self.state.globals['solutions'] = (scanf0, scanf1)scanf_symbol = '__isoc99_scanf'project.hook_symbol(scanf_symbol, ReplacementScanf())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 = istored_solutions = solution_state.globals['solutions']scanf0_solution = solution_state.solver.eval(stored_solutions[0])scanf1_solution = solution_state.solver.eval(stored_solutions[1])print("[+] Success! Solution is: {0} {1}".format(scanf0_solution,scanf1_solution))#print(scanf0_solution, scanf1_solution)else:raise Exception('Could not find the solution')if __name__ == "__main__":Go()运行一下查看结果
黑客大神告诉你:Angr_CTF从精通到弃坑文章插图
之前的步骤很多都和上一题一样 , 只不过在编写模拟的scanf函数的时候有一些不太一样
class ReplacementScanf(angr.SimProcedure):def run(self, format_string, param0, param1):scanf0 = claripy.BVS('scanf0', 32)scanf1 = claripy.BVS('scanf1', 32)scanf0_address = param0self.state.memory.store(scanf0_address, scanf0, endness=project.arch.memory_endness)scanf1_address = param1self.state.memory.store(scanf1_address, scanf1, endness=project.arch.memory_endness)还记得之前在05_angr_symbolic_memory我们学会的如何符号化内存吗?因为我们这里Scanf是要向内存写入数据的 , 于是我们利用使用 state.memory 的 .store(addr, val) 接口将符号位向量写入两个字符串的内存区域
globals这里的关键我们都知道Python的变量生存周期 , 在这里scanf0和scanf1是函数ReplacementScanf的局部变量 , 为了让函数外部也能获得我们输入的符号位向量 , 从而调用求解器获得答案 , 需要将这两个符号位向量变为全局变量 , 这里我们需要调用带有全局状态的globals插件中“保存”对我们的符号值的引用 。 globals插件允许使用列表 , 元组或多个键的字典来存储多个位向量
self.state.globals['solutions'] = (scanf0, scanf1)之后的操作与其他题目类似 , 不再赘述
参考文献【1】angr官方文档——
【2】angr 系列教程(一)核心概念及模块解读—— #toc-14
【3】王田园. 符号执行的路径爆炸及约束求解问题研究[D].大连海事大学,2019.
【4】曹琰. 面向软件脆弱性分析的并行符号执行技术研究[D].解放军信息工程大学,2013.
【黑客大神告诉你:Angr_CTF从精通到弃坑】本文由ZERO-A-ONE原创发布 转载 , 请参考转载声明 , 注明出处: