Commit 21414656 authored by Michael Cohen's avatar Michael Cohen
Browse files

Added tests.

parent 45d6165d
Pipeline #31047101 failed with stages
in 4 minutes and 46 seconds
......@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"regexp"
"time"
"github.com/olekukonko/tablewriter"
kingpin "gopkg.in/alecthomas/kingpin.v2"
......@@ -58,7 +59,7 @@ func doLS() {
table.Append([]string{
info.MFTId,
fmt.Sprintf("%v", info.Size),
fmt.Sprintf("%v", info.Mtime),
fmt.Sprintf("%v", info.Mtime.In(time.UTC)),
fmt.Sprintf("%v", info.IsDir),
info.Name,
})
......
......@@ -11,13 +11,14 @@ import (
)
type FileInfo struct {
MFTId string
Mtime time.Time
Atime time.Time
Ctime time.Time
Name string
IsDir bool
Size int64
MFTId string
Mtime time.Time
Atime time.Time
Ctime time.Time
Name string
NameType string
IsDir bool
Size int64
}
func GetRootMFTEntry(image io.ReaderAt) (*MFT_ENTRY, error) {
......@@ -158,9 +159,10 @@ func ListDir(root *MFT_ENTRY) []*FileInfo {
Ctime: time.Unix(
filename.Get("mft_modified").
AsInteger(), 0),
Name: filename.Name() + ads,
IsDir: is_dir,
Size: attr.Size(),
Name: filename.Name() + ads,
NameType: filename.Get("name_type").AsString(),
IsDir: is_dir,
Size: attr.Size(),
})
}
}
......
{
"01 Open by path": [
{
"MFTId": "46-128-1",
"Mtime": "2018-09-24T17:55:29+10:00",
"Atime": "2018-09-24T17:55:29+10:00",
"Ctime": "2018-09-24T17:55:29+10:00",
"Name": "Hello world text document.txt",
"NameType": "POSIX",
"IsDir": false,
"Size": 12
},
{
"MFTId": "46-128-5",
"Mtime": "2018-09-24T17:55:29+10:00",
"Atime": "2018-09-24T17:55:29+10:00",
"Ctime": "2018-09-24T17:55:29+10:00",
"Name": "Hello world text document.txt:goodbye.txt",
"NameType": "POSIX",
"IsDir": false,
"Size": 20
}
],
"02 Folder B stat": [
"[MFT_ENTRY] @ 0xb400",
" 0x000 magic [string 'FILE']",
" 0x004 fixup_offset [uint16] 0x30",
" 0x006 fixup_count [uint16] 0x3",
" 0x008 logfile_sequence_number [uint64] 0x10c532",
" 0x010 sequence_value [uint16] 0x1",
" 0x012 link_count [uint16] 0x1",
" 0x014 attribute_offset [uint16] 0x38",
" 0x016 flags [flags 3 'DIRECTORY, ALLOCATED']",
" 0x018 mft_entry_size [uint16] 0x218",
" 0x01c mft_entry_allocated [uint16] 0x400",
" 0x020 base_record_reference [uint64] 0x0",
" 0x028 next_attribute_id [uint16] 0x5",
" 0x02c record_number [uint32] 0x2d",
"Attribute:",
"[NTFS_RESIDENT_ATTRIBUTE] @ 0x38",
" 0x000 type $STANDARD_INFORMATION",
" 0x004 length [uint32] 0x60",
" 0x008 resident RESIDENT",
" 0x009 name_length [uint8] 0x0",
" 0x00a name_offset [uint16] 0x0",
" 0x00e attribute_id [uint16] 0x0",
" 0x010 content_size [uint32] 0x48",
" 0x014 content_offset [uint16] 0x18",
"Data: ",
"00000000 bc a8 fa f0 db 53 d4 01 f7 d1 2b ff db 53 d4 01 |.....S....+..S..|",
"00000010 f7 d1 2b ff db 53 d4 01 fe 69 76 27 dc 53 d4 01 |..+..S...iv'.S..|",
"00000020 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|",
"00000030 00 00 00 00 08 01 00 00 00 00 00 00 00 00 00 00 |................|",
"00000040 00 00 00 00 00 00 00 00 |........|",
"",
"[STANDARD_INFORMATION] @ 0x0",
" 0x000 create_time [WinFileTime] 0x5ba89868 (2018-09-24 07:55:20 +0000 UTC)",
" 0x008 file_altered_time [WinFileTime] 0x5ba89880 (2018-09-24 07:55:44 +0000 UTC)",
" 0x010 mft_altered_time [WinFileTime] 0x5ba89880 (2018-09-24 07:55:44 +0000 UTC)",
" 0x018 file_accessed_time [WinFileTime] 0x5ba898c4 (2018-09-24 07:56:52 +0000 UTC)",
" 0x020 flags [flags 800 '']",
" 0x024 max_versions [uint32] 0x0",
" 0x028 version [uint32] 0x0",
" 0x02c class_id [uint32] 0x0",
" 0x030 owner_id [uint32] 0x0",
" 0x034 sid [uint32] 0x108",
" 0x038 quota [uint64] 0x0",
" 0x040 usn [uint32] 0x0",
"[NTFS_RESIDENT_ATTRIBUTE] @ 0x98",
" 0x000 type $FILE_NAME",
" 0x004 length [uint32] 0x70",
" 0x008 resident RESIDENT",
" 0x009 name_length [uint8] 0x0",
" 0x00a name_offset [uint16] 0x0",
" 0x00e attribute_id [uint16] 0x3",
" 0x010 content_size [uint32] 0x52",
" 0x014 content_offset [uint16] 0x18",
"Data: ",
"00000000 29 00 00 00 00 00 01 00 bc a8 fa f0 db 53 d4 01 |)............S..|",
"00000010 bc a8 fa f0 db 53 d4 01 bc a8 fa f0 db 53 d4 01 |.....S.......S..|",
"00000020 bc a8 fa f0 db 53 d4 01 00 00 00 00 00 00 00 00 |.....S..........|",
"00000030 00 00 00 00 00 00 00 00 00 08 00 10 00 00 00 00 |................|",
"00000040 08 00 46 00 6f 00 6c 00 64 00 65 00 72 00 20 00 |..F.o.l.d.e.r. .|",
"00000050 42 00 |B.|",
"",
"[FILE_NAME] @ 0x0",
" 0x000 mftReference [BitField] 0x29",
" 0x006 seq_num [int16] 0x1",
" 0x008 created [WinFileTime] 0x5ba89868 (2018-09-24 07:55:20 +0000 UTC)",
" 0x010 file_modified [WinFileTime] 0x5ba89868 (2018-09-24 07:55:20 +0000 UTC)",
" 0x018 mft_modified [WinFileTime] 0x5ba89868 (2018-09-24 07:55:20 +0000 UTC)",
" 0x020 file_accessed [WinFileTime] 0x5ba89868 (2018-09-24 07:55:20 +0000 UTC)",
" 0x028 allocated_size [uint64] 0x0",
" 0x030 size [uint64] 0x0",
" 0x038 flags [flags 10000800 '']",
" 0x03c reparse_value [uint32] 0x0",
" 0x040 _length_of_name [uint8] 0x8",
" 0x041 name_type POSIX",
" 0x042 name [int8] 0x46",
"Name: Folder B",
"",
"[NTFS_RESIDENT_ATTRIBUTE] @ 0x108",
" 0x000 type $OBJECT_ID",
" 0x004 length [uint32] 0x28",
" 0x008 resident RESIDENT",
" 0x009 name_length [uint8] 0x0",
" 0x00a name_offset [uint16] 0x0",
" 0x00e attribute_id [uint16] 0x4",
" 0x010 content_size [uint32] 0x10",
" 0x014 content_offset [uint16] 0x18",
"Data: ",
"00000000 cb c6 8d e9 52 b5 e8 11 89 49 68 07 15 7f f1 51 |....R....Ih....Q|",
"",
"[NTFS_RESIDENT_ATTRIBUTE] @ 0x130",
" 0x000 type $INDEX_ROOT",
" 0x004 length [uint32] 0xe0",
" 0x008 resident RESIDENT",
" 0x009 name_length [uint8] 0x4",
" 0x00a name_offset [uint16] 0x18",
" 0x00e attribute_id [uint16] 0x1",
" 0x010 content_size [uint32] 0xc0",
" 0x014 content_offset [uint16] 0x20",
"Name: $I30",
"Data: ",
"00000000 30 00 00 00 01 00 00 00 00 10 00 00 04 00 00 00 |0...............|",
"00000010 10 00 00 00 b0 00 00 00 b0 00 00 00 00 00 00 00 |................|",
"00000020 2e 00 00 00 00 00 01 00 90 00 7c 00 00 00 00 00 |..........|.....|",
"00000030 2d 00 00 00 00 00 01 00 cf e2 69 f6 db 53 d4 01 |-.........i..S..|",
"00000040 cf 93 7b 1d dc 53 d4 01 cf 93 7b 1d dc 53 d4 01 |..{..S....{..S..|",
"00000050 cf 93 7b 1d dc 53 d4 01 10 00 00 00 00 00 00 00 |..{..S..........|",
"00000060 0c 00 00 00 |....|",
""
],
"03 Hello world.txt": "12: Hello world!",
"04 Hello world.txt:goodbye.txt": "20: Goodbye cruel world.",
"05 Compressed ones.bin hash": "2949120: f581eebdb9a49a622c305d4e44977bc91a4a1204"
}
\ No newline at end of file
package ntfs_test
import (
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
"github.com/sebdah/goldie"
"github.com/stretchr/testify/assert"
ntfs "www.velocidex.com/golang/go-ntfs"
)
func split(message string) interface{} {
if !strings.Contains(message, "\n") {
return message
}
return strings.Split(message, "\n")
}
func TestNTFS(t *testing.T) {
result := make(map[string]interface{})
assert := assert.New(t)
fd, err := os.Open("test_data/test.ntfs.dd")
assert.NoError(err, "Unable to open file")
root, err := ntfs.GetRootMFTEntry(fd)
assert.NoError(err, "Unable to open file")
// Open directory by path.
dir, err := root.Open("Folder A/Folder B")
assert.NoError(err, "Open by path")
result["01 Open by path"] = ntfs.ListDir(dir)
result["02 Folder B stat"] = split(dir.DebugString())
// Open by mft id
mft_idx, attr, id, err := ntfs.ParseMFTId("46-128-5")
assert.NoError(err, "ParseMFTId")
assert.Equal(mft_idx, int64(46))
assert.Equal(attr, int64(128))
assert.Equal(id, int64(5))
buf := make([]byte, 3000000)
reader, err := ntfs.GetDataForPath(
"Folder A/Folder B/Hello world text document.txt", root)
assert.NoError(err, "GetDataForPath")
n, _ := reader.ReadAt(buf, 0)
result["03 Hello world.txt"] = fmt.Sprintf("%v: %s", n, string(buf[:n]))
reader, err = ntfs.GetDataForPath(
"Folder A/Folder B/Hello world text document.txt:goodbye.txt",
root)
assert.NoError(err, "GetDataForPath ADS")
n, _ = reader.ReadAt(buf, 0)
result["04 Hello world.txt:goodbye.txt"] = fmt.Sprintf(
"%v: %s", n, string(buf[:n]))
reader, err = ntfs.GetDataForPath("ones.bin", root)
assert.NoError(err, "Open compressed ones.bin")
n, _ = reader.ReadAt(buf, 0)
h := sha1.New()
h.Write(buf[:n])
result["05 Compressed ones.bin hash"] = fmt.Sprintf(
"%v: %s", n, hex.EncodeToString(h.Sum(nil)))
result_json, _ := json.MarshalIndent(result, "", " ")
goldie.Assert(t, "TestNTFS", result_json)
}
......@@ -28,7 +28,7 @@ func (self *WinFileTimeParser) AsInteger(offset int64, reader io.ReaderAt) int64
}
func (self *WinFileTimeParser) AsString(offset int64, reader io.ReaderAt) string {
return self.AsDate(offset, reader).String()
return self.AsDate(offset, reader).In(time.UTC).String()
}
func (self *WinFileTimeParser) DebugString(offset int64, reader io.ReaderAt) string {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment