Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix possible recursion bug. #30

Merged
merged 1 commit into from
Sep 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions parser/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,16 +681,18 @@ func (self *ATTRIBUTE_LIST_ENTRY) Attributes(
attr_list_entry := self.Profile.ATTRIBUTE_LIST_ENTRY(
self.Reader, self.Offset+offset)

Printf("ATTRIBUTE_LIST_ENTRY %v\n",
attr_list_entry.DebugString())
Printf("%v ATTRIBUTE_LIST_ENTRY %v\n", mft_entry.Record_number(),
DebugString(attr_list_entry, ""))

// The attribute_list_entry points to a different MFT
// entry than the one we are working on now. We need
// to fetch it from there.
mft_ref := attr_list_entry.MftReference()
if ntfs.RootMFT != nil &&
attr_list_entry.MftReference() != uint64(mft_entry.Record_number()) {
mft_ref != uint64(mft_entry.Record_number()) {

Printf("Fetching from MFT Entry %v\n", attr_list_entry.MftReference())
Printf("While working on %v - Fetching from MFT Entry %v\n",
mft_entry.Record_number(), mft_ref)
attr, err := attr_list_entry.GetAttribute(ntfs)
if err != nil {
Printf("Error %v\n", err)
Expand Down Expand Up @@ -723,14 +725,13 @@ func (self *ATTRIBUTE_LIST_ENTRY) GetAttribute(
if err != nil {
return nil, err
}
for _, attr := range mft.EnumerateAttributes(ntfs) {
if attr.Type().Value == uint64(mytype) &&
attr.Attribute_id() == uint16(myid) {
return attr, nil
}
res, err := mft.GetDirectAttribute(ntfs, mytype, uint16(myid))
if err != nil {
Printf("MFT %v not found in target\n", mft.Record_number())
} else {
Printf("Found %v\n", DebugString(res, " "))
}

return nil, errors.New("No attribute found.")
return res, err
}

// The STANDARD_INDEX_HEADER has a second layer of fixups.
Expand Down
2 changes: 1 addition & 1 deletion parser/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Debugger interface {

func DebugString(arg interface{}, indent string) string {
debugger, ok := arg.(Debugger)
if ok {
if debug && ok {
lines := strings.Split(debugger.DebugString(), "\n")
for idx, line := range lines {
lines[idx] = indent + line
Expand Down
47 changes: 47 additions & 0 deletions parser/mft.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,53 @@ func (self *MFT_ENTRY) EnumerateAttributes(ntfs *NTFSContext) []*NTFS_ATTRIBUTE
return result
}

// See https://github.com/CCXLabs/CCXDigger/issues/13

// It is possible that an attribute list is pointing to an mft entry
// which also contains an attribute list. The second attribute list
// may also point to another entry inside the first MFT entry. This
// causes an infinite loop.

// Previous versions of the code erroneously called
// EnumerateAttributes to resolve a foreign attribute reference but
// this is not strictly correct because a foreign reference is never
// indirect and so never should traverse ATTRIBUTE_LISTs recursively
// anyway.

// The GetDirectAttribute() function looks for an exact attribute and
// type inside an MFT entry without following any attribute
// lists. This breaks the recursion and is a more correct approach.

// Search the MFT entry for a contained attribute - does not expand
// ATTRIBUTE_LISTs. This version is suitable to be called from within
// an ATTRIBUTE_LIST expansion.
func (self *MFT_ENTRY) GetDirectAttribute(
ntfs *NTFSContext, attr_type uint64, attr_id uint16) (*NTFS_ATTRIBUTE, error) {
offset := int64(self.Attribute_offset())

for {
// Instantiate the attribute over the fixed up address space.
attribute := self.Profile.NTFS_ATTRIBUTE(self.Reader, offset)

// Reached the end of the MFT entry.
mft_size := int64(self.Mft_entry_size())
attribute_size := int64(attribute.Length())
if attribute_size == 0 ||
attribute_size+offset > mft_size {
break
}

if attribute.Type().Value == attr_type &&
attribute.Attribute_id() == attr_id {
return attribute, nil
}

// Go to the next attribute.
offset += int64(attribute.Length())
}
return nil, errors.New("No attribute found.")
}

// Open the MFT entry specified by a path name. Walks all directory
// indexes in the path to find the right MFT entry.
func (self *MFT_ENTRY) Open(ntfs *NTFSContext, filename string) (*MFT_ENTRY, error) {
Expand Down