Tuesday, May 19, 2009

Using memfetch, page 37

This line is somewhat mysterious:
memfetch will dump everything in memory for a specific process; simply look through the binary files for the address of /bin/sh
I've never used memfetch, so may as well get into it now. First, you'll need to get a hold of it and compile it. Download it from Zalewski's site, and, if you're like me and don't have your Linux kernel headers in your include path already, edit the #include line for 'page.h' to
#include "/usr/src/linux/include/asm/page.h"
Googling around for some examples on using memfetch to actually find the address of /bin/sh turns up little, other than copy-pastes of this very section of Shellcoders (like this one). So, not much luck there. After some trial and error, I have a procedure together now which seems to work pretty well.

Memfetch won't run on a process that's already being traced (like, via gdb), so the easiest way to search for /bin/sh is to write a program that hangs around a while. I wrote sleeper.c for this:
int main(void) {
printf("process id: %d\n", getpid());
sleep(30);
}
At this point, compile and run sleeper.c as normal. Note the process ID, and in another terminal, run memfetch , grep for "/bin/sh", note which dump it's in, look for its offset, and do a little arithmetic to figure out where this string lives. Below is a screen capture of the process.
todb@mazikeen:~/dev/sc/memfetch$ ./memfetch 2882
memfetch 0.05b by Michal Zalewski
[+] Attached to PID 2882 (/home/todb/dev/sc/sleep).
[*] Writing master information to mfetch.lst...
Writing map at 0x08048000 (4096 bytes)... [N] done (map-000.bin)
Writing map at 0x08049000 (4096 bytes)... [N] done (map-001.bin)
Writing map at 0x0804a000 (4096 bytes)... [N] done (map-002.bin)
Writing mem at 0xb7e6c000 (4096 bytes)... [S] done (mem-003.bin)
Writing map at 0xb7e6d000 (1409024 bytes)... [S] done (map-004.bin)
Writing map at 0xb7fc5000 (8192 bytes)... [S] done (map-005.bin)
Writing map at 0xb7fc7000 (4096 bytes)... [S] done (map-006.bin)
Writing mem at 0xb7fc8000 (12288 bytes)... [S] done (mem-007.bin)
Writing mem at 0xb7fe0000 (12288 bytes)... [S] done (mem-008.bin)
Writing map at 0xb7fe3000 (106496 bytes)... [S] done (map-009.bin)
Writing mem at 0xb7ffd000 (4096 bytes)... [S] done (mem-010.bin)
Writing map at 0xb7ffe000 (4096 bytes)... [S] done (map-011.bin)
Writing map at 0xb7fff000 (4096 bytes)... [S] done (map-012.bin)
Writing mem at 0xbffeb000 (86016 bytes)... [S] done (mem-013.bin)
[*] Done (14 matching). Have a nice day.
todb@mazikeen:~/dev/sc/memfetch$ grep '/bin/sh' *.bin
Binary file map-004.bin matches
todb@mazikeen:~/dev/sc/memfetch$ irb
irb(main):001:0> f = File.open('map-004.bin') {|f| f.read} ; nil
=> nil
irb(main):002:0> hex # A quicky irb function that converts dec to hex for return values.
=> true
irb(main):003:0> loc = f.index('/bin/sh') # the offset into mem-004.bin
=> 13cc73
irb(main):004:0> start = 0xb7e6d000 # Remember, that's where map-004.bin starts.
=> b7e6d000
irb(main):005:0> start + loc # The location of /bin/sh.
=> b7fa9c73
To verify this value, I re-ran sleep with gdb attached:

todb@mazikeen:~/dev/sc$ gdb ./sleep
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i486-linux-gnu"...
(gdb) break main
Breakpoint 1 at 0x8048432
(gdb) r
Starting program: /home/todb/dev/sc/sleep

Breakpoint 1, 0x08048432 in main ()
Current language: auto; currently asm
(gdb) x/s 0xb7fa9c73
0xb7fa9c73: "/bin/sh"
(gdb)
Ta-da! So there you have it, using memfetch to find the location of the string "/bin/sh" for use in a return-to-libc style stack exploit. Remember, for this to work consistently, you need to disable ASLR with sudo /sbin/sysctl -w kernel.randomize_va_space=0, as mentioned here.

PS, one useful links I found while puzzling this out is Securiteam's GDB cheat sheet, at: http://www.securiteam.com/securityreviews/5UP0B2KCKI.html. Another is c0ntex's https://www.securinfos.info/english/security-whitepapers-hacking-tutorials/Return-to-libc.txt, which is essentially the same as this Shellcoder's section, but just presented a little differently.

Also, the astute reader will notice about a month lapsed between the last blog post and this one; finals and work and real life intruded on this work for a little bit. Hopefully, I'm back in a position to devote some time to this every day again.

8 comments:

  1. Hi

    I like your irb/ruby script to detect the location of /bin/sh. But memfetch comes with a small perl script called
    mffind.pl which can be used for this:

    perl mffind.pl "/bin/sh"

    Regards

    ReplyDelete
  2. I'm working through TSH, and this helped me find '/bin/sh'. Thanks!!

    ReplyDelete
  3. I am sorry, but I am having some problems compiling the memfetch program. I have changed the #include to:
    /usr/src/linux-headers-2.6.38-10/arch/x86/include/asm/page.h

    I am getting the 'PAGE_SIZE undeclared' error and don't know where to turn. I have googled the hell out of this and have not found a solution for UBUNTU 11.04 x86. Any ideas guys? Thanks.

    ReplyDelete
  4. Hey guys, I have found a nice alternative at the 'securitytube' site. Here a link to the video: http://www.securitytube.net/video/258

    This is a part of the "buffer overflow" series. Great site.

    ReplyDelete
  5. To answer the above query, I edited the memfetch.c file to include:

    #DEFINE PAGE_SIZE 4096

    4096 being the page size for Intel x86. Obviously change as required for your arch!

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I have tried on CentOS. Didn't have the kernel source and I have installed in using yum install kernel-devel.

    Then, simply edited memfetch.c
    Replaced in the #include, the "asm/page.h" With: "sys/user.h" (without the "")

    then everything was alright. :)

    ReplyDelete
  8. My solution was comment the line:
    #include

    And, then add the following line into the function main:

    PAGE_SIZE = getpagesize();

    I like the irb version, quite simple;-) I wrote a python version:
    https://github.com/citypw/arsenal-4-sec-testing/blob/master/audit/find_mem.py

    Thank to the author! It's a great reading!

    ReplyDelete