/** Forward in a tree until the value */ tree<AstNode>::iterator forward(const tree<AstNode>::iterator& from, const string& untilStr, const tree<AstNode>& tr) { tree<AstNode>::iterator ret = from; while(ret->getType() != untilStr) { ret = tr.child(ret, 0); } return ret; }
/** Insert a new statement. - Create a new inner_statement_list - Add the statement under it */ bool insert_statement(const tree<AstNode>::iterator& where, const tree<AstNode>::iterator& what, tree<AstNode>& tr) { if (where->getType() == "text" && where->getValue() == "$enter_the_new_statement") { // rewind to the inner_statement_list tree<AstNode>::iterator top = where; do { top = tr.parent(top); } while (top->getType() != "inner_statement" && tr.child(top,0)->getType() != "statement"); top = tr.parent(top); if (top->getType() != "inner_statement_list") return false; else { top = tr.append_child(top, AstNode("inner_statement_list")); top = tr.append_child(top, AstNode("inner_statement")); if (what->getType() == "statement") { top = tr.append_child(top, AstNode("statement")); //cout << "Seems to be okay..." << endl; move_branch(top, what, tr); } } return true; } return false; }
/** Generic control flow modification */ void ControlFlow::operator()(tree<AstNode>& tr, MapClasses* classes, MapVariables* vars, MapFunctions *func) { // 1 - Detect which if modifiying (select all the unticked_statement grand children of top_statement) AstNodeIteratorList affectedNode, untouchedBeforeNode, untouchedAfterNode; bool after = detectAfterStmt(tr); bool before = detectBeforeStmt(tr); tree<AstNode>::iterator endStatement; tree<AstNode> def = *(flowAST.getTreeConstPtr()); tree<AstNode>::iterator iter, parent, grandparent; if (!after && !before) { for (iter=tr.begin(); iter!=tr.end();++iter) { if (iter->getType() == "statement" && tr.parent(iter)->getType() == "top_statement") { // We put the parent =? 'statement' in the list affectedNode.push_back(iter); } } } else { // feed the untouched and affected AstNodeIteratorList* curList = before ? &untouchedBeforeNode : &affectedNode; for (iter=tr.begin(); iter!=tr.end();++iter) { if (iter->getType() == "statement" && tr.parent(iter)->getType() == "top_statement") curList->push_back(iter); else if (before && iter->getType() == "text" && iter->getValue() == "$__START_OBF_HERE") { // remove the previously inserted stuff (the branch with this declaration curList->pop_back(); curList = &affectedNode; // rewind in order to include this variable into the generated obfuscated ast endStatement = iter; do { endStatement = def.parent(endStatement); } while (endStatement->getType() != "statement" && def.parent(endStatement)->getType() != "top_statement"); curList->push_back(endStatement); } else if (after && iter->getType() == "text" && iter->getValue() == "$__END_OBF_HERE") curList = &untouchedAfterNode; } } // 2 - Let's study a little out resource... AstNodeIteratorList branchs; AstNodeIteratorList br_func; AstNodeIteratorList br_classe; // 2+3/4 - Cut the external resource to implant it into the tree (get the nodes into the flowAST) for (tree<AstNode>::iterator iter=def.begin(); iter!=def.end(); ++iter) { if (iter->getValue() == "$enter_the_new_statement") { endStatement = iter; // rewind to the statement, not interesting by everything after this statement do { endStatement = def.parent(endStatement); } while (endStatement->getType() != "statement" && def.parent(endStatement)->getType() != "inner_statement"); } else if (iter->getType() == "top_statement") { if (tr.child(iter,0)->getType() == "function_declaration_statement") br_func.push_back(iter); else if (tr.child(iter,0)->getType() == "class_declaration_statement") br_classe.push_back(iter); else branchs.push_back(iter); } } // // 3 - Adding the nodes: merging the two trees tree<AstNode>::iterator topDeclarations = tr.begin(); for (;topDeclarations!= tr.end(); ++topDeclarations) { if (topDeclarations->getType() == "top_statement_list") { for (tree<AstNode>::iterator tmp=topDeclarations;tmp->getType()=="top_statement_list";++tmp) topDeclarations = tmp; break; } } // Insert the classes for (AstNodeIteratorList::iterator bter=br_classe.begin();bter!=br_classe.end();++bter) insert_branch(topDeclarations, *bter, tr, *(flowAST.getTreeConstPtr())); // Insert the functions for (AstNodeIteratorList::iterator bter=br_func.begin();bter!=br_func.end();++bter) insert_branch(topDeclarations, *bter, tr, *(flowAST.getTreeConstPtr())); // if (before && untouchedBeforeNode.size() > 0) { for (AstNodeIteratorList::iterator bter=untouchedBeforeNode.begin();bter!=untouchedBeforeNode.end();++bter) insert_branch(topDeclarations, *bter, tr, *(flowAST.getTreeConstPtr())); } // Insert the obfuscation template (empty) for (AstNodeIteratorList::iterator bter=branchs.begin();bter!=branchs.end();++bter) insert_branch(topDeclarations, *bter, tr, *(flowAST.getTreeConstPtr())); //Select the place to insert for (tree<AstNode>::iterator iter=tr.begin();iter!=tr.end();++iter) { if (iter->getType() == "text" && iter->getValue() == "$enter_the_new_statement") { // Let's Insert Here!! for (AstNodeIteratorList::iterator jter=affectedNode.begin(); jter!=affectedNode.end();++jter) { insert_statement(iter, *jter ,tr); } } } // if (after && untouchedAfterNode.size() > 0) { for (AstNodeIteratorList::iterator bter=untouchedAfterNode.begin();bter!=untouchedAfterNode.end();++bter) insert_branch(topDeclarations, *bter, tr, *(flowAST.getTreeConstPtr())); } // generate random names the remove the '$enter_the_new_statement' applyModification(tr); clean_pattern(tr); }