Bug 31599 - [gdb] setting breakpoint prevents value being from written to address via read
Summary: [gdb] setting breakpoint prevents value being from written to address via read
Status: UNCONFIRMED
Alias: None
Product: gdb
Classification: Unclassified
Component: breakpoints (show other bugs)
Version: 13.1
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-04-03 04:58 UTC by k4lizen
Modified: 2024-04-05 16:17 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
the executable used to reproduce (2.67 KB, application/x-executable)
2024-04-03 04:58 UTC, k4lizen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description k4lizen 2024-04-03 04:58:53 UTC
Created attachment 15449 [details]
the executable used to reproduce

gdb version: GNU gdb (Debian 13.2-1) 13.2
OS: Linux kali 6.6.9-amd64

The binary I used to reproduced this is from a pwn challenge, so I don't have the source code. The binary is in the attachment. It is a 32-bit ELF file.
What the binary does is:
1. uses `prctl` to make it so the `execve` syscall can't be called
2. `read`s at most 200 bytes from stdin, into the address 0x0804a060. this address is in a `rw-` mapping on my machine, and has the symbol "shellcode"
3. calls the address (0x0804a060)
4. segfaults, probably because the mapping thats called isn't executable

The Problem:
When a break point for 0x0804a060 is set (and enabled), the `read` call doesn't actually read the first byte of the input. This makes it so the byte at 0x0804a060 is null (0x00). If the breakpoint isn't created or is disabled, the `read` call properly puts the first byte of the input at 0x0804a060. The rest of the input is put in its proper place, regardless of the breakpoint.

In the example below, I will set a breakpoint at 0x08048582, which is the instruction right after the `read` call. And print the first byte of 0x0804a060. The behaviour is the same regardless of the breakpoint at 0x08048582, which can be checked by stepping through instruction-by-instruction.

====================
With the 0x0804a060 (shellcode) breakpoint set.
==

└─$ gdb orw
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from orw...
(No debugging symbols found in orw)
(gdb) break *0x08048582
Breakpoint 1 at 0x8048582
(gdb) break *0x0804a060
Breakpoint 2 at 0x804a060
(gdb) r
Starting program: /home/hacker/ctf/pwnabletw/orw/orw 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Give my your shellcode:AAAA

Breakpoint 1, 0x08048582 in main ()
(gdb) x/1bx 0x804a060
0x804a060 <shellcode>:  0x00
(gdb)
=========
Without setting the 0x0804a060 (shellcode) breakpoint
===

└─$ gdb orw      
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from orw...
(No debugging symbols found in orw)
(gdb) break *0x08048582
Breakpoint 1 at 0x8048582
(gdb) r
Starting program: /home/hacker/ctf/pwnabletw/orw/orw 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Give my your shellcode:AAAA

Breakpoint 1, 0x08048582 in main ()
(gdb) x/1bx 0x0804a060
0x804a060 <shellcode>:  0x41
(gdb)
===============

I can produce screenshots from Ghidras decompilation if necessary.
Comment 1 k4lizen 2024-04-03 05:38:49 UTC
It also seems this redditor has encountered this issue on this binary: https://www.reddit.com/r/LiveOverflow/comments/19fmj8t/help_with_pwnabletw_orw_challenge/
Although a comment on the post says "This video has all the details:<video link>", the video does not in-fact have all the details. i.e. this bug isn't mentioned.
Comment 2 Tom Tromey 2024-04-03 18:44:46 UTC
> When a break point for 0x0804a060 is set (and enabled), the `read` call doesn't actually read the first byte of the input

I wonder what it returns and if it sets errno.
Comment 3 k4lizen 2024-04-05 16:17:27 UTC
(In reply to Tom Tromey from comment #2)
> > When a break point for 0x0804a060 is set (and enabled), the `read` call doesn't actually read the first byte of the input
> 
> I wonder what it returns and if it sets errno.

It sets eax to the number of bytes it read (and as if it actually read the first byte, if the breakpoint is set, even though it didnt). It doesn't set errno (although errno itself is set for me from the printf call (which does actually print, so I don't know what thats about)).