From cc00bf8d240f8c2b63e0bdc9c34970b85a82468f Mon Sep 17 00:00:00 2001 From: Claudio Matsuoka Date: Sat, 6 Jan 2024 22:40:05 -0300 Subject: [PATCH 1/2] Add option to list cluster chains When option -@ is used to get cluster information, show the list of cluster chains if option -n is also specified. Signed-off-by: Claudio Matsuoka --- man/fatcat.1 | 8 +++++++- src/analysis/FatChains.cpp | 10 ++++++++-- src/analysis/FatChains.h | 4 +++- src/fatcat.cpp | 23 +++++++++++++++++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/man/fatcat.1 b/man/fatcat.1 index 8984fe8..c1c4e24 100644 --- a/man/fatcat.1 +++ b/man/fatcat.1 @@ -76,7 +76,13 @@ be unreadable. .RS 4 This will display information about the given \fBcluster\fP. It will display its address, which is the offset of the cluster in the image, and the FAT entries (next cluster, unallocated -or end of cluster) +or end of cluster). A list of cluster chains is displayed if \fB-n\fB is used. +.RE + +.PP +\fB\-n\fP +.RS 4 +List cluster chains when displaying cluster information. .RE .PP diff --git a/src/analysis/FatChains.cpp b/src/analysis/FatChains.cpp index a51e396..8ad6947 100644 --- a/src/analysis/FatChains.cpp +++ b/src/analysis/FatChains.cpp @@ -306,7 +306,7 @@ void FatChains::displayOrphaned(list orphanedChains) cout << endl; } -int FatChains::chainSize(int cluster, bool *isContiguous) +int FatChains::chainSize(int cluster, bool *isContiguous, list& segments) { set visited; int length = 0; @@ -316,15 +316,21 @@ int FatChains::chainSize(int cluster, bool *isContiguous) *isContiguous = true; } + int start = cluster; + do { stop = true; int currentCluster = cluster; visited.insert(cluster); length++; cluster = system.nextCluster(cluster); - if (system.validCluster(cluster) && cluster!=FAT_LAST) { + if (cluster==FAT_LAST) { + segments.push_back(pair(start, currentCluster)); + } else if (system.validCluster(cluster)) { if (currentCluster+1 != cluster && isContiguous != NULL) { *isContiguous = false; + segments.push_back(pair(start, currentCluster)); + start = cluster; } if (visited.find(cluster) != visited.end()) { cerr << "! Loop detected, " << currentCluster << " points to " << cluster << " that I already met" << endl; diff --git a/src/analysis/FatChains.h b/src/analysis/FatChains.h index b6180c2..cf012f0 100644 --- a/src/analysis/FatChains.h +++ b/src/analysis/FatChains.h @@ -14,6 +14,8 @@ using namespace std; +typedef pair Segment; + class FatChains : public FatModule { public: @@ -55,7 +57,7 @@ class FatChains : public FatModule /** * Size of a chain in the FAT */ - int chainSize(int cluster, bool *isContiguous); + int chainSize(int cluster, bool *isContiguous, list& segments); protected: bool saveEntries; diff --git a/src/fatcat.cpp b/src/fatcat.cpp index ce23ca0..fea8a16 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -52,6 +52,7 @@ void usage() cout << endl; cout << "FAT Hacking" << endl; cout << " -@ [cluster]: Get the cluster address and information" << endl; + cout << " -n: enable listing of cluster chains in cluster information" << endl; cout << " -2: analysis & compare the 2 FATs" << endl; cout << " -b [file]: backup the FATs (see -t)" << endl; cout << "* -p [file]: restore (patch) the FATs (see -t)" << endl; @@ -117,6 +118,9 @@ int main(int argc, char *argv[]) // -@: get the cluster address bool address = false; + // -n: list cluster chains + bool showChains = false; + // -k: analysis the chains bool chains = false; @@ -158,7 +162,7 @@ int main(int argc, char *argv[]) OutputFormatType outputFormat = Default; // Parsing command line - while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:ob:p:w:v:mt:Sze:O:fk:a:F:")) != -1) { + while ((index = getopt(argc, argv, "il:L:r:R:s:dc:hx:2@:nob:p:w:v:mt:Sze:O:fk:a:F:")) != -1) { switch (index) { case 'a': attributesProvided = true; @@ -202,6 +206,9 @@ int main(int argc, char *argv[]) address = true; cluster = ATOU(optarg); break; + case 'n': + showChains = true; + break; case 'o': chains = true; break; @@ -329,13 +336,25 @@ int main(int argc, char *argv[]) bool isContiguous = false; FatChains chains(fat); - unsigned long long size = chains.chainSize(cluster, &isContiguous); + list segments; + unsigned long long size = chains.chainSize(cluster, &isContiguous, segments); printf("Chain size: %llu (%llu / %s)\n", size, size*fat.bytesPerCluster, prettySize(size*fat.bytesPerCluster).c_str()); if (isContiguous) { printf("Chain is contiguous\n"); } else { printf("Chain is not contiguous\n"); } + + if (showChains) { + list::iterator it; + int num=1; + for (it=segments.begin(); it != segments.end(); num++,it++) { + int start = it->first; + int end = it->second; + int size = end - start + 1; + printf("Chain %d: %d..%d (%d clusters)\n", num, start, end, size); + } + } } else if (chains) { FatChains chains(fat); chains.chainsAnalysis(); From a5b33d60d169b0d2eace73de6b3cc58fd243a2d7 Mon Sep 17 00:00:00 2001 From: Claudio Matsuoka Date: Sun, 7 Jan 2024 18:31:03 -0300 Subject: [PATCH 2/2] Remove redundant contiguous chain parameter Use the cluster chain lists to determine whether the data allocation is contiguous. Signed-off-by: Claudio Matsuoka --- src/analysis/FatChains.cpp | 10 ++-------- src/analysis/FatChains.h | 2 +- src/fatcat.cpp | 5 ++--- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/analysis/FatChains.cpp b/src/analysis/FatChains.cpp index 8ad6947..71c3954 100644 --- a/src/analysis/FatChains.cpp +++ b/src/analysis/FatChains.cpp @@ -306,16 +306,11 @@ void FatChains::displayOrphaned(list orphanedChains) cout << endl; } -int FatChains::chainSize(int cluster, bool *isContiguous, list& segments) +int FatChains::chainSize(int cluster, list& segments) { set visited; int length = 0; bool stop; - - if (isContiguous != NULL) { - *isContiguous = true; - } - int start = cluster; do { @@ -327,8 +322,7 @@ int FatChains::chainSize(int cluster, bool *isContiguous, list& segment if (cluster==FAT_LAST) { segments.push_back(pair(start, currentCluster)); } else if (system.validCluster(cluster)) { - if (currentCluster+1 != cluster && isContiguous != NULL) { - *isContiguous = false; + if (currentCluster+1 != cluster) { segments.push_back(pair(start, currentCluster)); start = cluster; } diff --git a/src/analysis/FatChains.h b/src/analysis/FatChains.h index cf012f0..59e657f 100644 --- a/src/analysis/FatChains.h +++ b/src/analysis/FatChains.h @@ -57,7 +57,7 @@ class FatChains : public FatModule /** * Size of a chain in the FAT */ - int chainSize(int cluster, bool *isContiguous, list& segments); + int chainSize(int cluster, list& segments); protected: bool saveEntries; diff --git a/src/fatcat.cpp b/src/fatcat.cpp index fea8a16..35855b5 100644 --- a/src/fatcat.cpp +++ b/src/fatcat.cpp @@ -333,13 +333,12 @@ int main(int argc, char *argv[]) int next2 = fat.nextCluster(cluster, 1); printf("FAT1: %u (%08x)\n", next1, next1); printf("FAT2: %u (%08x)\n", next2, next2); - bool isContiguous = false; FatChains chains(fat); list segments; - unsigned long long size = chains.chainSize(cluster, &isContiguous, segments); + unsigned long long size = chains.chainSize(cluster, segments); printf("Chain size: %llu (%llu / %s)\n", size, size*fat.bytesPerCluster, prettySize(size*fat.bytesPerCluster).c_str()); - if (isContiguous) { + if (segments.size() < 2) { printf("Chain is contiguous\n"); } else { printf("Chain is not contiguous\n");