Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
pico2-swd-riscv — Libreria di probe di debug SWD per core RISC-V RP2350. Fornisce halt/resume/step, accesso a registri e memoria, esecuzione di codice e tracciamento delle istruzioni su due fili GPIO utilizzando il bit-banging PIO. | Kitploit
Strumenti/GitHubGitHub/jackdoe/pico2-swd-riscv
Sicurezza Sistemi EmbeddedReverse EngineeringDebuggerHacking HardwareSicurezza HardwareAnalisi del Firmware
GitHubjackdoe/pico2-swd-riscv

pico2-swd-riscv

Libreria di probe di debug SWD per core RISC-V RP2350. Fornisce halt/resume/step, accesso a registri e memoria, esecuzione di codice e tracciamento delle istruzioni su due fili GPIO utilizzando il bit-banging PIO.

Vedi Repository
8536 mesi faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

pico2-swd-riscv

Sonda di debug SWD per core RISC-V (Hazard3) RP2350. Una Pico2 esegue il debug di un'altra tramite due fili GPIO.

0. AVVISO VIBE CODE (SCRITTO DA UN UMANO)

Circa l'80% del codice è stato fatto con vibe coding; Il readme è quasi completamente generato (tranne l'intera sezione del vibe-code-warning). Ho passato molte notti con l'oscilloscopio e la documentazione e ho realizzato un prototipo funzionante in grado di fare sba/read/write regs e comandi astratti e progbuf, il resto è stato fatto con claude code. I test sono una suite di test completa e uso il nucleo della libreria nei miei progetti, ma, come si dice, "hic sunt dracones". Ho anche letto il readme e il codice non sembrava avere nulla di sbagliato (e ho rimosso le parti errate/poco chiare).

Questo progetto è stato il mio caso di studio di vibecoding di un progetto più complesso che non capisco al 100% e per il quale non esiste codice esistente ovvio che possa essere "usato". È iniziato come ~1000 righe di codice che avevo scritto e conoscevo molto bene, leggendo la documentazione su rp2350, arm swd e riscv debug, catturando dati con oscilloscopio e openocd, poi decodificandoli e analizzando la sequenza di wakeup e poi i comandi read/write. Dopo averlo fatto funzionare l'ho dato a claude per trasformarlo in una libreria da usare in altri progetti, e poi l'ho costruito lentamente.

Dopo circa 3-4k righe di codice ho perso completamente il filo di ciò che stava succedendo, e non considererei più questo codice come scritto da me, ma aggiungere sempre più test sembrava "bello", o almeno rassicurante.

C'è stato un po' di gaslighting, in particolare quando ha frainteso dap_read_mem32 pensando che leggesse dalla RAM e non dal protocollo MEM-AP TAR/DRW/RDBUFF, il che ha portato a un'incredibile quantità di assurdità.

In generale direi che è stata un'esperienza orribile, anche se ci sono volute 10 ore per scrivere quasi 10000 righe di codice, non considero questo mio progetto, e non provo alcun senso di realizzazione o crescita.

Al contrario, usare l'AI per leggere tutta la documentazione (che è migliaia di pagine) e scrivere script utili per decodificare i dati dell'oscilloscopio, creare struct C impacchettate dai documenti e così via, è stato molto piacevole, e mi sono sentito bene dopo. Il momento in cui ho letto il primo registro e poi quando sono stato in grado di leggere la memoria tramite SBA mi sono sentito fantastico.

Il problema principale è il taste, quando scrivo codice sento se è buono o cattivo, mentre lo scrivo, so se è sbagliato, ma usando claude code mi desensibilizzo molto rapidamente e non riesco a distinguere, "si legge" OK, ma non so come si sente. In questo caso è successo quando il codice è cresciuto circa 4x, da 1k a 4k righe. E peggio di tutto, il mio modello mentale del codice è completamente svanito, e con esso la mia proprietà.

I token non hanno ragione o scopo, il che rende la lettura del codice ridicolmente difficile, perché ogni token può essere una totale assurdità. Quando si legge codice umano i simboli hanno uno scopo, qualcuno ha pensato "Metterò questo in una variabile, poi ne controllerò lo stato.", quindi fingo di essere loro e penso perché lo avrebbero scritto? Poco dopo capisco, perché sono umani e io sono umano. Ma i simboli dell'AI non hanno ragione, e peggio di tutto, sembrano tutti ingannevolmente corretti, quindi devo pensare 10 volte di più se sono sbagliati. Con qualsiasi codice umano (incluso il proprio) è abbastanza facile valutare quanto ci si possa fidare, ed è abbastanza coerente, con il codice AI, una funzione può essere molto meglio di quello che avresti scritto tu, e il codice 2 righe sotto può essere immondizia cargo culted che sembra incredibilmente buona, ma è strutturalmente sbagliata.

