2 điểm bởi GN⁺ 2024-07-18 | 1 bình luận | Chia sẻ qua WhatsApp
  • Rabbit R1 là một thiết bị dựa trên ứng dụng chạy trên Android 13 AOSP theo kiểu kiosk mode, và đã có thể thực hiện tethered jailbreak để lấy root shell mà không cần mở khóa bootloader hay thay đổi bộ nhớ trong
  • Cách jailbreak này vẫn để nguyên quá trình xác minh của chuỗi khởi động MediaTek, rồi thay thế image tùy chỉnh được nạp qua USB ngay trong bộ nhớ vào thời điểm ngay trước khi image boot đã được xác minh thực sự được sử dụng
  • R1 dùng MediaTek MT6765, 4GB DRAM và 128GB eMMC; ngay cả khi ro.boot.verifiedbootstate ở trạng thái green thì vẫn có thể truy cập uid=0(root) qua TCP bind shell
  • Log trong bộ nhớ trong lưu lại vị trí GPS, tên WiFi, ID trạm phát xung quanh, IP công khai, token người dùng cho API backend của Rabbit, cùng MP3 giọng nói của Rabbit và bản chép lời; trong RabbitOS v0.8.112, việc ghi log đã được giảm bớt và đã bổ sung tùy chọn khôi phục cài đặt gốc
  • Rabbit Inc. đang ở trạng thái vi phạm GPL2 vì không công khai mã nguồn driver bánh xe cuộn hall-effect và driver mô-tơ camera xoay được liên kết tĩnh với Linux kernel, và tính đến ngày 22/7 vẫn chưa phản hồi các câu hỏi liên quan

Điểm khởi đầu của việc phân tích Rabbit R1

  • Rabbit R1 bị giới phê bình đánh giá tiêu cực, và trên thị trường đồ cũ, các máy còn nguyên seal đang được bán với giá thấp hơn mức niêm yết 200 USD
  • RabbitOS không phải là một mô hình AI cục bộ riêng biệt mà là một ứng dụng chạy trên Android 13 AOSP theo kiểu kiosk mode, giao tiếp với đám mây qua JSON API trên WebSocket
  • API key bị lộ từng được đưa tin trước đó được cho là rò rỉ từ mã nguồn phía máy chủ, chứ không được lưu trong thiết bị
  • Các bản cập nhật ứng dụng sau đó đã áp dụng công cụ obfuscation thương mại, đồng thời có logic phát hiện công cụ phân tích như Magisk và Frida cũng như kiểm tra xem có phải thiết bị R1 hay không
  • Vì chỉ phân tích tĩnh đã trở nên bất tiện để lần vết, tác giả đã mua một chiếc R1 trên eBay với giá £122 và tiến hành phân tích lúc runtime trong khi giữ firmware gốc càng nguyên trạng càng tốt

Phần cứng R1 và trạng thái bảo mật cơ bản

  • R1 sử dụng SoC MediaTek MT6765, 4GB DRAM và bộ nhớ eMMC 128GB
    • MT6765 có kamakiri, một bootrom exploit đã được biết đến từ năm 2019
    • Dung lượng lưu trữ 128GB có vẻ là một lựa chọn khá lạ với một thiết bị vốn không có nhiều dữ liệu cục bộ
  • Chủ sở hữu R1 đã xác nhận rằng có thể dùng mtkclient để unlock bootloader, flash custom ROM hoặc root máy
  • Mục tiêu phân tích không phải là nạp một image hệ thống Android tùy chỉnh, mà là quan sát firmware cài sẵn từ nhà máy trong trạng thái gần như nguyên bản nhất có thể
  • Cách mở khóa bootloader rồi cài Magisk có nhiều vấn đề
    • Có thể làm hỏng OTA delta update
    • Có thể bị mã chống phân tích hiện tại phát hiện
    • Các bản cập nhật sau này có thể phát hiện nếu kiểm tra những giá trị như ro.boot.verifiedbootstate
  • Vì vậy, cần một hướng đi có thể lấy quyền root cục bộ trong khi giảm tối đa các điểm thay đổi để thu hẹp bề mặt mà logic chống phân tích có thể nhận ra

