Solved

Question about the object serialization specifcation as used in Joshua Bloch's "Effective Java Programming Language Guide" (pg. 227)

Posted on 2006-06-13
8
615 Views
Last Modified: 2011-08-18
In the serialization chapter of the book mentioned in this title, on page 227, Joshua Bloch shows how to gain access to references of private fields of an improperly constructed serializable class using "rogue object references".  I read through the Java Object Serialization Specification, as he suggested, for more info, but I still do not exactly understand how he did it (specifically, what the hex values in the byte array he constructed mean).  Can anyone help me out with this?

P.S. I figure it might get me into some legal trouble if I copy the contents of the section of the chapter I just mentioned from Bloch's book.  I suspect a lot of java developers actually posses this book (if they don't, they should).  So, obviously, only owners of this book with the book handy will be able to help.
0
Comment
Question by:abcast
8 Comments
 
LVL 5

Expert Comment

by:tbboyett
ID: 16898927
I don't own the book but maybe this site will help you understand serialization a little better:
http://www.mactech.com/articles/mactech/Vol.14/14.04/JavaSerialization

It has a full example of using serialization
0
 
LVL 92

Expert Comment

by:objects
ID: 16900108
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 16900683
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:abcast
ID: 16902789
What I'm most intetested is an explanation of Bloch's exact example.  So, if anyone can provide that for me, it would be most appreciated.  If you don't have the book, you won't be able to help.
0
 
LVL 9

Expert Comment

by:matthew016
ID: 16908876
Hi,
The hexa values shown in the example are a
representation of a serialized "Period" object in hexadecimal.

Now here is a way on how to find the hexa values to get an incorrect "Period",
like in the example :
starting date : Fri Jan 01 12:00:00 PST 1999 ;
ending date :  Sun Jan 01 12:00:00 PST 1984 ;
So the aim is to create an object Period with those two dates, and 'hack' the test
"if (this.start.compareTo(this.end) > 0)" in the constructor.

1)

Firstly I will create a correct Period with, for example,
starting date : Sun Jan 01 21:00:00 CET 1984 ;
ending date   : Sun Jan 01 21:00:01 CET 1984 ;

