• Angr-CTF学习笔记11-13


    11_angr_sim_scanf

    汇编代码:

    1. .text:0804862A push 14h ; n
    2. .text:0804862C push 0 ; c
    3. .text:0804862E lea eax, [ebp+key_string]
    4. .text:08048631 push eax ; s
    5. .text:08048632 call _memset
    6. .text:08048637 add esp, 10h
    7. .text:0804863A lea eax, [ebp+key_string]
    8. .text:0804863D mov dword ptr [eax], 444E4848h
    9. .text:08048643 mov dword ptr [eax+4], 50484156h ; 初始化Key-String
    10. .text:0804864A mov [ebp+index], 0
    11. .text:08048651 jmp short loc_8048680
    12. .text:08048653 ; ---------------------------------------------------------------------------
    13. .text:08048653
    14. .text:08048653 loc_8048653: ; CODE XREF: main+8F↓j
    15. .text:08048653 lea edx, [ebp+key_string]
    16. .text:08048656 mov eax, [ebp+index]
    17. .text:08048659 add eax, edx
    18. .text:0804865B movzx eax, byte ptr [eax]
    19. .text:0804865E movsx eax, al
    20. .text:08048661 sub esp, 8
    21. .text:08048664 push [ebp+index]
    22. .text:08048667 push eax
    23. .text:08048668 call complex_function ; complex_function() 对key-string 进行计算
    24. .text:0804866D add esp, 10h
    25. .text:08048670 mov ecx, eax
    26. .text:08048672 lea edx, [ebp+key_string]
    27. .text:08048675 mov eax, [ebp+index]
    28. .text:08048678 add eax, edx
    29. .text:0804867A mov [eax], cl
    30. .text:0804867C add [ebp+index], 1
    31. .text:08048680
    32. .text:08048680 loc_8048680: ; CODE XREF: main+5C↑j
    33. .text:08048680 cmp [ebp+index], 7
    34. .text:08048684 jle short loc_8048653 ; for (index =0 index <=7 ; ++ index )

    程序第一步先对Key-String 进行运算,该题的难点在于main() 里面多个scanf() .

    1. text:08048689 push offset aEnterThePasswo ; "Enter the password: "
    2. .text:0804868E call _printf
    3. .text:08048693 add esp, 10h
    4. .text:08048696 cmp [ebp+var_24], 0DEADBEEFh
    5. .text:0804869D jnz loc_804C196
    6. .text:080486A3 cmp [ebp+var_24], 0DEADBEEFh
    7. .text:080486AA jnz loc_804A423
    8. .text:080486B0 cmp [ebp+var_24], 0DEADBEEFh
    9. .text:080486B7 jz loc_8049570
    10. .text:080486BD cmp [ebp+var_24], 0DEADBEEFh
    11. .text:080486C4 jnz loc_8048E1D
    12. .text:080486CA cmp [ebp+var_24], 0DEADBEEFh
    13. .text:080486D1 jz loc_8048A7A
    14. .text:080486D7 cmp [ebp+var_24], 0DEADBEEFh
    15. .text:080486DE jz loc_80488AF
    16. .text:080486E4 cmp [ebp+var_24], 0DEADBEEFh
    17. .text:080486EB jnz loc_80487D0
    18. .text:080486F1 cmp [ebp+var_24], 0DEADBEEFh
    19. .text:080486F8 jnz short loc_8048765
    20. .text:080486FA sub esp, 4
    21. .text:080486FD push offset buffer1
    22. .text:08048702 push offset buffer0
    23. .text:08048707 push offset aUU ; "%u %u"
    24. .text:0804870C call ___isoc99_scanf
    25. .text:08048711 add esp, 10h
    26. .text:08048714 cmp [ebp+var_2C], 0
    27. .text:08048718 jz short loc_8048758
    28. .text:0804871A sub esp, 4
    29. .text:0804871D push 4 ; n
    30. .text:0804871F lea eax, [ebp+key_string]
    31. .text:08048722 push eax ; s2
    32. .text:08048723 push offset buffer0 ; s1
    33. .text:08048728 call _strncmp
    34. .text:0804872D add esp, 10h
    35. .text:08048730 test eax, eax
    36. .text:08048732 jnz short loc_8048758
    37. .text:08048734 sub esp, 4
    38. .text:08048737 push 4 ; n
    39. .text:08048739 lea eax, [ebp+key_string]
    40. .text:0804873C add eax, 4
    41. .text:0804873F push eax ; s2
    42. .text:08048740 push offset buffer1 ; s1
    43. .text:08048745 call _strncmp
    44. .text:0804874A add esp, 10h
    45. .text:0804874D test eax, eax
    46. .text:0804874F jnz short loc_8048758
    47. .text:08048751 mov eax, 1
    48. .text:08048756 jmp short loc_804875D
    49. .text:08048758 ; ---------------------------------------------------------------------------
    50. .text:08048758
    51. .text:08048758 loc_8048758: ; CODE XREF: main+123↑j
    52. .text:08048758 ; main+13D↑j ...
    53. .text:08048758 mov eax, 0
    54. .text:0804875D
    55. .text:0804875D loc_804875D: ; CODE XREF: main+161↑j
    56. .text:0804875D mov [ebp+var_2C], eax
    57. .text:08048760 jmp loc_804FC81
    58. .text:08048765 ; ---------------------------------------------------------------------------
    59. .text:08048765
    60. .text:08048765 loc_8048765: ; CODE XREF: main+103↑j
    61. .text:08048765 sub esp, 4
    62. .text:08048768 push offset buffer1
    63. .text:0804876D push offset buffer0
    64. .text:08048772 push offset aUU ; "%u %u"
    65. .text:08048777 call ___isoc99_scanf
    66. .text:0804877C add esp, 10h
    67. .text:0804877F cmp [ebp+var_2C], 0
    68. .text:08048783 jz short loc_80487C3
    69. .text:08048785 sub esp, 4
    70. .text:08048788 push 4 ; n
    71. .text:0804878A lea eax, [ebp+key_string]
    72. .text:0804878D push eax ; s2
    73. .text:0804878E push offset buffer0 ; s1
    74. .text:08048793 call _strncmp
    75. .text:08048798 add esp, 10h
    76. .text:0804879B test eax, eax
    77. .text:0804879D jnz short loc_80487C3
    78. .text:0804879F sub esp, 4
    79. .text:080487A2 push 4 ; n
    80. .text:080487A4 lea eax, [ebp+key_string]
    81. .text:080487A7 add eax, 4
    82. .text:080487AA push eax ; s2
    83. .text:080487AB push offset buffer1 ; s1
    84. .text:080487B0 call _strncmp
    85. .text:080487B5 add esp, 10h
    86. .text:080487B8 test eax, eax
    87. .text:080487BA jnz short loc_80487C3
    88. .text:080487BC mov eax, 1
    89. .text:080487C1 jmp short loc_80487C8

    我们的关注点在于scanf() ,这里标明了用户有两个输入,分别为4 字节.然后我们就需要Hook scanf() 来对buffer 进行符号构造,代码如下:

    1. def main(argv):
    2. path_to_binary = argv[1]
    3. project = angr.Project(path_to_binary)
    4. initial_state = project.factory.entry_state()
    5. class ReplacementScanf(angr.SimProcedure):
    6. def run(self, format_string, scanf0_address, scanf1_address ):
    7. scanf0 = claripy.BVS('scanf0', 4 * 8)
    8. scanf1 = claripy.BVS('scanf1', 4 * 8)
    9. self.state.memory.store(scanf0_address, scanf0, endness=project.arch.memory_endness)
    10. self.state.memory.store(scanf1_address, scanf1, endness=project.arch.memory_endness)
    11. self.state.globals['solution0'] = scanf0
    12. self.state.globals['solution1'] = scanf1
    13. scanf_symbol = '__isoc99_scanf'
    14. project.hook_symbol(scanf_symbol, ReplacementScanf())
    15. simulation = project.factory.simgr(initial_state)
    16. def is_successful(state):
    17. stdout_output = state.posix.dumps(sys.stdout.fileno())
    18. return 'Good Job' in str(stdout_output)
    19. def should_abort(state):
    20. stdout_output = state.posix.dumps(sys.stdout.fileno())
    21. return 'Try again' in str(stdout_output)
    22. simulation.explore(find=is_successful, avoid=should_abort)
    23. if simulation.found:
    24. solution_state = simulation.found[0]
    25. stored_solutions0 = solution_state.globals['solution0']
    26. stored_solutions1 = solution_state.globals['solution1']
    27. solution0 = solution_state.se.eval(stored_solutions0)
    28. solution1 = solution_state.se.eval(stored_solutions1)
    29. print(solution0,solution1)

    12_angr_veritesting

    汇编代码:

    1. .text:080485ED push 21h ; n
    2. .text:080485EF push 0 ; c
    3. .text:080485F1 lea eax, [ebp+input_buffer]
    4. .text:080485F4 push eax ; s
    5. .text:080485F5 call _memset
    6. .text:080485FA add esp, 10h
    7. .text:080485FD sub esp, 0Ch
    8. .text:08048600 push offset aEnterThePasswo ; "Enter the password: "
    9. .text:08048605 call _printf
    10. .text:0804860A add esp, 10h
    11. .text:0804860D sub esp, 8
    12. .text:08048610 lea eax, [ebp+input_buffer]
    13. .text:08048613 push eax
    14. .text:08048614 push offset a32s ; "%32s"
    15. .text:08048619 call ___isoc99_scanf ; 用户输入一个32字节的Buffer
    16. .text:0804861E add esp, 10h
    17. .text:08048621 mov [ebp+var_3C], 0
    18. .text:08048628 mov [ebp+var_34], 0
    19. .text:0804862F mov [ebp+index], 0
    20. .text:08048636 jmp short loc_8048666
    21. .text:08048638 ; ---------------------------------------------------------------------------
    22. .text:08048638
    23. .text:08048638 loc_8048638: ; CODE XREF: main+A5↓j
    24. .text:08048638 lea edx, [ebp+input_buffer]
    25. .text:0804863B mov eax, [ebp+index]
    26. .text:0804863E add eax, edx
    27. .text:08048640 movzx eax, byte ptr [eax]
    28. .text:08048643 movsx ebx, al
    29. .text:08048646 mov eax, [ebp+index]
    30. .text:08048649 add eax, 5Bh
    31. .text:0804864C sub esp, 8
    32. .text:0804864F push eax
    33. .text:08048650 push 4Fh
    34. .text:08048652 call complex_function ; 对用户输入进行计算
    35. .text:08048657 add esp, 10h
    36. .text:0804865A cmp ebx, eax
    37. .text:0804865C jnz short loc_8048662
    38. .text:0804865E add [ebp+var_3C], 1
    39. .text:08048662
    40. .text:08048662 loc_8048662: ; CODE XREF: main+97↑j
    41. .text:08048662 add [ebp+index], 1
    42. .text:08048666
    43. .text:08048666 loc_8048666: ; CODE XREF: main+71↑j
    44. .text:08048666 cmp [ebp+index], 1Fh
    45. .text:0804866A jle short loc_8048638
    46. .text:0804866C cmp [ebp+var_3C], ' '
    47. .text:08048670 jnz short loc_804868C
    48. .text:08048672 movzx eax, byte ptr [ebp+var_C]
    49. .text:08048676 test al, al
    50. .text:08048678 jnz short loc_804868C ; 对输入进行计算
    51. .text:0804867A sub esp, 0Ch
    52. .text:0804867D push offset aGoodJob ; "Good Job."
    53. .text:08048682 call _puts
    54. .text:08048687 add esp, 10h
    55. .text:0804868A jmp short loc_804869C
    56. .text:0804868C ; ---------------------------------------------------------------------------
    57. .text:0804868C
    58. .text:0804868C loc_804868C: ; CODE XREF: main+AB↑j
    59. .text:0804868C ; main+B3↑j
    60. .text:0804868C sub esp, 0Ch
    61. .text:0804868F push offset s ; "Try again."
    62. .text:08048694 call _puts
    63. .text:08048699 add esp, 10h

    这个示例和01 题是一样的,唯独不同的一点是这个循环比之前的要大,导致直接用01 题的解题方法不能直接计算出结果,因为循环过大导致路径爆炸,所以在执行的时候会消耗很多资源.

    幸运的是,project.factory.simgr() 函数提供veritesting 参数来指定是否要自动合并路径,避免路径爆炸的问题.具体细节参考论文:https://users.ece.cmu.edu/~dbrumley/pdf/Avgerinos et al._2014_Enhancing Symbolic Execution with Veritesting.pdf

    1. import angr
    2. import sys
    3. project = angr.Project(sys.argv[1])
    4. initial_state = project.factory.entry_state()
    5. simulation = project.factory.simgr(initial_state,veritesting = True)
    6. def is_successful(state):
    7. stdout_output = state.posix.dumps(sys.stdout.fileno())
    8. return 'Good Job.' in str(stdout_output) # :boolean
    9. def should_abort(state):
    10. stdout_output = state.posix.dumps(sys.stdout.fileno())
    11. return 'Try again.' in str(stdout_output) # :boolean
    12. simulation.explore(find = is_successful,avoid = should_abort)
    13. if simulation.found :
    14. solution_state = simulation.found[0]
    15. print(solution_state.posix.dumps(sys.stdin.fileno()))

    Angr函数使用总结:

    project.factory.simgr(初始化状态,veritesting = True) => veritesting 默认为False

    13_angr_static_binary

    汇编代码:

    1. .text:08048953 push offset aEnterThePasswo ; "Enter the password: "
    2. .text:08048958 call printf
    3. .text:0804895D add esp, 10h
    4. .text:08048960 sub esp, 8
    5. .text:08048963 lea eax, [ebp+s1]
    6. .text:08048966 push eax
    7. .text:08048967 push offset a8s ; "%8s"
    8. .text:0804896C call __isoc99_scanf ; 用户输入
    9. .text:08048971 add esp, 10h
    10. .text:08048974 mov [ebp+var_38], 0
    11. .text:0804897B jmp short loc_80489AA
    12. .text:0804897D ; ---------------------------------------------------------------------------
    13. .text:0804897D
    14. .text:0804897D loc_804897D: ; CODE XREF: main+B0↓j
    15. .text:0804897D lea edx, [ebp+s1]
    16. .text:08048980 mov eax, [ebp+var_38]
    17. .text:08048983 add eax, edx
    18. .text:08048985 movzx eax, byte ptr [eax]
    19. .text:08048988 movsx eax, al
    20. .text:0804898B sub esp, 8
    21. .text:0804898E push [ebp+var_38]
    22. .text:08048991 push eax
    23. .text:08048992 call complex_function
    24. .text:08048997 add esp, 10h
    25. .text:0804899A mov ecx, eax
    26. .text:0804899C lea edx, [ebp+s1]
    27. .text:0804899F mov eax, [ebp+var_38]
    28. .text:080489A2 add eax, edx
    29. .text:080489A4 mov [eax], cl
    30. .text:080489A6 add [ebp+var_38], 1
    31. .text:080489AA
    32. .text:080489AA loc_80489AA: ; CODE XREF: main+7D↑j
    33. .text:080489AA cmp [ebp+var_38], 7
    34. .text:080489AE jle short loc_804897D ; 使用for 循环不断调用complex_function() 对数据进行计算
    35. .text:080489B0 sub esp, 8
    36. .text:080489B3 lea eax, [ebp+s2]
    37. .text:080489B6 push eax ; s2
    38. .text:080489B7 lea eax, [ebp+s1]
    39. .text:080489BA push eax ; s1
    40. .text:080489BB call _strcmp
    41. .text:080489C0 add esp, 10h
    42. .text:080489C3 test eax, eax
    43. .text:080489C5 jz short loc_80489D9
    44. .text:080489C7 sub esp, 0Ch
    45. .text:080489CA push offset aTryAgain ; "Try again."
    46. .text:080489CF call puts
    47. .text:080489D4 add esp, 10h
    48. .text:080489D7 jmp short loc_80489E9
    49. .text:080489D9 ; ---------------------------------------------------------------------------
    50. .text:080489D9
    51. .text:080489D9 loc_80489D9: ; CODE XREF: main+C7↑j
    52. .text:080489D9 sub esp, 0Ch
    53. .text:080489DC push offset aGoodJob ; "Good Job."
    54. .text:080489E1 call puts
    55. .text:080489E6 add esp, 10h
    56. .text:080489E9

    这个示例的逻辑和01 题是一样的,主要不同的地方是在于这个程序是静态链接编译的,所以程序中包含了一些libc 的函数实现,但是这里可能会存在两个问题:1.这些函数里面隐藏一些出题人的坑;2.这些函数里面的实现可能会依赖其他的系统函数或者实现方式不相同.所以12 题主要是让我们通过Hook 的方式重定向函数中被调用的libc 的函数

    首先,Linux 下启动main() 函数需要通过__libc_start_main 对程序进行初始化,然后再跳转到main() 函数;其次,在main() 函数里面调用了printf ,scanf ,puts ,所以我们需要通过Hook 来重定向它们.

    幸运的是,我们不需要重新实现这些函数的实现,Angr 代码库里面已经帮我们实现了一部分libc 的函数库,所以我们只需要倒入它们即可.

    1. import angr
    2. import sys
    3. project = angr.Project(sys.argv[1])
    4. initial_state = project.factory.entry_state()
    5. simulation = project.factory.simgr(initial_state,veritesting = True)
    6. project.hook(0x804ed40, angr.SIM_PROCEDURES['libc']['printf']())
    7. project.hook(0x804ed80, angr.SIM_PROCEDURES['libc']['scanf']())
    8. project.hook(0x804f350, angr.SIM_PROCEDURES['libc']['puts']())
    9. project.hook(0x8048d10, angr.SIM_PROCEDURES['glibc']['__libc_start_main']())
    10. def is_successful(state):
    11. stdout_output = state.posix.dumps(sys.stdout.fileno())
    12. return 'Good Job.' in str(stdout_output) # :boolean
    13. def should_abort(state):
    14. stdout_output = state.posix.dumps(sys.stdout.fileno())
    15. return 'Try again.' in str(stdout_output) # :boolean
    16. simulation.explore(find = is_successful,avoid = should_abort)
    17. if simulation.found :
    18. solution_state = simulation.found[0]
    19. print(solution_state.posix.dumps(sys.stdin.fileno()))

    Angr函数使用总结:

    angr.SIM_PROCEDURES[ 系统库名 ] [ 系统函数名 ] () => 获取Angr 内部实现的系统函数

    14_angr_shared_library

    编译14_angr_shared_library 存在一个小坑,就是在执行命令Python generate.py 1234 14_angr_shared_library 时会报错,内容如下:

    1. root@sec:~/angr_ctf/14_angr_shared_library# python generate.py 1234 14_angr_shared_library
    2. gcc: error: 14_angr_shared_library: No such file or directory

    这是因为generate.py 里面有一个Bug ,在最后的一个gcc 编译命令因为-L 参数缺少了指定当前目录,导致在寻找lib14_angr_shared_library.so 的时候找到了系统库目录,所以gcc 抛出了这个找不到14_angr_shared_library: No such file or directory 的问题,代码修改如下:

    1. with tempfile.NamedTemporaryFile(delete=False, suffix='.c') as temp:
    2. temp.write(c_code)
    3. temp.seek(0)
    4. - os.system('gcc -m32 -I . -L ' + '/'.join(output_file.split('/')[0:-1]) + ' -o ' + output_file + ' ' + temp.name + ' -l' + output_file.split('/')[-1])
    5. + os.system('gcc -m32 -I . -L . ' + '/'.join(output_file.split('/')[0:-1]) + ' -o ' + output_file + ' ' + temp.name + ' -l' + output_file.split('/')[-1])

    程序汇编代码如下:

    1. .text:080486A2 push 10h ; n
    2. .text:080486A4 push 0 ; c
    3. .text:080486A6 lea eax, [ebp+s]
    4. .text:080486A9 push eax ; s
    5. .text:080486AA call _memset
    6. .text:080486AF add esp, 10h
    7. .text:080486B2 sub esp, 0Ch
    8. .text:080486B5 push offset format ; "Enter the password: "
    9. .text:080486BA call _printf
    10. .text:080486BF add esp, 10h
    11. .text:080486C2 sub esp, 8
    12. .text:080486C5 lea eax, [ebp+s]
    13. .text:080486C8 push eax
    14. .text:080486C9 push offset a8s ; "%8s"
    15. .text:080486CE call ___isoc99_scanf ; 用户输入
    16. .text:080486D3 add esp, 10h
    17. .text:080486D6 sub esp, 8
    18. .text:080486D9 push 8
    19. .text:080486DB lea eax, [ebp+s]
    20. .text:080486DE push eax
    21. .text:080486DF call _validate ; 调用验证
    22. .text:080486E4 add esp, 10h
    23. .text:080486E7 test eax, eax
    24. .text:080486E9 jz short loc_80486FD
    25. .text:080486EB sub esp, 0Ch
    26. .text:080486EE push offset s ; "Good Job."
    27. .text:080486F3 call _puts

    _validate() 函数是在另一个so 库中存在的,我们继续分析完当前程序的代码

    1. .plt:08048550 _validate proc near ; CODE XREF: main+64↓p
    2. .plt:08048550 jmp ds:off_804A020
    3. .plt:08048550 _validate endp
    4. .got.plt:0804A020 off_804A020 dd offset validate
    5. extern:0804A04C extrn validate:near

    我们来分析一下lib14_angr_shared_library.so 的代码:

    1. .text:000006D7 public validate
    2. .text:000006D7 validate proc near ; DATA XREF: LOAD:00000250↑o
    3. .text:000006D7
    4. .text:000006D7 s2 = byte ptr -24h
    5. .text:000006D7 var_10 = dword ptr -10h
    6. .text:000006D7 var_C = dword ptr -0Ch
    7. .text:000006D7 s1 = dword ptr 8
    8. .text:000006D7 arg_4 = dword ptr 0Ch
    9. .text:000006D7
    10. .text:000006D7 ; __unwind {
    11. .text:000006D7 push ebp
    12. .text:000006D8 mov ebp, esp
    13. .text:000006DA push esi
    14. .text:000006DB push ebx
    15. .text:000006DC sub esp, 20h
    16. .text:000006DF call __x86_get_pc_thunk_bx
    17. .text:000006E4 add ebx, 191Ch
    18. .text:000006EA cmp [ebp+arg_4], 7
    19. .text:000006EE jg short loc_6FA
    20. .text:000006F0 mov eax, 0
    21. .text:000006F5 jmp loc_77D
    22. .text:000006FA ; ---------------------------------------------------------------------------
    23. .text:000006FA
    24. ; .....

    点击关注,共同学习!安全狗的自我修养

    github haidragon

  • 相关阅读:
    数据结构练级之路【链表带环问题】
    JVM内存模型篇【JVM内存模型】
    qt中的数据库操作和数据库的加密存储(SQLite三)
    几行代码实现用Python输出表情包
    MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选
    js-函数式编程-部分应用柯里化-partial和compose-条件和结果、结果和结果
    微信小程序 java网上购物商城系统
    比UUID更快更安全NanoID到底是怎么实现的?(荣耀典藏版)
    电子企业如何克服实施数字工厂管理系统的难题
    koa使用Sequelize:定义数据结构
  • 原文地址:https://blog.csdn.net/sinat_35360663/article/details/127588218