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

[Bug] Unexpected results from heap commands when debugging 32 bit binaries. #961

Open
1 of 9 tasks
Fruerlund opened this issue Jul 13, 2023 · 2 comments
Open
1 of 9 tasks

Comments

@Fruerlund
Copy link

Fruerlund commented Jul 13, 2023

GEF+GDB version

gef➤  version
GEF: (Standalone)
Blob Hash(/home/user/.gef-a85368fc771dcbb4db2b41818781e182845015b9.py): 1a409c397646df9c0b8549d576cd7c7f8ec1ef47
SHA256(/home/user/.gef-a85368fc771dcbb4db2b41818781e182845015b9.py): f096ff3bf50df08dbbc698a919360014f86f1eea315011cdabebd72a30a5bce8
GDB: 11.2
GDB-Python: 3.9

Operating System

Linux 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 GNU/Linux

Describe the issue you encountered

Target binary:

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ file level05
level05: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.15, BuildID[sha1]=2cf47809a1a841f6990910071c09e6053e9f57ac, with debug_info, not stripped

Fusion VM:

fusion@fusion:~$ uname -a 
Linux fusion 3.0.0-13-generic-pae #22-Ubuntu SMP Wed Nov 2 15:17:35 UTC 2011 i686 i686 i386 GNU/Linux

fusion@fusion:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.10
Release:        11.10
Codename:       oneiric

fusion@fusion:~$ ldd --version
ldd (Ubuntu EGLIBC 2.13-20ubuntu5) 2.13

Host VM:

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ uname -a
Linux LAPTOP-M65IV45R 5.10.16.3-microsoft-standard-WSL2 #1 SMP Fri Apr 2 22:23:49 UTC 2021 x86_64 GNU/Linux

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ ldd --version
ldd (Debian GLIBC 2.31-13+deb11u5) 2.31

During examination of heap chunks the heap commands works unexpectially and doesn't recognize any allocated chunks.

Do you read the docs and look at previously closed issues/PRs for similar cases?

Yes

Architecture impacted

  • X86
  • X64
  • ARM
  • ARM64
  • MIPS
  • MIPS64
  • PPC
  • PPC64
  • RISCV

Describe your issue. Without a proper reproduction step-by-step, your issue will be ignored.

Provide a step-by-step to reproduce your issue.

REMOTE ENVIRONMENT (32 BIT):

1. Setup environment.

Fusion VM:
fusion@fusion:~$ sudo gdbserver :1234 --attach 1424 [sudo] password for fusion: Attached; pid = 1424 Listening on port 1234

Host VM:

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ gdb
0.00ms using Python engine 3.9
gef➤  file level05
Reading symbols from level05...
gef➤  gef-remote 192.168.56.113 1234
Reading /lib/i386-linux-gnu/libc.so.6 from remote target...
[... snip ... ]

Code:
   0xb777c421 <__kernel_vsyscall+13> nop
   0xb777c422 <__kernel_vsyscall+14> int    0x80
 → 0xb777c424 <__kernel_vsyscall+16> pop    ebp
   0xb777c425 <__kernel_vsyscall+17> pop    edx
   0xb777c426 <__kernel_vsyscall+18> pop    ecx
   0xb777c427 <__kernel_vsyscall+19> ret
   0xb777c428                  add    BYTE PTR [esi], ch
   0xb777c42a                  jae    0xb777c494

