rizinorg / rizin

UNIX-like reverse engineering framework and command-line toolset.
https://rizin.re
GNU Lesser General Public License v3.0
2.51k stars 341 forks source link

UAF when trying to use obr to rebase a binary #4525

Open s1gse9v opened 3 weeks ago

s1gse9v commented 3 weeks ago

When trying to use obr to rebase a binary, a heap-use-after-free occurs. This happens with various binaries and offsets.

Work environment

Questions Answers
OS/arch/bits (mandatory) Archlinux x86-64
File format of the file you reverse (mandatory) ELF
Architecture/bits of the file (mandatory) x86/64
rizin -v full output, not truncated (mandatory) rizin 0.8.0 @ linux-x86-64, built with asan from dev (6e4ea01a97e4f4e21030c01eab54024117f1e744)

Expected behavior

obr should rebase the program to the given address.

Actual behavior

A heap-use-after-free occurs, leading to a segmentation fault.

Steps to reproduce the behavior

Asan output

./bin/rizin -c 'obr 0x555555554000' /bin/cat
WARNING: Neither hash nor gnu_hash exist. Falling back to heuristics for deducing the number of dynamic symbols...
WARNING: Neither hash nor gnu_hash exist. Falling back to heuristics for deducing the number of dynamic symbols...
WARNING: Neither hash nor gnu_hash exist. Falling back to heuristics for deducing the number of dynamic symbols...
=================================================================
==62838==ERROR: AddressSanitizer: heap-use-after-free on address 0x5030000f1518 at pc 0x7f31ce5a65f3 bp 0x7ffc92b62e60 sp 0x7ffc92b62e50
READ of size 8 at 0x5030000f1518 thread T0
    #0 0x7f31ce5a65f2 in vf_read ../librz/core/cvfile.c:92
    #1 0x7f31d20ca9b9 in rz_io_plugin_read ../librz/io/io_plugin.c:89
    #2 0x7f31d20c8a27 in rz_io_desc_read ../librz/io/io_desc.c:208
    #3 0x7f31d20c9c2a in rz_io_desc_read_at ../librz/io/io_desc.c:354
    #4 0x7f31d20c0c92 in rz_io_fd_read_at ../librz/io/io_fd.c:76
    #5 0x7f31d20bcc4e in fd_read_at_wrap ../librz/io/io.c:18
    #6 0x7f31d20bd200 in on_map_skyline ../librz/io/io.c:75
    #7 0x7f31d20be217 in rz_io_vread_at_mapped ../librz/io/io.c:285
    #8 0x7f31d20be344 in rz_io_read_at ../librz/io/io.c:303
    #9 0x7f31ce56d9c0 in rz_core_block_read ../librz/core/cio.c:247
    #10 0x7f31ce6487da in rz_core_seek ../librz/core/seek.c:119
    #11 0x7f31ce732f0c in handle_ts_tmp_seek_stmt_internal ../librz/core/cmd/cmd.c:3909
    #12 0x7f31ce7328f5 in handle_ts_tmp_seek_stmt ../librz/core/cmd/cmd.c:3889
    #13 0x7f31ce7449fa in handle_ts_stmt ../librz/core/cmd/cmd.c:5117
    #14 0x7f31ce7455d7 in handle_ts_statements_internal ../librz/core/cmd/cmd.c:5174
    #15 0x7f31ce744e3d in handle_ts_statements ../librz/core/cmd/cmd.c:5139
    #16 0x7f31ce746377 in core_cmd_tsrzcmd ../librz/core/cmd/cmd.c:5286
    #17 0x7f31ce746829 in rz_core_cmd ../librz/core/cmd/cmd.c:5334
    #18 0x7f31ce746dfd in rz_core_cmdf ../librz/core/cmd/cmd.c:5424
    #19 0x7f31ce4f951c in rz_core_bin_apply_sections ../librz/core/cbin.c:1009
    #20 0x7f31ce4f3250 in rz_core_bin_apply_info ../librz/core/cbin.c:269
    #21 0x7f31ce4f3802 in rz_core_bin_apply_all_info ../librz/core/cbin.c:313
    #22 0x7f31ce77babf in rz_open_binary_rebase_handler ../librz/core/cmd/cmd_open.c:760
    #23 0x7f31ce74e1da in argv_call_cb ../librz/core/cmd/cmd_api.c:739
    #24 0x7f31ce74e945 in call_cd ../librz/core/cmd/cmd_api.c:798
    #25 0x7f31ce74eaad in rz_cmd_call_parsed_args ../librz/core/cmd/cmd_api.c:816
    #26 0x7f31ce72e8cc in handle_ts_arged_stmt_internal ../librz/core/cmd/cmd.c:3559
    #27 0x7f31ce72daf0 in handle_ts_arged_stmt ../librz/core/cmd/cmd.c:3507
    #28 0x7f31ce7449fa in handle_ts_stmt ../librz/core/cmd/cmd.c:5117
    #29 0x7f31ce7455d7 in handle_ts_statements_internal ../librz/core/cmd/cmd.c:5174
    #30 0x7f31ce744e3d in handle_ts_statements ../librz/core/cmd/cmd.c:5139
    #31 0x7f31ce746377 in core_cmd_tsrzcmd ../librz/core/cmd/cmd.c:5286
    #32 0x7f31ce746888 in rz_core_cmd_lines ../librz/core/cmd/cmd.c:5342
    #33 0x7f31d380a4cf in run_commands ../librz/main/rizin.c:339
    #34 0x7f31d3811ff7 in rz_main_rizin ../librz/main/rizin.c:1413
    #35 0x556d340cc8a4 in main ../binrz/rizin/rizin.c:57
    #36 0x7f31d2839c87  (/usr/lib/libc.so.6+0x25c87) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #37 0x7f31d2839d4b in __libc_start_main (/usr/lib/libc.so.6+0x25d4b) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #38 0x556d340cc1a0 in _start (/home/s1gs3gv/Hackery/c/rizin/build_dbg_asan/bin/rizin+0x21a0) (BuildId: d0e8bf9c46eed2653042e9c9a6b28c870e96b0e4)