Alla fine direi di aver acquisito una buona comprensione dei fili, dei tempi e dei meccanismi di basso livello ap/dp, sba e progbuf, ma mi pento di non aver scritto tutto da solo, anche se ci avesse messo 10 volte tanto.

Odio fottutamente questa situazione.

E non posso fare a meno di provare disgusto e vergogna. È questa la programmazione ora? Spero davvero che sia una fase intermedia e che cambi in meglio, il problema è che non so cosa sia "meglio", sembra che per alcuni sia non scrivere codice, per altri non modellare il problema e per altri ancora non dover pensare. Per me non ne sono sicuro, voglio creare cose, e molte volte non voglio sapere qualcosa, ma voglio usarla, ad esempio il controller host USB rp2350, il modo in cui devi riarmare gli interrupt e il modo in cui il registro epx è condiviso è fastidiosissimo, probabilmente per buoni motivi, ma voglio solo usarlo per creare il mio driver CBI.

Immagino che la domanda sia: qual è la cosa che voglio creare? Perché puoi salire molto nella pila, dai registri del chip USB a CBI a UFI a FAT16 al sistema operativo del computer vecchia scuola che sto costruendo, ma perché fermarsi? fare gli schemi, i pcb, i file cad, magari inviarli automaticamente alla fabbrica? e poi spedirli a me? ma perché fermarsi? creare il mio negozio web, iniziare a vendere, creare una community, pubblicità, marketing, generare video di unboxing, magari qualche meme virale? elaborare gli ordini direttamente dalla fabbrica, on demand, se c'è un problema, è pronto con l'assistenza clienti.

Cosa faccio nel frattempo? Me ne sto sulla spiaggia? Odio la spiaggia.

Dove finisce?

PS: come ha detto il poeta: il prezzo per ottenere ciò che vuoi, è ottenere ciò che una volta volevi.

Architettura

root@kitploit:~
Application
    |
rp2350.c    RISC-V Debug Module (halt/resume/step, registers, memory, trace)
    |
dap.c       Debug Access Port (DP/AP registers, bank caching, MEM-AP)
    |
swd_protocol.c  SWD wire protocol (PIO bit-banging, packet encoding, retry)
    |
swd.pio     PIO state machine (4-cycle SWCLK, bidirectional SWDIO)

Ogni livello mantiene il proprio stato e comunica solo con il vicino.

Utilizzo

root@kitploit:~
swd_config_t config = swd_config_default();
config.pin_swclk = 2;
config.pin_swdio = 3;

swd_target_t *target = swd_target_create(&config);
swd_connect(target);
rp2350_init(target);

rp2350_halt(target, 0);
swd_result_t pc = rp2350_read_pc(target, 0);
rp2350_resume(target, 0);

swd_target_destroy(target);

Controllo Hart

root@kitploit:~
rp2350_halt(target, 0);
rp2350_step(target, 0);
rp2350_resume(target, 0);
rp2350_reset(target, 0, true);

swd_result_t pc = rp2350_read_pc(target, 0);
rp2350_write_pc(target, 0, 0x20000000);

swd_result_t val = rp2350_read_reg(target, 0, 5);
rp2350_write_reg(target, 0, 5, 0xDEADBEEF);

uint32_t regs[32];
rp2350_read_all_regs(target, 0, regs);

swd_result_t csr = rp2350_read_csr(target, 0, 0x300);
rp2350_write_csr(target, 0, 0x300, value);

Entrambi gli hart (0 e 1) sono controllabili indipendentemente.

Accesso alla Memoria

Non intrusivo tramite System Bus Access. Funziona mentre l'hart è in esecuzione.

root@kitploit:~
swd_result_t val = rp2350_read_mem32(target, 0x20000000);
rp2350_write_mem32(target, 0x20000000, 0xDEADBEEF);

rp2350_read_mem16(target, addr);
rp2350_write_mem8(target, addr, byte);

