安界|自动重构Meterpreter绕过杀软·续( 三 )
然后运行:bashclang-astdump.shtest/messagebox_simple.c>test/messagebox_simple.c.ast
文章图片
在源代码中定位函数调用基本上等于查找CallExpr类型的AST节点 。 如上面的截图所示 , 实际调用的函数名是在其某个子节点中被指定的 , 因此后面应该可以访问它 。 找到给定API的函数调用
为了枚举给定函数的每个函数调用 , 根据需要我们选择了ASTMatcher 。 首先 , 正确使用这个匹配器的语法很重要 , 因为它比上一篇文章中使用的语法要复杂一些 。 为了得到正确的结果 , 我们选择依靠clang-query来完成 , 这是一个非常有价值的交互式工具 , 允许在源代码上运行自定义查询 。 有趣的是 , 它也基于libTooling , 并且其功能远比在本文章中展示的功能要强大得多(更多细节请参阅此处) 。 clang-query>matchcallExpr(callee(functionDecl(hasName("MessageBoxA"))))Match#1:/Users/vladimir/dev/scrt/avcleaner/test/messagebox_simple.c:6:5:note:"root"bindshereMessageBoxA(NULL,"Test","Something",MB_OK);^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1match.clang-query>
反复试验可以迅速找到到有效的解决方案 。 现在通过验证我们发现匹配器工作良好 , 我们可以像前面的文章中提到的一样创建一个新的ASTConsumer 。 基本上 , 它是复制我们对clang-query所做的工作 , 只不过是在C++中:classApiCallConsumer:publicclang::ASTConsumer{public:ApiCallConsumer(std::stringApiName,std::stringTypeDef,std::stringLibrary):_ApiName(std::move(ApiName)),_TypeDef(std::move(TypeDef)),_Library(std::move(Library)){}voidHandleTranslationUnit(clang::ASTContext&Context)override{usingnamespaceclang::ast_matchers;usingnamespaceAVObfuscator;llvm::outs()<<"[ApiCallObfuscation]RegisteringASTMatcherfor"<<_ApiName<<"n";MatchFinderFinder;ApiMatchHandlerHandler(&ASTRewriter,_ApiName,_TypeDef,_Library);constautoMatcher=callExpr(callee(functionDecl(hasName(_ApiName)))).bind("callExpr");Finder.addMatcher(Matcher,&Handler);Finder.matchAST(Context);}private:std::string_ApiName;std::string_TypeDef;std::string_Library;};
我们发现此实现最重要的细节是能否提供匹配许多不同函数的能力 , 并且由于最终的目标是为每个替换的API函数前面插入LoadLibrary/GetProcAddress , 因此我们需要能够在函数原型中提供要加载的DLL名称 。
这样做可以优雅地注册与要替换的API一样多的ASTConsumers 。 此ASTConsumer的实例化必须在ASTFrontendAction中完成:
文章图片
这是我们在上一篇文章中对现有代码所做的唯一修改 。 从这里开始 , 其他东西都可以通过我们将要添加的一组代码来实现 , 首先创建ApiMatchHandler.cpp , 匹配器必须提供一个回调函数 , 所以让我们给它一个:voidApiMatchHandler::run(constMatchResult&Result){llvm::outs()<<"Found"<<_ApiName<<"n";constauto*CallExpression=Result.Nodes.getNodeAs
("callExpr");handleCallExpr(CallExpression,Result.Context);}
在本文开始的任务分解步骤的具体实现过程中 , 我们可以在代码层面给他做一些位置调换 , 例如使用以下方法:boolhandleCallExpr(constclang::CallExpr*CallExpression,clang::ASTContext*constpContext);boolreplaceIdentifier(constclang::CallExpr*CallExpression,conststd::string&ApiName,conststd::string&NewIdentifier);booladdGetProcAddress(constclang::CallExpr*pCallExpression,clang::ASTContext*constpContext,conststd::string&NewIdentifier,std::string&ApiName);clang::SourceRangefindInjectionSpot(clang::ASTContext*constContext,clang::ast_type_traits::DynTypedNodeParent,constclang::CallExpr&Literal,uint64_tIterations);替换函数调用
- 极客码头|想更新时还能手动更新,比第三方好用,无后门禁用Win10自动更新
- 裁员|英工程师为公司奉献20年,疫情期间被裁,补偿仅为两支自动铅笔
- 兵器数据库|撑死一年也就130架,为何不能自动化生产?,F-35脉动生产线
- 产业气象站|为什么有时候自动广告会比手动广告效果好?深入解析匹配逻辑
- 天下快谈|欠费3个月后,别以为会被自动注销,使用“实名制”的手机卡
- 中国信息报道|力争成为国内自动灭火装备领域的领导品牌,国安达成功过会
- 微信支付|正式确认!微信这项功能要关闭,避免自动扣钱,望周知
- 幸运番茄|让冠军车手的大脑来改变自动驾驶
- 汽车之家|微博暗示造车 藏33传感器 拥有L4级自动驾驶,索尼剑指特斯拉
- 聚成教育|Excel表格技巧—如何根据单元格大小自动调整文字大小