📄 decompile5.c
字号:
listItem(names[i], SWFACTION_INITOBJECT); puts(" : "); listItem(values[i], SWFACTION_INITOBJECT); if(i < nEntries-1) puts(", "); } puts(" }"); break; } case SWFACTION_INITARRAY: { int i, nEntries = (int)t->left; Stack *values = (Stack *)t->right; puts("[ "); for(i=0; i<nEntries; ++i) { listItem(values[i], SWFACTION_INITOBJECT); if(i < nEntries-1) puts(", "); } puts(" ]"); break; } default: break; } }}static int isStatement(Stack s){ Tree t; if(s->type != 't') return 0; t = s->data.tree; switch(t->action) { case SWFACTION_NEXTFRAME: case SWFACTION_PREVFRAME: case SWFACTION_PLAY: case SWFACTION_STOP: case SWFACTION_TOGGLEQUALITY: case SWFACTION_STOPSOUNDS: case SWFACTION_GOTOFRAME: case SWFACTION_GETURL: case SWFACTION_SETTARGET: case SWFACTION_GOTOLABEL: case SWFACTION_SETVARIABLE: case SWFACTION_SETTARGETEXPRESSION: case SWFACTION_SETPROPERTY: case SWFACTION_DUPLICATECLIP: case SWFACTION_REMOVECLIP: case SWFACTION_TRACE: case SWFACTION_STARTDRAGMOVIE: case SWFACTION_STOPDRAGMOVIE: case SWFACTION_WAITFORFRAMEEXPRESSION: case SWFACTION_BRANCHALWAYS: case SWFACTION_GETURL2: case SWFACTION_BRANCHIFTRUE: case SWFACTION_CALLFRAME: case SWFACTION_GOTOEXPRESSION: /* case SWFACTION_CALLFUNCTION: case SWFACTION_CALLMETHOD: */ case SWFACTION_VAR: case SWFACTION_VAREQUALS: case SWFACTION_DELETE: case SWFACTION_POP: case SWFACTION_RETURN: case SWFACTION_SETMEMBER: case SWFACTION_DECLARENAMES: case SWFACTION_WITH: case SWFACTION_DEFINEFUNCTION: case SWFACTION_ENUMERATE: return 1; default: return 0; }}/*static Stack readStatement(FILE *f){ Stack s; for(;;) { if(feof(f)) return NULL; if((s = readActionRecord(f)) == NULL) return NULL; if((int)s == -1) *//* declarenames *//* continue; if(stack == NULL && reg0 == NULL && isStatement(s)) *//* supposedly, we've got a complete statement. *//* return s; else push(s); }}*/static Stack negateExpression(Stack s){ Tree t = s->data.tree; Stack ret; if(s->type != 't') return s; if(t->action == SWFACTION_LOGICALNOT) { ret = t->left; /* free(t); */ return ret; } return newTree(s, SWFACTION_LOGICALNOT, NULL);}void showStack(){ Stack s = stack; while(s != NULL && (s->type != 't' || s->data.tree->action != SWFACTION_DEFINEFUNCTION)) { listItem(s, SWFACTION_END); putchar('\n'); s = s->next; }}int readStatements(FILE *f, int length, Stack **slist){ Stack s, start = stack, *statements; int i, n, off, end = fileOffset + length; int wasNull = 0; /* XXX - should use our own stack here? */ while(fileOffset<end) { if(feof(f)) break; off = fileOffset; if((s = readActionRecord(f)) != NULL) { push(s); if(s->offset == 0) s->offset = off; wasNull = 0; } else /* blah. */ wasNull = 1; /* showStack(); putchar('\n'); */ } s = stack; n = 0; /* count statements */ while(s && s != start) { ++n; s = s->next; } /* load statements from stack into array */ *slist = statements = (Stack *)malloc((n+1)*sizeof(Stack)); for(i=n-1; i>=0; --i) statements[i] = pop(); /* give branch something to target */ s = newStack(); statements[n] = s; s->offset = fileOffset; if(wasNull) --s->offset; return n;}void listStatements(Stack *statements, int n){ int i; for(i=0; i<=n; ++i) { printf("%03i|%04i: ", i, statements[i]->offset); listItem(statements[i], SWFACTION_END); putchar(';'); putchar('\n'); }}void decompileStatements(Stack *statements, int n){ resolveOffsets(statements, n); untangleBranches(statements, 0, n, BRANCH_NONE, gIndent); putchar('\n');}void decompile5Action(FILE *f, int length, int indent){ Stack *statements = NULL; int n; gIndent = indent; n = readStatements(f, length, &statements); /* listStatements(statements, n); */ decompileStatements(statements, n); if(stack != NULL) { printf("Decompiler error: stack not empty!\n"); printf("Here's what's left over:\n\n"); /* dump stack remains */ while(stack) { listItem(stack, SWFACTION_END); putchar(';'); putchar('\n'); stack = stack->next; } destroy(stack); stack = NULL; assert(0); }}static void resolveOffsets(Stack *statements, int nStatements){ int i, j; /* first change branch byte offsets to statement offsets */ for(i=0; i<nStatements; ++i) { Tree t = statements[i]->data.tree; if(t->action == SWFACTION_BRANCHIFTRUE || t->action == SWFACTION_BRANCHALWAYS) { int offset = (int)t->right + statements[i+1]->offset; if((int)t->right == 0) { /* don't know why this would happen, but it does.. */ t->right = (Stack)i; statements[i]->target = i; continue; } else if((int)t->right > 0) { for(j=i+2; j<nStatements; ++j) { if(statements[j]->offset > offset) error("went too far!"); if(statements[j]->offset == offset) break; } if(j==nStatements+1) error("couldn't find (forward) target offset!"); } else { for(j=i; j>=0; --j) { if(statements[j]->offset < offset) error("went too far!"); if(statements[j]->offset == offset) break; } if(j==-1) error("couldn't find (backward) target offset!"); } t->right = (Stack)j; statements[j]->target = i; } }}#define INDENT { int ii=indent; while(--ii>=0) { putchar(' '); putchar(' '); } }static void untangleBranches(Stack *statements, int start, int stop, Branchtype type, int indent){ Stack s; Tree t; int i, offset, end, hasElse, wasIf = 0; for(i=start; i<stop; ++i) { s = statements[i]; t = s->data.tree; if(s->target > i && t->action != SWFACTION_BRANCHIFTRUE) { /* it's a do loop */ int target = s->target; if(s->target < start || s->target > stop) error("stmt %i: do target (%i) outside scope (%i,%i)!", i, s->target, start, stop); putchar('\n'); INDENT puts("do\n"); INDENT puts("{\n"); s->target = -1; untangleBranches(statements, i, target, BRANCH_DO, indent+1); INDENT puts("}\n"); INDENT puts("while("); listItem(statements[target]->data.tree->left, SWFACTION_END); puts(");\n"); wasIf = 1; i = target; continue; } if(t->action == SWFACTION_BRANCHALWAYS) error("stmt %i: unexpected unconditional branch!", i); if(t->action != SWFACTION_BRANCHIFTRUE) { /* it's just a statement. */ if(wasIf) putchar('\n'); INDENT listItem(s, SWFACTION_END); putchar(';'); putchar('\n'); wasIf = 0; continue; } /* it's a conditional branch */ offset = (int)t->right; if(offset < start || offset > stop) error("stmt %i: branch target (%i) outside scope (%i,%i)!", i, offset, start, stop); if(offset < i) error("stmt %i: Unexpected backwards branch!", i); if(type==BRANCH_WHILE || type==BRANCH_DO) { if(offset == stop) { INDENT puts("break;\n"); continue; } else if(offset == start) { INDENT puts("continue;\n"); continue; /*ha!*/ } } if(statements[offset-1]->data.tree->action == SWFACTION_BRANCHALWAYS && (int)statements[offset-1]->data.tree->right == i) { /* it's a while loop */ putchar('\n'); INDENT puts("while("); listItem(negateExpression(t->left), SWFACTION_END); puts(")\n"); if(i < offset-3) { INDENT putchar('{'); putchar('\n'); } untangleBranches(statements, i+1, offset-1, BRANCH_WHILE, indent+1); if(i < offset-3) { INDENT putchar('}'); putchar('\n'); } wasIf = 1; i = offset-1; continue; } /* it's just an if */ if(i>start) putchar('\n'); if(statements[offset-1]->data.tree->action == SWFACTION_BRANCHALWAYS) { /* got an else */ hasElse = 1; end = (int)statements[offset-1]->data.tree->right; } else { hasElse = 0; end = offset; } if(end < start || end > stop) error("stmt %i: else target (%i) outside scope (%i,%i)!", i, end, start, stop); if(end < i) error("stmt %i: Unexpected backwards branch!", i); INDENT puts("if("); /* XXX - would like to reverse else and if if expression is already negated.. */ listItem(negateExpression(t->left), SWFACTION_END); putchar(')'); putchar('\n'); if(i < offset-(hasElse?3:2)) { INDENT putchar('{'); putchar('\n'); } /* if hasElse, i+1 to offset-1 */ untangleBranches(statements, i+1, offset-(hasElse?1:0), BRANCH_IF, indent+1); if(i < offset-(hasElse?3:2)) { INDENT putchar('}'); putchar('\n'); } /* swallow up else-ifs */ for(;;) { int newOff; if(!hasElse) break; if(statements[offset]->data.tree->action != SWFACTION_BRANCHIFTRUE) break; newOff = (int)statements[offset]->data.tree->right; /* make sure we're still in this if's else bit */ if(statements[newOff-1]->data.tree->action != SWFACTION_BRANCHALWAYS || (int)statements[newOff-1]->data.tree->right != end) break; i = offset; offset = newOff; s = statements[i]; t = s->data.tree; INDENT puts("else if("); listItem(negateExpression(t->left), SWFACTION_END); putchar(')'); putchar('\n'); if(i < offset-(hasElse?3:2)) { INDENT putchar('{'); putchar('\n'); } if(offset-(hasElse?1:0) < i+1) { /* gimpy code */ INDENT puts(" ;\n"); break; } untangleBranches(statements, i+1, offset-(hasElse?1:0), BRANCH_IF, indent+1); if(i < offset-(hasElse?3:2)) { INDENT putchar('}'); putchar('\n'); } } /* now take out ending else */ if(hasElse) { INDENT puts("else\n"); if(offset+2 < end) { INDENT putchar('{'); putchar('\n'); } untangleBranches(statements, offset, end, BRANCH_ELSE, indent+1); if(offset+2 < end) { INDENT putchar('}'); putchar('\n'); } } wasIf = 1; i = end-1; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -