정보보안(49회차) 노트


수동 분석

분석하려는 ence 라는 파일의 mbr은 누가 의도적으로 손상시킴
>mbr의 크기는 512(446 + 64(파티션테이블) + 2(시그니쳐)) 바이트임.
-63섹터, 4306239섹터에 vbr과 시그니쳐가 존재하지만 파티션 테이블이 공백임
--그러니 저 두 섹터위치 값을 16 진수로 변환하고 파티션 테이블의 오프셋 ** 에 넣어준다.
클릭하여 fix_mbr.py 코드 보기
					
					
					
					"""
fix_mbr.py

이미지 파일의 MBR 파티션 테이블에서 1번과 2번 파티션의 start LBA와 섹터 수를 채워 새로운 이미지로 저장합니다.

기본 동작:
  - 1번 파티션 start LBA = 63
  - 2번 파티션 start LBA = 4306239
  - 1번 섹터 수 = 2번 start - 1번 start
  - 2번 섹터 수 = 디스크 총 섹터 수 - 2번 start

사용법:
  python fix_mbr.py 260607_ence.001
  python fix_mbr.py input.001 -o output.001 --p1 63 --p2 4306239 --p1-type 0x83 --p2-type 0x83
"""

from __future__ import annotations

import argparse
import shutil
import struct
import sys
from pathlib import Path


def update_image_stream(inp: Path, outp: Path, new_first_sector: bytes) -> None:
    """첫 섹터(new_first_sector)를 교체하고 나머지는 스트리밍으로 복사합니다."""
    with inp.open('rb') as fr, outp.open('wb') as fw:
        fw.write(new_first_sector)
        # fr is at pos 0; advance to 512
        fr.seek(512)
        shutil.copyfileobj(fr, fw)


def update_partition_entry(mbr: bytearray, index: int, start_lba: int, num_sectors: int, part_type: int = 0x83, boot_flag: int = 0x00) -> None:
    table_off = 0x1BE
    off = table_off + index * 16
    # boot flag
    mbr[off] = boot_flag & 0xFF
    # CHS start (leave zero)
    mbr[off + 1:off + 4] = b"\x00\x00\x00"
    # type
    mbr[off + 4] = part_type & 0xFF
    # CHS end (leave zero)
    mbr[off + 5:off + 8] = b"\x00\x00\x00"
    # start LBA
    mbr[off + 8:off + 12] = struct.pack('<I', start_lba)
    # number of sectors
    mbr[off + 12:off + 16] = struct.pack('<I', num_sectors)


def main(argv=None):
    p = argparse.ArgumentParser(description='Fix MBR partition starts and sizes')
    p.add_argument('input', help='입력 이미지 파일')
    p.add_argument('-o', '--output', help='수정된 이미지 출력 파일 (기본: <input>.fixed.001)')
    p.add_argument('--p1', type=int, default=63, help='1번 파티션 start LBA (default=63)')
    p.add_argument('--p2', type=int, default=4306239, help='2번 파티션 start LBA (default=4306239)')
    p.add_argument('--p1-type', type=lambda x: int(x, 0), default=0x83, help='1번 파티션 타입 (hex/dec, default=0x83)')
    p.add_argument('--p2-type', type=lambda x: int(x, 0), default=0x83, help='2번 파티션 타입 (hex/dec, default=0x83)')
    args = p.parse_args(argv)

    inp = Path(args.input)
    if not inp.exists():
        print('Input file not found:', inp, file=sys.stderr)
        return 2

    outp = Path(args.output) if args.output else inp.with_name(inp.stem + '.fixed' + inp.suffix)
    bakp = inp.with_suffix(inp.suffix + '.bak')

    # backup
    shutil.copy2(inp, bakp)
    print(f'Backup created: {bakp}')

    size = inp.stat().st_size
    if size < 512:
        print('Input image too small (<512 bytes)', file=sys.stderr)
        return 3
    total_sectors = size // 512

    p1_start = args.p1
    p2_start = args.p2
    if not (0 <= p1_start < total_sectors and 0 <= p2_start < total_sectors):
        print('Start LBA values out of range for this image', file=sys.stderr)
        return 4

    if p2_start <= p1_start:
        print('p2 start must be greater than p1 start', file=sys.stderr)
        return 5

    p1_sectors = p2_start - p1_start
    p2_sectors = total_sectors - p2_start

    # Read only first sector, modify it, then stream-copy remainder
    with inp.open('rb') as fr:
        first = bytearray(fr.read(512))
    # Update partition entries 0 and 1 in the first sector
    update_partition_entry(first, 0, p1_start, p1_sectors, part_type=args.p1_type, boot_flag=0x00)
    update_partition_entry(first, 1, p2_start, p2_sectors, part_type=args.p2_type, boot_flag=0x00)
    # Ensure boot signature exists
    first[510:512] = b"\x55\xAA"

    # Stream out
    update_image_stream(inp, outp, bytes(first))
    print(f'Wrote fixed image: {outp}')
    print(f'Partition 1: start={p1_start}, sectors={p1_sectors}')
    print(f'Partition 2: start={p2_start}, sectors={p2_sectors}')
    return 0


if __name__ == '__main__':
    raise SystemExit(main())					


이 코드의 중요한 부분
이미지 파일의 MBR 파티션 테이블에서 1번과 2번 파티션의 start LBA와 섹터 수를 채워 새로운 이미지로 저장합니다.
기본 동작:
- 1번 파티션 start LBA = 63
- 2번 파티션 start LBA = 4306239
- 1번 섹터 수 = 2번 start - 1번 start
- 2번 섹터 수 = 디스크 총 섹터 수 - 2번 start

----------------------------------------------
자동 분석
비정상적인 파일시스템을 정상으로 바꿔주는 파이썬 프로그램을 만들어보자!
1. 물리적인 하드 디스크를 연결 할 수 있다.
2. 데이터를 읽을 수 있다.