Open ghost opened 2 years ago
Also checked with the master branch. Same problem.
also, e dbg.malloc = glibc
has been set as well as e dbg.glibc.demangle = true
and still same thing
Thanks for the detailed report, the dmh command isnt actively maintained or tested, it will be good to port the code from pwndbg to support last versions of glibc which i assume is the problem, as the heap structures change over time, would you like to help on that?
r2frida also have dmh support but i think its macos/ios specific as its not implemented on linux
@trufae Yeah absolutely. I was in the process of writing some heap inspection programs myself anyway since there is virtually none out there, and the few that are, are too old or dont work with various versions. Give me a basic rundow of what needs to be done basically and where I should start digging through the sources.
@trufae I have forked the repo and started fixing some of the issues I mentioned. I already fixed the issue with the thread arena prints. If you want to follow along or have any hints or comments, here is the repo link to my devel branch: https://github.com/majorendian/radare2/tree/g0zar_devel
I managed to get this working by manually finding the address of the main arena. Turns out radare2 gets the wrong address mapping for libc. Instead of fetching the data segment of libc, it fetches some random segment based on how they are mapped. Its possible to partially fix this by manually finding the main arena and then doing dmhm @ <actuall_address_of_main_arena>
and then the output seems to look a lot more reasonable. But it periodically gets busted so i will still need to fix this.
Based on the structures present in r_heap_glibc.h
it seems like the newest/up-to-date structures are present. So its very likely the bug is simply in fetching the wrong segment from the dm
mappings for libc. The code in question:
if (is_debugged) {
RListIter *iter;
RDebugMap *map;
r_debug_map_sync (core->dbg);
r_list_foreach (core->dbg->maps, iter, map) {
/* Try to find the main arena address using the glibc's symbols. */
if ((strstr (map->name, "/libc-") || strstr (map->name, "/libc."))
&& first_libc && main_arena_sym == GHT_MAX) {
first_libc = false;
main_arena_sym = GH (get_main_arena_with_symbol) (core, map);
}
if ((strstr (map->name, "/libc-") || strstr (map->name, "/libc."))
&& map->perm == R_PERM_RW) {
libc_addr_sta = map->addr;
libc_addr_end = map->addr_end;
break;
}
}
} else {
Some extra info, checked which map gets associated with the main arena. Its an 'unkn' map region right after the libc RW region (the correct one)
[0x7f90d46044a0]> dmha
main_arena @ 0x7f90d46044a0
thread arena @ 0x0
[0x7f90d46044a0]> dm.
0x00007f90d45ff000 - 0x00007f90d4609000 * usr 40K s rw- unk1 unk1
[0x7f90d46044a0]> dm
0x000055fbde276000 - 0x000055fbde277000 - usr 4K s r-- /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out ; loc.imp._ITM_registerTMCloneTable
0x000055fbde277000 - 0x000055fbde278000 - usr 4K s r-x /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out ; map._home_tino_Software_cyberdiskdir_cyber_trainning_research_experiments_first_fit_testing_c_a.out.r_x
0x000055fbde278000 - 0x000055fbde279000 - usr 4K s r-- /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out ; map._home_tino_Software_cyberdiskdir_cyber_trainning_research_experiments_first_fit_testing_c_a.out.r__
0x000055fbde279000 - 0x000055fbde27a000 - usr 4K s r-- /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out ; map._home_tino_Software_cyberdiskdir_cyber_trainning_research_experiments_first_fit_testing_c_a.out.rw_
0x000055fbde27a000 - 0x000055fbde27b000 - usr 4K s rw- /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out /home/tino/Software/cyberdiskdir/cyber/trainning/research/experiments/first_fit_testing/c/a.out ; obj._GLOBAL_OFFSET_TABLE_
0x000055fbdfdd3000 - 0x000055fbdfdf4000 - usr 132K s rw- [heap] [heap]
0x00007f90d440d000 - 0x00007f90d4410000 - usr 12K s rw- unk0 unk0
0x00007f90d4410000 - 0x00007f90d4438000 - usr 160K s r-- /lib64/libc.so.6 /lib64/libc.so.6
0x00007f90d4438000 - 0x00007f90d45a1000 - usr 1.4M s r-x /lib64/libc.so.6 /lib64/libc.so.6
0x00007f90d45a1000 - 0x00007f90d45f9000 - usr 352K s r-- /lib64/libc.so.6 /lib64/libc.so.6
0x00007f90d45f9000 - 0x00007f90d45fd000 - usr 16K s r-- /lib64/libc.so.6 /lib64/libc.so.6
0x00007f90d45fd000 - 0x00007f90d45ff000 - usr 8K s rw- /lib64/libc.so.6 /lib64/libc.so.6
0x00007f90d45ff000 - 0x00007f90d4609000 * usr 40K s rw- unk1 unk1
0x00007f90d4626000 - 0x00007f90d4628000 - usr 8K s r-- /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
0x00007f90d4628000 - 0x00007f90d464e000 - usr 152K s r-x /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 ; map._lib64_ld_linux_x86_64.so.2.r_x
0x00007f90d464e000 - 0x00007f90d4659000 - usr 44K s r-- /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 ; map._lib64_ld_linux_x86_64.so.2.r__
0x00007f90d465a000 - 0x00007f90d465c000 - usr 8K s r-- /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 ; map._lib64_ld_linux_x86_64.so.2.rw_
0x00007f90d465c000 - 0x00007f90d465e000 - usr 8K s rw- /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 ; r15
0x00007ffd5d132000 - 0x00007ffd5d154000 - usr 136K s rw- [stack] [stack] ; map._stack_.rw_
0x00007ffd5d16e000 - 0x00007ffd5d172000 - usr 16K s r-- [vvar] [vvar] ; map._vvar_.r__
0x00007ffd5d172000 - 0x00007ffd5d174000 - usr 8K s r-x [vdso] [vdso] ; map._vdso_.r_x
0xffffffffff600000 - 0xffffffffff601000 - usr 4K s --x [vsyscall] [vsyscall] ; map._vsyscall_.__x
[0x7f90d46044a0]>
Hey @majorendian sorry for my late reply.
So it seems like the problem is just a wrong detection of the region containing the glibc to find out the global. this code has changed a couple of times and the reason was mainly that on some distros this library was placed on a different path so it was impossible to have a 100%. and we should be adding tests for this, but that's not easy because we may probably use chroots inside privileged containers to do that in ghci to emulate different distros easily.
if you have some fixes for this issue or maybe a workaround feel free to submit a PR with the contents of your branch. Feel free to join irc, discord or telegram chats if you want a faster response. ive been busy this weekend O:)
thanks for digging in!
ping?
@trufae Sorry I have a few things going on at the moment. I might join the discord. Right now I only have a fix for the thread_arena spam.
can you send a PR with that fix? so the changes are not lost at least 👍
@trufae I submited a pull request for the thread_arena spam. Sorry for my late reply.
Environment
Description
the entire suite of dmh* subcommands is useless. im sorry i have to say it like this but really, nothing works as intended.
dmh
related commands have the following issues: 1) cant find main arena, complains that "this address is not part of any arenas" have to check all arenas withdmha
only to be greeted by this:I have to scroll all the way up for the main arena address, sometimes, it prints several kilobytes of "thread arena" into my terminal, when there are no threads to begin with. 2) dmhb and friends straight up dont work, shows a bunch of "corrupted" bins and chunk when they arent, dmh doesnt show any chunks only the top chunk, but sometimes it shows other chunks, feels random. 3) "corrupted" bins after 3 mallocs
4) example of a fast bin chunk of size 100 bytes
6) dmhg shows nothing but the top chunk. 7) main_arena pointer doesnt actually point to the heap, so its like a garbage pointer of some sort 8) you get the picture.
cant use the module/functionality in any useful capacity. The rest of the program works fine. Is there another program i could use to inspect the heap more reliably?
The only real "expected" output I can provide, is the ones you feature in some videos and tutorials, and for example from pwndbg. i am providing output from pwndbg
heap
andvmmap
commands for comparissionSo, i'd expect the radare2 output to be simmilar to the one of pwndbg
Same binary was used as attached. its nothing more than a .c file with 3 mallocs and 3 frees.
Test
compile the attached file run with r2 -d a.out step through program until som mallocs/frees run any dmh* command
cfile.tgz
system
Linux localhost 5.15.41-gentoo-x86_64 #1 SMP Sat Jun 25 12:51:37 CEST 2022 x86_64 Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz GenuineIntel GNU/Linux
glibc