Skip to content

Commit

Permalink
Step 1 of rewriting WriteProcessMemory to a syscall, handle if condit…
Browse files Browse the repository at this point in the history
…ions.
  • Loading branch information
plowsec committed Oct 13, 2020
1 parent a88f3af commit 80fdecb
Show file tree
Hide file tree
Showing 6 changed files with 43,650 additions and 4,302 deletions.
125 changes: 124 additions & 1 deletion ApiMatchHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ bool ApiMatchHandler::replaceIdentifier(const CallExpr *CallExpression, const st
bool ApiMatchHandler::handleCallExpr(const CallExpr *CallExpression, clang::ASTContext *const pContext) {

std::string Identifier = getFunctionIdentifier(CallExpression);

if(shouldReplaceWithSyscall(Identifier)) {

rewriteApiToSyscall(CallExpression, pContext, Identifier);
return true;
}

std::string Replacement = Utils::translateStringToIdentifier(Identifier);

if (!addGetProcAddress(CallExpression, pContext, Replacement, Identifier))
Expand Down Expand Up @@ -115,4 +122,120 @@ ApiMatchHandler::findInjectionSpot(clang::ASTContext *const Context, clang::ast_

return findInjectionSpot(Context, parent, Literal, ++Iterations);
}
}
}

static std::vector<std::string> GetArgs(const CallExpr *CallExpression) {
std::vector<std::string> Args;
clang::LangOptions LangOpts;
LangOpts.CPlusPlus = true;
clang::PrintingPolicy Policy(LangOpts);

for (int i = 0; i < CallExpression->getNumArgs(); i++) {

std::string TypeS;
llvm::raw_string_ostream s(TypeS);
CallExpression->getArg(i)->printPretty(s, 0, Policy);
Args.push_back(s.str());
}

return Args;
}
bool ApiMatchHandler::shouldReplaceWithSyscall(std::string ApiName) {

return std::find(Syscalls.begin(), Syscalls.end(), ApiName) != Syscalls.end();
}

void ApiMatchHandler::rewriteApiToSyscall(const clang::CallExpr *pExpr, clang::ASTContext *const pContext,
std::string ApiName) {

if (ApiName == "WriteProcessMemory") {

llvm::outs() << "[*] Found WriteProcessMemory\n";

std::vector<std::string> FunctionArgs = GetArgs(pExpr);

std::ostringstream params(std::ostringstream::out);
// reussite = ((fZwWriteVirtualMemory(handleProcess, (VOID*)adresseBase, adresseSource, longueur, &dwBytesWrite) != 0) && (dwBytesWrite == longueur));

params << "("
<< FunctionArgs.at(0) << ", "
<< FunctionArgs.at(1) << ", (PVOID)("
<< FunctionArgs.at(2) << "), (ULONG)("
<< FunctionArgs.at(3) << "), (PULONG)("
<< FunctionArgs.at(4) << "))";
std::string Replacement = params.str();

SourceRange Range(pExpr->getBeginLoc(), pExpr->getEndLoc());
std::string Suffix = "";

if(isInsideIfCondition(pExpr, pContext)) {
llvm::outs() << "CompountStmt > IfStmt\n";

Suffix = "==ERROR_SUCCESS";
}

llvm::outs() << "Replacing with " << Replacement + Suffix << "\n";

ASTRewriter->ReplaceText(Range, "toto" + params.str() + Suffix);
return;
}
}

std::vector<std::string>
ApiMatchHandler::getParents(const Expr& pExpr, clang::ast_type_traits::DynTypedNode Node,
clang::ASTContext *const Context, std::vector<std::string> &CurrentParents,
uint64_t Iterations) {

if (Iterations > Globs::CLIMB_PARENTS_MAX_ITER) {
return CurrentParents;
}

ASTContext::DynTypedNodeList parents = Context->getParents(pExpr);

if (Iterations > 0) {
parents = Context->getParents(Node);
}

for (const auto &parent : parents) {

StringRef ParentNodeKind = parent.getNodeKind().asStringRef();

if (ParentNodeKind.find("Cast") != std::string::npos) {

return getParents(pExpr, parent, Context, CurrentParents, ++Iterations);
}

CurrentParents.push_back(ParentNodeKind);
return getParents(pExpr, parent, Context, CurrentParents, ++Iterations);
}

return CurrentParents;
}