Chuỗi khởi động dựa trên MediaTek

  • Chuỗi khởi động được cấu thành bởi logic của MediaTek, và điểm khởi đầu là bootrom được cố định trong silicon CPU
  • Sau khi khởi tạo phần cứng cơ bản, bootrom nạp Preloader từ phân vùng eMMC boot0 vào SRAM
    • Preloader có chữ ký và bootrom sẽ xác minh chữ ký đó
    • Tuy vậy, trên R1 có khả năng việc xác minh thực tế không diễn ra, nên cần kiểm chứng thêm
  • Preloader khởi tạo DRAM rồi nạp ba image từ phân vùng GPT của eMMC vào DRAM
    • tee: Arm Trusted Firmware, EL3
    • gz: GenieZone Hypervisor, EL2
    • lk: Little Kernel, EL1
  • LK triển khai Android Verified Boot 2.0dm-verity
    • Nếu bootloader ở trạng thái locked, máy sẽ từ chối khởi động khi xác minh thất bại
    • Nếu unlocked, máy sẽ hiện cảnh báo và đặt các cờ liên quan đến orange state
    • Nếu xác minh dm-verity thất bại thì máy cũng không khởi động được, kể cả khi bootloader đã unlocked
  • Khi xác minh thành công, LK sẽ giải nén Linux kernel để khởi động, và kernel sẽ chạy /init trong initramfs
  • R1 dùng A/B partitioning, vì vậy boot sẽ là boot_a hoặc boot_b tùy slot đang hoạt động
  • Trạng thái lock/unlock của bootloader được lưu trong phân vùng GPT seccfg
    • seccfg gồm một vài cờ và một hash đã mã hóa
    • Byte cuối của phân vùng frp có liên quan đến việc cho phép unlock bootloader như fastboot flashing unlock

carroot: tethered jailbreak không đụng vào bộ nhớ lưu trữ

  • Root of trust của chuỗi tin cậy nằm ở hash chứng chỉ trong efuse của CPU và mã bootrom dùng để xác minh nó
  • MT6765 có bootrom exploit kamakiri, nhưng trên R1 thì ngay cả không cần exploit, chế độ USB bootloader của brom và Preloader vẫn nhận image DA unsigned để thực thi trong bộ nhớ
  • Tác giả đã tự tạo DA payload để Preloader nạp vào DRAM
  • Luồng hoạt động như sau
    • Nạp một image Android boot tùy chỉnh vào DRAM qua USB
    • Cài hook ngay trước khi Preloader nhảy sang LK
    • Quay lại Preloader và tiếp tục quá trình khởi động bình thường
    • Preloader nạp và xác minh các image tee, gz, lk từ eMMC
    • Ngay trước khi vào LK, hook được kích hoạt để cài thêm hook và patch bên trong LK
    • LK nạp và xác minh phân vùng boot gốc từ eMMC
    • Đúng lúc image boot được sao chép từ mã AVB sang phần mã khởi động Linux, hook sẽ thay thế nó bằng image boot tùy chỉnh đã nạp qua USB
    • Một thông điệp tùy chỉnh cũng được hiển thị trên màn hình
  • Điểm cốt lõi là dữ liệu được đem đi xác minh vẫn giữ nguyên, rồi dữ liệu đã bị patch mới được thay thế sau khi xác minh nhưng ngay trước khi sử dụng
  • Bộ nhớ flash hoàn toàn không bị sửa đổi, và toàn bộ quá trình jailbreak chỉ diễn ra trong bộ nhớ
    • Khởi động lại là thiết bị trở về trạng thái sạch
    • Việc khôi phục nguyên trạng trong quá trình reverse engineering cũng dễ dàng
  • Image boot tùy chỉnh sử dụng flashable-android-rootkit
    • Nó thay thế binary /init mặc định để chèn một payload là dịch vụ user space có đặc quyền cao nhất
    • Công cụ patch image magiskboot được lấy từ dự án Magisk
    • Để build và chạy magiskboot trên Linux thông thường, tác giả dùng magiskboot_build
  • Payload là một TCP bind shell đơn giản
    • Đây không phải cách kín đáo và ứng dụng Rabbit có thể phát hiện ra
    • Nếu cần có thể cải tiến sau