0x5030000f1518 is located 8 bytes inside of 24-byte region [0x5030000f1510,0x5030000f1528)
freed by thread T0 here:
    #0 0x7f31d30fb422 in free /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x7f31ced314f2 in rz_bin_virtual_file_free ../librz/bin/bin.c:1039
    #2 0x7f31d2bc5803 in pvector_free_elem ../librz/util/vector.c:371
    #3 0x7f31d2bc3640 in vector_free_elems ../librz/util/vector.c:57
    #4 0x7f31d2bc37c2 in rz_vector_clear ../librz/util/vector.c:73
    #5 0x7f31d2bc3707 in rz_vector_fini ../librz/util/vector.c:66
    #6 0x7f31d2bc5a5a in rz_pvector_free ../librz/util/vector.c:416
    #7 0x7f31ced3e578 in rz_bin_set_and_process_file ../librz/bin/bobj_process_file.c:31
    #8 0x7f31ced3c33a in rz_bin_object_process_plugin_data ../librz/bin/bobj_process.c:150
    #9 0x7f31ce5549e0 in rz_core_bin_rebase ../librz/core/cfile.c:831
    #10 0x7f31ce77ba7d in rz_open_binary_rebase_handler ../librz/core/cmd/cmd_open.c:759
    #11 0x7f31ce74e1da in argv_call_cb ../librz/core/cmd/cmd_api.c:739
    #12 0x7f31ce74e945 in call_cd ../librz/core/cmd/cmd_api.c:798
    #13 0x7f31ce74eaad in rz_cmd_call_parsed_args ../librz/core/cmd/cmd_api.c:816
    #14 0x7f31ce72e8cc in handle_ts_arged_stmt_internal ../librz/core/cmd/cmd.c:3559
    #15 0x7f31ce72daf0 in handle_ts_arged_stmt ../librz/core/cmd/cmd.c:3507
    #16 0x7f31ce7449fa in handle_ts_stmt ../librz/core/cmd/cmd.c:5117
    #17 0x7f31ce7455d7 in handle_ts_statements_internal ../librz/core/cmd/cmd.c:5174
    #18 0x7f31ce744e3d in handle_ts_statements ../librz/core/cmd/cmd.c:5139
    #19 0x7f31ce746377 in core_cmd_tsrzcmd ../librz/core/cmd/cmd.c:5286
    #20 0x7f31ce746888 in rz_core_cmd_lines ../librz/core/cmd/cmd.c:5342
    #21 0x7f31d380a4cf in run_commands ../librz/main/rizin.c:339
    #22 0x7f31d3811ff7 in rz_main_rizin ../librz/main/rizin.c:1413
    #23 0x556d340cc8a4 in main ../binrz/rizin/rizin.c:57
    #24 0x7f31d2839c87  (/usr/lib/libc.so.6+0x25c87) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #25 0x7f31d2839d4b in __libc_start_main (/usr/lib/libc.so.6+0x25d4b) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #26 0x556d340cc1a0 in _start (/home/s1gs3gv/Hackery/c/rizin/build_dbg_asan/bin/rizin+0x21a0) (BuildId: d0e8bf9c46eed2653042e9c9a6b28c870e96b0e4)

