🔐

03. boot.img를 풀었다가 다시 만들면 왜 같은 파일이 나오지 않는가

단계
Boot & AVB
상태
완료
순서
3
시기
2024.06.03–06.04
요약
mkbootimg·ramdisk·header·offset과 byte comparison을 통해 재패키징 불일치 문제를 좁혔다.
🔐
이 글의 질문 · 원본 boot.img를 풀었다가 그대로 다시 만들었는데 왜 동일한 파일이 나오지 않는가?

boot.img 안의 kernel과 ramdisk

bootloader는 boot.img를 읽어 kernel과 ramdisk를 메모리에 올린다. ramdisk, 즉 initramfs는 kernel이 처음 root filesystem으로 사용하는 영역이고, 그 안의 init은 fstab에 따라 초기 mount를 수행한다.
기존 firmware의 boot.img를 unmkbootimg로 분리했다.
unmkbootimg --input boot.img \ --kernel kernel.img \ --ramdisk ramdisk.cpio.gz kernel written to 'kernel.img' (24627216 bytes) ramdisk written to 'ramdisk.cpio.gz' (743509 bytes)
tool이 출력한 재조립 명령은 다음과 같았다.
mkbootimg --base 0 --pagesize 2048 --board SRPVD01I001 \ --kernel_offset 0x10008000 \ --ramdisk_offset 0x10000000 \ --second_offset 0x00000000 \ --tags_offset 0x10000000 \ --kernel kernel.img \ --ramdisk ramdisk.cpio.gz \ -o boot1.img
kernel과 ramdisk를 수정하지 않고 그대로 다시 합쳤다. 당연히 같은 파일이 나올 것이라고 생각했다.

발표자료에서 정리한 판단 근거

mkbootimg·unmkbootimg 가설과 AVB 문제의 발견 (중간발표 슬라이드 21–30)
mkbootimg·unmkbootimg 가설과 AVB 문제의 발견 (중간발표 슬라이드 21–30)

첫 번째 차이: byte 41

cmp boot1.img boot.img boot1.img boot.img differ: byte 41, line 1
차이가 파일의 아주 앞부분에서 발생했기 때문에 처음에는 시간이나 header의 부가 정보라고 생각했다. hex editor로 해당 byte를 맞춘 뒤 다시 비교했다.
cmp boot1.img boot.img boot1.img boot.img differ: byte 577, line 1
다시 수정한 뒤에는 차이가 byte 1645로 이동했다. 한 byte를 맞추는 문제가 아니라 header와 정렬, offset, 또는 mkbootimg 구현 자체가 달라 발생하는 문제였다.

당시 세운 원인 가설

  • 사용한 mkbootimg tool이 오래되어 firmware를 만든 버전과 다를 수 있다.
  • unmkbootimg가 출력한 offset만으로는 Samsung boot.img의 모든 header 정보를 복원하지 못할 수 있다.
  • kernel이나 ramdisk가 아니라 padding·alignment·header field에서 차이가 날 수 있다.
  • 동일한 의미의 boot image라도 binary 전체가 byte-for-byte 동일하지 않을 수 있다.
6월 4일 회의에서는 이 문제를 다음처럼 정리했다.
mkbootimg로 다시 합친 이미지가 원본과 다르다. 정확한 offset을 찾는 것과 AVB를 우회하는 것, 두 가지를 따로 해결해야 한다.
6월 24일에는 repacked file을 실제로 flashing해서 반응을 확인하는 방향도 제시했다. 단순 binary diff만 계속 보는 것이 아니라, 그 차이가 실제 boot에 영향을 주는 차이인지 확인하려는 것이었다.

문제를 둘로 분리하기

boot.img를 다시 만드는 문제와, 다시 만든 boot.img를 장치가 받아들이는 문제는 같지 않았다. 다음 단계부터는 두 번째 문제인 AVB와 vbmeta를 따로 분석하기 시작했다.