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
612 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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 

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

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
how to add new optional parameter to JSP 1 40
factorial example 4 39
Windows 10 IE Certificate Issue 10 45
hibernate example using maven 12 41
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers will learn about the different types of variables in Java and how to declare them. Decide the type of variable desired: Put the keyword corresponding to the type of variable in front of the variable name: Use the equal sign to assign a v…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

808 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