|
|
@ -2,12 +2,28 @@ package web
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"bytes"
|
|
|
|
|
|
|
|
"encoding/binary"
|
|
|
|
"encoding/json"
|
|
|
|
"encoding/json"
|
|
|
|
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/lqqyt2423/go-mitmproxy/flow"
|
|
|
|
"github.com/lqqyt2423/go-mitmproxy/flow"
|
|
|
|
uuid "github.com/satori/go.uuid"
|
|
|
|
uuid "github.com/satori/go.uuid"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// message:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type: 1/2/3/4
|
|
|
|
|
|
|
|
// messageFlow
|
|
|
|
|
|
|
|
// version 1 byte + type 1 byte + id 36 byte + waitIntercept 1 byte + content left bytes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type: 11/12
|
|
|
|
|
|
|
|
// messageEdit
|
|
|
|
|
|
|
|
// version 1 byte + type 1 byte + id 36 byte + header len 4 byte + header content bytes + body len 4 byte + [body content bytes]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// type: 21
|
|
|
|
|
|
|
|
// messageMeta
|
|
|
|
|
|
|
|
// version 1 byte + type 1 byte + content left bytes
|
|
|
|
|
|
|
|
|
|
|
|
const messageVersion = 1
|
|
|
|
const messageVersion = 1
|
|
|
|
|
|
|
|
|
|
|
|
type messageType byte
|
|
|
|
type messageType byte
|
|
|
@ -19,8 +35,9 @@ const (
|
|
|
|
messageTypeResponseBody messageType = 4
|
|
|
|
messageTypeResponseBody messageType = 4
|
|
|
|
|
|
|
|
|
|
|
|
messageTypeChangeRequest messageType = 11
|
|
|
|
messageTypeChangeRequest messageType = 11
|
|
|
|
|
|
|
|
messageTypeChangeResponse messageType = 12
|
|
|
|
|
|
|
|
|
|
|
|
messageTypeChangeInterceptUri messageType = 21
|
|
|
|
messageTypeChangeBreakPointRules messageType = 21
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var allMessageTypes = []messageType{
|
|
|
|
var allMessageTypes = []messageType{
|
|
|
@ -29,7 +46,8 @@ var allMessageTypes = []messageType{
|
|
|
|
messageTypeResponse,
|
|
|
|
messageTypeResponse,
|
|
|
|
messageTypeResponseBody,
|
|
|
|
messageTypeResponseBody,
|
|
|
|
messageTypeChangeRequest,
|
|
|
|
messageTypeChangeRequest,
|
|
|
|
messageTypeChangeInterceptUri,
|
|
|
|
messageTypeChangeResponse,
|
|
|
|
|
|
|
|
messageTypeChangeBreakPointRules,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func validMessageType(t byte) bool {
|
|
|
|
func validMessageType(t byte) bool {
|
|
|
@ -41,73 +59,207 @@ func validMessageType(t byte) bool {
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type message struct {
|
|
|
|
type message interface {
|
|
|
|
|
|
|
|
bytes() []byte
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type messageFlow struct {
|
|
|
|
mType messageType
|
|
|
|
mType messageType
|
|
|
|
id uuid.UUID
|
|
|
|
id uuid.UUID
|
|
|
|
waitIntercept byte
|
|
|
|
waitIntercept byte
|
|
|
|
content []byte
|
|
|
|
content []byte
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func newMessage(mType messageType, id uuid.UUID, content []byte) *message {
|
|
|
|
func newMessageFlow(mType messageType, f *flow.Flow) *messageFlow {
|
|
|
|
return &message{
|
|
|
|
var content []byte
|
|
|
|
|
|
|
|
var err error = nil
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mType == messageTypeRequest {
|
|
|
|
|
|
|
|
content, err = json.Marshal(f.Request)
|
|
|
|
|
|
|
|
} else if mType == messageTypeRequestBody {
|
|
|
|
|
|
|
|
content = f.Request.Body
|
|
|
|
|
|
|
|
} else if mType == messageTypeResponse {
|
|
|
|
|
|
|
|
content, err = json.Marshal(f.Response)
|
|
|
|
|
|
|
|
} else if mType == messageTypeResponseBody {
|
|
|
|
|
|
|
|
content, err = f.Response.DecodedBody()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
panic(errors.New("invalid message type"))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return &messageFlow{
|
|
|
|
mType: mType,
|
|
|
|
mType: mType,
|
|
|
|
id: id,
|
|
|
|
id: f.Id,
|
|
|
|
content: content,
|
|
|
|
content: content,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func parseMessage(data []byte) *message {
|
|
|
|
func (m *messageFlow) bytes() []byte {
|
|
|
|
if len(data) < 39 {
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
|
|
|
|
buf.WriteByte(byte(messageVersion))
|
|
|
|
|
|
|
|
buf.WriteByte(byte(m.mType))
|
|
|
|
|
|
|
|
buf.WriteString(m.id.String()) // len: 36
|
|
|
|
|
|
|
|
buf.WriteByte(m.waitIntercept)
|
|
|
|
|
|
|
|
buf.Write(m.content)
|
|
|
|
|
|
|
|
return buf.Bytes()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type messageEdit struct {
|
|
|
|
|
|
|
|
mType messageType
|
|
|
|
|
|
|
|
id uuid.UUID
|
|
|
|
|
|
|
|
request *flow.Request
|
|
|
|
|
|
|
|
response *flow.Response
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func parseMessageEdit(data []byte) *messageEdit {
|
|
|
|
|
|
|
|
// 2 + 36 + 4 + 4
|
|
|
|
|
|
|
|
if len(data) < 46 {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if data[0] != messageVersion {
|
|
|
|
|
|
|
|
|
|
|
|
mType := (messageType)(data[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id, err := uuid.FromString(string(data[2:38]))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !validMessageType(data[1]) {
|
|
|
|
|
|
|
|
|
|
|
|
hl := (int)(binary.BigEndian.Uint32(data[38:42]))
|
|
|
|
|
|
|
|
if 42+hl+4 > len(data) {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
headerContent := data[42 : 42+hl]
|
|
|
|
|
|
|
|
|
|
|
|
id, err := uuid.FromString(string(data[3:39]))
|
|
|
|
bl := (int)(binary.BigEndian.Uint32(data[42+hl : 42+hl+4]))
|
|
|
|
|
|
|
|
if 42+hl+4+bl != len(data) {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bodyContent := data[42+hl+4:]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msg := &messageEdit{
|
|
|
|
|
|
|
|
mType: mType,
|
|
|
|
|
|
|
|
id: id,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mType == messageTypeChangeRequest {
|
|
|
|
|
|
|
|
req := new(flow.Request)
|
|
|
|
|
|
|
|
err := json.Unmarshal(headerContent, req)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
req.Body = bodyContent
|
|
|
|
|
|
|
|
msg.request = req
|
|
|
|
|
|
|
|
} else if mType == messageTypeChangeResponse {
|
|
|
|
|
|
|
|
res := new(flow.Response)
|
|
|
|
|
|
|
|
err := json.Unmarshal(headerContent, res)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
res.Body = bodyContent
|
|
|
|
|
|
|
|
msg.response = res
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
msg := newMessage(messageType(data[1]), id, data[39:])
|
|
|
|
|
|
|
|
msg.waitIntercept = data[2]
|
|
|
|
|
|
|
|
return msg
|
|
|
|
return msg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func newMessageRequest(f *flow.Flow) *message {
|
|
|
|
func (m *messageEdit) bytes() []byte {
|
|
|
|
content, err := json.Marshal(f.Request)
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
|
|
|
|
buf.WriteByte(byte(messageVersion))
|
|
|
|
|
|
|
|
buf.WriteByte(byte(m.mType))
|
|
|
|
|
|
|
|
buf.WriteString(m.id.String()) // len: 36
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if m.mType == messageTypeChangeRequest {
|
|
|
|
|
|
|
|
headerContent, err := json.Marshal(m.request)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newMessage(messageTypeRequest, f.Id, content)
|
|
|
|
hl := make([]byte, 4)
|
|
|
|
|
|
|
|
binary.BigEndian.PutUint32(hl, (uint32)(len(headerContent)))
|
|
|
|
|
|
|
|
buf.Write(hl)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bodyContent := m.request.Body
|
|
|
|
|
|
|
|
bl := make([]byte, 4)
|
|
|
|
|
|
|
|
binary.BigEndian.PutUint32(bl, (uint32)(len(bodyContent)))
|
|
|
|
|
|
|
|
buf.Write(bl)
|
|
|
|
|
|
|
|
buf.Write(bodyContent)
|
|
|
|
|
|
|
|
} else if m.mType == messageTypeChangeResponse {
|
|
|
|
|
|
|
|
headerContent, err := json.Marshal(m.response)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
hl := make([]byte, 4)
|
|
|
|
|
|
|
|
binary.BigEndian.PutUint32(hl, (uint32)(len(headerContent)))
|
|
|
|
|
|
|
|
buf.Write(hl)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bodyContent := m.response.Body
|
|
|
|
|
|
|
|
bl := make([]byte, 4)
|
|
|
|
|
|
|
|
binary.BigEndian.PutUint32(bl, (uint32)(len(bodyContent)))
|
|
|
|
|
|
|
|
buf.Write(bl)
|
|
|
|
|
|
|
|
buf.Write(bodyContent)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func newMessageRequestBody(f *flow.Flow) *message {
|
|
|
|
type messageMeta struct {
|
|
|
|
return newMessage(messageTypeRequestBody, f.Id, f.Request.Body)
|
|
|
|
mType messageType
|
|
|
|
|
|
|
|
breakPointRules []*breakPointRule
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func newMessageResponse(f *flow.Flow) *message {
|
|
|
|
func parseMessageMeta(data []byte) *messageMeta {
|
|
|
|
content, err := json.Marshal(f.Response)
|
|
|
|
content := data[2:]
|
|
|
|
|
|
|
|
rules := make([]*breakPointRule, 0)
|
|
|
|
|
|
|
|
err := json.Unmarshal(content, &rules)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return newMessage(messageTypeResponse, f.Id, content)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func newMessageResponseBody(f *flow.Flow) *message {
|
|
|
|
return &messageMeta{
|
|
|
|
body, _ := f.Response.DecodedBody()
|
|
|
|
mType: messageType(data[1]),
|
|
|
|
return newMessage(messageTypeResponseBody, f.Id, body)
|
|
|
|
breakPointRules: rules,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (m *message) bytes() []byte {
|
|
|
|
func (m *messageMeta) bytes() []byte {
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
buf.WriteByte(byte(messageVersion))
|
|
|
|
buf.WriteByte(byte(messageVersion))
|
|
|
|
buf.WriteByte(byte(m.mType))
|
|
|
|
buf.WriteByte(byte(m.mType))
|
|
|
|
buf.WriteByte(m.waitIntercept)
|
|
|
|
|
|
|
|
buf.WriteString(m.id.String()) // len: 36
|
|
|
|
content, err := json.Marshal(m.breakPointRules)
|
|
|
|
buf.Write(m.content)
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
panic(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.Write(content)
|
|
|
|
|
|
|
|
|
|
|
|
return buf.Bytes()
|
|
|
|
return buf.Bytes()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func parseMessage(data []byte) message {
|
|
|
|
|
|
|
|
if len(data) < 2 {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if data[0] != messageVersion {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !validMessageType(data[1]) {
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mType := (messageType)(data[1])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if mType == messageTypeChangeRequest || mType == messageTypeChangeResponse {
|
|
|
|
|
|
|
|
return parseMessageEdit(data)
|
|
|
|
|
|
|
|
} else if mType == messageTypeChangeBreakPointRules {
|
|
|
|
|
|
|
|
return parseMessageMeta(data)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
log.Warnf("invalid message type %v", mType)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|