graf

10. 파일 구조 확인 본문

RSW-725R/분석 자료 (공개용)

10. 파일 구조 확인

graf 2026. 4. 22. 10:25

갑자기 든 의문인데 

이 장치를 오랫동안 분석하면서 느낀 점은, 
장치의 보안 설계가 그닥 치밀하지 않다는 점이다. 

 

그런데 굳이 인증서랑 개인키만 암호화해놓았다는 가정이 이해가 되질 않는다. 

그리고 데이터가 헤더 쪽만 살아있고 뒷부분이 파싱이 안됐는데 
오히려 검출이 안되게 하려면 헤더만 암호화하는게 나았지 않았을까? 

 

이렇게 생각하니 뭔가 이상하다. 
내가 파싱을 잘못한건 아닐까? 
아님 내가 뭔가 실수를 했던건 아닐까..? 

 

 

$ binwalk ./esp_backup.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
402130        0x622D2         AES Inverse S-Box
402386        0x623D2         AES S-Box
411384        0x646F8         SHA256 hash constants, little endian
1049093       0x100205        Certificate in DER format (x509 v3), header length: 4, sequence length: 833
1051141       0x100A05        Certificate in DER format (x509 v3), header length: 4, sequence length: 857
1053189       0x101205        Private key in DER format (PKCS header length: 4, sequence length: 1188

 

이게 빈워크가 찾은 인증서와 개인키 위치인데 

 

 

해당 위치로 가보면 뭔가 잘려있는 듯한 구조가 보이고 
맨 뒤에 파일명이 들어가있었다. 

 

 

000002e0  31 54 fc 42 d3 c7 46 1f  23 ad d9 0f 48 70 9a d9  |1T.B..F.#...Hp..|
000002f0  75 78 71 d1 72 43 34 75  6e 57 59 01 80 00 00 7e  |uxq.rC4unWY....~|
00000300  00 ec fd 00 02 00 00 01  2f 63 61 2e 64 65 72 00  |......../ca.der.|
00000310  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  00 02 00 03 00 04 00 ff  |................|
00000330  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000340  ff ff ff ff ff                                    |.....|
00000345

 

이게 이상이 있다고 생각했던 인증서 뒷 부분인데 
암호화라기엔 너무 허술하지 않나? 
오히려 뭔가 패딩에 가까워보이는데? 

혹시 자동으로 파싱 안되게 크기 정보만 건든건가? 

 

 

$ strings -t x ./esp_backup.bin | grep "ca.der"
   /ca.der
  /ca.der
  /ca.der
  /ca.der
  /ca.der

 

근데 파일명을 찾아보면 단순 리터럴이라기엔 이상할 정도로 많이 나온단 말이지? 

이거 펌웨어가 사용하는 나름의 파일 시스템이 있어서 
파일이 연속 공간에 들어간게 아니라 분할 저장돼있는거 아니야? 

 

한번 파일명 나오는 지점 다 확인해보자. 

 

 

1. 블록 구조 확인

   61 64 65 64 00 2f 63 61  2e 64 65 72 00 70 72 69  |aded./ca.der.pri|
   76 61 74 65 20 6b 65 79  20 6e 6f 74 20 6c 6f 61  |vate key not loa|

   01 80 00 00 7e 00 ec fd  00 01 00 00 01 2f 63 61  |....~......../ca|
   2e 64 65 72 00 00 00 00  00 00 00 00 00 00 00 00  |.der............|

   01 80 00 00 7e 00 ec fd  00 02 00 00 01 2f 63 61  |....~......../ca|
   2e 64 65 72 00 00 00 00  00 00 00 00 00 00 00 00  |.der............|

   01 80 00 00 7e 00 ec fd  00 03 00 00 01 2f 63 61  |....~......../ca|
   2e 64 65 72 00 00 00 00  00 00 00 00 00 00 00 00  |.der............|

   01 80 00 00 f8 00 ec fd  45 03 00 00 01 2f 63 61  |........E..../ca|
   2e 64 65 72 00 00 00 00  00 00 00 00 00 00 00 00  |.der............|

 

파일 명이 나오는 곳을 다 모아봤는데 전부 형태가 같다.. 
심지어 인덱스 번호로 추정되는 것도 보인다. 

 

이거 완전 전형적인 블록 파일 시스템 구조잖아. 
젠장 왜 이걸 생각 못했지?? 

 

개인키 쪽도 확인해보자. 

 

   64 00 2f 70 72 69 76 61  74 65 2e 64 65 72 00 63  |d./private.der.c|
   65 72 74 20 6e 6f 74 20  6c 6f 61 64 65 64 00 46  |ert not loaded.F|

   03 80 00 00 7e 00 ec fd  00 01 00 00 01 2f 70 72  |....~......../pr|
   69 76 61 74 65 2e 64 65  72 00 00 00 00 00 00 00  |ivate.der.......|

   03 80 00 00 7e 00 ec fd  00 02 00 00 01 2f 70 72  |....~......../pr|
   69 76 61 74 65 2e 64 65  72 00 00 00 00 00 00 00  |ivate.der.......|

   03 80 00 00 7e 00 ec fd  00 03 00 00 01 2f 70 72  |....~......../pr|
   69 76 61 74 65 2e 64 65  72 00 00 00 00 00 00 00  |ivate.der.......|

   03 80 00 00 7e 00 ec fd  00 04 00 00 01 2f 70 72  |....~......../pr|
   69 76 61 74 65 2e 64 65  72 00 00 00 00 00 00 00  |ivate.der.......|

   03 80 00 00 f8 00 ec fd  a8 04 00 00 01 2f 70 72  |............./pr|
   69 76 61 74 65 2e 64 65  72 00 00 00 00 00 00 00  |ivate.der.......|

 

맞네.. 똑같네... 

 

아니 나 그럼 후킹 뭐하러 한거야. 
ISA 뭐하러 뜯어본거야! 

 

하.. 어쩐지 왜 앞부분만 평문인가 싶었는데 

 

그래도 분석 마저 해보자. 
블록의 구조만 알아낸다면 후킹 없이도 추출이 가능할거다. 

 

   03 80 00 00 7e 00 ec fd  00 01 00 00 01 2f 70 72  |....~......../pr|
{REDACTED}

   03 00 00 00 fc 30 82 04  a4 02 01 00 02 82 01 01  |.....0..........|
{REDACTED}

   03 00 01 00 fc 4b a2 70  21 4c 83 cc 95 6c d5 18  |.....K.p!L...l..|
{REDACTED}

   03 00 02 00 fc 5c c9 a3  5c 36 d0 c4 bb 21 10 15  |.....\..\6...!..|
{REDACTED}

   03 80 00 00 7e 00 ec fd  00 02 00 00 01 2f 70 72  |....~......../pr|
{REDACTED}

   03 00 03 00 fc f7 99 11  68 7a fa f0 07 12 cc 26  |........hz.....&|
{REDACTED}

   03 80 00 00 7e 00 ec fd  00 03 00 00 01 2f 70 72  |....~......../pr|
{REDACTED}

   03 00 04 00 fc 07 30 31  7b 07 1c 58 32 58 f0 c9  |......01{..X2X..|
{REDACTED}

   03 80 00 00 7e 00 ec fd  00 04 00 00 01 2f 70 72  |....~......../pr|
{REDACTED}

   03 80 00 00 f8 00 ec fd  a8 04 00 00 01 2f 70 72  |............./pr|
{REDACTED}

 

0번부터 총 다섯개의 블록이 확인되었고 
각 파일들의 오프셋이 모두 5로 시작하던걸 보면 블록 헤더도 5바이트로 추정된다. 

마지막 블록 제외하고 블록마다 크기도 같다.. 젠장 
헤더 빼고 블록들 전부 잘라서 이어붙여보자. 

 

 

2. 파일 결합

2.1 pk 추출

dd if=esp_backup.bin of=pk_block0.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=pk_block1.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=pk_block2.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=pk_block3.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=pk_block4.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))

