Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
pico2-swd-riscv | Kitploit
Outils/GitHubGitHub/jackdoe/pico2-swd-riscv
Sécurité des Systèmes EmbarquésRétro-ingénierieDébogueursHacking MatérielSécurité MatérielleAnalyse de Micrologiciel
GitHubjackdoe/pico2-swd-riscv

pico2-swd-riscv

Voir le dépôt
853il y a 6 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

pico2-swd-riscv

Son de débogage SWD pour les cœurs RISC-V (Hazard3) RP2350. Un Pico2 en débogue un autre via deux fils GPIO.

0. VIBE CODE WARNING (ÉCRIT PAR UN HUMAIN)

Environ 80% du code est du vibe codé ; le readme est presque entièrement généré (sauf toute la section d'avertissement vibe-code). J'ai passé de nombreuses nuits avec l'oscilloscope et la doc et j'ai créé un prototype fonctionnel capable de faire des sba/read/write regs et des commandes abstraites et progbuf, le reste a été fait avec claude code. Les tests sont une suite de tests assez complète et j'utilise le cœur de la bibliothèque dans mes propres projets, mais, comme on dit, « hic sunt dracones ». J'ai aussi lu le readme et le code n'avait rien de mal (et j'ai supprimé les parties fausses/peu claires).

Ce projet était mon cas d'étude de vibecoding d'un projet plus compliqué que je ne comprends pas à 100% et pour lequel il n'existe pas de code existant évident pouvant être « utilisé ». Il a commencé comme ~1000 lignes que j'avais écrites et que je connaissais très bien, lisant les docs rp2350, arm swd et riscv debug, capturant des données avec oscilloscope et openocd, puis les décodant et analysant la séquence de réveil puis les commandes de lecture/écriture. Après l'avoir fait fonctionner, je l'ai donné à claude pour en faire une bibliothèque que je pourrais utiliser dans d'autres projets, puis je l'ai lentement développé.

Après environ 3 à 4 000 lignes de code, j'ai complètement perdu le fil de ce qui se passait, et je ne considérerais pas ce code comme étant le mien, mais ajouter de plus en plus de tests semblait « bien », ou du moins rassurant.

Il y a eu un certain gaslighting, en particulier quand il a mal compris dap_read_mem32 en pensant qu'il lisait depuis la RAM et non le protocole MEM-AP TAR/DRW/RDBUFF, ce qui a conduit à une quantité incroyable de non-sens.

Dans l'ensemble, je dirais que c'était une expérience horrible, même s'il a fallu 10 heures pour écrire près de 10 000 lignes de code, je ne considère pas ce projet comme le mien, et je n'ai aucun sentiment d'accomplissement ou de croissance.

En revanche, utiliser l'IA pour lire tous les docs (des milliers de pages) et écrire des scripts utiles pour décoder les données d'oscilloscope, créer des structures C packées à partir des docs, etc., était très agréable, et je me suis senti bien après. Le moment où j'ai lu le premier registre et puis quand j'ai pu lire la mémoire via SBA, je me suis senti incroyablement bien.

Le problème principal est le « goût », quand j'écris du code, je sens si c'est bon ou mauvais, au moment où je l'écris, je sais si c'est faux, mais en utilisant claude code, je deviens très vite insensibilisé et je ne peux tout simplement pas dire, ça « se lit » OK, mais je ne sais pas ce que ça ressent. Dans ce cas, c'est arrivé quand le code a grossi d'environ 4 fois, de 1k à 4k lignes. Et pire de tout, mon modèle mental du code a complètement disparu, et avec lui, ma propriété.

Les tokens n'ont ni raison ni but, ce qui rend la lecture du code ridiculement difficile, car chaque token peut être un non-sens complet. Quand on lit du code humain, les symboles ont un but, quelqu'un a pensé « Je vais mettre ça dans une variable, plus tard je vérifierai son statut. », donc je fais comme si j'étais lui, et je pense pourquoi aurait-il écrit cela ? Peu après je comprends, car ils sont humains et je suis humain. Mais les symboles de l'IA n'ont aucune raison, et pire de tout, ils ont tous l'air trompeusement corrects, donc je dois réfléchir 10 fois plus fort pour savoir si c'est faux. Avec tout code humain (y compris le vôtre), il est assez facile d'évaluer à quel point vous pouvez lui faire confiance, et c'est assez cohérent, avec le code de l'IA, une fonction peut être bien meilleure que ce que vous auriez écrit, et le code 2 lignes en dessous peut être un ramassis de cargo culting qui a l'air incroyablement bon, mais structurellement faux.

Au final, je dirais que j'ai acquis une bonne compréhension des fils, des timings, et des mécanismes de bas niveau ap/dp, sba et progbuf, mais je regrette de ne pas avoir tout écrit moi-même, même si cela aurait pris 10 fois plus de temps.

