void ProjectExplorerWindow::RemoveFileSymbols(wxTreeItemId node, const stdext::hash_set<Project::File*>& fileSet) { ItemData* data = static_cast<ItemData*>(m_tree->GetItemData(node)); if (data != NULL && data->isFile && fileSet.find((Project::File *)data->file) != fileSet.end()) { m_tree->Delete(node); } else { // Recurse into the children. wxTreeItemIdValue cookie; wxTreeItemId child = m_tree->GetFirstChild(node, cookie); while (child.IsOk()) { wxTreeItemId next = m_tree->GetNextChild(node, cookie); RemoveFileSymbols(child, fileSet); child = next; } } }
/** @brief 클러스터의 후보들 중 현재 클러스터에 가장 적합하게 연결될 클러스터를 찾는다 @param inClusterNo 현재 클러스터 번호 @param inClusterCandidates 뒤에 연결될 클러스터의 후보 @param inClustersHaveRecord 레코드를 가지고 있는 클러스터 @param outAlreadyAddedCluster 클러스터 후보들중에 이미 추가되기로 결정된 클러스터가 있는지 여부 */ std::vector<uint64_t> ClusterReassembler::findBestMatchingClusters(uint64_t inClusterNo, std::vector<CLUSTER_INFO>& inClusterCandidates, const stdext::hash_set<uint64_t>& inClustersHaveRecord, bool& outAlreadyAddedCluster) { std::vector<uint64_t> resultClusters; uint8_t clusterBuffer[CLUSTER_SIZE] = {0,}; uint8_t* mergedClusterBuffer = NULL; uint32_t clusterCandidateIndex = 0; uint32_t recordPos = 0; uint32_t nextClusterBufferPos = 0; outAlreadyAddedCluster = false; for (clusterCandidateIndex = 0; clusterCandidateIndex < inClusterCandidates.size(); ++clusterCandidateIndex) { if (inClusterNo == inClusterCandidates[clusterCandidateIndex].clusterNo) { outAlreadyAddedCluster = true; break; } } if (!outAlreadyAddedCluster) { nextClusterBufferPos = CLUSTER_SIZE; fragmentedFile_.readData(inClusterNo * CLUSTER_SIZE, clusterBuffer, CLUSTER_SIZE); uint32_t lastRecordPos = 0; EVTX_RECORD_HEADER* lastRecord = NULL; // 현재 클러스터에서(1클러스터) 가장 마지막 레코드를 찾는다 for (recordPos = 0; recordPos < CLUSTER_SIZE - EVTX_RECORD_HEADER_SIZE; recordPos += 8) { if (EvtxRecordValidator::isValidRecordHeader(clusterBuffer + recordPos)) { lastRecordPos = recordPos; break; } } lastRecord = (EVTX_RECORD_HEADER*)(clusterBuffer + lastRecordPos); // 가장 마지막 레코드가 3개 이상의 클러스터에 걸쳐져 있으면 if (lastRecordPos + lastRecord->length1 > CLUSTER_SIZE * 2) { uint32_t needClusterCount = 0; uint64_t checkClusterNo = 0; bool clustersHaveNoRecord = true; if (lastRecordPos + lastRecord->length1 % CLUSTER_SIZE == 0) { needClusterCount = ((lastRecordPos + lastRecord->length1) - CLUSTER_SIZE) / CLUSTER_SIZE; } else { needClusterCount = ((lastRecordPos + lastRecord->length1) - CLUSTER_SIZE) / CLUSTER_SIZE + 1; } mergedClusterBuffer = new uint8_t[CLUSTER_SIZE * (needClusterCount + 2)]; for (checkClusterNo = inClusterNo + 1; checkClusterNo < inClusterNo + 1 + needClusterCount; ++checkClusterNo) { if (inClustersHaveRecord.find(checkClusterNo) != inClustersHaveRecord.end()) { clustersHaveNoRecord = false; break; } } // 어쩔수 없이 레코드의 클러스터들이 연속되어 있다고 가정하고 맨처음과 마지막을 뺀 중간 클러스터 데이터들을 정한다 if (clustersHaveNoRecord) { for (uint64_t insertClusterNo = inClusterNo + 1; insertClusterNo < inClusterNo + 1 + needClusterCount; ++insertClusterNo) { resultClusters.push_back(insertClusterNo); fragmentedFile_.readData(insertClusterNo * CLUSTER_SIZE, mergedClusterBuffer + nextClusterBufferPos, CLUSTER_SIZE); nextClusterBufferPos += CLUSTER_SIZE; } } } else { mergedClusterBuffer = new uint8_t[CLUSTER_SIZE * 2]; } memcpy(mergedClusterBuffer, clusterBuffer, CLUSTER_SIZE); // 이어붙일 클러스터 후보군에 대하여 for (clusterCandidateIndex = 0; clusterCandidateIndex < inClusterCandidates.size(); ++clusterCandidateIndex) { uint32_t mergedLastRecordPos = 0; EVTX_RECORD_HEADER* mergedLastRecord = NULL; // 실제로 클러스터들을 조립하여 보고 fragmentedFile_.readData(inClusterCandidates[clusterCandidateIndex].clusterNo * CLUSTER_SIZE, (mergedClusterBuffer + nextClusterBufferPos), CLUSTER_SIZE); for (recordPos = 0; recordPos < CLUSTER_SIZE; recordPos += 8) { if (EvtxRecordValidator::isValidRecordHeader(mergedClusterBuffer + recordPos)) { mergedLastRecordPos = recordPos; break; } } // 올바른 레코드가 되는지 확인하여 올바른 레코드가 되면 가장 적합한 클러스터라 정한다 if (EvtxRecordValidator::isValidRecord(mergedClusterBuffer + mergedLastRecordPos, nextClusterBufferPos + CLUSTER_SIZE - mergedLastRecordPos)) { mergedLastRecord = (EVTX_RECORD_HEADER*)(mergedClusterBuffer + mergedLastRecordPos); uint32_t parseSize = 0; BinXmlStream xmlStream(mergedClusterBuffer + mergedLastRecordPos + EVTX_RECORD_HEADER_SIZE, (mergedLastRecord->length1 - 0x1C > nextClusterBufferPos) ? nextClusterBufferPos : (mergedLastRecord->length1 - 0x1C), mergedLastRecord->numLogRecord); xmlStream.parse(&parseSize); if (parseSize > nextClusterBufferPos || mergedLastRecord->length1 - 0x1C - parseSize < 8) { resultClusters.push_back(inClusterCandidates[clusterCandidateIndex].clusterNo); break; } } } if (mergedClusterBuffer != NULL) { delete [] mergedClusterBuffer; } } return resultClusters; }
/** @brief 파일로부터 레코드의 정보들을 모은다 @param inRecordCarvedAreas 스킵할 영역 @param outRecordInfoMap 클러스터 번호 / 레코드정보 쌍으로 된 맵 @param outClustersHaveRecord 레코드를 가지고 있는 클러스터들 */ void ClusterReassembler::buildRecordInfoMap(CarvedAreas& inCarvedAreas, RecordInfoMap& outRecordInfoMap, stdext::hash_set<uint64_t>& outClustersHaveRecord) { SignatureFinder recordHeaderFinder(fragmentedFile_, EVTX_RECORD_HEADER_MAGIC, 4, 8, &inCarvedAreas, EVTX_RECORD_HEADER_SIZE); uint8_t* recordBuffer = NULL; EVTX_RECORD_HEADER* evtxRecordHeader = NULL; uint64_t foundFilePos = 0; uint64_t clusterNumber = 0; uint32_t clusterCrc = 0; uint8_t clusterBuffer[CLUSTER_SIZE] = {0,}; uint32_t clusterIndex = 0; outClustersHaveRecord.clear(); while ((recordBuffer = recordHeaderFinder.getNext(&foundFilePos)) != NULL) { evtxRecordHeader = (EVTX_RECORD_HEADER*)recordBuffer; if (EvtxRecordValidator::isValidRecordHeader(recordBuffer)) { clusterNumber = foundFilePos / CLUSTER_SIZE; fragmentedFile_.readData(clusterNumber * CLUSTER_SIZE, clusterBuffer, CLUSTER_SIZE); clusterCrc = update_crc32(0, clusterBuffer, CLUSTER_SIZE); if (outClustersHaveRecord.find(clusterNumber) == outClustersHaveRecord.end()) { outClustersHaveRecord.insert(clusterNumber); } // 레코드와 클러스터를 매핑중 중복된 레코드 아이디가 있으면 if (outRecordInfoMap.find(evtxRecordHeader->numLogRecord) != outRecordInfoMap.end()) { bool crcFound = false; // 클러스터의 crc를 비교하여 없는 crc이면 해당 클러스터를 레코드 아이디의 클러스터 후보군에 추가 for (clusterIndex = 0; clusterIndex < outRecordInfoMap[evtxRecordHeader->numLogRecord].size(); ++clusterIndex) { if (outRecordInfoMap[evtxRecordHeader->numLogRecord][clusterIndex].clusterCrc == clusterCrc) { crcFound = true; break; } } if (!crcFound) { outRecordInfoMap[evtxRecordHeader->numLogRecord].push_back(CLUSTER_INFO(clusterNumber, clusterCrc)); } } else { std::vector<CLUSTER_INFO> clusterInfos; clusterInfos.push_back(CLUSTER_INFO(clusterNumber, clusterCrc)); outRecordInfoMap[evtxRecordHeader->numLogRecord] = clusterInfos; } } } recordHeaderFinder.closeMap(); }