/ analysis / unscramble.c
unscramble.c
 1  // run with gcc -Wall -g -o unscramble unscramble.c && ./unscramble
 2  #include <stdint.h>
 3  #include <string.h>
 4  #include <stdio.h>
 5  #include <stdarg.h>
 6  
 7  void dump(const uint8_t *p, const size_t len, const char* msg, ...) {
 8    va_list args;
 9    va_start(args, msg);
10    vfprintf(stderr,msg, args);
11    va_end(args);
12    fprintf(stderr," ");
13    for(size_t i=0;i<len;i++)
14      fprintf(stderr,"%02x", p[i]);
15    fprintf(stderr,"\n");
16  }
17  
18  void unscramble(uint8_t *ct) {
19    uint8_t tmp, r2, r3;
20    uint8_t tbit, CY;
21    int dptr = 0;
22    dptr = 6; // skip first block which is a nonce
23    // see scramble.py for how the bits of *dptr and *intmem[4a..4c] are processed before output
24    // unscrambles bits
25    uint8_t buf[3];
26    do {
27      uint8_t r0 = 0;
28      for(r2 = 5; r2>0; r2--) {
29        tmp = ct[dptr];            // 1b58
30        CY=tmp<0xfe;               // set carry due to CJNE at 1b59
31        if(tmp!=0xfe) dptr++;
32        tmp--; // 1b5f dec a
33        tmp = (tmp << 4) | (tmp >> 4); // 1b60 swap a
34        for(r3 = 4;r3>0;r3--) {
35          // 1b61 rlc a
36          tbit=CY;
37          CY=tmp & 0x80;
38          tmp=(tmp<<1) | tbit;
39          // 1b62 xchg A, INTMEM[r0]
40          uint8_t tmp1 = tmp;
41          tmp=buf[r0];
42          buf[r0]=tmp1;
43          // 1b63 rrc a
44          tbit = CY;
45          CY = tmp & 1;
46          tmp = tbit | (tmp >> 1);
47          // 1b64 xchg a, intmem[r0]
48          tmp1 = tmp;
49          tmp=buf[r0];
50          buf[r0]=tmp1;
51          r0++;
52          CY=r0<3;
53          if(r0==3) r0=0;
54        }
55      }
56      for(r0 = 0;r0!=3;r0++) {
57        tmp = buf[r0]; // 1b71
58        CY=r0<2;
59        if(r0==2) {
60          // 1b75 rrc a
61          tbit=CY;
62          CY=tmp&1;
63          tmp = (tbit << 7) | (tmp >> 1);
64        }
65  
66        // 1b76 rrc a
67        tbit=CY;
68        CY=tmp&1;
69        tmp = (tbit << 7) | (tmp >> 1);
70        tmp &= 0x3f; // 1b7a
71        printf("%02x", tmp);
72      }
73    } while (ct[dptr++]!=0xfe && ct[dptr]!=' ' && ct[dptr]!=0xfe);
74    printf("\n");
75  }
76  
77  int main(void) {
78    // navelpluis
79    const uint8_t ct[]="LEEIC BIIKY DBCFE DPKLB ECILE\xfe";
80                       //"JDMNJ AEJHP CPBLO JPJDD BEDNG\xfe"
81    // hello world
82    //const uint8_t ct[]="BAMLK GAFFJ EOBCP EEIMP CDAFP\xfe";
83    //const uint8_t ct[]="HMBGL MMAEG OILPM LBCHE NCAFJ\xfe";
84    //const uint8_t ct[]="HMMHI EAPIO OGBBI HLOPI GGIEK\xfe";
85    // other msg
86    uint8_t ctx[sizeof ct-1]={0};
87    int i;
88    for(i=0;ct[i]!=0xfe;i++) {
89      ctx[i]=(ct[i] & 0x3f);
90    }
91    ctx[i]=ct[i];
92    unscramble(ctx);
93  
94    return 0;
95  }