Công cụ jailbreak dựa trên WebSerial và kết quả thực thi

  • Để thao tác với thiết bị MediaTek, mtkclient vốn đã cung cấp các chức năng cần thiết, nhưng để hiểu rõ cách hoạt động, tác giả đã tự viết một USB client bằng Python
  • Sau đó nó được port sang js/WebSerial để có thể jailbreak Rabbit R1 được kết nối vật lý ngay từ một trang web
  • Tên jailbreak được đặt là carroot như một cách chơi chữ với rabbit
  • Công cụ thử nghiệm được công bố tại r1_jailbreak
  • Kết quả khi kết nối bằng TCP bind shell sau khi khởi động như sau
$ rlwrap nc 192.168.0.69 1337


# id
uid=0(root) gid=0(root) groups=0(root) context=u:r:rootkit:s0


# getprop ro.boot.verifiedbootstate
green
  • Hệ thống vẫn nhận diện trạng thái secure boot là green nhưng đồng thời cho phép truy cập root shell
  • SELinux domain rootkit được thiết lập bởi flashable-android-rootkit

Giao diện thiết bị dùng cho phân tích và tài liệu tham khảo

  • Ảnh tháo máy iFixit của R1 cho thấy các pad test được ghi là TX và RX, đây là các pad test UART
  • UART cung cấp log debug cho toàn bộ chuỗi khởi động
    • Giai đoạn brom dùng 115200 baud
    • Các giai đoạn sau dùng 921600 baud
    • Mức logic là 1.8V, nhưng trên thiết bị phân tích thì 3.3V cũng hoạt động mà không gây hư hại
  • Preloader sẽ tắt UART logging nếu không nhấn phím volume-up
    • R1 không có phím volume-up, nên tác giả đã patch Preloader để vô hiệu hóa kiểm tra này
    • Preloader đã patch có thể khởi động bằng USB download mode của bootrom
  • Trong command line của Linux kernel, tác giả đã patch thêm các cờ sau để xuất log kernel qua UART
earlycon console=ttyS1,921600

Dữ liệu cá nhân được phát hiện trong log nội bộ

  • R1 đã ghi log văn bản theo ngày tại Android/data/tech.rabbit.r1launcher.r1/files/logs/ trong bộ nhớ trong
  • Tính đến ngày 7/7/2024, thư mục log có các tệp .log của nhiều ngày khác nhau, một số tệp có kích thước vài MB
  • Log bao gồm các dữ liệu sau
    • Vị trí GPS chính xác
    • Tên mạng WiFi
    • ID trạm phát xung quanh được thu thập ngay cả khi không có SIM
    • Địa chỉ IP hướng Internet
    • Token người dùng dùng để xác thực với API backend của Rabbit
    • MP3 được mã hóa Base64 cho toàn bộ nội dung Rabbit nói với người dùng và bản chép lời văn bản
  • Trong số đó, dữ liệu vị trí GPS và ID trạm phát xung quanh cũng được gửi lên máy chủ Rabbit
  • Có hai vấn đề chính
    • Thiết bị không có bảo mật phần cứng đáng kể nhưng lại ghi log dữ liệu quá chi tiết
    • Người dùng thông thường không có cách khôi phục cài đặt gốc, khiến các log này gần như tồn tại vĩnh viễn
  • Trong bối cảnh giao dịch máy cũ diễn ra sôi động, log của người dùng trước có thể còn sót lại khi bán, tặng hoặc thải bỏ thiết bị
  • Trong khuyến cáo bảo mật, RabbitOS v0.8.112 đã giảm việc ghi log và bổ sung tùy chọn khôi phục cài đặt gốc trong phần cài đặt
  • Đây là phản ứng được thực hiện khá nhanh, và được đánh giá là trường hợp đầu tiên Rabbit phản ứng tương đối chủ động trước các vấn đề về quyền riêng tư và bảo mật người dùng

Phạm vi tùy biến AOSP thực tế

  • Trước các bài viết cho rằng RabbitOS chỉ là một ứng dụng đơn thuần, Rabbit từng giải thích rằng đây là một AOSP được tùy biến rất nhiều với “lower level firmware modifications”
  • Những tùy biến đã được xác nhận đến nay chủ yếu là theo hướng loại bỏ các chức năng Android để duy trì single-app kiosk mode
    • Không có navigation bar
    • Không có notification bar
    • Có các biện pháp nhằm ngăn kích hoạt ADB
  • Một ứng dụng tên Judy chạy nền và sẽ vô hiệu hóa ADB nếu phát hiện ADB đang hoạt động
  • Ngày 4/7, @MarcelD505 đã công bố một cách kiosk escape bắt đầu từ trình duyệt đăng nhập WiFi captive portal để đi vào ứng dụng Android system settings
  • Trong bản cập nhật mới nhất, Rabbit đã chặn đường này bằng cách xóa hoàn toàn ứng dụng Android system settings khỏi thiết bị
  • Các thay đổi AOSP bespoke được xác nhận cho tới nay có vẻ gần với việc loại bỏ chức năng hơn là bổ sung chức năng mới
  • Cho đến hiện tại vẫn chưa xác nhận được lý do kỹ thuật nào cho thấy RabbitOS ở dạng hiện tại không thể chỉ là một ứng dụng smartphone thông thường

