2025_02 실수로 덮어쓴 파일 복구
실수
## 원래 의도 # virsh dumpxml engine > engine.ovirt1.xml ## 잘못 실행된 명령 # virsh dumpxml engine > engine.ovirt1.qcow2 ## 원래 파일 용량 약 30GB # ls -alht engine.ovirt1* -rw-r--r--. 1 qemu qemu 6.8K 2025-02-26 Wed 05:06:48 engine.ovirt1.qcow2 -rw-r--r--. 1 root root 9.6K 2025-02-26 Wed 05:03:52 engine.ovirt1.xml
QnA ext4 파일시스템 덮어쓰기 방식 by (Claude 3 Sonet)
Q
CentOS8 이고 ext4 파일 시스템이야
30GB 짜리 engine.ovirt1.qcow2 가 있어
내가 잘못해서 echo XML > engine.ovirt1.qcow2 을 했어
이 때, 새로운 inode 에 내용을 작성하고 링크만 바꾸는 식으로 파일을 관리해?
아니면 engine.ovirt1.qcow2 의 시작 섹터에 내용을 바꿔버려?
A
파일 시스템이 ext4이고 echo XML > engine.ovirt1.qcow2 명령을 실행했을 때 일어나는 일은 두 번째 경우입니다. 이 명령은 기존 파일의 시작 부분에 새 내용을 덮어씁니다.
이 명령이 실행되면 다음과 같은 일이 발생합니다:
파일 시스템은 새로운 inode를 생성하지 않습니다.
기존 engine.ovirt1.qcow2 파일의 동일한 inode를 유지합니다.
파일의 크기를 XML 문자열 길이로 줄이고(truncate), 기존 파일의 처음 몇 바이트를 XML 내용으로 덮어씁니다.
원본 파일의 나머지 데이터는 디스크에 물리적으로 여전히 존재할 수 있지만, 논리적으로는 더 이상 파일의 일부로 간주되지 않습니다.
이것이 데이터 복구가 가능할 수도 있는 이유입니다. 원본 데이터의 대부분이 물리적으로 디스크에 여전히 존재하지만, 파일 시스템에서는 그 데이터를 접근할 수 없게 됩니다. 파일의 크기가 줄어들었기 때문에, 파일 시스템은 크기를 넘어선 데이터를 "없는" 것으로 취급합니다.
복구의 핵심은 파일 시스템이 아닌 디스크 섹터 레벨에서 직접 데이터에 접근하는 방법을 찾는 것입니다.
파일 섹터 확인
Q
특정 파일의 시작 블럭번호와 끝 블럭번호를 아는 방법
A
filefrag -v 파일경로 # 이 명령어는 파일의 각 조각(extent)이 어디에 위치하는지 자세히 보여줍니다. hdparm --fibmap 파일경로 # 이 명령어는 파일의 실제 물리적 블록 위치를 보여줍니다.
Run
# filefrag -v engine.ovirt1.qcow2 Filesystem type is: 58465342 File size of engine.ovirt1.qcow2 is 6941 (2 blocks of 4096 bytes) ext: logical_offset: physical_offset: length: expected: flags: 0: 0.. 1: 56952621.. 56952622: 2: last,eof engine.ovirt1.qcow2: 1 extent found # hdparm --fibmap engine.ovirt1.qcow2 engine.ovirt1.qcow2: filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors. byte_offset begin_LBA end_LBA sectors 0 455620968 455620983 16 잘못 덮혀진 파일이거든 이걸 시작부터 40GB 영역을 dd로 떠서 /mnt/usb2/sectors.bin 에 옮겨주고 파일시스템의 흔적을 찾아줘
섹터 백업
Q
이 파일의 시작부터 40GB 영역을 dd로 떠서 /mnt/usb2/sectors.bin 에 옮겨주고 파일시스템의 흔적을 찾아줘
A
네, 파일의 물리적 위치 정보를 확인했고 이제 해당 영역을 dd로 백업한 후 복구 과정을 진행해 보겠습니다.
# 40GB 복사 (hdparm에서 찾은 시작 LBA 사용) dd if=/dev/sdX of=/mnt/usb2/sectors.bin bs=512 skip=455620968 count=83886080 # (40GB = 83886080 * 512 바이트 섹터)
Q
파일시스템과 마운트 정보는 다음과 같아. input을 수정해줘
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 931G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 930G 0 part ├─cl-root 253:0 0 866.5G 0 lvm / └─cl-home 253:2 0 32G 0 lvm /home sdb 8:16 1 239G 0 disk └─sdb1 8:17 1 239G 0 part /mnt/usb2 # cat /etc/fstab /dev/mapper/cl-root / xfs defaults 0 0 /dev/mapper/cl-home /home xfs defaults 0 0
A
dd if=/dev/mapper/cl-root of=/mnt/usb2/sectors.bin bs=512 skip=455620968 count=83886080 status=progress
QFI 시그니처 찾기
A
이제 이 백업 파일에서 qcow2 파일의 흔적을 찾아보겠습니다:
# qcow2 헤더 찾기 (QFI 시그니처) hexdump -C /mnt/usb2/sectors.bin | head -20 # 또는 바이너리 검색 grep -a -b "QFI\xfb" /mnt/usb2/sectors.bin
RUN
QFI 시그니처 찾기 실패
XFS 시그니처 찾기
Q
xfs 파일 시스템의 흔적을 찾아보려는데
A
# sectors.bin에서 XFSB 패턴 재확인 hexdump -C /mnt/usb2/sectors.bin | grep -A 4 "58 46 53 42"
Run
# hexdump -C /mnt/usb2/sectors.bin | grep -A 4 "58 46 53 42" 02f20000 58 46 53 42 00 00 10 00 00 00 00 00 00 1f ff 00 |XFSB............| 02f20010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 02f20020 44 a6 a6 13 4e 21 47 8b a9 09 ab 65 3c 9d 39 df |D...N!G....e<.9.| 02f20030 00 00 00 00 00 10 00 04 00 00 00 00 00 00 00 40 |...............@|
XFS 파일시스템 추출
Q
이걸 바탕으로 xfs 파일시스템을 추출할 수 있어?
A
# sectors.bin에서 발견된 위치부터 XFS 파일시스템 추출 dd if=/mnt/usb2/sectors.bin of=/mnt/usb2/xfs_extracted.img bs=512 skip=96768 # 추출된 이미지 마운트해보기 mkdir /mnt/xfs_test mount -t xfs -o loop,ro /mnt/usb2/xfs_extracted.img /mnt/xfs_test