SHARE
TWEET

unshc decompile/decrypt shc ARM binaries

a guest Sep 12th, 2013 108 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/perl -w
  2. # Public Domain
  3. # By Veg with very little pride
  4. # V1.0 2013
  5.  
  6. # Recover a script 'compiled' with the dreadful tool "shc" on ARM.
  7. # This is my version of unshc.sh <http://www.l0d.org/Decrypt_an_shc_crypted_file.html>
  8. # but for ARM binaries.
  9. # If you or anyone you know has been tempted to use shc for any purpose whatsoever,
  10. # please seek help from your local psychiatrist or cryptologist.
  11.  
  12. my @names = ("msg1", "date", "shll", "inlo", "xecc", "lsto", "tst1", "chk1", "msg2", "rlax", "opts", "text", "tst2", "chk2", "pswd");
  13. my $inxsh = 0;
  14. my $gotkey = 0;
  15. my @size;
  16. my @addr;
  17. my @fakemem;
  18. my $ct = 0;
  19. my %reg;
  20.  
  21. my $objdump = "arm-linux-gnueabi-objdump";
  22. my $bin = $ARGV[0];
  23.  
  24. sub load {
  25.     my ($addr, $bytes) = @_;
  26.     my $index = hex($addr);
  27.     $bytes =~ s/ //g;
  28.     for($i = 0; $i <16; $i++) {
  29.         my $byte = (length($bytes) >= $i * 2) ? hex(substr($bytes, $i * 2, 2)) : 0;
  30.         $fakemem[$index + $i] = $byte;
  31.     }
  32. }
  33.  
  34. die if ! -f $bin;
  35. system($objdump." -d ".$bin. " >disas.txt");
  36. system($objdump." -s ".$bin. " >dump");
  37.  
  38. open O, ">dec.c" or die;
  39.  
  40.  
  41. open DI,"disas.txt" or die;
  42. while(<DI>) {
  43.     next if (!$inxsh && !($_ =~ '<xsh>:'));
  44.     $inxsh=1;
  45.     if ($_ =~/(ldr|mov)\s+(r[013]),\s*(.*)/) {
  46.         $reg{$2} = $3;
  47.     } elsif ((!$gotkey) && ($_ =~/bl\s+[^<]+\s+<key>/)) {
  48.         $gotkey = 1;
  49.         $size[scalar(@names) -1] = $reg{r1};
  50.         $addr[scalar(@names) -1] = $reg{r3};
  51.     } elsif ($_ =~/bl\s+[^<]+\s+<arc4>/) {
  52.         $size[$ct] = $reg{r1};
  53.         $addr[$ct] = exists($reg{r3}) ? $reg{r3} : $reg{r0};
  54.         undef(%reg);
  55.         $ct++;
  56.     } elsif ($_ =~/^\s*([\da-f]+):\s+([\da-f]+)\s/) {
  57.         $fakemem[hex($1)] = hex($2);
  58.     }
  59. }
  60. close DI;
  61.  
  62. for(my $c = 0; $c < @size; $c++) {
  63.     if ($size[$c] =~ /^#(\d+)/) {
  64.         $size[$c] = $1;
  65.     } elsif ($size[$c] =~ /\s+;\s*([\da-f]+)/) {
  66.         $size[$c] = $fakemem[hex($1)];
  67.     }
  68.     $addr[$c] =~ /\s+;\s*([\da-f]+)/;
  69.     $addr[$c] = $fakemem[hex($1)];
  70.     #printf("#define ".$names[$c]."_z 0x%x %d %d\n",$size[$c], $size[$c], $addr[$c]);
  71.     printf(O "#define ".$names[$c]."_z 0x%x\n",$size[$c]);
  72. }
  73.  
  74. @fakemem=();
  75.  
  76. open D, "dump" or die;
  77. while(<D>) {
  78.     next if ! ($_ =~ /^\s*\d+/);
  79.     my ($addr, $bytes) = $_ =~/^\s*([\da-f]+)\s+([\da-f\s]+)\s\s.*/;
  80.     load($addr, $bytes);
  81. }
  82. close D;
  83.  
  84.  
  85. for(my $c=0; $c < @addr; $c++) {
  86.     my $adr = $addr[$c];
  87.     my $len = $size[$c];
  88.     print O 'static char '.$names[$c].' [] ="';
  89.     for(my $i = 0; $i < $len ; $i++) {
  90.         printf( O '\x%02x', $fakemem[($adr + $i)]);
  91.         if ($i % 16 == 0xf) {
  92.             printf(O "\"\n\"");
  93.         }
  94.     }
  95.     print O "\";\n";
  96. }
  97.  
  98. $dec = <<END;
  99.  
  100. #define      hide_z     4096
  101.  
  102. /* rtc.c */
  103.  
  104. #include <sys/stat.h>
  105. #include <sys/types.h>
  106.  
  107. #include <errno.h>
  108. #include <stdio.h>
  109. #include <stdlib.h>
  110. #include <string.h>
  111. #include <time.h>
  112. #include <unistd.h>
  113.  
  114. /* 'Alleged RC4' */
  115.  
  116. static unsigned char stte[256], indx, jndx, kndx;
  117.  
  118. /*
  119.  * Reset arc4 stte.
  120.  */
  121. void stte_0(void)
  122. {
  123.         indx = jndx = kndx = 0;
  124.         do {
  125.                 stte[indx] = indx;
  126.         } while (++indx);
  127. }
  128.  
  129. /*
  130.  * Set key. Can be used more than once.
  131.  */
  132. void key(void * str, int len)
  133. {
  134.         unsigned char tmp, * ptr = (unsigned char *)str;
  135.         while (len > 0) {
  136.                 do {
  137.                         tmp = stte[indx];
  138.                         kndx += tmp;
  139.                         kndx += ptr[(int)indx % len];
  140.                         stte[indx] = stte[kndx];
  141.                         stte[kndx] = tmp;
  142.                 } while (++indx);
  143.                 ptr += 256;
  144.                 len -= 256;
  145.         }
  146. }
  147.  
  148. /*
  149.  * Crypt data.
  150.  */
  151. void arc4(void * str, int len)
  152. {
  153.         unsigned char tmp, * ptr = (unsigned char *)str;
  154.         while (len > 0) {
  155.                 indx++;
  156.                 tmp = stte[indx];
  157.                 jndx += tmp;
  158.                 stte[indx] = stte[jndx];
  159.                 stte[jndx] = tmp;
  160.                 tmp += stte[indx];
  161.                 *ptr ^= stte[tmp];
  162.                 ptr++;
  163.                 len--;
  164.         }
  165. }
  166.  
  167. /* End of ARC4 */
  168.  
  169. /*
  170.  * Key with file invariants.
  171.  */
  172. int key_with_file(char * file)
  173. {
  174.         struct stat statf[1];
  175.         struct stat control[1];
  176.  
  177.         if (stat(file, statf) < 0)
  178.                 return -1;
  179.  
  180.         /* Turn on stable fields */
  181.         memset(control, 0, sizeof(control));
  182.         control->st_ino = statf->st_ino;
  183.         control->st_dev = statf->st_dev;
  184.         control->st_rdev = statf->st_rdev;
  185.         control->st_uid = statf->st_uid;
  186.         control->st_gid = statf->st_gid;
  187.         control->st_size = statf->st_size;
  188.         control->st_mtime = statf->st_mtime;
  189.         control->st_ctime = statf->st_ctime;
  190.         key(control, sizeof(control));
  191.         return 0;
  192. }
  193.  
  194. void rmarg(char ** argv, char * arg)
  195. {
  196.         for (; argv && *argv && *argv != arg; argv++);
  197.         for (; argv && *argv; argv++)
  198.                 *argv = argv[1];
  199. }
  200.  
  201. int chkenv(int argc)
  202. {
  203.         char buff[512];
  204.         unsigned mask, m;
  205.         int l, a, c;
  206.         char * string;
  207.         extern char ** environ;
  208.  
  209.         mask  = (unsigned)chkenv;
  210.         mask ^= (unsigned)getpid() * ~mask;
  211.         sprintf(buff, "x%x", mask);
  212.         string = getenv(buff);
  213.         l = strlen(buff);
  214.         if (!string) {
  215.                 /* 1st */
  216.                 sprintf(&buff[l], "=%u %d", mask, argc);
  217.                 putenv(strdup(buff));
  218.                 return 0;
  219.         }
  220.         c = sscanf(string, "%u %d%c", &m, &a, buff);
  221.         if (c == 2 && m == mask) {
  222.                 /* 3rd */
  223.                 rmarg(environ, &string[-l - 1]);
  224.                 return 1 + (argc - a);
  225.         }
  226.         return -1;
  227. }
  228.  
  229. char * xsh(int argc, char ** argv)
  230. {
  231.         char * scrpt;
  232.         int ret, i, j;
  233.         char ** varg;
  234.  
  235.         stte_0();
  236.          key(pswd, pswd_z);
  237.         arc4(msg1, msg1_z);
  238.         arc4(date, date_z);
  239.         if (date[0] && date[0]<time(NULL))
  240.                 return msg1;
  241.         arc4(shll, shll_z);
  242.         arc4(inlo, inlo_z);
  243.         arc4(xecc, xecc_z);
  244.         arc4(lsto, lsto_z);
  245.         arc4(tst1, tst1_z);
  246.          key(tst1, tst1_z);
  247.         arc4(chk1, chk1_z);
  248.         if ((chk1_z != tst1_z) || memcmp(tst1, chk1, tst1_z))
  249.                 return tst1;
  250.         ret = chkenv(argc);
  251.         arc4(msg2, msg2_z);
  252.         if (ret < 0)
  253.                 return msg2;
  254.         varg = (char **)calloc(argc + 10, sizeof(char *));
  255.         if (!varg)
  256.                 return 0;
  257.         if (1) {
  258.                 arc4(rlax, rlax_z);
  259.                 if (!rlax[0] && key_with_file(shll))
  260.                         return shll;
  261.                 arc4(opts, opts_z);
  262.                 arc4(text, text_z);
  263.                 //FILE *fp = fopen("script","w");
  264.                 //fwrite(text, 1, text_
  265.  
  266.                 printf("%s",text);
  267.                 return 0;
  268.                 arc4(tst2, tst2_z);
  269.                  key(tst2, tst2_z);
  270.                 arc4(chk2, chk2_z);
  271.                 if ((chk2_z != tst2_z) || memcmp(tst2, chk2, tst2_z))
  272.                         return tst2;
  273.                 if (text_z < hide_z) {
  274.                         /* Prepend spaces til a hide_z script size. */
  275.                         scrpt = malloc(hide_z);
  276.                         if (!scrpt)
  277.                                 return 0;
  278.                         memset(scrpt, (int) ' ', hide_z);
  279.                         memcpy(&scrpt[hide_z - text_z], text, text_z);
  280.                 } else {
  281.                         scrpt = text;   /* Script text */
  282.                 }
  283.         } else {                        /* Reexecute */
  284.                 if (*xecc) {
  285.                         scrpt = malloc(512);
  286.                         if (!scrpt)
  287.                                 return 0;
  288.                         sprintf(scrpt, xecc, argv[0]);
  289.                 } else {
  290.                         scrpt = argv[0];
  291.                 }
  292.         }
  293.         j = 0;
  294.         varg[j++] = argv[0];            /* My own name at execution */
  295.         if (ret && *opts)
  296.                 varg[j++] = opts;       /* Options on 1st line of code */
  297.         if (*inlo)
  298.                 varg[j++] = inlo;       /* Option introducing inline code */
  299.         varg[j++] = scrpt;              /* The script itself */
  300.         if (*lsto)
  301.                 varg[j++] = lsto;       /* Option meaning last option */
  302.         i = (ret > 1) ? ret : 0;        /* Args numbering correction */
  303.         while (i < argc)
  304.                 varg[j++] = argv[i++];  /* Main run-time arguments */
  305.         varg[j] = 0;                    /* NULL terminated array */
  306.         int q =0 ;
  307.         printf("Running: %s", shll);
  308.         while (varg[q]) {
  309.             printf(" \\"%s\\"", varg[q++]);
  310.         }
  311.         printf("\\n");
  312.         execvp(shll, varg);
  313.         return shll;
  314. }
  315.  
  316. int main(int argc, char ** argv)
  317. {
  318.         argv[1] = xsh(argc, argv);
  319.         return 1;
  320. }
  321. END
  322.  
  323. print O $dec;
  324. close O;
  325. system("gcc -o dec dec.c && ./dec");
RAW Paste Data
Top