(I create a new class for this)
class Test implements java.io.Serializable {
    public static void main(String[] args) {
       try {
              Date start = new Date(84,00,01,21,0,0);
              Date end   = new Date(84,00,01,21,0,1);
              Period period = new Period(start,end);
[...]

Now I translate the new object 'Period' into bytes :

[...]
            ByteArrayOutputStream o = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(o);
            out.writeObject(period);
            out.flush();
[...]

Then I am going to convert the values in the byte array obtained into hexadecimal values :

[...]
            byte[] b = new byte[10000];
            b = o.toByteArray();
            int cpt = 0;
            for(int i=0; i<b.length; ++i) {
                  String hexstr = Integer.toHexString(b[i]);
                  //System.out.println(hexstr);
                System.out.print(Integer.toHexString( 0x10000 | b[i]).substring(1).toUpperCase());
                System.out.print(", ");
               cpt++;
                if(cpt==8) {System.out.println();cpt=0;}
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

I have this as result :

FFFFFAC, FFFFFED, 0000, 0005, 0073, 0072, 0000, 0006,
0050, 0065, 0072, 0069, 006F, 0064, 0040, 007E,
FFFFFF8, 002B, 004F, 0046, FFFFFC0, FFFFFF4, 0002, 0000,
0002, 004C, 0000, 0003, 0065, 006E, 0064, 0074,
0000, 0010, 004C, 006A, 0061, 0076, 0061, 002F,
0075, 0074, 0069, 006C, 002F, 0044, 0061, 0074,
0065, 003B, 004C, 0000, 0005, 0073, 0074, 0061,
0072, 0074, 0071, 0000, 007E, 0000, 0001, 0078,
0070, 0073, 0072, 0000, 000E, 006A, 0061, 0076,
0061, 002E, 0075, 0074, 0069, 006C, 002E, 0044,
0061, 0074, 0065, 0068, 006A, FFFFF81, 0001, 004B,
0059, 0074, 0019, 0003, 0000, 0000, 0078, 0070,
0077, 0008, 0000, 0000, 0000, 0066, FFFFFDF, 006E,
0021, FFFFFE8, 0078, 0073, 0071, 0000, 007E, 0000,
0003, 0077, 0008, 0000, 0000, 0000, 0066, FFFFFDF,
006E, 001E, 0000, 0078


2)

Now I do the same thing with more Period objects

I see that the 23 last bytes are always changing according to different Period objects :

0066, FFFFFDF, 006E,
0021, FFFFFE8, 0078, 0073, 0071, 0000, 007E, 0000,
0003, 0077, 0008, 0000, 0000, 0000, 0066, FFFFFDF,
006E, 001E, 0000, 0078

I also notice that the 6 first bytes (of the 23 last bytes) memorize the first date,
and the 6 last bytes memorize the last date.

Now I just need to inverse these bytes and I can make a hacked Period object.

3)

Do the same thing now for

starting date : Sun Jan 01 12:00:00 PST 1984 ;
ending date :  Fri Jan 01 12:00:00 PST 1999 ;
(a correct Period)

Then u inverse the 6 bytes.

U have this :

    private static final byte[] serializedForm = new byte[] {
          (byte) 0xAC, (byte) 0xED, 0x00, 0x05, 0x73, 0x72, 0x00, 0x06,
          0x50, 0x65, 0x72, 0x69, 0x6F, 0x64, 0x40, 0x7E,
          (byte) 0xF8, 0x2B, 0x4F, 0x46, (byte) 0xC0, (byte) 0xF4, 0x02, 0x00,
          0x02, 0x4C, 0x00, 0x03, 0x65, 0x6E, 0x64, 0x74,
          0x00, 0x10, 0x4C, 0x6A, 0x61, 0x76, 0x61, 0x2F,
          0x75, 0x74, 0x69, 0x6C, 0x2F, 0x44, 0x61, 0x74,
          0x65, 0x3B, 0x4C, 0x00, 0x05, 0x73, 0x74, 0x61,
          0x72, 0x74, 0x71, 0x00, 0x7E, 0x00, 0x01, 0x78,
          0x70, 0x73, 0x72, 0x00, 0x0E, 0x6A, 0x61, 0x76,
          0x61, 0x2E, 0x75, 0x74, 0x69, 0x6C, 0x2E, 0x44,
          0x61, 0x74, 0x65, 0x68, 0x6A, (byte) 0x81, 0x01, 0x4B,
          0x59, 0x74, 0x19, 0x03, 0x00, 0x00, 0x78, 0x70,
          0x77, 0x08, 0x00, 0x00, 0x00,
          
          0x66, (byte) 0xDF,  0x6E, 0x1E, 0x00, 0x78,
          
          0x73, 0x71, 0x00, 0x7E, 0x00, 0x03, 0x77, 0x08, 0x00, 0x00, 0x00,
          
          (byte) 0xD5, 0x17, 0x69, 0x22, 0x00, 0x78
    };

With the hexavalues u modified, u do now like in the example "BogusPeriod" in the book :

I can't paste the code here for copyright, just look at the example and see what he does with the array of hexa's.

Hope that helped,
sorry for bad english,
0
 

Author Comment

by:abcast
ID: 16911624
Thanks for the detailed description, matthew016.  However, I was actually looking for an explanation of the example posted after the BogusPeriod code.  The code I speak of is that which he created to gain references to the 2 private variables that make up a Period object.  See the MutablePeriod class following the BogusPeriod class.  In MutablePeriod, he appends rogue "previous object refs" to the serialized file.  How he knew how to do this, and what the 5 values in his byte array mean are what I am stuck on.
0
 
LVL 9

Accepted Solution

by:
matthew016 earned 500 total points
ID: 16917778
To get a reference on an object u have to code :

0x71 (int) handle
as explained in the Java Object Serialization Specification.

Each object written to the stream is assigned a handle that is used to refer back to the object.
The first handler as a value of 0x7e 0x00 0x00, second one 0x7e 0x00 0x01, ...

int is 4 bytes so it becomes : 0x00 0x7e 0x00 0x..

So if I resume we get :
0x71 0x00 0x7e 0x00 0x??
?? -> the rank of the handler of the start date object that we are trying to find.

A way to find the correct rank start date's handler and en date's handler is to try all values
0x71 0x00 0x7e 0x00 0x00
0x71 0x00 0x7e 0x00 0x01
0x71 0x00 0x7e 0x00 0x02
...
Append those values after the Period object and try to cast to a Date object

You'll notice that :

handler 0  = java.io.ObjectStreamClass object
handler 1 = java.lang.String object
handler 2 = Period object
handler 3 = java.io.ObjectStreamClass object
handler 4 = java.util.Date object
handler 5 = java.util.Date object
0
 

Author Comment

by:abcast
ID: 16920388
Thanks!
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

820 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question