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
618 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

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

Java had always been an easily readable and understandable language.  Some relatively recent changes in the language seem to be changing this pretty fast, and anyone that had not seen any Java code for the last 5 years will possibly have issues unde…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Suggested Courses

752 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