Using SerializationDumper for Java Deserialization and CTFs

I recently found out about SerializationDumper, and I wanted to share an example usage.

SerializationDumper - Introduction

During the BSidesRDU EverSec CTF, there was a ysoserial challenge that I used CyberChef to solve.

That said, a bit after the conference, I found out about SerializationDumper, which also solved it like a breeze.

You can find the tool on GitHub, and you can use it to dump any Java serialization streams.


First, I cloned the repository to my local machine.

root@kali:~/tools# git clone
Cloning into 'SerializationDumper'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 65 (delta 0), reused 4 (delta 0), pack-reused 59
Unpacking objects: 100% (65/65), done.

Next, I tried to run the script, but did not have my Java runtime installed.

root@kali:~/tools# cd SerializationDumper/
root@kali:~/tools# ls
LICENSE      MANIFEST.MF    build.bat     src/
root@kali:~/tools/SerializationDumper# chmod +x 
root@kali:~/tools/SerializationDumper# ./ 
No Java runtime present, requesting install.
No Java runtime present, requesting install.

Once I fixed my Java installation, the tool installed fine.

root@kali:~/tools/SerializationDumper# ./ 
mkdir: out: File exists
added manifest
adding: nb/(in = 0) (out= 0)(stored 0%)
adding: nb/deser/(in = 0) (out= 0)(stored 0%)
adding: nb/deser/SerializationDumper.class(in = 23776) (out= 11001)(deflated 53%)
adding: nb/deser/support/(in = 0) (out= 0)(stored 0%)
adding: nb/deser/support/ClassDetails.class(in = 1823) (out= 867)(deflated 52%)
adding: nb/deser/support/ClassDataDesc.class(in = 1993) (out= 956)(deflated 52%)
adding: nb/deser/support/ClassField.class(in = 655) (out= 388)(deflated 40%)

Usage/Capturing Flags

With SerializationDumper installed, I ran it against the ysoserial payload from the CTF. Unfortunately, I received a STREAM_MAGIC error, and it would not dump the stream.

root@kali:~/tools/SerializationDumper# java -jar SerializationDumper.jar -r ctf-serialization.txt 

Unknown RMI packet type - 0x72
STREAM_MAGIC - 0x4f 30
Invalid STREAM_MAGIC, should be 0xac ed

After looking at the error and my input file, I realized that it wanted the actual serialized data as opposed to the base64 encoded version.

root@kali:~/tools/SerializationDumper# cat ctf-serialization.txt | base64 -D > ctf-decoded.txt

With the decoded payload, I was able to successfully dump the stream. Note: I removed a lot of the output, as it tends to be very long.

root@kali:~/tools/SerializationDumper# java -jar SerializationDumper.jar -r ctf-decoded.txt 

STREAM_MAGIC - 0xac ed
  TC_OBJECT - 0x73
    TC_CLASSDESC - 0x72
        Length - 23 - 0x00 17
        Value - java.util.PriorityQueue - 0x6a6176612e7574696c2e5072696f726974795175657565
      serialVersionUID - 0x94 da 30 b4 fb 3f 82 b1
      newHandle 0x00 7e 00 00
      classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLE
      fieldCount - 2 - 0x00 02
          Int - I - 0x49
            Length - 4 - 0x00 04
            Value - size - 0x73697a65
          Object - L - 0x4c
            Length - 10 - 0x00 0a
            Value - comparator - 0x636f6d70617261746f72
            TC_STRING - 0x74
              newHandle 0x00 7e 00 01
              Length - 22 - 0x00 16
              Value - Ljava/util/Comparator; - 0x4c6a6176612f7574696c2f436f6d70617261746f723b
        TC_ENDBLOCKDATA - 0x78
        TC_NULL - 0x70
    newHandle 0x00 7e 00 02
            (int)2 - 0x00 00 00 02

I found the command that the flag was located in towards the bottom of the stream.

Index 1186:
  (byte)1 - 0x01
Index 1187:
  (byte)0 - 0x00
Index 1188:
  (byte)16 - 0x10
Index 1189:
  (byte)106 (ASCII: j) - 0x6a
Index 1190:
  (byte)97 (ASCII: a) - 0x61
Index 1191:
  (byte)118 (ASCII: v) - 0x76
Index 1192:
  (byte)97 (ASCII: a) - 0x61
Index 1193:
  (byte)47 (ASCII: /) - 0x2f
Index 1194:
  (byte)108 (ASCII: l) - 0x6c
Index 1195:
  (byte)97 (ASCII: a) - 0x61
Index 1196:
  (byte)110 (ASCII: n) - 0x6e
Index 1197:
  (byte)103 (ASCII: g) - 0x67
Index 1198:
  (byte)47 (ASCII: /) - 0x2f
Index 1199:
  (byte)83 (ASCII: S) - 0x53
Index 1200:
  (byte)116 (ASCII: t) - 0x74
Index 1201:
  (byte)114 (ASCII: r) - 0x72
Index 1202:
  (byte)105 (ASCII: i) - 0x69
Index 1203:
  (byte)110 (ASCII: n) - 0x6e
Index 1204:
  (byte)103 (ASCII: g) - 0x67
Index 1205:
  (byte)7 - 0x07
Index 1206:
  (byte)0 - 0x00
Index 1207:
  (byte)48 (ASCII: 0) - 0x30
Index 1208:
  (byte)1 - 0x01
Index 1209:
  (byte)0 - 0x00
Index 1210:
  (byte)16 - 0x10
Index 1211:
  (byte)101 (ASCII: e) - 0x65
Index 1212:
  (byte)99 (ASCII: c) - 0x63
Index 1213:
  (byte)104 (ASCII: h) - 0x68
Index 1214:
  (byte)111 (ASCII: o) - 0x6f
Index 1215:
  (byte)32 (ASCII:  ) - 0x20
Index 1216:
  (byte)121 (ASCII: y) - 0x79
Index 1217:
  (byte)115 (ASCII: s) - 0x73
Index 1218:
  (byte)48 (ASCII: 0) - 0x30
Index 1219:
  (byte)115 (ASCII: s) - 0x73
Index 1220:
  (byte)51 (ASCII: 3) - 0x33
Index 1221:
  (byte)114 (ASCII: r) - 0x72
Index 1222:
  (byte)105 (ASCII: i) - 0x69
Index 1223:
  (byte)52 (ASCII: 4) - 0x34
Index 1224:
  (byte)48 (ASCII: 0) - 0x30
Index 1225:
  (byte)85 (ASCII: U) - 0x55
Index 1226:
  (byte)115 (ASCII: s) - 0x73
Index 1227:
  (byte)8 - 0x08
Index 1228:
  (byte)0 - 0x00
Index 1229:
  (byte)50 (ASCII: 2) - 0x32
Index 1230:
  (byte)1 - 0x01
Index 1231:
  (byte)0 - 0x00
Index 1232:
  (byte)4 - 0x04
Index 1233:
  (byte)101 (ASCII: e) - 0x65
Index 1234:
  (byte)120 (ASCII: x) - 0x78
Index 1235:
  (byte)101 (ASCII: e) - 0x65
Index 1236:
  (byte)99 (ASCII: c) - 0x63
Index 1237:
  (byte)1 - 0x01
Index 1238:
  (byte)0 - 0x00

If you can't tell, this runs `exec echo ys0s3ri40Us`, which was the flag for the CTF challenge.

SerializationDumper - Flag

SerializationDumper - Conclusion

This was a handy tool and made dumping the stream easy.

It can also now rebuild streams with some modification, so should make some deserialization exploitation easier.

I would love if it had some logic to make things more human readable, but that would take a lot more work.

I'm hoping to do an actual Java deserialization post soon, so let me know if you have a notable example or target.

doyler on Githubdoyler on Twitter
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.


Filed under Security Not Included

2 Responses to Using SerializationDumper for Java Deserialization and CTFs

  1. Pingback: Using SerializationDumper for Java Deserialization and CTFs | – The Library 6.0

  2. Pingback: Bug Bytes #48 – 20 char XSS, HackerOne accidental account takeover & one-time ☎️ – INTIGRITI

Leave a Reply

Your email address will not be published. Required fields are marked *

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

This site uses Akismet to reduce spam. Learn how your comment data is processed.