Guest User

unshc decompile/decrypt shc ARM binaries

a guest
Sep 12th, 2013
257
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

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×