Điều người dùng R1 thông thường nên lưu ý

  • Nếu lo ngại máy có thể đã bị jailbreak ngoài ý muốn, chỉ cần tắt rồi bật lại nguồn
    • Nếu máy khởi động bình thường mà không hiện cảnh báo, nhìn chung có thể là an toàn
    • Tuy vậy, nếu brom được cấu hình để khởi động một image Preloader unsigned từ eMMC thì chưa thể chắc chắn và cần kiểm tra thêm
  • Sẽ tốt hơn nếu có thể flash lại bằng stock firmware image đáng tin cậy do nhà cung cấp cung cấp, nhưng Rabbit không đưa ra phương án như vậy
  • Nếu để R1 ở trạng thái unattended, dữ liệu lưu trên máy có thể bị người có kiến thức liên quan trích xuất khá dễ dàng
  • Trước khi bán, tặng hoặc thải bỏ, người dùng nên dùng tùy chọn khôi phục cài đặt gốc mới được bổ sung trước

Vi phạm GPL và kết luận

  • Ngoài bánh xe cuộn và camera xoay, Rabbit R1 gần với một thiết bị Android MediaTek thông thường hơn là phần cứng đặc biệt
  • Việc tùy biến AOSP chủ yếu mang tính loại bỏ các chức năng sẵn có để ép thiết bị vào single-app kiosk mode
  • Bảo mật của chuỗi khởi động không hiệu quả, khiến thiết bị khó có thể được bỏ mặc một cách an toàn
  • Rabbit Inc. đang vi phạm giấy phép GPL2 của Linux kernel
    • Driver phát hiện bánh xe cuộn hall-effect vẫn ở trạng thái closed-source
    • Driver điều khiển stepper motor xoay camera cũng ở trạng thái closed-source
    • Cả hai driver đều được liên kết tĩnh vào image kernel GPL
  • Ngày 12/7, tác giả đã liên hệ Rabbit Inc. để hỏi bình luận về nội dung bài viết và kế hoạch tuân thủ GPL, nhưng tính đến ngày 22/7 vẫn chưa nhận được phản hồi
  • Công cụ tethered jailbreak được công bố là công cụ thử nghiệm nhằm giúp nhà nghiên cứu truy cập chiếc R1 mà mình sở hữu, đồng thời về sau có thể giúp người dùng nâng cao mở rộng chức năng của thiết bị

