목록2026/04/22 (13)
graf
일단 개인키와 인증서의 추출은 성공을 했는데 만약 개인키와 인증서를 모든 장치에서 공유하고 있다면 더 큰 문제가 된다. 이를 확인하기 위해 제품을 추가로 분석해봤다. RSW-725R 동일한 모델이다. 기판 색깔이 흰색으로 바뀐걸 제외하면 구성은 모두 동일하다. 1. 부팅 메시지 확인부팅 메시지를 먼저 확인해봤다. ets Jan 8 2013,rst cause:1, boot mode:(3,1)load 0x4010f000, len 1392, room 16 tail 0chksum 0xd0csum 0xd0v3d128e5c~ld 이번에 확인한 부팅 메시지 ets Jan 8 2013,rst cause:1, boot mode:(3,6)load 0x4010f000, len 1392, room 16 tai..
cp ./esp_backup.bin ./test9.bin 마지막 테스트가 됐으면 좋겠다. 1. 데이터 추가printf "\x25\x78\x3a\x20\x00\x25\x78\x20\x00\x0a\x00" | dd of=test9.bin bs=1 seek=$((0x600)) count=11 conv=notrunc 문자열을 약간 바꿨다. 중간에 널문자를 껴서 %x:, %x, \n 세개의 문자열로 구성했다. {주소}: {16바이트} 형식으로 출력할거다. 램이 80kb 정도 되니까 이렇게 출력해도 5천줄은 나올거다. printf "\x00\x06\x20\x40" | dd of=test9.bin bs=1 seek=$((0x610)) count=4 conv=notruncprintf "\x08\x55\x10\x4..
현재 계획은 후킹으로 메모리를 통째로 덤프하는거다. 원래는 개인키가 로드된 버퍼를 찾아서 깔끔하게 출력하는게 계획이었다. 이제 그럴 필요가 없어지긴 했지만.. 그래도 이왕 준비한거 설계상의 결함을 증명해서 키가 암호화된 상태였어도 안전하지 않았음을 보일거다. 사용 예정인 함수는 이거다. 이 함수로 데이터를 16진수 형태로 꺼내야겠다. 1. test5 - 포멧 출력 테스트cp ./esp_backup.bin ./test5.bin 이번에도 ets_printf의 사용 가능 여부를 먼저 테스트를 해볼거다. 번거롭지만 어쩔 수 없다. 나중에 오류가 생겼을 때 거꾸로 원인을 찾는 것보다는 이게 낫다. 그래도 준비는 다 돼있으니 그렇게 오래 걸리진 않을거다. 1.1 리터럴 추가이번에 추가해야하는 데이..
갑자기 든 의문인데 이 장치를 오랫동안 분석하면서 느낀 점은, 장치의 보안 설계가 그닥 치밀하지 않다는 점이다. 그런데 굳이 인증서랑 개인키만 암호화해놓았다는 가정이 이해가 되질 않는다. 그리고 데이터가 헤더 쪽만 살아있고 뒷부분이 파싱이 안됐는데 오히려 검출이 안되게 하려면 헤더만 암호화하는게 나았지 않았을까? 이렇게 생각하니 뭔가 이상하다. 내가 파싱을 잘못한건 아닐까? 아님 내가 뭔가 실수를 했던건 아닐까..? $ binwalk ./esp_backup.binDECIMAL HEXADECIMAL DESCRIPTION--------------------------------------------------------------------------------402130 ..
후킹을 위한 준비는 모두 끝났다. 계획한대로 0x600 인근 영역에 내가 만든 바이너리를 넣고 디버깅 메시지를 출력할 때 print 대신 내 함수가 호출되게 할 것이다. 리터럴같은 데이터에는 접근이 가능했지만 실행 권한은 제한돼있을 수도 있다. 이번 테스트를 통해 코드 실행 가능 여부와 대략적인 xip 영역의 범위를 확인할 수 있을 것이다. 이거만 성공한다면 거의 끝난거나 다름 없다. 제발 성공했으면 좋겠다. 1. 후킹 지점 확인후킹할 지점은 여기다. 저 call0 printf 대신 내가 넣은 함수를 실행시킬 것이다. 원래 개인키 로드 직후로 하려고 했지만 계획이 바뀌었으니 세개의 파일이 모두 로드가 끝난 시점으로 했다. 이 함수는 원래대로라면 "ca loaded"라고 출력됐어야한다. 1.1..
세번째 테스트에서는 후킹을 통해 임의 코드를 실행해볼 것이다. xtensa는 바이너리가 상당히 난해한 편이라 설계를 위한 준비가 필요하다. 1. 코드 설계cp ./esp_backup.bin ./test3.bin 테스트할 펌웨어는 원본에서 새로 복사했다. 1.1 출력할 문자열 입력printf "\x01\x02\x03\x04\x05\x06\x07\x08" | dd of=test3.bin bs=1 seek=$((0x600)) count=11 conv=notruncprintf "\x09\x0a\x0b\x0c\x0d\x0e\x0f\x00" | dd of=test3.bin bs=1 seek=$((0x608)) count=11 conv=notrunc 출력할 문자열로 아스키로 표현되지 않는 바이트 코드를 넣었다..
리버싱 실패 후 쓰러져있던 차에 떠오른 방법이다. 변조된 펌웨어를 올려서 로드가 끝난 개인키를 uart로 보내버릴 수는 없을까? 만약 성공한다면 복잡하게 복호화 동작을 분석할 필요도 없이 개발자가 만들어놓은 로직을 그대로 갖다 쓸 수 있을 것이다. 1. 가능성 확인어쩌면 충분히 해볼만 할지도 모르겠다는 생각이 든다. 그래도 먼저 몇가지 확인해야할 것들이 있다. 1.1 펌웨어 업로드 방법일단 새로 만든 펌웨어를 장치에 업로드할 수 있어야한다. python3 -m esptoolesptool.py v4.9.0positional arguments: {load_ram,dump_mem,read_mem,write_mem,write_flash,run,image_info,make_image,elf2image,..
삽질을 좀 하긴 했지만 세그먼트를 모두 확보하는데 성공했다. 이번 분석 목표는 추출한 세그먼트에서 인증서와 개인키의 디코딩 혹은 복호화 루틴의 존재 유무를 찾는거다. 리버싱은 깊게 공부해본 적이 없긴 한데,, 그래도 한번 시도나 해보자. 1. 문자열 참조 위치 찾기대부분의 문자열 리터럴들은 세그먼트 1과 5에 몰려있다. private key loaded는 세그먼트 5번에서 나왔다. 오프셋은 0x3ea로드되는 주소를 고려하면 0x3ffe8570 + 0x3ea = 0x3ffe895a이 데이터를 참조하는 곳이 있다면 그곳에 개인키를 로드하는 동작이 있다는 말이다. 세그먼트가 로드되는 주소를 기준으로 문자열 주소를 계산하고이 값을 참조하는 명령어들을 찾아봤지만 나오는게 하나도 없었다. strin..