bool ApiMatchHandler::isInsideIfCondition(const clang::CallExpr *pExpr, clang::ASTContext *const pContext) {

std::vector<std::string> Parents;
getParents(*pExpr, clang::ast_type_traits::DynTypedNode(), pContext, Parents, 0);

for(auto& parent : Parents){
llvm::outs() << "Parent is : " << parent << "\n";
}
auto it = std::find(Parents.begin(), Parents.end(), "IfStmt");
if(it != Parents.end()) {
// WriteProcessMemory call is located within an If statement. Now we should check if it's the
// in the If condition or the If Body.

auto CompoundStmtIt = std::find(Parents.begin(), Parents.end(), "CompoundStmt");

if( CompoundStmtIt == Parents.end()){
return true;
}

if(CompoundStmtIt > it) {
// WriteProcessMememory is inside a CompoundStmt, inside an IfStmt
return true;
}
}

return false;
}
15 changes: 15 additions & 0 deletions ApiMatchHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ class ApiMatchHandler : public clang::ast_matchers::MatchFinder::MatchCallback {
const std::string &NewIdentifier);

bool handleCallExpr(const clang::CallExpr *CallExpression, clang::ASTContext *const pContext);

bool shouldReplaceWithSyscall(std::string ApiName);

void rewriteApiToSyscall(const clang::CallExpr *pExpr, clang::ASTContext *const pContext, std::string ApiName);

bool isInsideIfCondition(const clang::CallExpr *pExpr, clang::ASTContext *const pContext);

std::vector<std::string>
getParents(const clang::Expr &pExr, clang::ast_type_traits::DynTypedNode Node, clang::ASTContext *const Context,
std::vector<std::string> &CurrentParents, uint64_t Iterations);
};

static std::map<std::string, std::string> ApiToHide_samlib = {
Expand Down Expand Up @@ -94,4 +104,9 @@ static std::map<std::string, std::string> ApiToHide_samlib = {
{"SamCloseHandle", "typedef NTSTATUS(__stdcall* _SamCloseHandle)(SAMPR_HANDLE SamHandle);"},
{"SamFreeMemory", "typedef NTSTATUS(__stdcall* _SamFreeMemory)(PVOID Buffer);"}
};

static std::vector<std::string> Syscalls = {
"WriteProcessMemory",
"CreateRemoteThread"
};
#endif //AVCLEANER_APIMATCHHANDLER_H
4 changes: 4 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ namespace AVObfuscator {
auto Cons = std::make_unique<ApiCallConsumer*>(new ApiCallConsumer("MessageBoxA", MessageBoxATypeDef,
"User32.dll"));
consumers.push_back(*Cons);

auto Cons2 = std::make_unique<ApiCallConsumer*>(new ApiCallConsumer("WriteProcessMemory", MessageBoxATypeDef,
"User32.dll"));
consumers.push_back(*Cons2);
}

auto TheConsumer = std::make_unique<Consumer>();
Expand Down
7 changes: 6 additions & 1 deletion test/base_inject.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "metsrv.h"
#include "base_inject.h"
#include "remote_thread.h"
#include "../../ReflectiveDLLInjection/inject/src/LoadLibraryR.h"
#include "LoadLibraryR.h"
#include <Tlhelp32.h>

// see '/msf3/external/source/shellcode/x86/migrate/executex64.asm'
Expand Down Expand Up @@ -196,6 +196,11 @@ DWORD inject_via_apcthread( Remote * remote, Packet * response, HANDLE hProcess,

memset( lpNopSled, 0x90, mbi.RegionSize );

if(true){
WriteProcessMemory( hProcess, lpRemoteAddress, lpNopSled, mbi.RegionSize, NULL );
BREAK_ON_ERROR( "ratatatatatat" )

}
if( !WriteProcessMemory( hProcess, lpRemoteAddress, lpNopSled, mbi.RegionSize, NULL ) )
BREAK_ON_ERROR( "[INJECT] inject_via_apcthread: WriteProcessMemory lpNopSled failed" )

Expand Down
Loading

0 comments on commit 80fdecb

Please sign in to comment.