⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decompile5.c

📁 flash swf file player
💻 C
📖 第 1 页 / 共 4 页
字号:
/*  take a stack, turn it into a tree.  e.g.:  cmd        stack  push 'a'   'a'  push 'a'   'a' 'a'  getvar     'a'  a  push '1'   'a'  a   1  add        'a'  a+1  setvar     a = a+1*/#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>#include "decompile.h"#include "read.h"#include "action.h"#define puts(s) fputs((s),stdout)static int gIndent;typedef enum{  BRANCH_NONE = 0,  BRANCH_WHILE,  BRANCH_DO,  BRANCH_IF,  BRANCH_ELSE} Branchtype;static int readStatements(FILE *f, int length, Stack **slist);void decompileStatements(Stack *statements, int n);static void listItem(Stack s, Action parent);static void resolveOffsets(Stack *statements, int nStatements);static void untangleBranches(Stack *statements, int start, int stop,			     Branchtype type, int indent);static Stack negateExpression(Stack s);char **dictionary;Stack reg0;static int isNum(char *s){  float f = atof(s);  if(f != 0 || s[0] == '0')    return true;  else    return false;}int intVal(Stack s){  if(s->type == 'i')    return s->data.inum;  if(s->type == 'd')    return (int)floor(s->data.dnum);  if(s->type == 's')    return atoi(s->data.string);  if(s->type == 't')    error("Can't call intVal on a tree!");  return 0;}static Stack stack = NULL;static Stack newStack(){  Stack s = (Stack)malloc(sizeof(struct _stack));  memset(s, 0, sizeof(struct _stack));  s->target = -1;  return s;}static void destroyTree(Stack s){  if(!s)    return;  if(s->type == 't')  {    destroyTree(s->data.tree->left);    destroyTree(s->data.tree->right);    free(s->data.tree);  }  else if(s->type == 's')    free(s->data.string);  free(s);}static void destroy(Stack s){  if(!s)    return;  if(s->type == 't')    free(s->data.tree);  else if(s->type == 's')    free(s->data.string);  free(s);}#define min(a,b) (((a)<(b))?(a):(b))/* XXX - this is lame nomenclature */static Stack newTreeBase(Stack left, Action action, Stack right){  Tree t = (Tree)malloc(sizeof(struct _tree));  Stack s = newStack();  t->left = left;  t->right = right;  t->action = action;  s->type = 't';  s->data.tree = t;  return s;}static Stack newTree(Stack left, Action action, Stack right){  Stack s = newTreeBase(left, action, right);  /* propagate offset values- tree head should have offset = min of its     children */  if(left == NULL)  {    if(right == NULL)      s->offset = 0;    else      s->offset = right->offset;  }  else  {    if(right == NULL)      s->offset = left->offset;    else      s->offset = min(left->offset, right->offset);  }  return s;}static Stack newString(const char *string){  Stack s = newStack();  s->type = 's';  s->data.string = string;  return s;}static Stack newDouble(double d){  Stack s = newStack();  s->type = 'd';  s->data.dnum = d;  return s;}static Stack newInteger(int i){  Stack s = newStack();  s->type = 'i';  s->data.inum = i;  return s;}static Stack newProperty(Property prop){  Stack s = newStack();  s->type = 'p';  s->data.prop = prop;  return s;}static Stack pop(){  Stack s = stack;  if(!stack)    error("blown stack!");  stack = stack->next;  return s;}static void push(Stack s){  s->next = stack;  stack = s;}static char *negateString(char *s){  int i, l = strlen(s)+1;  char *New = realloc(s, l+1);  for(i=l; i>0; --i)    New[i] = New[i-1];  New[0] = '-';  return New;}/* looks like setProperty has been replaced by setMember in F5   but it still uses the pushdata property type */static Property getSetProperty(int prop){  switch(prop)  {    case SWF_SETPROPERTY_X:               return PROPERTY_X;    case SWF_SETPROPERTY_Y:               return PROPERTY_Y;    case SWF_SETPROPERTY_XSCALE:          return PROPERTY_XSCALE;    case SWF_SETPROPERTY_YSCALE:          return PROPERTY_YSCALE;    case SWF_SETPROPERTY_ALPHA:           return PROPERTY_ALPHA;    case SWF_SETPROPERTY_VISIBILITY:      return PROPERTY_VISIBLE;    case SWF_SETPROPERTY_ROTATION:        return PROPERTY_ROTATION;    case SWF_SETPROPERTY_NAME:            return PROPERTY_NAME;    case SWF_SETPROPERTY_HIGHQUALITY:     return PROPERTY_HIGHQUALITY;    case SWF_SETPROPERTY_SHOWFOCUSRECT:   return PROPERTY_FOCUSRECT;    case SWF_SETPROPERTY_SOUNDBUFFERTIME: return PROPERTY_SOUNDBUFTIME;    default: return -1;  }}static Stack readActionRecord(FILE *f){  int length = 0, type = readUInt8(f);  if((type&0x80) == 0x80)    length = readUInt16(f);  switch(type)  {    case SWFACTION_POP:      return newTree(NULL, type, NULL);      /*      return NULL; */    /* no-arg */    case SWFACTION_GETTIMER:    case SWFACTION_STOPDRAGMOVIE:    case SWFACTION_NEXTFRAME:    case SWFACTION_PREVFRAME:    case SWFACTION_PLAY:    case SWFACTION_STOP:    case SWFACTION_TOGGLEQUALITY:    case SWFACTION_STOPSOUNDS:      return newTree(NULL, type, NULL);    /* one-arg */    case SWFACTION_STRINGLENGTH:    case SWFACTION_INT:    case SWFACTION_RANDOM:    case SWFACTION_MBLENGTH:    case SWFACTION_ORD:    case SWFACTION_CHR:    case SWFACTION_MBORD:    case SWFACTION_MBCHR:    case SWFACTION_LOGICALNOT:    case SWFACTION_GETVARIABLE:    case SWFACTION_REMOVECLIP:    case SWFACTION_TRACE:    case SWFACTION_SETTARGETEXPRESSION:    case SWFACTION_CALLFRAME:      return newTree(pop(), type, NULL);    /* two-arg */    case SWFACTION_ADD:    case SWFACTION_MULTIPLY:    case SWFACTION_DIVIDE:    case SWFACTION_EQUAL:    case SWFACTION_LESSTHAN:    case SWFACTION_LOGICALAND:    case SWFACTION_LOGICALOR:    case SWFACTION_STRINGEQ:    case SWFACTION_STRINGCONCAT:    case SWFACTION_STRINGCOMPARE:	{      Stack right = pop();      Stack left = pop();      return newTree(left, type, right);	}    case SWFACTION_SETVARIABLE:    {      Stack right = pop();      Stack left = pop();      if(right->type == 't' &&	 right->data.tree->action == SWFACTION_SETREGISTER)      {	/* copy tree to register so we can use it on getregister */	/* and remove the register bit so we don't loop endlessly */	reg0 = newTree(left, type, right->data.tree->right);	destroy(right);	return NULL;      }      else	return newTree(left, type, right);    }    case SWFACTION_GETPROPERTY:    {      Stack right = pop();      Stack left = pop();      if(right->type == 's')      {	Stack New = newProperty(atoi(right->data.string));	destroy(right);	right = New;      }      return newTree(left, type, right);    }    case SWFACTION_SUBTRACT:    {      Stack right = pop();      Stack left = pop();      /* XXX - shouldn't we move this to listArithmetic? */      if(left->type == 's' &&	 strcmp(left->data.string, "0") == 0)      {	destroy(left);	right->data.string = negateString(right->data.string);	return right;      }      return newTree(left, type, right);    }    /* three-arg */    case SWFACTION_SETPROPERTY:	{	  Stack value = pop();	  Stack property = pop();	  Stack target = pop();      if(property->type == 's')      {	Stack New = newProperty(atoi(property->data.string));	destroy(property);	property = New;      }	      return newTree(newTree(target, type, property),		     SWFACTION_SETVARIABLE, value);	}    case SWFACTION_MBSUBSTRING:    case SWFACTION_SUBSTRING:	{	  Stack s3 = pop();	  Stack s2 = pop();	  Stack s1 = pop();      return newTree(s1, type, newTree(s2, type, s3));	}    case SWFACTION_DUPLICATECLIP:    {      Stack level = pop();      Stack target = pop();      Stack source = pop();      Stack arg;      if(level->type == 'i' &&	 level->data.inum >= DUPCLIP_NUMBER)      {	arg = level;	arg->data.inum -= DUPCLIP_NUMBER;      }      else      {	if(level->type != 't' ||	   (level->data.tree->action != SWFACTION_ADD &&	    level->data.tree->action != SWFACTION_NEWADD))	  error("magic number 0x4000 not found in duplicateClip target level!");	if(level->data.tree->left->type == 'i' &&	   level->data.tree->left->data.inum == DUPCLIP_NUMBER)	{	  arg = level->data.tree->right;	  level->data.tree->right = NULL;	}	else if(level->data.tree->right->type == 'i' &&		level->data.tree->right->data.inum == DUPCLIP_NUMBER)	{	  arg = level->data.tree->left;	  level->data.tree->left = NULL;	}	else	  error("magic number 0x4000 not found in duplicateClip target level!");	destroy(level);      }      return newTree(source, type, newTree(target, type, arg));    }    /* weird ops */    case SWFACTION_STARTDRAGMOVIE:    {      Stack target = pop();      Stack lockmouse = pop();      Stack constraint = pop();      if(constraint->type == 't')	error("Sorry, decompiler can't deal with conditional constraint in dragMovie!");      if(intVal(constraint) == 0)	return newTree(constraint, type, newTree(lockmouse, type, target));      else {		Stack p4 = pop();		Stack p3 = pop();		Stack p2 = pop();		Stack p1 = pop();	return newTree(newTree(newTree(p1, type, p2), type,			       newTree(p3, type, p4)), type,		       newTree(lockmouse, type, target));	  }    }    case SWFACTION_PUSHDATA:    {      Stack s = NULL;      int end = fileOffset + length;      int type;      int off = fileOffset - 3; /* save statement offset */      while(fileOffset < end)      {	if(s != NULL)	  push(s);	switch(type = readUInt8(f))	{	  case 0: /* string */	    s = newString(readString(f));	    break;	  case 1: /* property - not used? */	    readUInt16(f); /* 0x0000 */	    s = newProperty(getSetProperty(readUInt16(f)));	    break;	  case 2: /* null? */	    s = newString("NULL");	    break;	  case 3: /* ??? */	    s = newString("data type 0x03 (?)");	    break;	  case 4: /* register? */	    if(readUInt8(f) != 0)	      error("Sorry, can't deal with other than reg0!");	    s = reg0;	    s->offset = reg0->offset;	    //	    reg0 = NULL;	    break;	  case 5: /* boolean? */	    s = newString((readUInt8(f) == 0) ? "false" : "true");	    break;	  case 6: /* double */	    s = newDouble(readDouble(f));	    break;	  case 7: /* int */	    s = newInteger(readSInt32(f));	    break;	  case 8: /* dictionary ref */	    s = newString(dictionary[readUInt8(f)]);	    break;	  default:	    error("Unknown data type %i", type);	}	if(s->offset == 0)	  s->offset = off;      }      return s;    }    case SWFACTION_GOTOFRAME:      return newTreeBase((Stack)readUInt16(f), type, NULL);    case SWFACTION_GETURL:    {      char *url = readString(f);      char *target = readString(f);      return newTreeBase((Stack)url, type, (Stack)target);    }    case SWFACTION_GETURL2:    {	  Stack target = pop();	  Stack url = pop();      Stack s = newTree(url, type, target);      Stack t = newTreeBase((Stack)readUInt8(f), type, s);      t->offset = s->offset;      return t;    }    case SWFACTION_WAITFORFRAMEEXPRESSION:      return newTreeBase((Stack)readUInt8(f), type, NULL);    case SWFACTION_GOTOEXPRESSION:    {      Stack s = pop();      Stack t = newTreeBase(s, type, (Stack)readUInt8(f));      t->offset = s->offset;      return t;    }    case SWFACTION_SETTARGET:    case SWFACTION_GOTOLABEL:      return newTreeBase((Stack)readString(f), type, NULL);    /* branches */    case SWFACTION_BRANCHIFTRUE:    {      Stack s = pop(), t;      int offset = readSInt16(f);      Action action;      /* if there's a dup or !dup in the condition, we've got an || or && */      /* XXX - silly hackery wrapping things in nots so the untangler	 recognises it.  Would be nice to clean up. */      if(s->type == 't' &&	 ((action = s->data.tree->action) == SWFACTION_DUP || /* it's an or */	  ((action = s->data.tree->action) == SWFACTION_LOGICALNOT && /* and */	   s->data.tree->left->type == 't' &&	   s->data.tree->left->data.tree->action == SWFACTION_DUP)))      {	int start = fileOffset; /* we're at the start of the next statement */	int off;	int end = start+offset; /* should be a logical not statement */	if(action == SWFACTION_DUP)	  push(newTree(s, SWFACTION_LOGICALOR, NULL));	else	{	  push(newTree(s->data.tree->left, SWFACTION_LOGICALAND, NULL));	  destroy(s);	}	/* now grab statements between here and end */	while(fileOffset < end)	{	  if(feof(f))	    break;	  off = fileOffset;	  if((s = readActionRecord(f)) != NULL)	  {	    push(s);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -