Skip to content

Commit

Permalink
feat: 增加对流式解析的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
p1g3 committed Jan 19, 2024
1 parent dc93d09 commit 6701283
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 4 deletions.
52 changes: 52 additions & 0 deletions commons/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,63 @@ import (
"io"
)

type CommonStream interface {
io.ReadSeeker
ReadN(n int) (bs []byte, err error)
PeekN(n int) (bs []byte, err error)
EOF() bool
CurrentIndex() int64
}

type ReadSeekerStream struct {
io.ReadSeeker
offset int64
err error
}

func (s *ReadSeekerStream) Read(b []byte) (n int, err error) {
if _, err = s.Seek(s.offset, io.SeekStart); err != nil {
s.err = err
return
}
n, err = s.ReadSeeker.Read(b)
s.offset += int64(n)
return
}

func (s *ReadSeekerStream) ReadN(n int) (bs []byte, err error) {
bs = make([]byte, n)
_, err = io.ReadFull(s, bs)
return
}

func (s *ReadSeekerStream) PeekN(n int) (bs []byte, err error) {
oldOffset := s.offset
bs, err = s.ReadN(n)
s.offset = oldOffset
return
}

func (s *ReadSeekerStream) EOF() bool {
return s.err != nil
}

func (s *ReadSeekerStream) CurrentIndex() int64 {
return s.offset
}

type Stream struct {
bs []byte
current int64
}

func NewStreamFromReadSeeker(rs io.ReadSeeker) *ReadSeekerStream {
return &ReadSeekerStream{
ReadSeeker: rs,
offset: 0,
}
}

func NewStream(bs []byte) *Stream {
return &Stream{
bs: bs,
Expand Down
17 changes: 13 additions & 4 deletions serz/buffer.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@ package serz

import (
"github.com/phith0n/zkar/commons"
"io"
)

type ObjectStream struct {
*commons.Stream
commons.CommonStream
handler uint32
references map[uint32]Object
}

func NewObjectStream(bs []byte) *ObjectStream {
return &ObjectStream{
Stream: commons.NewStream(bs),
handler: JAVA_BASE_WRITE_HANDLE,
references: make(map[uint32]Object),
CommonStream: commons.NewStream(bs),
handler: JAVA_BASE_WRITE_HANDLE,
references: make(map[uint32]Object),
}
}

func NewObjectStreamFromReadSeeker(r io.ReadSeeker) *ObjectStream {
return &ObjectStream{
CommonStream: commons.NewStreamFromReadSeeker(r),
handler: JAVA_BASE_WRITE_HANDLE,
references: make(map[uint32]Object),
}
}

Expand Down
42 changes: 42 additions & 0 deletions serz/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"github.com/phith0n/zkar/commons"
"io"
"os"
)

Expand All @@ -19,6 +20,37 @@ type Serialization struct {
Contents []*TCContent
}

func FromReadSeeker(r io.ReadSeeker, len int) (*Serialization, error) {
var stream = NewObjectStreamFromReadSeeker(r)
var ser = new(Serialization)

// read magic number 0xACED
bs, err := stream.ReadN(2)
if err != nil || !bytes.Equal(bs, JAVA_STREAM_MAGIC) {
return nil, fmt.Errorf("invalid magic number")
}
ser.MagicNumber = JAVA_STREAM_MAGIC

// read stream version
bs, err = stream.ReadN(2)
if err != nil || !bytes.Equal(bs, JAVA_STREAM_VERSION) {
fmt.Fprintf(os.Stderr, "[warn] invalid stream version %v", bs)
}
ser.StreamVersion = bs

for i := 0; i < len; i++ {
var content *TCContent
content, err = readTCContent(stream)
if err != nil {
return nil, err
}

ser.Contents = append(ser.Contents, content)
}

return ser, nil
}

func FromBytes(data []byte) (*Serialization, error) {
var bs []byte
var err error
Expand Down Expand Up @@ -62,6 +94,16 @@ func FromJDK8u20Bytes(data []byte) (*Serialization, error) {
return FromBytes(data)
}

func FromJDK8u20ReadSeeker(data []byte) (*Serialization, error) {
data = bytes.Replace(
data,
[]byte{0x00, 0x7e, 0x00, 0x09},
[]byte{0x00, 0x7e, 0x00, 0x09, JAVA_TC_ENDBLOCKDATA},
1,
)
return FromReadSeeker(bytes.NewReader(data), 1)
}

func (ois *Serialization) ToString() string {
var b = commons.NewPrinter()
b.Printf("@Magic - %s", commons.Hexify(ois.MagicNumber))
Expand Down
13 changes: 13 additions & 0 deletions serz/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ func extractPackage(name string) string {
return name
}

func TestJDK8u20FromReadSeeker(t *testing.T) {
var filename = "../testcases/pwntester/JDK8u20.ser"
data, err := ioutil.ReadFile(filename)
require.Nil(t, err)

ser, err := FromJDK8u20ReadSeeker(data)
require.Nilf(t, err, "an error is occurred in file %v", filename)
serFromBytes, err := FromJDK8u20Bytes(data)
require.Equal(t, ser, serFromBytes)
require.Nilf(t, err, "an error is occurred in file %v", filename)
require.Truef(t, bytes.Equal(data, ser.ToJDK8u20Bytes()), "original data is different from generation data in file %v", filename)
}

func TestYsoserial(t *testing.T) {
walkAndTest("../testcases/ysoserial/*.ser", t, func(filename string, data []byte, ser *Serialization) {
require.Truef(
Expand Down

0 comments on commit 6701283

Please sign in to comment.