uint32_t buf[256];
rp2350_read_mem_block(target, 0x20000000, buf, 256);
rp2350_write_mem_block(target, 0x20000000, buf, 256);

I trasferimenti a blocchi utilizzano l'auto-incremento SBA per le prestazioni.

Esecuzione di Codice

root@kitploit:~
const uint32_t program[] = {
    0x200415b7,  // lui  a1, 0x20040
    0xabcd0537,  // lui  a0, 0xabcd0
    0x00a5a223,  // sw   a0, 4(a1)
    0x0000006f,  // j    . (loop)
};

rp2350_execute_code(target, 0, 0x20000000, program, 4);

Carica nella SRAM di destinazione, verifica, imposta PC, riprende.

Tracciamento delle Istruzioni

root@kitploit:~
bool on_instruction(const trace_record_t *rec, void *ctx) {
    printf("0x%08x: 0x%08x\n", rec->pc, rec->instruction);
    return true;
}

int traced = rp2350_trace(target, 0, 100, on_instruction, NULL, false);

Esegue passo passo le istruzioni tramite DCSR.step. ~5ms per istruzione senza cattura registro, ~80ms con cattura registro completa.

Buffer di Programma

Esecuzione diretta di istruzioni RISC-V in contesto di debug:

root@kitploit:~
uint32_t progbuf[] = {
    0x34202473,  // csrr s0, mcause
    0x00100073   // ebreak
};
rp2350_execute_progbuf(target, 0, progbuf, 2);
swd_result_t mcause = rp2350_read_reg(target, 0, 8);

L'accesso CSR utilizza questo internamente poiché Hazard3 non supporta comandi CSR astratti.

Compilazione

root@kitploit:~
add_subdirectory(lib/pico2-swd-riscv)
target_link_libraries(your_app pico2_swd_riscv)

Verbositù di debug (a tempo di compilazione):

root@kitploit:~
set(PICO2_SWD_DEBUG_LEVEL 3)  # 0=none, 1=warn, 2=info, 3=debug

Interni

Protocollo Wire

SWD utilizza pacchetti di richiesta a 8 bit (start, APnDP, RnW, addr[3:2], parity, stop, park), ACK a 3 bit (OK=1, WAIT=2, FAULT=4) e fasi dati a 33 bit con parità. I cicli di turnaround gestiscono i cambi di direzione SWDIO. Le risposte WAIT vengono ritentate automaticamente (default: 5 tentativi, backoff di 100us).

Codifica DP_SELECT di RP2350

Non standard: [15:12]=APSEL, [11:8]=0xD, [7:4]=bank, [0]=ctrlsel. Il 0xD nei bit[11:8] è richiesto ma non documentato.

Attivazione DM

Handshake a tre fasi tramite CSW del Bank 1: disattivazione (0x00000000), attivazione (0x00000001), configurazione completa (0x07FFFFC1). Risposta di stato prevista: 0x04010001.

Accesso ai Registri

GPR tramite comandi astratti (regno 0x1000+n, trasferimento a 32 bit). CSR tramite buffer di programma: salva s0, esegue csrr s0, <csr> o csrw <csr>, s0, legge/ripristina s0.

Accesso al Bus di Sistema

SBCS configurato con sbaccess=32bit e sbreadonaddr. Scrivere SBADDRESS0 attiva la lettura del bus; i dati sono immediatamente disponibili in SBDATA0. I trasferimenti a blocchi abilitano sbautoincrement per letture/scritture in streaming senza impostare l'indirizzo per ogni parola.

Passo Singolo

Legge DCSR tramite progbuf, imposta il bit step (bit 2), riprende l'hart. L'hart esegue un'istruzione e rientra in modalità debug. Cancella il bit step dopo.

Limitazioni

  • Nessun breakpoint hardware (modulo trigger rimosso, pianificato per la reimplementazione)
  • Nessun SWD multi-drop
  • Nessuna decodifica di istruzioni compresse (legge correttamente, non decodifica i mnemonici)
  • Nessuna programmazione flash (ottenibile tramite rp2350_execute_code con uno stub)
  • Nessuna profilazione ciclo-esatta

Riferimenti

  • RISC-V External Debug Support v0.13
  • ARM Debug Interface Architecture Specification ADIv5/v6
  • RP2350 Datasheet, Chapter 3.5
  • ARM CoreSight SWD-DP Technical Reference Manual

Licenza

MIT. Vedi LICENSE.

Scarica lo strumento