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
603 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
Comment Utility
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
Comment Utility
0
 
LVL 30

Expert Comment

by:mayankeagle
Comment Utility
0
 

Author Comment

by:abcast
Comment Utility
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 9

Expert Comment

by:matthew016
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Thanks!
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

763 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now