previously allocated by thread T0 here:
    #0 0x7f31d30fc34a in calloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:77
    #1 0x7f31ced9b43c in virtual_files ../librz/bin/p/bin_elf.inc:1644
    #2 0x7f31ced3e5bb in rz_bin_set_and_process_file ../librz/bin/bobj_process_file.c:32
    #3 0x7f31ced3c33a in rz_bin_object_process_plugin_data ../librz/bin/bobj_process.c:150
    #4 0x7f31ced3862a in rz_bin_object_new ../librz/bin/bobj.c:529
    #5 0x7f31ced2353c in rz_bin_file_new_from_buffer ../librz/bin/bfile.c:139
    #6 0x7f31ced2c274 in rz_bin_open_buf ../librz/bin/bin.c:291
    #7 0x7f31ced2c911 in rz_bin_open_io ../librz/bin/bin.c:349
    #8 0x7f31ce553eec in core_file_do_load_for_io_plugin ../librz/core/cfile.c:729
    #9 0x7f31ce555da3 in rz_core_bin_load ../librz/core/cfile.c:971
    #10 0x7f31d380f7f0 in rz_main_rizin ../librz/main/rizin.c:1148
    #11 0x556d340cc8a4 in main ../binrz/rizin/rizin.c:57
    #12 0x7f31d2839c87  (/usr/lib/libc.so.6+0x25c87) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #13 0x7f31d2839d4b in __libc_start_main (/usr/lib/libc.so.6+0x25d4b) (BuildId: 32a656aa5562eece8c59a585f5eacd6cf5e2307b)
    #14 0x556d340cc1a0 in _start (/home/s1gs3gv/Hackery/c/rizin/build_dbg_asan/bin/rizin+0x21a0) (BuildId: d0e8bf9c46eed2653042e9c9a6b28c870e96b0e4)

SUMMARY: AddressSanitizer: heap-use-after-free ../librz/core/cvfile.c:92 in vf_read
Shadow bytes around the buggy address:
  0x5030000f1280: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
  0x5030000f1300: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
  0x5030000f1380: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
  0x5030000f1400: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
  0x5030000f1480: fd fd fd fd fa fa fd fd fd fa fa fa fd fd fd fd
=>0x5030000f1500: fa fa fd[fd]fd fa fa fa fd fd fd fd fa fa fd fd
  0x5030000f1580: fd fd fa fa fd fd fd fd fa fa fd fd fd fa fa fa
  0x5030000f1600: fd fd fd fa fa fa fd fd fd fd fa fa fd fd fd fa
  0x5030000f1680: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
  0x5030000f1700: fd fa fa fa fd fd fd fd fa fa fd fd fd fd fa fa
  0x5030000f1780: fd fd fd fa fa fa fd fd fd fa fa fa 00 00 06 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==62838==ABORTING
s1gse9v commented 3 weeks ago

I might get around to fix this myself, but I would appreciate some pointers on how the rebasing is implemented

XVilka commented 3 weeks ago

I might get around to fix this myself, but I would appreciate some pointers on how the rebasing is implemented

Sorry for the late answer. The rebasing is implemented in multiple files, and you can see them in the stacktrace. Looking at the stacktrace my blind guess that it wasn't removed from the skyline after it was freed, see io->map_skyline