Threads:
[#0] Id 1, stopped 0xb777c424 in __kernel_vsyscall (), reason: SIGTRAP

Trace:
[#0] 0xb777c424 → __kernel_vsyscall()
[#1] 0xb76b73ce → poll()
[#2] 0xb779fa8d → fdtask(v=0x0)
[#3] 0xb77a1396 → taskstart(y=0xb9746110, x=0x0)
[#4] 0xb76315ab → makecontext()
[#5] 0xb9746110 → data16 fs je 0xb9746175

2. Interact with code

Connect to target binary and perform two commands which uses calloc and strdup to allocate memory. Perform this a couple of times

user@LAPTOP-M65IV45R:~$ nc 192.168.56.113 20005
** welcome to level05 **
isup CHUNK1garbagedata
isup CHUNK2garbagedata
isup CHUNK3garbagedata

3. Examine heap


gef➤  vmmap
[ Legend:  Code | Heap | Stack ]
Start      End        Offset     Perm Path
0x56647000 0x56649000 0x00000000 r-- /home/user/binaryexploitation/level05_d/a.out
0x56649000 0x5664c000 0x00002000 r-x /home/user/binaryexploitation/level05_d/a.out
0x5664c000 0x5664d000 0x00005000 r-- /home/user/binaryexploitation/level05_d/a.out
0x5664d000 0x5664e000 0x00006000 rw- /home/user/binaryexploitation/level05_d/a.out
0x5664e000 0x56651000 0x00000000 rw-
0x585d0000 0x585f2000 0x00000000 rw- [heap]


(remote) gef➤  search-pattern "CHUNK1"
[+] Searching 'CHUNK1' in memory
[+] In '[heap]'(0xb9746000-0xb9767000), permission=rw-
  0xb9756860 - 0xb9756871  →   "CHUNK1garbagedata"

(remote) gef➤  search-pattern "CHUNK2"
[+] Searching 'CHUNK2' in memory
[+] In '[heap]'(0xb9746000-0xb9767000), permission=rw-
  0xb9756888 - 0xb9756899  →   "CHUNK2garbagedata"

(remote) gef➤  search-pattern "CHUNK3"
[+] Searching 'CHUNK3' in memory
[+] In '[heap]'(0xb9746000-0xb9767000), permission=rw-
  0xb97565c5 - 0xb97565d6  →   "CHUNK3garbagedata"
  0xb97568b0 - 0xb97568c1  →   "CHUNK3garbagedata"

(remote) gef➤  heap chunks
[!] Invalid arena

(remote) gef➤  heap arena

(remote) gef➤  heap chunks -a
[!] Invalid arena

(remote) gef➤  heap chunk 0xb97568b0
Chunk(addr=0xb97568b0, size=0x18, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Chunk size: 24 (0x18)
Usable size: 20 (0x14)
Previous chunk size: 0 (0x0)
PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA

LOCAL ENVIRONMENT (32 BIT):

In this setup I've ported the source code made the nessecary code adjusements and compiled the source code on my host VM using a newer versions of LIBC.

In this setup the binary is running locally on the host VM with the specifications shown earlier.

The same GDB setup is used, however skipping remote debug and attaching directly to the running binary using its PID. The interaction with the binary is identical to that of the remote.

Target binary:

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ file a.out
a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=84c2e6f3ea4145a586430172545fbc1d750c1af6, for GNU/Linux 3.2.0, with debug_info, not stripped
[+] Searching 'CHUNK1' in memory
[+] In '[heap]'(0x585d0000-0x585f2000), permission=rw-
  0x585e0a00 - 0x585e0a11  →   "CHUNK1garbagedata"

gef➤  search-pattern "CHUNK2"
[+] Searching 'CHUNK2' in memory
[+] In '[heap]'(0x585d0000-0x585f2000), permission=rw-
  0x585e0a30 - 0x585e0a41  →   "CHUNK2garbagedata"

gef➤  search-pattern "CHUNK3"
[+] Searching 'CHUNK3' in memory
[+] In '[heap]'(0x585d0000-0x585f2000), permission=rw-
  0x585e0761 - 0x585e0772  →   "CHUNK3garbagedata"
  0x585e0a60 - 0x585e0a71  →   "CHUNK3garbagedata"

gef➤  heap chunks
Chunk(addr=0x585d0010, size=0x0, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x585d0010     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]

gef➤  heap arena
Arena(base=0xf7f26740, top=0x585e0a78, last_remainder=0x0, next=0xf7f26740)

gef➤  heap chunks -a
Arena(base=0xf7f26740, top=0x585e0a78, last_remainder=0x0, next=0xf7f26740)
Chunk(addr=0x585d0010, size=0x0, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x585d0010     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]
[!] Invalid arena

gef➤  heap chunk 0x585e0a00
Chunk(addr=0x585e0a00, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Chunk size: 32 (0x20)
Usable size: 28 (0x1c)
Previous chunk size: 0 (0x0)
PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA

gef➤  heap chunk 0x585e0a30
Chunk(addr=0x585e0a30, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Chunk size: 32 (0x20)
Usable size: 28 (0x1c)
Previous chunk size: 0 (0x0)
PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA

gef➤  heap chunk 0x585e0a60
Chunk(addr=0x585e0a60, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Chunk size: 32 (0x20)
Usable size: 28 (0x1c)
Previous chunk size: 0 (0x0)
PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA

gef➤  x/i 0xf7f26740
   0xf7f26740:  add    BYTE PTR [eax],al

LOCAL ENVIRONMENT (64 BIT)

Reproduce the previous setup steps for LOCAL ENVIRONMENT 32 BIT.

Instead targeting a 64-bit compiled version.

Target binary:

user@LAPTOP-M65IV45R:~/binaryexploitation/level05_d$ file a64.out
a64.out: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=9efa6c2233190407fb27aefef0e577652c8a3fc1, for GNU/Linux 3.2.0, with debug_info, not stripped

The same commands are sent and the heap output works as expected.

Chunk(addr=0x564e6fda2010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fda2010     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]
Chunk(addr=0x564e6fda22a0, size=0x210, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fda22a0     10 60 b1 84 3a 7f 00 00 b0 24 da 6f 4e 56 00 00    .`..:....$.oNV..]
Chunk(addr=0x564e6fda24b0, size=0x8640, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fda24b0     66 64 74 61 73 6b 00 00 00 00 00 00 00 00 00 00    fdtask..........]
Chunk(addr=0x564e6fdaaaf0, size=0x8640, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdaaaf0     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................]
Chunk(addr=0x564e6fdb3130, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb3130     04 00 00 00 00 00 00 00 50 31 db 6f 4e 56 00 00    ........P1.oNV..]
Chunk(addr=0x564e6fdb3150, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb3150     43 48 55 4e 4b 31 67 61 72 62 61 67 65 64 61 74    CHUNK1garbagedat]
Chunk(addr=0x564e6fdb3170, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb3170     04 00 00 00 00 00 00 00 90 31 db 6f 4e 56 00 00    .........1.oNV..]
Chunk(addr=0x564e6fdb3190, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb3190     43 48 55 4e 4b 32 67 61 72 62 61 67 65 64 61 74    CHUNK2garbagedat]
Chunk(addr=0x564e6fdb31b0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb31b0     04 00 00 00 00 00 00 00 d0 31 db 6f 4e 56 00 00    .........1.oNV..]
Chunk(addr=0x564e6fdb31d0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
    [0x0000564e6fdb31d0     43 48 55 4e 4b 33 67 61 72 62 61 67 65 64 61 74    CHUNK3garbagedat]
Chunk(addr=0x564e6fdb31f0, size=0xfe20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)  ←  top chunk

Minimalist test case

Use this field for a minimal code to compile and spot the issue:

// compile with gcc -fPIE -pic -o my_issue.out my_issue.c
int main(){ return 0; }

You can also provide a Dockerfile if you prefer

Additional context?

Challenge found here: http://exploit.education/fusion/level05/

Image for fusion found here: http://exploit.education/downloads/

@Fruerlund Fruerlund changed the title [Bug] Unexpected results from heap commands when debugging. [Bug] Unexpected results from heap commands when debugging 32 bit binaries. Jul 13, 2023
@hugsy hugsy self-assigned this Jul 17, 2023
@hugsy hugsy added this to the 2023.08 milestone Jul 21, 2023
@hugsy
Copy link
Owner

hugsy commented Jul 22, 2023

@Fruerlund I'd like to look into this bug. Can you upload those binaries to this issue?
Also do you have the libc symbol installed? If not, you need to set the main_arena address using heap set-arena. Then gef should be able to recover the heap chunks. If you don't know the address you can try this

@hugsy
Copy link
Owner

hugsy commented Aug 9, 2023

@Fruerlund Ping?

@hugsy hugsy modified the milestones: 2023.08, next Aug 20, 2023
@hugsy hugsy removed their assignment Aug 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants