Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

search-pattern: Don't stop searching when read_memory fails #675

Merged

Conversation

ammarfaizi2
Copy link
Contributor

search-pattern: Don't stop searching when read_memory fails

Komori Kuzuyu <[email protected]> wrote:
> search-pattern command stop finding string pattern after error "Cannot
> access memory at address xxxxxxxxxxxx". Checking /proc/$pid/maps the
> address mentioned in error is readable but cannot be read from gdb.
>
> The memory is a mapped file to /dev/dri/renderD128
>

Do not assume virtual memory that has read bit is always directly
readable from userspace. We have a special case where /proc/$pid/maps
shows virtual memory address with a read bit, but it cannot be read from
the GDB.

This commit adds an exception handler for read_memory on search-pattern
command when such a special case occurs.

Before this commit, the search-pattern command stops when it meets the
above case (unhandled exception).

After this commit, the search-pattern command continues the scan when
read_memory fails. We still of course, show the error message indicates
that the read_memory fails.

The special case after this commit looks like this:
    gef➤  search-pattern "However"
    [+] Searching 'However' in memory
    [+] In '/usr/lib/x86_64-linux-gnu/dri/radeonsi_dri.so'(0x7fffe5576000-0x7fffe59b6000), permission=r--
      0x7fffe55f8ec6 - 0x7fffe55f8efd  →   "However, if the abstract value is too large, the o[...]"
      0x7fffe55ff01b - 0x7fffe55ff052  →   "However, if the abstract value is too large, the o[...]"
    [!] Cannot access memory at address 0x7fffeb00b000
    [!] Cannot access memory at address 0x7fffeb0d4000
    [!] Cannot access memory at address 0x7fffef49f000
    [+] In '/usr/lib/x86_64-linux-gnu/libbrotlicommon.so.1.0.9'(0x7ffff72ab000-0x7ffff72ca000), permission=r--
      0x7ffff72bb287 - 0x7ffff72bb2be  →   "However, compositionclear:both;cooperationwithin t[...]"
      0x7ffff72bd4ae - 0x7ffff72bd4e5  →   "However, inprogrammersat least inapproximatealthou[...]"
      0x7ffff72bd834 - 0x7ffff72bd867  →   "However thelead to the\t<a href="/was grantedpeople"
      0x7ffff72be10f - 0x7ffff72be146  →   "However, intelligence" tabindex="float:right;Commo[...]"
      0x7ffff72c1c99 - 0x7ffff72c1cd0  →   "However, the An example ofcompared withquantities [...]"
      0x7ffff72c1f4a - 0x7ffff72c1f81  →   "However, thisDepartment ofthe remainingeffect on t[...]"
      0x7ffff72c2451 - 0x7ffff72c2488  →   "However, manythe presidentHowever, someis thought [...]"
      0x7ffff72c246b - 0x7ffff72c24a2  →   "However, someis thought tountil the endwas announc[...]"
      0x7ffff72c2ff8 - 0x7ffff72c302a  →   "However, theand eventuallyAt the end of because of"
      0x7ffff72c3c36 - 0x7ffff72c3c6d  →   "However, it isbecame part ofin relation topopular [...]"
      0x7ffff72c66da - 0x7ffff72c670c  →   "However, there aresrc="http://staticsuggested that"
      0x7ffff72c6c32 - 0x7ffff72c6c69  →   "However, since the/div>\n</div>\n<div left; margin[...]"
    gef➤

Fixes: https://github.com/hugsy/gef/issues/674
Reported-by: Komori Kuzuyu <[email protected]>
Signed-off-by: Ammar Faizi <[email protected]>
Signed-off-by: Komori Kuzuyu <[email protected]>

How Has This Been Tested?

Architecture Yes/No Comments
x86-32 ✖️
x86-64 ✔️
ARM ✖️
AARCH64 ✖️
MIPS ✖️
POWERPC ✖️
SPARC ✖️
RISC-V ✖️
make tests ✔️

Checklist

  • My PR was done against the dev branch, not master.
  • My code follows the code style of this project.
  • My change includes a change to the documentation, if required.
  • My change adds tests as appropriate.
  • I have read and agree to the CONTRIBUTING document.

Fixes: #674

@ammarfaizi2
Copy link
Contributor Author

I want to deliver one more patch regarding the last review by @Grazfather.
#673 (comment)

I hope it is fine to put the commit together here. I will rebase if it must be in separated PR.

@ammarfaizi2 ammarfaizi2 force-pushed the handle-search-pattern-special-case branch from 954dc94 to 63084b0 Compare July 7, 2021 10:19
@ammarfaizi2
Copy link
Contributor Author

Test Output (Linux x86_64)