cat ./pk_block0.der ./pk_block1.der ./pk_block2.der ./pk_block3.der ./pk_block4.der > pk.der

되길 바라야할지 안되길 바라야할지.. 

 

 

dumpasn1 ./pk.der

미친 에러가 안 났어! 
에러가 안 났어!!!! 

아니!!!! 

 

 

키 추출 하나에 한달을 쏟았는데...! 
캡스톤 깔고 기드라 깔고 툴체인 깔고! 
리버싱하고 루틴 추적하고 후킹 설계하고! 
ISA 문서 뒤져가며 바이너리까지 직접 계산했는데! 

 

이제 진짜 성공이 코앞이었는데! 

대체 왜 이제야 깨닫는건데.... 







나는 왜 이 모양일까. 
대체 몇시간을 삽질한거야.. 

 

이젠 시간 단위가 아니지. 며칠을 삽질한거야.. 

 

그래도 인증서도 마저 추출해보자. 

 

 

2.2 cert 추출

dd if=esp_backup.bin of=cert_block0.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=cert_block1.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=cert_block2.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=cert_block3.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))

cat ./cert_block0.der ./cert_block1.der ./cert_block2.der ./cert_block3.der > ./cert.der

 

여기다 한달을... 하..... 

 

 

$ openssl x509 -in ./cert.der -inform DER -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            {REDACTED}
        Signature Algorithm: {REDACTED}
        Issuer: OU = Amazon Web Services O=Amazon.com Inc. L=Seattle ST=Washington C=US
        Validity
            Not Before: {REDACTED}
            Not After : {REDACTED}
        Subject: CN = AWS IoT Certificate
        Subject Public Key Info:
            Public Key Algorithm: {REDACTED}
                Public-Key: (2048 bit)
                Modulus:
                    {REDACTED}
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Authority Key Identifier:
                {REDACTED}
            X509v3 Subject Key Identifier:
                {REDACTED}
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: critical
                Digital Signature
    Signature Algorithm: {REDACTED}
    Signature Value:
        {REDACTED}

 

