无法理解混淆的C代码

Ras*_*yak 3 c obfuscation

我看到这个代码http://www.cise.ufl.edu/~manuel/obfuscate/obfuscate.html(http://www.cise.ufl.edu/~manuel/obfuscate/savastio)网站.但是这个代码非常非常疯狂 当它发生时,我无法理解发生了什么.请帮我.让我知道每一行执行时发生了什么.例如,printf函数在那里,如果我们将看到没有被称为" Enter the number"的语句.但仍然在执行它时问" Enter the number".来自哪里.为什么代码是这样编写的.它看起来像" n!"(虽然它意味着阶乘).请帮我.

#include <stdio.h>

#define l11l 0xFFFF
#define ll1 for
#define ll111 if
#define l1l1 unsigned
#define l111 struct
#define lll11 short
#define ll11l long
#define ll1ll putchar
#define l1l1l(l) l=malloc(sizeof(l111 llll1));l->lll1l=1-1;l->ll1l1=1-1;
#define l1ll1 *lllll++=l1ll%10000;l1ll/=10000;
#define l1lll ll111(!l1->lll1l){l1l1l(l1->lll1l);l1->lll1l->ll1l1=l1;}\
lllll=(l1=l1->lll1l)->lll;ll=1-1;
#define llll 1000




                                                     l111 llll1 {
                                                     l111 llll1 *
      lll1l,*ll1l1        ;l1l1                      lll11 lll [
      llll];};main      (){l111 llll1                *ll11,*l1l,*
      l1, *ll1l, *    malloc ( ) ; l1l1              ll11l l1ll ;
      ll11l l11,ll  ,l;l1l1 lll11 *lll1,*            lllll; ll1(l
      =1-1 ;l< 14; ll1ll("\t\"8)>l\"9!.)>vl"         [l]^'L'),++l
      );scanf("%d",&l);l1l1l(l1l) l1l1l(ll11         ) (l1=l1l)->
      lll[l1l->lll[1-1]     =1]=l11l;ll1(l11         =1+1;l11<=l;
      ++l11){l1=ll11;         lll1 = (ll1l=(         ll11=l1l))->
      lll; lllll =(            l1l=l1)->lll;         ll=(l1ll=1-1
      );ll1(;ll1l->             lll1l||l11l!=        *lll1;){l1ll
      +=l11**lll1++             ;l1ll1 ll111         (++ll>llll){
      l1lll lll1=(              ll1l =ll1l->         lll1l)->lll;
      }}ll1(;l1ll;              ){l1ll1 ll111        (++ll>=llll)
      { l1lll} } *              lllll=l11l;}
      ll1(l=(ll=1-              1);(l<llll)&&
      (l1->lll[ l]              !=l11l);++l);        ll1 (;l1;l1=
      l1->ll1l1,l=              llll){ll1(--l        ;l>=1-1;--l,
      ++ll)printf(              (ll)?((ll%19)        ?"%04d":(ll=
      19,"\n%04d")              ):"%4d",l1->         lll[l] ) ; }
                                                     ll1ll(10); }
Run Code Online (Sandbox Code Playgroud)

huo*_*uon 10

首先,您可以正确缩进代码并删除由#defines 引起的间接.缩进可以由GNUindent完成,gcc -E并将进行预处理.假设代码在factorial.c(这需要使用命令行):

> gcc -E factorial.c | indent > clean_factorial.c
Run Code Online (Sandbox Code Playgroud)

需要注意的是预处理步骤将全部stdio.h转入clean_factorial.c; 但那是无关紧要的信息,所以我们应该#include<stdio.h>在运行之前注释掉/删除gcc -E.这基本上给出:

struct llll1
{
  struct llll1 *lll1l, *ll1l1;
  unsigned short lll[1000];
};
main ()
{
  struct llll1 *ll11, *l1l, *l1, *ll1l, *malloc ();
  unsigned long l1ll;
  long l11, ll, l;
  unsigned short *lll1, *lllll;
  for (l = 1 - 1; l < 14; putchar ("\t\"8)>l\"9!.)>vl"[l] ^ 'L'), ++l);
  scanf ("%d", &l);
  l1l = malloc (sizeof (struct llll1));
  l1l->lll1l = 1 - 1;
  l1l->ll1l1 = 1 - 1;
  ll11 = malloc (sizeof (struct llll1));
  ll11->lll1l = 1 - 1;
  ll11->ll1l1 = 1 - 1;
  (l1 = l1l)->lll[l1l->lll[1 - 1] = 1] = 0xFFFF;
  for (l11 = 1 + 1; l11 <= l; ++l11)
    {
      l1 = ll11;
      lll1 = (ll1l = (ll11 = l1l))->lll;
      lllll = (l1l = l1)->lll;
      ll = (l1ll = 1 - 1);
      for (; ll1l->lll1l || 0xFFFF != *lll1;)
        {
          l1ll += l11 ** lll1++;
          *lllll++ = l1ll % 10000;
          l1ll /= 10000;
          if (++ll > 1000)
            {
              if (!l1->lll1l)
                {
                  l1->lll1l = malloc (sizeof (struct llll1));
                  l1->lll1l->lll1l = 1 - 1;
                  l1->lll1l->ll1l1 = 1 - 1;;
                  l1->lll1l->ll1l1 = l1;
                }
              lllll = (l1 = l1->lll1l)->lll;
              ll = 1 - 1;
              lll1 = (ll1l = ll1l->lll1l)->lll;
            }
        }
      for (; l1ll;)
        {
          *lllll++ = l1ll % 10000;
          l1ll /= 10000;
          if (++ll >= 1000)
            {
              if (!l1->lll1l)
                {
                  l1->lll1l = malloc (sizeof (struct llll1));
                  l1->lll1l->lll1l = 1 - 1;
                  l1->lll1l->ll1l1 = 1 - 1;;
                  l1->lll1l->ll1l1 = l1;
                }
              lllll = (l1 = l1->lll1l)->lll;
              ll = 1 - 1;
            }
        }
      *lllll = 0xFFFF;
    }
  for (l = (ll = 1 - 1); (l < 1000) && (l1->lll[l] != 0xFFFF); ++l);
  for (; l1; l1 = l1->ll1l1, l = 1000)
    {
      for (--l; l >= 1 - 1; --l, ++ll)
        printf ((ll) ? ((ll % 19) ? "%04d" : (ll =
                                              19, "\n%04d")) : "%4d",
                l1->lll[l]);
    }
  putchar (10);
}
Run Code Online (Sandbox Code Playgroud)

这有点可读,我们可以做一些事情,比如重命名变量,以便我们可以轻松区分它们,即使我们还不知道它们做了什么.例如,这将重命名的结构来structure,并调用它里面的指针leftright(你可以在你的编辑器中找到替换工具这样做太):

> sed -i 's/llll1/structure/g; s/lll1l/left/g; s/ll1l1/right/g;' clean_factorial.c
Run Code Online (Sandbox Code Playgroud)

(你必须小心订单,或者替换lll可能与之相冲突lllll).

还有其他一些简单的事情要做:

  • 1 - 1发生了很多:用它替换0(以及1 + 1替换它2代替0).
  • "\t\"8)>l\"9!.)>vl"[l] ^ 'L'在xor'ing之后,只是沿着字符串打印每个字符的行'L'(找出原因!它可能有助于将putcharfor循环的主体放入,而不是在逗号语句中).
  • putchar(10) 只是打印一个新行.
  • 了解逗号运算符.

除此之外,这只是一项艰苦的工作.您可以而且应该使用调试器之类的工具来跟踪执行流程并找出正在发生的事情.