Click to toggle contents
ammarfaizi2@integral:~/project/now/gef$ make test -j4
make[1]: warning: -j4 forced in submake: resetting jobserver mode.
make[1]: Entering directory '/home/ammarfaizi2/project/now/gef/tests/binaries'
[+] Building 'bss.out'
[+] Building 'canary.out'
[+] Building 'checksec-no-canary.out'
[+] Building 'checksec-no-nx.out'
[+] Building 'checksec-no-pie.out'
[+] Building 'default.out'
[+] Building 'format-string-helper.out'
[+] Building 'heap-analysis.out'
[+] Building 'heap.out'
[+] Building 'heap-fastbins.out'
[+] Building 'heap-non-main.out'
[+] Building 'heap-tcache.out'
[+] Building 'nested2.out'
[+] Building 'nested.out'
[+] Building 'pattern.out'
[+] Building 'set-permission.out'
make[1]: Leaving directory '/home/ammarfaizi2/project/now/gef/tests/binaries'
python3 tests/runtests.py
test_func_base (__main__.TestGdbFunctionsUnit) ... ok
test_func_bss (__main__.TestGdbFunctionsUnit) ... ok
test_func_got (__main__.TestGdbFunctionsUnit) ... ok
test_func_heap (__main__.TestGdbFunctionsUnit) ... ok
test_func_stack (__main__.TestGdbFunctionsUnit) ... ok
test_cmd_aliases (__main__.TestGefCommandsUnit) ... ok
test_cmd_canary (__main__.TestGefCommandsUnit) ... ok
test_cmd_capstone_disassemble (__main__.TestGefCommandsUnit) ... ok
test_cmd_checksec (__main__.TestGefCommandsUnit) ... ok
test_cmd_dereference (__main__.TestGefCommandsUnit) ... ok
test_cmd_edit_flags (__main__.TestGefCommandsUnit) ... ok
test_cmd_elf_info (__main__.TestGefCommandsUnit) ... ok
test_cmd_entry_break (__main__.TestGefCommandsUnit) ... ok
test_cmd_format_string_helper (__main__.TestGefCommandsUnit) ... ok
test_cmd_functions (__main__.TestGefCommandsUnit) ... ok
test_cmd_got (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_analysis (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_arenas (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_bins_fast (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_bins_non_main (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_bins_tcache (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_bins_tcache_all (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_chunk (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_chunks (__main__.TestGefCommandsUnit) ... ok
test_cmd_heap_set_arena (__main__.TestGefCommandsUnit) ... ok
test_cmd_hexdump (__main__.TestGefCommandsUnit) ... ok
test_cmd_highlight (__main__.TestGefCommandsUnit) ... ok
test_cmd_keystone_assemble (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_byte (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_dword (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_qword (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_qword_symbol (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_string (__main__.TestGefCommandsUnit) ... ok
test_cmd_patch_word (__main__.TestGefCommandsUnit) ... ok
test_cmd_pattern_create (__main__.TestGefCommandsUnit) ... ok
test_cmd_pattern_search (__main__.TestGefCommandsUnit) ... ok
test_cmd_print_format (__main__.TestGefCommandsUnit) ... ok
test_cmd_process_search (__main__.TestGefCommandsUnit) ... ok
test_cmd_process_status (__main__.TestGefCommandsUnit) ... ok
test_cmd_registers (__main__.TestGefCommandsUnit) ... ok
test_cmd_reset_cache (__main__.TestGefCommandsUnit) ... ok
test_cmd_ropper (__main__.TestGefCommandsUnit) ... ok
test_cmd_scan (__main__.TestGefCommandsUnit) ... ok
test_cmd_search_pattern (__main__.TestGefCommandsUnit) ... ok
test_cmd_set_permission (__main__.TestGefCommandsUnit) ... ok
test_cmd_shellcode (__main__.TestGefCommandsUnit) ... ok
test_cmd_shellcode_get (__main__.TestGefCommandsUnit) ... ok
test_cmd_shellcode_search (__main__.TestGefCommandsUnit) ... ok
test_cmd_stub (__main__.TestGefCommandsUnit) ... ok
test_cmd_theme (__main__.TestGefCommandsUnit) ... ok
test_cmd_trace_run (__main__.TestGefCommandsUnit) ... ok
test_cmd_unicorn_emulate (__main__.TestGefCommandsUnit) ... ok
test_cmd_vmmap (__main__.TestGefCommandsUnit) ... ok
test_cmd_xfiles (__main__.TestGefCommandsUnit) ... ok
test_cmd_xinfo (__main__.TestGefCommandsUnit) ... ok
test_cmd_xor_memory (__main__.TestGefCommandsUnit) ... ok
test_config_show_opcodes_size (__main__.TestGefConfigUnit)
Check opcodes are correctly shown ... ok
test_func_get_filepath (__main__.TestGefFunctionsUnit) ... ok
test_func_get_memory_alignment (__main__.TestGefFunctionsUnit) ... ok
test_func_get_pid (__main__.TestGefFunctionsUnit) ... ok
test_func_set_arch (__main__.TestGefFunctionsUnit) ... ok
test_func_which (__main__.TestGefFunctionsUnit) ... ok
test_context_correct_registers_refresh_with_frames (__main__.TestNonRegressionUnit)
Ensure registers are correctly refreshed when changing frame (PR #668) ... ok
test_registers_show_registers_in_correct_order (__main__.TestNonRegressionUnit)
Ensure the registers are printed in the correct order (PR #670). ... ok

----------------------------------------------------------------------
Ran 65 tests in 249.796s

OK
make[1]: warning: -j4 forced in submake: resetting jobserver mode.
make[1]: Entering directory '/home/ammarfaizi2/project/now/gef/tests/binaries'
[+] Cleaning stuff
make[1]: Leaving directory '/home/ammarfaizi2/project/now/gef/tests/binaries'
ammarfaizi2@integral:~/project/now/gef$ 

@ammarfaizi2 ammarfaizi2 force-pushed the handle-search-pattern-special-case branch from 63084b0 to 030cb6d Compare July 7, 2021 10:37
ammarfaizi2 referenced this pull request in ammarfaizi2/gef Jul 7, 2021
This commit introduces 2 changes:
1) Change "info registers" to "info registers all". This will track more
registers and make sure they are not changed due to syscall.

2) Change `gdb_start_silent_cmd` to `gdb_run_cmd`. We don't need to use
`gdb_start_silent_cmd` because our `before` commands have already
started the process. And we can't see the register before we do
`set-permission` command if the process has not been started yet.

Therefore, it makes sense not to append `"entry-break"` (calling
`gdb_start_silent_cmd`).

Before this commit the result in commands will be like this:
      before = [
        # These two do the entry-break job!
        "starti",
        "si",

        "printf \"match_before\\n\"",
        "info registers all",
        "printf \"match_before\\n\"",
        "gef config context.clear_screen False",
        "gef config context.layout '-code -stack'",

        # This is unnecessary, because we have `starti` and `si`.
        # We can't reorder it because it is appended inside the
        # `gdb_start_silent_cmd`.
        "entry-break"
      ]
      cmd = "set-permission $sp"
      after = [
        "printf \"match_after\\n\"",
        "info registers all",
        "printf \"match_after\\n\""
      ]

After this commit:
      before = [
        "entry-break",
        "printf \"match_before\\n\"",
        "info registers all",
        "printf \"match_before\\n\""
      ]
      cmd = "set-permission $sp"
      after = [
        "printf \"match_after\\n\"",
        "info registers all",
        "printf \"match_after\\n\""
      ]

Link: hugsy#673 (comment)
Fixes: 5eb3b24 ("x86-64: Preserve RCX and R11 when calling mprotect_asm (syscall)")
Cc: Grazfather <[email protected]>
Signed-off-by: Ammar Faizi <[email protected]>
gef.py Outdated Show resolved Hide resolved
#
err(estr)
return []
else:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What other errors can we get?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Grazfather I don't yet know. But I think it is fine to throw away the other errors to the higher call stack if there is any.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, I was just wondering if you had seen others.

ammarfaizi2 added a commit to ammarfaizi2/gef that referenced this pull request Jul 7, 2021
This commit addresses code review from Grazfather.

Fixes: 01002fb ("search-pattern: Don't stop searching when read_memory fails")
Link: hugsy#675 (comment)
Signed-off-by: Ammar Faizi <[email protected]>
@Grazfather
Copy link
Collaborator

Can you squash the first and third commit? I will rebase and merge since this does 2 different things.

@ammarfaizi2
Copy link
Contributor Author

Cc: @komori-k
Please squash the first and third commit.

Komori Kuzuyu <[email protected]> wrote:
> search-pattern command stop finding string pattern after error "Cannot
> access memory at address xxxxxxxxxxxx". Checking /proc/$pid/maps the
> address mentioned in error is readable but cannot be read from gdb.
>
> The memory is a mapped file to /dev/dri/renderD128
>

Do not assume virtual memory that has read bit is always directly
readable from userspace. We have a special case where /proc/$pid/maps
shows virtual memory address with a read bit, but it cannot be read from
the GDB.

This commit adds an exception handler for read_memory on search-pattern
command when such a special case occurs.

Before this commit, the search-pattern command stops when it meets the
above case (unhandled exception).

After this commit, the search-pattern command continues the scan when
read_memory fails. We still of course, show the error message indicates
that the read_memory fails.

The special case after this commit looks like this:
    gef➤  search-pattern "However"
    [+] Searching 'However' in memory
    [+] In '/usr/lib/x86_64-linux-gnu/dri/radeonsi_dri.so'(0x7fffe5576000-0x7fffe59b6000), permission=r--
      0x7fffe55f8ec6 - 0x7fffe55f8efd  →   "However, if the abstract value is too large, the o[...]"
      0x7fffe55ff01b - 0x7fffe55ff052  →   "However, if the abstract value is too large, the o[...]"
    [!] Cannot access memory at address 0x7fffeb00b000
    [!] Cannot access memory at address 0x7fffeb0d4000
    [!] Cannot access memory at address 0x7fffef49f000
    [+] In '/usr/lib/x86_64-linux-gnu/libbrotlicommon.so.1.0.9'(0x7ffff72ab000-0x7ffff72ca000), permission=r--
      0x7ffff72bb287 - 0x7ffff72bb2be  →   "However, compositionclear:both;cooperationwithin t[...]"
      0x7ffff72bd4ae - 0x7ffff72bd4e5  →   "However, inprogrammersat least inapproximatealthou[...]"
      0x7ffff72bd834 - 0x7ffff72bd867  →   "However thelead to the\t<a href="/was grantedpeople"
      0x7ffff72be10f - 0x7ffff72be146  →   "However, intelligence" tabindex="float:right;Commo[...]"
      0x7ffff72c1c99 - 0x7ffff72c1cd0  →   "However, the An example ofcompared withquantities [...]"
      0x7ffff72c1f4a - 0x7ffff72c1f81  →   "However, thisDepartment ofthe remainingeffect on t[...]"
      0x7ffff72c2451 - 0x7ffff72c2488  →   "However, manythe presidentHowever, someis thought [...]"
      0x7ffff72c246b - 0x7ffff72c24a2  →   "However, someis thought tountil the endwas announc[...]"
      0x7ffff72c2ff8 - 0x7ffff72c302a  →   "However, theand eventuallyAt the end of because of"
      0x7ffff72c3c36 - 0x7ffff72c3c6d  →   "However, it isbecame part ofin relation topopular [...]"
      0x7ffff72c66da - 0x7ffff72c670c  →   "However, there aresrc="http://staticsuggested that"
      0x7ffff72c6c32 - 0x7ffff72c6c69  →   "However, since the/div>\n</div>\n<div left; margin[...]"
    gef➤

Fixes: hugsy#674
Reported-by: Komori Kuzuyu <[email protected]>
Signed-off-by: Ammar Faizi <[email protected]>
Signed-off-by: Komori Kuzuyu <[email protected]>
This commit introduces 2 changes:
1) Change "info registers" to "info registers all". This will track more
registers and make sure they are not changed due to syscall.

2. Change `gdb_start_silent_cmd` to `gdb_run_cmd`. We don't need to use
`gdb_start_silent_cmd` because our `before` commands have already
started the process. And we can't see the register before we do
`set-permission` command if the process has not been started yet.

Therefore, it makes sense not to append `"entry-break"` by calling
`gdb_start_silent_cmd`.

Before this commit the result in commands will be like this:
      before = [
        # These two do the entry-break job!
        "starti",
        "si",

        "printf \"match_before\\n\"",
        "info registers all",
        "printf \"match_before\\n\"",
        "gef config context.clear_screen False",
        "gef config context.layout '-code -stack'",

        # This is unecessary, because we have `starti` and `si`.
        # We can't reorder it because it is appended inside the
        # `gdb_start_silent_cmd`.
        "entry-break"
      ]
      cmd = "set-permission $sp"
      after = [
        "printf \"match_after\\n\"",
        "info registers all",
        "printf \"match_after\\n\""
      ]

After this commit:
      before = [
        "gef config context.clear_screen False",
        "gef config context.layout '-code -stack'",
        "entry-break",
        "printf \"match_before\\n\"",
        "info registers all",
        "printf \"match_before\\n\""
      ]
      cmd = "set-permission $sp"
      after = [
        "printf \"match_after\\n\"",
        "info registers all",
        "printf \"match_after\\n\""
      ]

Fixes: 5eb3b24 ("x86-64: Preserve RCX and R11 when calling mprotect_asm (syscall)")
Cc: Grazfather <[email protected]>
Signed-off-by: Ammar Faizi <[email protected]>
@komori-k komori-k force-pushed the handle-search-pattern-special-case branch from 4e8b9a7 to 73f41db Compare July 7, 2021 14:25
@komori-k
Copy link

komori-k commented Jul 7, 2021

@ammarfaizi2 done

@Grazfather Grazfather merged commit 593b5d3 into hugsy:dev Jul 7, 2021
@Grazfather
Copy link
Collaborator

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

search-pattern crashed when trying to read from memory mapped file /dev/dri/renderD128
3 participants