/cert.der 추출 성공

 

 

2.3 ca 추출

dd if=esp_backup.bin of=ca_block0.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=ca_block1.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=ca_block2.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))
dd if=esp_backup.bin of=ca_block3.der bs=1 skip=$(({REDACTED})) count=$((16*16-5))

cat ./ca_block0.der ./ca_block1.der ./ca_block2.der ./ca_block3.der > ./ca.der
$ openssl x509 -in ./ca.der -inform DER -text -noout
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            {REDACTED}
        Signature Algorithm: {REDACTED}
        Issuer: C = US, O = Amazon, CN = Amazon Root CA 1
        Validity
            Not Before: {REDACTED}
            Not After : {REDACTED}
        Subject: C = US, O = Amazon, CN = Amazon Root CA 1
        Subject Public Key Info:
            Public Key Algorithm: {REDACTED}
                Public-Key: (2048 bit)
                Modulus:
                    {REDACTED}
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
            X509v3 Subject Key Identifier:
                {REDACTED}
    Signature Algorithm: {REDACTED}
    Signature Value:
        {REDACTED}

 

./ca.der까지 전부 성공했다. 

난 왜 이렇게 멍청한거지? 
이렇게 당연한걸 왜 미리 생각을 안 한거지?? 

죽고싶다 진짜

 

 

3. 파일 정리

openssl x509 -in ./ca.der -inform DER -out ./ca.der -outform DER
openssl x509 -in ./cert.der -inform DER -out ./cert.der -outform DER
openssl rsa -in ./pk.der -inform DER -out ./pk.der -outform DER

 

깨끗하게 정리

 

 

전부 추출 끝났다. 
허탈할 정도로 너무 쉬웠다. 

 

 

4. 해시값 기록

$ openssl rsa  -inform DER -in pk.der -noout -modulus | sha256sum
2ffc65064620e76cafb106aa01949cc274f6636d89fa3a738bed32e8f179006f  -

$ openssl x509 -inform DER -in ./cert.der -pubkey -noout | openssl pkey -pubin -outform DER | sha256sum
dcf68f637fb11e1484b193ae97d6b50833c55bc2ea116983998e3aa44857f619  -

$ openssl x509 -inform DER -in ./ca.der -pubkey -noout | openssl pkey -pubin -outform DER | sha256sum
fbe3018031f9586bcbf41727e417b7d1c45c2f47f93be372a17b96b50757d5a2  -

 

 

5. 추가 파일 확인

파일로 추정되는 것이 하나 더 있다. 

 

 

위치로 가보면 명확하게 블록 구조가 보이지는 않고 
지난번에 확인한 와이파이 정보만 분할돼서 들어가있다. 

특별히 다른 내용은 없다. 

 

 

그래도 후킹까지는 마무리를 해야겠다. 

이걸 성공한다면 단순히 파일 저장 방식 뿐만 아니라 
제품의 설계 결함까지도 증명할 수 있을 거다.