Je déteste ça, bordel.

Et je ne peux pas m'empêcher de ressentir du dégoût et de la honte. Est-ce que c'est ça, la programmation maintenant ? J'espère vraiment que c'est une étape intermédiaire et que ça changera pour le mieux, le problème c'est que je ne sais pas ce qu'est « mieux », ça semble pour certaines personnes ne pas avoir à écrire le code, pour d'autres ne pas modéliser le problème et pour d'autres encore ne pas avoir à penser. Pour moi, je ne suis pas sûr, je veux faire des choses, et souvent je ne veux pas savoir quelque chose, mais je veux l'utiliser, par exemple le contrôleur hôte USB rp2350, la façon dont vous devez réarmer les interruptions et la façon dont le registre epx est partagé est super ennuyeuse, pour de bonnes raisons probablement, mais je veux juste l'utiliser pour créer mon pilote CBI.

Je suppose que la question est : qu'est-ce que je veux faire ? parce qu'on peut remonter la pile, des registres de la puce USB à CBI à UFI à FAT16 au système d'exploitation du vieil ordinateur que je fabrique, mais pourquoi s'arrêter ? faire les schémas, les PCBs, les fichiers CAO, peut-être l'envoyer automatiquement à l'usine ? et puis me l'expédier ? mais pourquoi s'arrêter ? créer ma boutique en ligne, commencer à vendre, créer une communauté, des pubs, du marketing, générer des vidéos de déballage, peut-être des memes viraux ? traiter les commandes directement à l'usine, à la demande, s'il y a un problème, il est prêt avec le service client.

Qu'est-ce que je fais entre-temps ? je m'assois sur la plage ? je déteste la plage.

Où ça s'arrête ?

PS : comme l'a dit le poète : le prix pour obtenir ce que vous voulez, c'est d'obtenir ce que vous vouliez autrefois.

Architecture

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)

Chaque couche maintient son propre état et ne communique qu'avec son voisin.

Usage

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);

Hart Control

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);

Les deux harts (0 et 1) sont contrôlables indépendamment.

Memory Access

Accès non intrusif via le bus système. Fonctionne pendant que le hart s'exécute.

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);

Les transferts par blocs utilisent l'auto-incrémentation SBA pour les performances.

Code Execution

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);

Télécharge dans la SRAM cible, vérifie, définit le PC, reprend.

Instruction Tracing

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);

Exécute pas à pas les instructions via DCSR.step. ~5ms par instruction sans capture de registre, ~80ms avec capture complète des registres.

Program Buffer

Exécution directe d'instructions RISC-V dans le contexte de débogage :

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'accès aux CSR utilise cela en interne car Hazard3 ne supporte pas les commandes CSR abstraites.

Building

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

Verbose de débogage (au moment de la compilation) :

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

Internals

Wire Protocol

SWD utilise des paquets de requête 8 bits (start, APnDP, RnW, addr[3:2], parity, stop, park), un ACK 3 bits (OK=1, WAIT=2, FAULT=4) et des phases de données 33 bits avec parité. Les cycles de turnaround gèrent les changements de direction SWDIO. Les réponses WAIT sont retentées automatiquement (par défaut : 5 tentatives, backoff de 100µs).

RP2350 DP_SELECT Encoding

Non standard : [15:12]=APSEL, [11:8]=0xD, [7:4]=bank, [0]=ctrlsel. Le 0xD dans les bits[11:8] est requis mais non documenté.

DM Activation

Handshake en trois phases via le Bank 1 CSW : désactiver (0x00000000), activer (0x00000001), configuration complète (0x07FFFFC1). Réponse de statut attendue : 0x04010001.

Register Access

GPR via commandes abstraites (regno 0x1000+n, transfert 32 bits). CSR via buffer de programme : sauvegarder s0, exécuter csrr s0, <csr> ou csrw <csr>, s0, lire/restaurer s0.

System Bus Access

SBCS configuré avec sbaccess=32bit et sbreadonaddr. L'écriture de SBADDRESS0 déclenche la lecture du bus ; les données sont immédiatement disponibles dans SBDATA0. Les transferts par blocs activent sbautoincrement pour des lectures/écritures en continu sans configuration d'adresse par mot.

Single-Step

Lire DCSR via progbuf, définir le bit step (bit 2), reprendre le hart. Le hart exécute une instruction et rentre à nouveau en mode débogage. Effacer le bit step après.

Limitations

  • Aucun point d'arrêt matériel (module de déclenchement retiré, prévu pour réimplémentation)
  • Pas de SWD multi-chute
  • Pas de décodage d'instructions compressées (lit correctement, ne décode pas les mnémoniques)
  • Pas de programmation flash (réalisable via rp2350_execute_code avec un stub)
  • Pas de profilage précis au cycle près

References

  • 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

License

MIT. See LICENSE.

Télécharger l’outil