1 bình luận

 
GN⁺ 2024-07-18
Ý kiến trên Hacker News
  • GPL yêu cầu phải công bố giấy phép và mã nguồn khi được yêu cầu, nhưng Truth Social đã lờ đi, thậm chí không công bố cả giấy phép cho đến khi bị phát hiện dùng mã AGPL, rồi lúc đó mới công bố mã nguồn
    Không biết Rabbit có thoát theo cách tương tự không

    • Không hẳn chính xác. GPL 2.0 yêu cầu tối thiểu phải công bố giấy phép khi phân phối, nhưng mã nguồn thực tế cũng có thể được cung cấp theo yêu cầu
      Trên thực tế, không thể truy vết các vi phạm mà chủ sở hữu quyền không biết, và thường họ quan tâm đến việc đưa bên vi phạm về trạng thái tuân thủ hơn là đòi bồi thường thiệt hại
      https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    • Rất có khả năng Rabbit đã đóng cửa trước khi các hệ quả liên quan đến GPL thực sự chạm tới họ
      Tôi tưởng phía Linux có ngoại lệ GPL cho kernel module, bất kể cách liên kết, nếu không cần sửa trực tiếp kernel
    • GPL vốn khó thực thi. Nhà sản xuất Boox là Onyx cũng từng bị chỉ ra vấn đề tương tự vài năm trước nhưng không có kết quả gì đáng kể, và tôi không nghĩ Rabbit sẽ gặp rắc rối vì chuyện này
  • Nội dung log này khá bừa bộn: có cả vị trí GPS chính xác, tên mạng WiFi, ID trạm phát sóng xung quanh ngay cả khi không có thẻ SIM, địa chỉ IP lộ ra bên ngoài, token người dùng để xác thực với API backend của Rabbit, cả MP3 mã hóa Base64 của mọi thứ Rabbit đã nói với người dùng cùng bản chép lời văn bản

    • Điều quan trọng là thông tin vị trí và trạm phát sóng có luôn được gửi lên máy chủ hay chỉ được gửi khi có yêu cầu
      Với một thiết bị được tạo ra để trả lời những câu như “quán ăn nào ổn gần đây?”, việc gửi ngữ cảnh vị trí kèm yêu cầu không có gì đáng ngạc nhiên; nhưng nếu nó liên tục stream vị trí mà không có lý do thì đáng lo ngại
      Tên WiFi cần được lưu để kết nối lại, và việc thấy địa chỉ IP trong log cục bộ cũng không quá lạ
      Token truy cập của người dùng cũng buộc phải được lưu trên thiết bị nếu muốn kết nối lại mà không phải đăng nhập mỗi lần. Tuy nhiên, để nguyên token trong log là thực hành không tốt, và nếu log nằm cùng nơi lưu trữ với DB hoặc file cấu hình đó thì bản thân việc này không hẳn là một vấn đề hoàn toàn mới. Nếu log được upload thẳng lên máy chủ thì tất nhiên là có vấn đề
    • MP3 được mã hóa Base64 thật vô lý. Thứ duy nhất nhận được là mức dùng dữ liệu tăng 33%
    • Xét cả mục đích của sản phẩm thì không đời nào toàn bộ dữ liệu này được thu thập một cách tình cờ
    • Phần lớn trong số này trông không giống vấn đề lớn
      Nếu muốn một thiết bị kiểu này hoạt động mượt mà và như có phép màu, nó phải liên tục nghe, nhìn và gửi vị trí. Thực ra để làm đúng thì cần suy luận cục bộ, và tôi không hiểu vì sao lại trả tiền cho một thứ mà 5 năm nữa Apple sẽ làm ra phiên bản tốt hơn nhiều, nhưng nếu đã mua thì cần cách vận hành như vậy
      Không thể vừa ghét các tập đoàn lớn vừa kỳ vọng một startup tạo ra sản phẩm tốt mà không có dữ liệu. Rabbit cần dữ liệu như thế này nếu muốn ít nhất có khả năng làm ra thứ tốt hơn trong tương lai
    • Khá nhiều phần giống với việc “một thiết bị được tin tưởng giao thông tin để cung cấp dịch vụ lưu thông tin đó vào log cho mục đích xử lý sự cố”
      Nếu nói chuyện này gây khó chịu thì cần giải thích cụ thể vì sao. Phần lớn tự thân nó không phải điều quá đáng lo
  • Buồn cười thật. Tôi từng làm ở Rabbit, đọc codebase rồi rời đi sau khi bị các lãnh đạo gaslight

    • Nếu được, tôi tò mò không biết dấu hiệu cảnh báo đầu tiên nhìn thấy trong codebase là gì
      Chỉ nhìn các jailbreak và lỗ hổng từ bên ngoài thôi cũng có vẻ như mới là phần nổi của tảng băng
    • Vậy chẳng phải anh nên kể vài chuyện nội bộ thú vị về cái gọi là “large action model” đó sao?
    • Coi như né được một viên đạn rồi
  • Rabbit không trả lời có lẽ vì luật sư đang xem xét sẽ kiện thế nào

    • Nếu thật vậy thì khá buồn cười
    • Nhìn doanh số thiết bị thì không biết họ có kham nổi chi phí luật sư không
    • Gửi yêu cầu bình luận vào chiều thứ Sáu rồi đăng kiểu “không có phản hồi” vào sáng thứ Hai thì nói thật là khá tệ
      Gần như không cho họ thời gian làm việc thực tế để trả lời
    • Nghĩ đến khả năng công ty liên quan sắp mất khả năng thanh toán, tôi chỉ xem đó như mức đe dọa từ mấy người làm Juicero gửi tới thôi
  • Các nhà phát triển RabbitOS có thể vá vấn đề này bằng cách thiết lập eFuse để chặn truy cập bootloader qua USB
    Moto cũng đã xử lý như vậy vài năm trước khi các thiết bị MediaTek dễ bị tấn công trên cùng bề mặt bootrom. Nếu tôi nhớ đúng thì eFuse này được thiết lập ở giai đoạn LK và được áp dụng qua bản cập nhật firmware OTA thông thường

  • Bài viết rất hay
    Phần mềm trông như rác, và công ty cho đến nay cũng không có vẻ tốt đẹp gì
    Dù vậy, nếu có thể dễ dàng chạy app tùy chỉnh, kể cả trong chế độ kiosk, thì form factor này có thể có những cách dùng khá thú vị
    Nếu có thể nhét tạm một PWA lên đó, nó sẽ nhanh hơn nhiều so với việc tự gắn ESP32, pin và màn hình, và trông như một thiết bị all-in-one khá ổn
    Lý tưởng nhất là có thể chạy an toàn hơn mà không cần dịch vụ Google, theo hướng giống GrapheneOS thì ổn
    Tôi chưa tìm thử, nhưng tò mò không biết có ví dụ sử dụng hoặc tài liệu tham khảo nào cho việc dùng kiểu này làm app tùy chỉnh đơn mục đích không

    • Ở trạng thái hiện tại, phần cứng vẫn khá đắt
      Nếu giá xuống dưới 50 USD, chẳng hạn sau khi họ tắt máy chủ, thì lúc đó tôi có thể đồng ý rằng đây là một nền tảng phần cứng ổn
  • Tiếc thật, tôi đã mong sản phẩm này thành công
    Hy vọng nó không trở thành một cục nợ cho các thử nghiệm giao diện người dùng phần cứng + AI trong tương lai. Tôi vẫn đồng tình với ý tưởng kiểu Bret Victor rằng ta có thể làm tốt hơn việc chạm và vuốt trên một hình chữ nhật bằng kính

    • Đúng, nhưng hình chữ nhật bằng kính đang cầm trên tay đã có đủ hiệu năng và tính năng phần cứng để cung cấp các giao diện khác như vậy
      Tiện hơn nữa thì smartwatch cũng có thể chuyển tiếp truy vấn sang điện thoại
      Dù Humane có vẻ không giải quyết được vấn đề thực tế, tôi vẫn tôn trọng phần nào vì họ thật sự thử làm thứ khác. Rabbit R1 thì chỉ là một món đồ linh tinh rẻ tiền
  • Hơi buồn cười là toàn bộ hoặc phần lớn thiện cảm ban đầu dành cho Rabbit đến từ thiết kế của Teenage Engineering
    Hy vọng TE sau này chọn khách hàng kỹ hơn. Người đứng sau Rabbit là một kẻ lừa đảo đã có tiếng

    • “Kẻ lừa đảo” đó nằm trong hội đồng quản trị TE, nên mọi chuyện đã mất kiểm soát rồi
    • Tôi muốn biết nguồn cho câu “người đứng sau Rabbit là một kẻ lừa đảo đã có tiếng”
      Có thể tìm theo tên, nhưng chất lượng tìm kiếm dạo này quá tệ nên tôi không định làm. Nếu có link trình bày kỹ hơn các chỉ trích thì sẽ hữu ích
  • Cái này giống Juicero của giới trợ lý AI

    • Juicero được thiết kế đẹp, có lẽ là quá mức, và hoạt động đúng như quảng cáo
      Chỉ là họ nghĩ mọi người sẽ trả một khoản tiền vô lý cho một cái máy ép các túi hỗn hợp trái cây đã cắt sẵn độc quyền của công ty. Mọi thứ vận hành đúng như dự định, chỉ có mô hình kinh doanh thực tế là phi lý
    • Cái này giống một máy ép Juicero không có bộ phận chức năng nào, thay vào đó chỉ có một đường ống nối về trụ sở Juicero để trộn nước ép từ nhiều nhà cung cấp rồi bơm ngược lại thiết bị với độ trễ 5 phút
  • Tôi đã kỳ vọng một trợ lý AI mã nguồn mở bảo vệ quyền riêng tư, kiểu kết hợp Mycroft(https://en.wikipedia.org/wiki/Mycroft_(software)) và Leon(https://getleon.ai)