2 width indent

This commit is contained in:
G0lge
2024-07-09 14:26:09 +03:00
parent 94caa264e3
commit 99d7de29d9
13 changed files with 6753 additions and 6929 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
BasedOnStyle: LLVM
IndentWidth: 4
IndentWidth: 2
PointerAlignment: Left
NamespaceIndentation: All
+133 -155
View File
@@ -9,169 +9,149 @@
class RemovePseudoStackPass
: public llvm::PassInfoMixin<RemovePseudoStackPass> {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
Value* memory = getMemory();
Value* memory = getMemory();
bool hasChanged = false;
Value* stackMemory = NULL;
for (auto& F : M) {
if (!stackMemory) {
llvm::IRBuilder<> Builder(
&*F.getEntryBlock().getFirstInsertionPt());
stackMemory = Builder.CreateAlloca(
llvm::Type::getInt128Ty(M.getContext()),
llvm::ConstantInt::get(
llvm::Type::getInt128Ty(M.getContext()), STACKP_VALUE),
"stackmemory");
}
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP =
llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
auto* MemoryOperand =
GEP->getOperand(GEP->getNumOperands() - 2);
// printvalue(MemoryOperand)
// printvalue(memory)
if (memory != MemoryOperand)
continue;
auto* OffsetOperand =
GEP->getOperand(GEP->getNumOperands() - 1);
// printvalue(OffsetOperand)
if (!isa<ConstantInt>(OffsetOperand))
continue; // ??? also we can use knwonbits here but
// MEH
if (auto* ConstInt = llvm::dyn_cast<llvm::ConstantInt>(
OffsetOperand)) {
uint64_t constintvalue =
(uint64_t)ConstInt->getZExtValue();
if (constintvalue < STACKP_VALUE) {
GEP->setOperand((GEP->getNumOperands() - 2),
stackMemory);
}
}
}
}
bool hasChanged = false;
Value* stackMemory = NULL;
for (auto& F : M) {
if (!stackMemory) {
llvm::IRBuilder<> Builder(&*F.getEntryBlock().getFirstInsertionPt());
stackMemory = Builder.CreateAlloca(
llvm::Type::getInt128Ty(M.getContext()),
llvm::ConstantInt::get(llvm::Type::getInt128Ty(M.getContext()),
STACKP_VALUE),
"stackmemory");
}
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
auto* MemoryOperand = GEP->getOperand(GEP->getNumOperands() - 2);
// printvalue(MemoryOperand)
// printvalue(memory)
if (memory != MemoryOperand)
continue;
auto* OffsetOperand = GEP->getOperand(GEP->getNumOperands() - 1);
// printvalue(OffsetOperand)
if (!isa<ConstantInt>(OffsetOperand))
continue; // ??? also we can use knwonbits here but
// MEH
if (auto* ConstInt =
llvm::dyn_cast<llvm::ConstantInt>(OffsetOperand)) {
uint64_t constintvalue = (uint64_t)ConstInt->getZExtValue();
if (constintvalue < STACKP_VALUE) {
GEP->setOperand((GEP->getNumOperands() - 2), stackMemory);
}
}
}
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
};
// refactor
class GEPLoadPass : public llvm::PassInfoMixin<GEPLoadPass> {
public:
void* file_base;
ZyanU8* data;
public:
void* file_base;
ZyanU8* data;
GEPLoadPass() { BinaryOperations::getBases(&file_base, &data); }
GEPLoadPass() { BinaryOperations::getBases(&file_base, &data); }
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
bool hasChanged = false;
for (auto& F : M) {
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP =
llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
bool hasChanged = false;
for (auto& F : M) {
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
auto* OffsetOperand =
GEP->getOperand(GEP->getNumOperands() - 1);
if (auto* ConstInt = llvm::dyn_cast<llvm::ConstantInt>(
OffsetOperand)) {
uint64_t constintvalue =
(uint64_t)ConstInt->getZExtValue();
if (uint64_t offset =
FileHelper::address_to_mapped_address(
file_base, constintvalue)) {
for (auto* User : GEP->users()) {
if (auto* LoadInst =
llvm::dyn_cast<llvm::LoadInst>(
User)) {
llvm::Type* loadType =
LoadInst->getType();
auto* OffsetOperand = GEP->getOperand(GEP->getNumOperands() - 1);
if (auto* ConstInt =
llvm::dyn_cast<llvm::ConstantInt>(OffsetOperand)) {
uint64_t constintvalue = (uint64_t)ConstInt->getZExtValue();
if (uint64_t offset = FileHelper::address_to_mapped_address(
file_base, constintvalue)) {
for (auto* User : GEP->users()) {
if (auto* LoadInst = llvm::dyn_cast<llvm::LoadInst>(User)) {
llvm::Type* loadType = LoadInst->getType();
unsigned byteSize =
loadType->getIntegerBitWidth() / 8;
uint64_t tempvalue;
unsigned byteSize = loadType->getIntegerBitWidth() / 8;
uint64_t tempvalue;
std::memcpy(
&tempvalue,
reinterpret_cast<const void*>(
data + offset),
byteSize);
std::memcpy(&tempvalue,
reinterpret_cast<const void*>(data + offset),
byteSize);
llvm::APInt readValue(byteSize * 8,
tempvalue);
llvm::Constant* newVal =
llvm::ConstantInt::get(loadType,
readValue);
llvm::APInt readValue(byteSize * 8, tempvalue);
llvm::Constant* newVal =
llvm::ConstantInt::get(loadType, readValue);
LoadInst->replaceAllUsesWith(newVal);
hasChanged = true;
}
}
}
}
}
LoadInst->replaceAllUsesWith(newVal);
hasChanged = true;
}
}
}
}
}
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
};
class ReplaceTruncWithLoadPass
: public llvm::PassInfoMixin<ReplaceTruncWithLoadPass> {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
bool hasChanged = false;
std::vector<llvm::Instruction*> toRemove;
for (auto& F : M) {
for (auto& BB : F) {
for (auto I = BB.begin(), E = BB.end(); I != E;) {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
bool hasChanged = false;
std::vector<llvm::Instruction*> toRemove;
for (auto& F : M) {
for (auto& BB : F) {
for (auto I = BB.begin(), E = BB.end(); I != E;) {
auto CurrentI = I++;
auto CurrentI = I++;
if (auto* TruncInst =
llvm::dyn_cast<llvm::TruncInst>(&*CurrentI)) {
if (auto* TruncInst = llvm::dyn_cast<llvm::TruncInst>(&*CurrentI)) {
if (TruncInst->getSrcTy()->isIntegerTy(64) &&
TruncInst->getDestTy()->isIntegerTy(32)) {
if (TruncInst->getSrcTy()->isIntegerTy(64) &&
TruncInst->getDestTy()->isIntegerTy(32)) {
if (auto* LoadInst = llvm::dyn_cast<llvm::LoadInst>(
TruncInst->getOperand(0))) {
if (auto* LoadInst = llvm::dyn_cast<llvm::LoadInst>(
TruncInst->getOperand(0))) {
llvm::LoadInst* newLoad = new llvm::LoadInst(
TruncInst->getType(),
LoadInst->getPointerOperand(), "passload",
false, LoadInst);
llvm::LoadInst* newLoad = new llvm::LoadInst(
TruncInst->getType(), LoadInst->getPointerOperand(),
"passload", false, LoadInst);
TruncInst->replaceAllUsesWith(newLoad);
TruncInst->replaceAllUsesWith(newLoad);
toRemove.push_back(TruncInst);
toRemove.push_back(TruncInst);
hasChanged = true;
}
}
}
}
hasChanged = true;
}
}
}
}
for (llvm::Instruction* Inst : toRemove) {
Inst->eraseFromParent();
}
toRemove.clear();
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
}
for (llvm::Instruction* Inst : toRemove) {
Inst->eraseFromParent();
}
toRemove.clear();
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
};
// very simple pass
@@ -182,41 +162,39 @@ to
%GEPLoadxd-5368713239- = inttoptr i64 5368725620 to ptr
*/
class RemovePseudoMemory : public llvm::PassInfoMixin<RemovePseudoMemory> {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
public:
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&) {
std::vector<llvm::Instruction*> toRemove;
Value* memory = getMemory();
std::vector<llvm::Instruction*> toRemove;
Value* memory = getMemory();
bool hasChanged = false;
for (auto& F : M) {
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP =
llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
if (GEP->getOperand(0) == memory) {
llvm::IntToPtrInst* newPTR = new llvm::IntToPtrInst(
GEP->getOperand(1), GEP->getType(),
GEP->getName(), GEP);
bool hasChanged = false;
for (auto& F : M) {
for (auto& BB : F) {
for (auto& I : BB) {
if (auto* GEP = llvm::dyn_cast<llvm::GetElementPtrInst>(&I)) {
if (GEP->getOperand(0) == memory) {
llvm::IntToPtrInst* newPTR = new llvm::IntToPtrInst(
GEP->getOperand(1), GEP->getType(), GEP->getName(), GEP);
GEP->replaceAllUsesWith(newPTR);
GEP->replaceAllUsesWith(newPTR);
toRemove.push_back(GEP);
toRemove.push_back(GEP);
hasChanged = true;
}
}
}
hasChanged = true;
}
for (llvm::Instruction* Inst : toRemove) {
Inst->eraseFromParent();
}
toRemove.clear();
}
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
for (llvm::Instruction* Inst : toRemove) {
Inst->eraseFromParent();
}
toRemove.clear();
}
return hasChanged ? llvm::PreservedAnalyses::none()
: llvm::PreservedAnalyses::all();
}
};
#endif
+134 -125
View File
@@ -5,143 +5,152 @@
#include <queue>
namespace funcsignatures {
// TODO: this is ugly
// TODO: this is ugly
std::unordered_map<uint64_t, functioninfo> functions;
std::unordered_map<std::string, functioninfo> functionsByName;
std::unordered_map<uint64_t, functioninfo> functions;
std::unordered_map<std::string, functioninfo> functionsByName{
{"MessageBoxW", functioninfo("MessageBoxW",
{
funcArgInfo(ZYDIS_REGISTER_RCX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RDX, I64, 1),
funcArgInfo(ZYDIS_REGISTER_R8, I64, 1),
funcArgInfo(ZYDIS_REGISTER_R9, I64, 0),
})},
{"GetTickCount64", functioninfo("GetTickCount64", {})},
};
void createOffsetMap() {
for (auto value : siglookup) {
for (auto offsets : value.second.offsets) {
functions[offsets] = value.second;
}
functionsByName[value.second.name] = value.second;
void createOffsetMap() {
for (auto value : siglookup) {
for (auto offsets : value.second.offsets) {
functions[offsets] = value.second;
}
functionsByName[value.second.name] = value.second;
}
}
functioninfo* getFunctionInfo(uint64_t addr) {
if (functions.count(addr) == 0)
return nullptr;
return &(functions[addr]);
}
functioninfo* getFunctionInfo(std::string name) {
if (functionsByName.count(name) == 0)
return nullptr;
return &(functionsByName[name]);
}
void functioninfo::add_offset(uint64_t offset) {
offsets.push_back(FileHelper::fileOffsetToRVA(offset));
}
void functioninfo::display() const {
std::cout << "Function Name: " << name << ", Offsets: ";
for (const auto& offset : offsets) {
std::cout << offset << " ";
}
std::cout << "end" << std::endl;
}
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
siglookup{
{{0x55, 0x48, 0x81, 0xEC, 0xA0, 00, 00, 00, 0x48, 0x8D, 0xAC, 0x24,
0x80, 00, 00, 00},
functioninfo("??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_"
"ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z")},
{{0x4C, 0x8B, 0xDC, 0x4D, 0x89, 0x43, 0x18, 0x4D, 0x89, 0x4B, 0x20,
0x48, 0x83, 0xEC, 0x38},
functioninfo("swprintf_s",
{
funcArgInfo(ZYDIS_REGISTER_RCX, I64, 1),
funcArgInfo(ZYDIS_REGISTER_RDX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R8, I64, 1),
funcArgInfo(ZYDIS_REGISTER_R9, I64, 0),
})}};
AhoCorasick::AhoCorasick(
const std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>& patterns_map) {
trie.emplace_back();
int id = 0;
for (const auto& [pattern, _] : patterns_map) {
int current = 0;
for (unsigned char c : pattern) {
if (trie[current].children.count(c) == 0) {
trie[current].children[c] = trie.size();
trie.emplace_back();
}
current = trie[current].children[c];
}
trie[current].output.push_back(id);
patterns[id++] = pattern;
}
build();
}
functioninfo* getFunctionInfo(uint64_t addr) {
if (functions.count(addr) == 0)
return nullptr;
return &(functions[addr]);
void AhoCorasick::build() {
std::queue<int> q;
for (const auto& [c, next] : trie[0].children) {
trie[next].fail = 0;
q.push(next);
}
functioninfo* getFunctionInfo(std::string name) {
if (functionsByName.count(name) == 0)
return nullptr;
return &(functionsByName[name]);
}
void functioninfo::add_offset(uint64_t offset) {
offsets.push_back(FileHelper::fileOffsetToRVA(offset));
}
void functioninfo::display() const {
std::cout << "Function Name: " << name << ", Offsets: ";
for (const auto& offset : offsets) {
std::cout << offset << " ";
while (!q.empty()) {
int current = q.front();
q.pop();
for (const auto& [c, next] : trie[current].children) {
int fail = trie[current].fail;
while (fail != -1 && trie[fail].children.count(c) == 0) {
fail = trie[fail].fail;
}
std::cout << "end" << std::endl;
}
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
siglookup{
{{0x55, 0x48, 0x81, 0xEC, 0xA0, 00, 00, 00, 0x48, 0x8D, 0xAC, 0x24,
0x80, 00, 00, 00},
functioninfo("??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_"
"ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z")},
{{0x4C, 0x8B, 0xDC, 0x4D, 0x89, 0x43, 0x18, 0x4D, 0x89, 0x4B, 0x20,
0x48, 0x83, 0xEC, 0x38},
functioninfo("swprintf_s",
{
funcArgInfo(ZYDIS_REGISTER_RCX, I64, 1),
funcArgInfo(ZYDIS_REGISTER_RDX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R8, I64, 1),
})}};
AhoCorasick::AhoCorasick(
const std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>& patterns_map) {
trie.emplace_back();
int id = 0;
for (const auto& [pattern, _] : patterns_map) {
int current = 0;
for (unsigned char c : pattern) {
if (trie[current].children.count(c) == 0) {
trie[current].children[c] = trie.size();
trie.emplace_back();
}
current = trie[current].children[c];
}
trie[current].output.push_back(id);
patterns[id++] = pattern;
if (fail != -1) {
trie[next].fail = trie[fail].children[c];
} else {
trie[next].fail = 0;
}
build();
trie[next].output.insert(trie[next].output.end(),
trie[trie[next].fail].output.begin(),
trie[trie[next].fail].output.end());
q.push(next);
}
}
}
void AhoCorasick::build() {
std::queue<int> q;
for (const auto& [c, next] : trie[0].children) {
trie[next].fail = 0;
q.push(next);
}
while (!q.empty()) {
int current = q.front();
q.pop();
for (const auto& [c, next] : trie[current].children) {
int fail = trie[current].fail;
while (fail != -1 && trie[fail].children.count(c) == 0) {
fail = trie[fail].fail;
}
if (fail != -1) {
trie[next].fail = trie[fail].children[c];
} else {
trie[next].fail = 0;
}
trie[next].output.insert(trie[next].output.end(),
trie[trie[next].fail].output.begin(),
trie[trie[next].fail].output.end());
q.push(next);
}
}
std::vector<std::pair<int, int>>
AhoCorasick::search(const std::vector<unsigned char>& text) {
std::vector<std::pair<int, int>> results;
int current = 0;
for (uint64_t i = 0; i < text.size(); ++i) {
while (current != -1 && trie[current].children.count(text[i]) == 0) {
current = trie[current].fail;
}
if (current == -1) {
current = 0;
continue;
}
current = trie[current].children[text[i]];
for (int id : trie[current].output) {
results.emplace_back(i - patterns[id].size() + 1, id);
}
}
return results;
}
std::vector<std::pair<int, int>>
AhoCorasick::search(const std::vector<unsigned char>& text) {
std::vector<std::pair<int, int>> results;
int current = 0;
for (uint64_t i = 0; i < text.size(); ++i) {
while (current != -1 &&
trie[current].children.count(text[i]) == 0) {
current = trie[current].fail;
}
if (current == -1) {
current = 0;
continue;
}
current = trie[current].children[text[i]];
for (int id : trie[current].output) {
results.emplace_back(i - patterns[id].size() + 1, id);
}
}
return results;
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
search_signatures(const std::vector<unsigned char>& data) {
AhoCorasick ac(siglookup);
std::vector<std::pair<int, int>> matches = ac.search(data);
for (const auto& [pos, id] : matches) {
auto it = siglookup.find(ac.patterns[id]);
if (it != siglookup.end()) {
it->second.add_offset(pos);
}
}
return siglookup;
}
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
search_signatures(const std::vector<unsigned char>& data) {
AhoCorasick ac(siglookup);
std::vector<std::pair<int, int>> matches = ac.search(data);
for (const auto& [pos, id] : matches) {
auto it = siglookup.find(ac.patterns[id]);
if (it != siglookup.end()) {
it->second.add_offset(pos);
}
}
return siglookup;
}
std::vector<unsigned char> convertToVector(const unsigned char* data,
size_t size) {
return std::vector<unsigned char>(data, data + size);
}
std::vector<unsigned char> convertToVector(const unsigned char* data,
size_t size) {
return std::vector<unsigned char>(data, data + size);
}
} // namespace funcsignatures
+103 -105
View File
@@ -6,116 +6,114 @@
namespace funcsignatures {
struct funcArgInfo {
uint8_t reg;
struct funcArgInfo {
uint8_t reg;
struct argTypeInfo {
uint8_t size : 4; // 4 bits for size
uint8_t isPtr : 1;
uint8_t pad : 3;
argTypeInfo(ArgType type, bool isPtr)
: size(static_cast<uint8_t>(type)), isPtr(isPtr ? 1 : 0),
pad(0) {}
} argtype;
funcArgInfo(uint8_t Reg, ArgType type, bool isPtr)
: reg(Reg), argtype(type, isPtr) {};
struct argTypeInfo {
uint8_t size : 4; // 4 bits for size
uint8_t isPtr : 1;
uint8_t pad : 3;
argTypeInfo(ArgType type, bool isPtr)
: size(static_cast<uint8_t>(type)), isPtr(isPtr ? 1 : 0), pad(0) {}
} argtype;
funcArgInfo(uint8_t Reg, ArgType type, bool isPtr)
: reg(Reg), argtype(type, isPtr) {};
};
using funcArgInfos = std::vector<funcsignatures::funcArgInfo>;
struct functioninfo {
functioninfo() {}
functioninfo(const std::string& Name) : name(Name) {}
functioninfo(const std::string& Name, std::vector<funcArgInfo> Args)
: name(Name), args(Args) {}
functioninfo(const std::string& Name, const std::vector<funcArgInfo> Args,
const std::vector<unsigned char> Bytes)
: name(Name), args(Args), bytes(Bytes) {}
std::vector<unsigned char> bytes;
std::string name;
//
funcArgInfos args = {funcArgInfo(ZYDIS_REGISTER_RAX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RCX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RDX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RBX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RSP, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RBP, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RSI, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RDI, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R8, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R9, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R10, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R11, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R12, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R13, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R14, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R15, I64, 0),
funcArgInfo(ZYDIS_REGISTER_DS, I64, 1)};
// DS represents memory
// (yeah i hate it aswell)
// so the default is
// rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15,memory
// also
// should SS represent stack ? (rsp+0x20 + (8 * arg) )
// (SS is always ptr)
std::vector<uint64_t> offsets;
void add_offset(uint64_t offset);
void display() const;
};
struct siginfo {
siginfo(const std::vector<unsigned char>& Bytes);
siginfo(const std::vector<unsigned char>& Bytes,
const std::vector<unsigned char>& Args);
std::vector<unsigned char> bytes;
std::vector<unsigned char> args;
};
struct VectorHash {
std::size_t operator()(const std::vector<unsigned char>& v) const {
std::hash<unsigned char> hasher;
std::size_t seed = 0;
for (unsigned char i : v) {
seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
class AhoCorasick {
public:
AhoCorasick(
const std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>& patterns_map);
std::vector<std::pair<int, int>>
search(const std::vector<unsigned char>& text);
struct Node {
std::map<unsigned char, int> children;
int fail = -1;
std::vector<int> output;
};
using funcArgInfos = std::vector<funcsignatures::funcArgInfo>;
struct functioninfo {
functioninfo() {}
functioninfo(const std::string& Name) : name(Name) {}
std::vector<Node> trie;
std::unordered_map<int, std::vector<unsigned char>> patterns;
functioninfo(const std::string& Name, std::vector<funcArgInfo> Args)
: name(Name), args(Args) {}
void build();
};
functioninfo(const std::string& Name,
const std::vector<funcArgInfo> Args,
const std::vector<unsigned char> Bytes)
: name(Name), args(Args), bytes(Bytes) {}
std::vector<unsigned char> bytes;
std::string name;
//
funcArgInfos args = {funcArgInfo(ZYDIS_REGISTER_RAX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RCX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RDX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RBX, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RSP, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RBP, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RSI, I64, 0),
funcArgInfo(ZYDIS_REGISTER_RDI, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R8, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R9, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R10, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R11, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R12, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R13, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R14, I64, 0),
funcArgInfo(ZYDIS_REGISTER_R15, I64, 0),
funcArgInfo(ZYDIS_REGISTER_DS, I64, 1)};
// DS represents memory
// (yeah i hate it aswell)
// so the default is
// rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15,memory
// also
// should SS represent stack ? (rsp+0x20 + (8 * arg) )
// (SS is always ptr)
std::vector<uint64_t> offsets;
void add_offset(uint64_t offset);
void display() const;
};
struct siginfo {
siginfo(const std::vector<unsigned char>& Bytes);
siginfo(const std::vector<unsigned char>& Bytes,
const std::vector<unsigned char>& Args);
std::vector<unsigned char> bytes;
std::vector<unsigned char> args;
};
struct VectorHash {
std::size_t operator()(const std::vector<unsigned char>& v) const {
std::hash<unsigned char> hasher;
std::size_t seed = 0;
for (unsigned char i : v) {
seed ^= hasher(i) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
};
class AhoCorasick {
public:
AhoCorasick(
const std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>& patterns_map);
std::vector<std::pair<int, int>>
search(const std::vector<unsigned char>& text);
struct Node {
std::map<unsigned char, int> children;
int fail = -1;
std::vector<int> output;
};
std::vector<Node> trie;
std::unordered_map<int, std::vector<unsigned char>> patterns;
void build();
};
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
search_signatures(const std::vector<unsigned char>& data);
std::vector<unsigned char> convertToVector(const unsigned char* data,
size_t size);
void createOffsetMap();
functioninfo* getFunctionInfo(uint64_t addr);
functioninfo* getFunctionInfo(std::string name);
extern std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>
siglookup;
std::unordered_map<std::vector<unsigned char>, functioninfo, VectorHash>
search_signatures(const std::vector<unsigned char>& data);
std::vector<unsigned char> convertToVector(const unsigned char* data,
size_t size);
void createOffsetMap();
functioninfo* getFunctionInfo(uint64_t addr);
functioninfo* getFunctionInfo(std::string name);
extern std::unordered_map<std::vector<unsigned char>, functioninfo,
VectorHash>
siglookup;
} // namespace funcsignatures
+496 -513
View File
File diff suppressed because it is too large Load Diff
+11 -11
View File
@@ -4,31 +4,31 @@
#include "includes.h"
namespace BinaryOperations {
const char* getName(uint64_t offset);
const char* getName(uint64_t offset);
void initBases(void* file_base, ZyanU8* data);
void initBases(void* file_base, ZyanU8* data);
void getBases(void** file_base, ZyanU8** data);
void getBases(void** file_base, ZyanU8** data);
bool readMemory(uint64_t addr, unsigned byteSize, APInt& value);
bool readMemory(uint64_t addr, unsigned byteSize, APInt& value);
bool isWrittenTo(uint64_t addr);
bool isWrittenTo(uint64_t addr);
}; // namespace BinaryOperations
namespace GEPStoreTracker {
void initDomTree(Function& F);
void initDomTree(Function& F);
void updateDomTree(Function& F);
void updateDomTree(Function& F);
Value* solveLoad(LoadInst* inst, bool buildTime = 1);
Value* solveLoad(LoadInst* inst, bool buildTime = 1);
DominatorTree* getDomTree();
DominatorTree* getDomTree();
void insertMemoryOp(StoreInst* inst);
void insertMemoryOp(StoreInst* inst);
void updateMemoryOp(StoreInst* inst);
void updateMemoryOp(StoreInst* inst);
}; // namespace GEPStoreTracker
+971 -994
View File
File diff suppressed because it is too large Load Diff
+283 -290
View File
@@ -9,56 +9,56 @@ void* file_base_g;
ZyanU8* data_g;
struct InstructionDependencyOrder {
bool operator()(Instruction* const& a, Instruction* const& b) const {
bool operator()(Instruction* const& a, Instruction* const& b) const {
Function* F = a->getFunction();
GEPStoreTracker::updateDomTree(*F);
DominatorTree* DT = GEPStoreTracker::getDomTree();
Function* F = a->getFunction();
GEPStoreTracker::updateDomTree(*F);
DominatorTree* DT = GEPStoreTracker::getDomTree();
return (comesBefore(b, a, *DT));
}
return (comesBefore(b, a, *DT));
}
};
void replaceAllUsesWithandReplaceRMap(Value* v, Value* nv,
ReverseRegisterMap rVMap) {
// if two values are same, we go in a infinite loop
if (v == nv)
return;
// if two values are same, we go in a infinite loop
if (v == nv)
return;
auto registerV = rVMap[v];
auto registerV = rVMap[v];
if (registerV) {
if (isa<Instruction>(v)) {
// auto registerI = cast<Instruction>(v);
SetRegisterValue(registerV, v);
}
}
v->replaceAllUsesWith(nv);
// redundant?
v = nv;
// dont ask me this i dont know
// users start from latest user
std::vector<User*> users;
for (auto& use : v->uses()) {
users.push_back(use.getUser());
}
// iterate over the users in reverse order
for (auto it = users.rbegin(); it != users.rend(); ++it) {
User* user = *it;
if (auto GEPuser = dyn_cast<GetElementPtrInst>(user)) {
for (auto StoreUser : GEPuser->users()) {
if (auto SI = dyn_cast<StoreInst>(StoreUser)) {
GEPStoreTracker::updateMemoryOp(SI);
}
}
if (registerV) {
if (isa<Instruction>(v)) {
// auto registerI = cast<Instruction>(v);
SetRegisterValue(registerV, v);
}
}
v->replaceAllUsesWith(nv);
// redundant?
v = nv;
// dont ask me this i dont know
// users start from latest user
std::vector<User*> users;
for (auto& use : v->uses()) {
users.push_back(use.getUser());
}
// iterate over the users in reverse order
for (auto it = users.rbegin(); it != users.rend(); ++it) {
User* user = *it;
if (auto GEPuser = dyn_cast<GetElementPtrInst>(user)) {
for (auto StoreUser : GEPuser->users()) {
if (auto SI = dyn_cast<StoreInst>(StoreUser)) {
GEPStoreTracker::updateMemoryOp(SI);
}
}
}
}
}
// simplify Users with BFS
@@ -71,72 +71,71 @@ void replaceAllUsesWithandReplaceRMap(Value* v, Value* nv,
// also refactor this
void simplifyUsers(Value* newValue, DataLayout& DL,
ReverseRegisterMap flippedRegisterMap) {
unordered_set<Value*> visited;
std::priority_queue<Instruction*, std::vector<Instruction*>,
InstructionDependencyOrder>
toSimplify;
for (User* user : newValue->users()) {
unordered_set<Value*> visited;
std::priority_queue<Instruction*, std::vector<Instruction*>,
InstructionDependencyOrder>
toSimplify;
for (User* user : newValue->users()) {
if (Instruction* userInst = dyn_cast<Instruction>(user)) {
toSimplify.push(userInst);
}
}
while (!toSimplify.empty()) {
auto simplifyUser = toSimplify.top();
toSimplify.pop();
auto nsv = simplifyValueLater(simplifyUser, DL);
visited.insert(simplifyUser);
printvalue(simplifyUser) printvalue(nsv);
if (isa<GetElementPtrInst>(simplifyUser)) {
for (User* user : simplifyUser->users()) {
if (Instruction* userInst = dyn_cast<Instruction>(user)) {
if (visited.find(userInst) == visited.end()) { // it can try to insert
// max 3 times here
toSimplify.push(userInst);
visited.insert(userInst);
}
}
}
}
while (!toSimplify.empty()) {
auto simplifyUser = toSimplify.top();
toSimplify.pop();
auto nsv = simplifyValueLater(simplifyUser, DL);
visited.insert(simplifyUser);
printvalue(simplifyUser) printvalue(nsv);
if (isa<GetElementPtrInst>(simplifyUser)) {
for (User* user : simplifyUser->users()) {
if (Instruction* userInst = dyn_cast<Instruction>(user)) {
if (visited.find(userInst) ==
visited.end()) { // it can try to insert max 3 times
// here
toSimplify.push(userInst);
visited.insert(userInst);
}
}
}
}
// if values are identical, we will get into a loop and cant simplify
if (simplifyUser == nsv) {
continue;
}
// if can simplify, continue?
for (User* user : simplifyUser->users()) {
if (Instruction* userInst = dyn_cast<Instruction>(user)) {
if (visited.find(userInst) == visited.end()) {
toSimplify.push(userInst);
visited.erase(userInst);
}
}
}
replaceAllUsesWithandReplaceRMap(simplifyUser, nsv, flippedRegisterMap);
// if values are identical, we will get into a loop and cant simplify
if (simplifyUser == nsv) {
continue;
}
// if can simplify, continue?
for (User* user : simplifyUser->users()) {
if (Instruction* userInst = dyn_cast<Instruction>(user)) {
if (visited.find(userInst) == visited.end()) {
toSimplify.push(userInst);
visited.erase(userInst);
}
}
}
replaceAllUsesWithandReplaceRMap(simplifyUser, nsv, flippedRegisterMap);
}
}
PATH_info getConstraintVal(llvm::Function* function, Value* constraint,
uint64_t& dest) {
PATH_info result = PATH_unsolved;
printvalue(constraint);
auto simplified_constraint = simplifyValueLater(
constraint,
function->getParent()->getDataLayout()); // this is such a hack
printvalue(simplified_constraint);
if (llvm::ConstantInt* constInt =
dyn_cast<llvm::ConstantInt>(simplified_constraint)) {
printvalue(constInt) dest = constInt->getZExtValue();
result = PATH_solved;
return result;
}
PATH_info result = PATH_unsolved;
printvalue(constraint);
auto simplified_constraint = simplifyValueLater(
constraint,
function->getParent()->getDataLayout()); // this is such a hack
printvalue(simplified_constraint);
if (llvm::ConstantInt* constInt =
dyn_cast<llvm::ConstantInt>(simplified_constraint)) {
printvalue(constInt) dest = constInt->getZExtValue();
result = PATH_solved;
return result;
}
return result;
}
// https://github.com/llvm/llvm-project/blob/30f6eafaa978b4e0211368976fe60f15fa9f0067/llvm/unittests/Support/KnownBitsTest.h#L38
@@ -148,254 +147,248 @@ possiblevalues.push_back(Value1); });
*/
template <typename FnTy>
void ForeachNumInKnownBits(const KnownBits& Known, FnTy Fn) {
unsigned Bits = Known.getBitWidth();
unsigned Max = 1 << Bits;
for (unsigned N = 0; N <= Max; ++N) {
APInt Num(Bits, N);
if ((Num & Known.Zero) != 0 || (~Num & Known.One) != 0) {
continue;
}
Fn(Num);
unsigned Bits = Known.getBitWidth();
unsigned Max = 1 << Bits;
for (unsigned N = 0; N <= Max; ++N) {
APInt Num(Bits, N);
if ((Num & Known.Zero) != 0 || (~Num & Known.One) != 0) {
continue;
}
Fn(Num);
}
}
std::vector<llvm::APInt> getPossibleValues(const llvm::KnownBits& known,
unsigned max_unknown) {
llvm::APInt base = known.One;
llvm::APInt unknowns = ~(known.Zero | known.One);
unsigned numBits = known.getBitWidth();
llvm::APInt base = known.One;
llvm::APInt unknowns = ~(known.Zero | known.One);
unsigned numBits = known.getBitWidth();
std::vector<llvm::APInt> values;
std::vector<llvm::APInt> values;
llvm::APInt combo(unknowns.getBitWidth(), 0);
for (uint64_t i = 0; i < (1ULL << max_unknown); ++i) {
llvm::APInt temp = base;
for (unsigned j = 0, currentBit = 0; j < numBits; ++j) {
if (unknowns[j]) {
temp.setBitVal(j, (i >> currentBit) & 1);
currentBit++;
}
}
if (std::find(values.begin(), values.end(), temp) == values.end()) {
values.push_back(temp);
}
llvm::APInt combo(unknowns.getBitWidth(), 0);
for (uint64_t i = 0; i < (1ULL << max_unknown); ++i) {
llvm::APInt temp = base;
for (unsigned j = 0, currentBit = 0; j < numBits; ++j) {
if (unknowns[j]) {
temp.setBitVal(j, (i >> currentBit) & 1);
currentBit++;
}
}
return values;
if (std::find(values.begin(), values.end(), temp) == values.end()) {
values.push_back(temp);
}
}
return values;
}
void final_optpass(Function* clonedFuncx) {
llvm::PassBuilder passBuilder;
llvm::PassBuilder passBuilder;
llvm::LoopAnalysisManager loopAnalysisManager;
llvm::FunctionAnalysisManager functionAnalysisManager;
llvm::CGSCCAnalysisManager cGSCCAnalysisManager;
llvm::ModuleAnalysisManager moduleAnalysisManager;
llvm::LoopAnalysisManager loopAnalysisManager;
llvm::FunctionAnalysisManager functionAnalysisManager;
llvm::CGSCCAnalysisManager cGSCCAnalysisManager;
llvm::ModuleAnalysisManager moduleAnalysisManager;
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
passBuilder.registerFunctionAnalyses(functionAnalysisManager);
passBuilder.registerLoopAnalyses(loopAnalysisManager);
passBuilder.crossRegisterProxies(
loopAnalysisManager, functionAnalysisManager, cGSCCAnalysisManager,
moduleAnalysisManager);
passBuilder.registerModuleAnalyses(moduleAnalysisManager);
passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
passBuilder.registerFunctionAnalyses(functionAnalysisManager);
passBuilder.registerLoopAnalyses(loopAnalysisManager);
passBuilder.crossRegisterProxies(loopAnalysisManager, functionAnalysisManager,
cGSCCAnalysisManager, moduleAnalysisManager);
llvm::ModulePassManager modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(OptimizationLevel::O0);
llvm::ModulePassManager modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(OptimizationLevel::O0);
llvm::Module* module = clonedFuncx->getParent();
llvm::Module* module = clonedFuncx->getParent();
bool changed;
do {
changed = false;
bool changed;
do {
changed = false;
size_t beforeSize = module->getInstructionCount();
modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(OptimizationLevel::O3);
modulePassManager.addPass(GEPLoadPass());
modulePassManager.addPass(ReplaceTruncWithLoadPass());
modulePassManager.addPass(RemovePseudoStackPass());
modulePassManager.run(*module, moduleAnalysisManager);
size_t afterSize = module->getInstructionCount();
if (beforeSize != afterSize) {
changed = true;
}
} while (changed);
size_t beforeSize = module->getInstructionCount();
modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(OptimizationLevel::O3);
modulePassManager.addPass(RemovePseudoMemory());
modulePassManager.addPass(GEPLoadPass());
modulePassManager.addPass(ReplaceTruncWithLoadPass());
modulePassManager.addPass(RemovePseudoStackPass());
modulePassManager.run(*module, moduleAnalysisManager);
size_t afterSize = module->getInstructionCount();
if (beforeSize != afterSize) {
changed = true;
}
} while (changed);
modulePassManager =
passBuilder.buildPerModuleDefaultPipeline(OptimizationLevel::O3);
modulePassManager.addPass(RemovePseudoMemory());
modulePassManager.run(*module, moduleAnalysisManager);
}
llvm::ValueToValueMapTy* flipVMap(const ValueToValueMapTy& VMap) {
ValueToValueMapTy* RevMap = new llvm::ValueToValueMapTy;
for (const auto& pair : VMap) {
(*RevMap)[pair.second] = const_cast<Value*>(pair.first);
}
return RevMap;
ValueToValueMapTy* RevMap = new llvm::ValueToValueMapTy;
for (const auto& pair : VMap) {
(*RevMap)[pair.second] = const_cast<Value*>(pair.first);
}
return RevMap;
}
PATH_info solvePath(Function* function, uint64_t& dest, Value* simplifyValue) {
PATH_info result = PATH_unsolved;
if (llvm::ConstantInt* constInt =
dyn_cast<llvm::ConstantInt>(simplifyValue)) {
dest = constInt->getZExtValue();
result = PATH_solved;
return result;
PATH_info result = PATH_unsolved;
if (llvm::ConstantInt* constInt =
dyn_cast<llvm::ConstantInt>(simplifyValue)) {
dest = constInt->getZExtValue();
result = PATH_solved;
return result;
}
auto flippedRegisterMap = flipRegisterMap();
while (dest == 0) {
if (PATH_info solved = getConstraintVal(function, simplifyValue, dest)) {
if (solved == PATH_solved) {
outs() << "Solved the constraint and moving to next path\n";
outs().flush();
return solved;
}
}
auto flippedRegisterMap = flipRegisterMap();
deque<llvm::Instruction*> worklist;
std::vector<llvm::Instruction*> visited_used;
std::unordered_set<llvm::Instruction*> visited_used_set;
while (dest == 0) {
// Start with the return instruction
worklist.push_front(cast<Instruction>(simplifyValue));
if (PATH_info solved =
getConstraintVal(function, simplifyValue, dest)) {
if (solved == PATH_solved) {
outs() << "Solved the constraint and moving to next path\n";
outs().flush();
return solved;
}
while (!worklist.empty()) {
llvm::Instruction* inst = worklist.front();
worklist.pop_front();
visited_used.emplace_back(inst);
for (unsigned i = 0, e = inst->getNumOperands(); i != e; ++i) {
llvm::Value* operand = inst->getOperand(i);
if (llvm::Instruction* opInst =
llvm::dyn_cast<llvm::Instruction>(operand)) {
printvalue(opInst);
if (visited_used_set.insert(opInst).second) {
worklist.push_back(opInst);
}
}
}
}
deque<llvm::Instruction*> worklist;
std::vector<llvm::Instruction*> visited_used;
std::unordered_set<llvm::Instruction*> visited_used_set;
Value* value_with_least_possible_values = nullptr;
unsigned int least_possible_value_value = INT_MAX;
KnownBits bitsof_least_possible_value(64);
// Start with the return instruction
worklist.push_front(cast<Instruction>(simplifyValue));
DataLayout DL(function->getParent());
while (!worklist.empty()) {
llvm::Instruction* inst = worklist.front();
worklist.pop_front();
visited_used.emplace_back(inst);
// find the VWLPV(value with least possible values) that builds up to
// the returnValue
for (auto I : visited_used) {
KnownBits KnownVal = analyzeValueKnownBits(I, DL);
for (unsigned i = 0, e = inst->getNumOperands(); i != e; ++i) {
llvm::Value* operand = inst->getOperand(i);
if (llvm::Instruction* opInst =
llvm::dyn_cast<llvm::Instruction>(operand)) {
printvalue(opInst);
if (visited_used_set.insert(opInst).second) {
worklist.push_back(opInst);
}
}
}
}
unsigned int possible_values =
llvm::popcount(~(KnownVal.Zero | KnownVal.One).getZExtValue()) * 2;
possible_values = min(possible_values, KnownVal.getBitWidth() * 2);
printvalue(I);
printvalue2(possible_values);
printvalue2(KnownVal);
if (!KnownVal.isConstant() && !KnownVal.hasConflict() &&
possible_values < least_possible_value_value && possible_values > 0) {
least_possible_value_value = possible_values;
value_with_least_possible_values = cast<Value>(I);
bitsof_least_possible_value = KnownVal;
}
Value* value_with_least_possible_values = nullptr;
unsigned int least_possible_value_value = INT_MAX;
KnownBits bitsof_least_possible_value(64);
// if constant, simplify later users?
// simplify it aswell
// if (KnownVal.isConstant() && !KnownVal.hasConflict()) {
printvalue(I) auto nsv = simplifyValueLater(I, DL);
printvalue(nsv);
DataLayout DL(function->getParent());
replaceAllUsesWithandReplaceRMap(I, nsv, flippedRegisterMap);
simplifyUsers(nsv, DL, flippedRegisterMap);
//}
}
// find the VWLPV(value with least possible values) that builds up to
// the returnValue
for (auto I : visited_used) {
KnownBits KnownVal = analyzeValueKnownBits(I, DL);
if (PATH_info solved = getConstraintVal(function, simplifyValue, dest)) {
if (solved == PATH_solved) {
return solved;
}
}
unsigned int possible_values =
llvm::popcount(~(KnownVal.Zero | KnownVal.One).getZExtValue()) *
2;
possible_values = min(possible_values, KnownVal.getBitWidth() * 2);
printvalue(I);
printvalue2(possible_values);
printvalue2(KnownVal);
if (!KnownVal.isConstant() && !KnownVal.hasConflict() &&
possible_values < least_possible_value_value &&
possible_values > 0) {
least_possible_value_value = possible_values;
value_with_least_possible_values = cast<Value>(I);
bitsof_least_possible_value = KnownVal;
}
// cout << "Total user: " << total_user << "\n";
if (least_possible_value_value == 0)
throw("something went wrong");
// if constant, simplify later users?
// simplify it aswell
// if (KnownVal.isConstant() && !KnownVal.hasConflict()) {
printvalue(I) auto nsv = simplifyValueLater(I, DL);
printvalue(nsv);
outs() << " value_with_least_possible_values: ";
value_with_least_possible_values->print(outs());
outs() << "\n";
outs().flush();
outs() << " bitsof_least_possible_value : " << bitsof_least_possible_value
<< "\n";
outs().flush();
outs() << " possible values: " << least_possible_value_value << " : \n";
replaceAllUsesWithandReplaceRMap(I, nsv, flippedRegisterMap);
simplifyUsers(nsv, DL, flippedRegisterMap);
//}
}
// print an optimized version?
std::string Filename = "output_trysolve.ll";
std::error_code EC;
raw_fd_ostream OS(Filename, EC);
function->getParent()->print(OS, nullptr);
if (PATH_info solved =
getConstraintVal(function, simplifyValue, dest)) {
if (solved == PATH_solved) {
return solved;
}
}
auto possible_values = getPossibleValues(bitsof_least_possible_value,
least_possible_value_value - 1);
auto original_value = value_with_least_possible_values;
// cout << "Total user: " << total_user << "\n";
if (least_possible_value_value == 0)
throw("something went wrong");
unsigned max_possible_values = possible_values.size();
for (unsigned i = 0; i < max_possible_values; i++) {
outs() << i << "-) v : " << possible_values[i] << "\n";
}
outs() << " value_with_least_possible_values: ";
value_with_least_possible_values->print(outs());
outs() << "\n";
outs().flush();
outs() << " bitsof_least_possible_value : "
<< bitsof_least_possible_value << "\n";
outs().flush();
outs() << " possible values: " << least_possible_value_value << " : \n";
cout << "\nWhich option do you select? ";
// TODO:
// store current state
// make it identify assumptions
// create a new lifter state
// should look like
// Lifter(function, basicblock, assumptions, registermap, memorymap)
//
unsigned long long option = 0;
timer::suspendTimer();
cin >> option;
timer::resumeTimer();
auto newValue = ConstantInt::get(
value_with_least_possible_values->getType(), possible_values[option]);
// print an optimized version?
std::string Filename = "output_trysolve.ll";
std::error_code EC;
raw_fd_ostream OS(Filename, EC);
function->getParent()->print(OS, nullptr);
// replace original value with the value we selected
replaceAllUsesWithandReplaceRMap(original_value, newValue,
flippedRegisterMap);
// original_value->replaceAllUsesWith(newValue);
auto possible_values = getPossibleValues(
bitsof_least_possible_value, least_possible_value_value - 1);
auto original_value = value_with_least_possible_values;
unsigned max_possible_values = possible_values.size();
for (unsigned i = 0; i < max_possible_values; i++) {
outs() << i << "-) v : " << possible_values[i] << "\n";
}
cout << "\nWhich option do you select? ";
// TODO:
// store current state
// make it identify assumptions
// create a new lifter state
// should look like
// Lifter(function, basicblock, assumptions, registermap, memorymap)
//
unsigned long long option = 0;
timer::suspendTimer();
cin >> option;
timer::resumeTimer();
auto newValue =
ConstantInt::get(value_with_least_possible_values->getType(),
possible_values[option]);
// replace original value with the value we selected
replaceAllUsesWithandReplaceRMap(original_value, newValue,
flippedRegisterMap);
// original_value->replaceAllUsesWith(newValue);
// simplify later usages
simplifyUsers(newValue, DL, flippedRegisterMap);
// simplify later usages
simplifyUsers(newValue, DL, flippedRegisterMap);
#ifdef _DEBUG
std::string Filename3 = "output_trysolve2.ll";
std::error_code EC3;
raw_fd_ostream OS3(Filename3, EC3);
function->print(OS3, nullptr);
// receive input, replace the value with received input
// re-run program
std::string Filename3 = "output_trysolve2.ll";
std::error_code EC3;
raw_fd_ostream OS3(Filename3, EC3);
function->print(OS3, nullptr);
// receive input, replace the value with received input
// re-run program
#endif
}
return result;
}
return result;
}
+4215 -4320
View File
File diff suppressed because it is too large Load Diff
+61 -61
View File
@@ -15,32 +15,32 @@
#ifndef _NODEV
#define printvalue(x) \
do { \
debugging::printLLVMValue(x, #x); \
} while (0);
do { \
debugging::printLLVMValue(x, #x); \
} while (0);
// outs() << " " #x " : "; x->print(outs()); outs() << "\n"; outs().flush();
#define printvalue2(x) \
do { \
debugging::printValue(x, #x); \
} while (0);
do { \
debugging::printValue(x, #x); \
} while (0);
#else
#define printvalue(x) ((void)0);
#define printvalue2(x) ((void)0);
#endif // _NODEV
#define printvalueforce(x) \
do { \
outs() << " " #x " : "; \
x->print(outs()); \
outs() << "\n"; \
outs().flush(); \
} while (0);
do { \
outs() << " " #x " : "; \
x->print(outs()); \
outs() << "\n"; \
outs().flush(); \
} while (0);
#define printvalueforce2(x) \
do { \
outs() << " " #x " : " << x << "\n"; \
outs().flush(); \
} while (0);
do { \
outs() << " " #x " : " << x << "\n"; \
outs().flush(); \
} while (0);
#pragma warning(disable : 4996)
#pragma warning(disable : 4146)
@@ -271,8 +271,8 @@ using namespace llvm;
#if LLVM_VERSION_MAJOR < 17
inline llvm::raw_ostream& operator<<(llvm::raw_ostream& OS,
const llvm::KnownBits& KB) {
KB.print(OS);
return OS;
KB.print(OS);
return OS;
}
#endif
@@ -288,60 +288,60 @@ using BBInfo = tuple<uint64_t, BasicBlock*, RegisterMap>;
enum FlagOperation { SET_VALUE, SET_ONE, SET_ZERO, TOGGLE };
enum Flag {
FLAG_CF = 0, // Carry flag
FLAG_RESERVED1 = 1, // Reserved, typically not used by programs
FLAG_PF = 2, // Parity flag
FLAG_RESERVED3 = 3, // Reserved, typically not used by programs
FLAG_AF = 4, // Adjust flag
FLAG_RESERVED5 = 5, // Reserved, typically not used by programs
FLAG_ZF = 6, // Zero flag
FLAG_SF = 7, // Sign flag
FLAG_TF = 8, // Trap flag
FLAG_IF = 9, // Interrupt enable flag
FLAG_DF = 10, // Direction flag
FLAG_OF = 11, // Overflow flag
FLAG_IOPL =
12, // I/O privilege level (286+ only) always all-1s on 8086 and 186
FLAG_IOPL2 =
13, // I/O privilege level (286+ only) always all-1s on 8086 and 186
FLAG_NT = 14, // Nested task flag (286+ only), always 1 on 8086 and 186
FLAG_MD = 15, // Mode flag (NEC V-series only), reserved on all Intel CPUs.
// Always 1 on 8086 / 186, 0 on 286 and later.
FLAG_RF = 16, // Resume flag (386+ only)
FLAG_VM = 17, // Virtual 8086 mode flag (386+ only)
FLAG_AC = 18, // Alignment Check (486+, ring 3),
FLAG_VIF = 19, // Virtual interrupt flag (Pentium+)
FLAG_VIP = 20, // Virtual interrupt pending (Pentium+)
FLAG_ID = 21, // Able to use CPUID instruction (Pentium+)
FLAG_RES22 = 22, // Reserved, typically not used by programs
FLAG_RES23 = 23, // Reserved, typically not used by programs
FLAG_RES24 = 24, // Reserved, typically not used by programs
FLAG_RES25 = 25, // Reserved, typically not used by programs
FLAG_RES26 = 26, // Reserved, typically not used by programs
FLAG_RES27 = 27, // Reserved, typically not used by programs
FLAG_RES28 = 28, // Reserved, typically not used by programs
FLAG_RES29 = 29, // Reserved, typically not used by programs
FLAG_AES = 30, // AES key schedule loaded flag
FLAG_AI = 31, // Alternate Instruction Set enabled
// reserved above 32-63
FLAGS_END = 64
FLAG_CF = 0, // Carry flag
FLAG_RESERVED1 = 1, // Reserved, typically not used by programs
FLAG_PF = 2, // Parity flag
FLAG_RESERVED3 = 3, // Reserved, typically not used by programs
FLAG_AF = 4, // Adjust flag
FLAG_RESERVED5 = 5, // Reserved, typically not used by programs
FLAG_ZF = 6, // Zero flag
FLAG_SF = 7, // Sign flag
FLAG_TF = 8, // Trap flag
FLAG_IF = 9, // Interrupt enable flag
FLAG_DF = 10, // Direction flag
FLAG_OF = 11, // Overflow flag
FLAG_IOPL =
12, // I/O privilege level (286+ only) always all-1s on 8086 and 186
FLAG_IOPL2 =
13, // I/O privilege level (286+ only) always all-1s on 8086 and 186
FLAG_NT = 14, // Nested task flag (286+ only), always 1 on 8086 and 186
FLAG_MD = 15, // Mode flag (NEC V-series only), reserved on all Intel CPUs.
// Always 1 on 8086 / 186, 0 on 286 and later.
FLAG_RF = 16, // Resume flag (386+ only)
FLAG_VM = 17, // Virtual 8086 mode flag (386+ only)
FLAG_AC = 18, // Alignment Check (486+, ring 3),
FLAG_VIF = 19, // Virtual interrupt flag (Pentium+)
FLAG_VIP = 20, // Virtual interrupt pending (Pentium+)
FLAG_ID = 21, // Able to use CPUID instruction (Pentium+)
FLAG_RES22 = 22, // Reserved, typically not used by programs
FLAG_RES23 = 23, // Reserved, typically not used by programs
FLAG_RES24 = 24, // Reserved, typically not used by programs
FLAG_RES25 = 25, // Reserved, typically not used by programs
FLAG_RES26 = 26, // Reserved, typically not used by programs
FLAG_RES27 = 27, // Reserved, typically not used by programs
FLAG_RES28 = 28, // Reserved, typically not used by programs
FLAG_RES29 = 29, // Reserved, typically not used by programs
FLAG_AES = 30, // AES key schedule loaded flag
FLAG_AI = 31, // Alternate Instruction Set enabled
// reserved above 32-63
FLAGS_END = 64
};
enum opaque_info { NOT_OPAQUE = 0, OPAQUE_TRUE = 1, OPAQUE_FALSE = 2 };
enum ROP_info {
ROP_return = 0,
REAL_return = 1,
ROP_return = 0,
REAL_return = 1,
};
enum JMP_info {
JOP_jmp = 0,
JOP_jmp_unsolved = 1,
JOP_jmp = 0,
JOP_jmp_unsolved = 1,
};
enum PATH_info {
PATH_unsolved = 0,
PATH_solved = 1,
PATH_unsolved = 0,
PATH_solved = 1,
};
// 8 << (arg.argtype.size - 1)
+158 -164
View File
@@ -21,214 +21,208 @@ void asm_to_zydis_to_lift(IRBuilder<>& builder, ZyanU8* data,
shared_ptr<vector<BBInfo>> blockAddresses,
ZyanU64 file_base) {
bool run = 1;
while (run) {
bool run = 1;
while (run) {
while (blockAddresses->size() > 0) {
while (blockAddresses->size() > 0) {
runtime_address = get<0>(blockAddresses->back());
uint64_t offset = FileHelper::address_to_mapped_address(
(void*)file_base, runtime_address);
runtime_address = get<0>(blockAddresses->back());
uint64_t offset = FileHelper::address_to_mapped_address((void*)file_base,
runtime_address);
debugging::doIfDebug([&]() {
cout << "runtime_addr: " << runtime_address
<< " offset:" << offset << " byte there: 0x"
<< (int)*(uint8_t*)(file_base + offset) << endl;
cout << "offset: " << offset
<< " file_base?: " << original_address
<< " runtime: " << runtime_address << endl;
});
debugging::doIfDebug([&]() {
cout << "runtime_addr: " << runtime_address << " offset:" << offset
<< " byte there: 0x" << (int)*(uint8_t*)(file_base + offset)
<< endl;
cout << "offset: " << offset << " file_base?: " << original_address
<< " runtime: " << runtime_address << endl;
});
auto nextBasicBlock = get<1>(blockAddresses->back());
added_blocks_addresses.push_back(blockAddresses->back());
auto nextBasicBlock = get<1>(blockAddresses->back());
added_blocks_addresses.push_back(blockAddresses->back());
builder.SetInsertPoint(nextBasicBlock);
builder.SetInsertPoint(nextBasicBlock);
// will use this for exploring multiple branches
setRegisters(get<2>(blockAddresses->back()));
//
// will use this for exploring multiple branches
setRegisters(get<2>(blockAddresses->back()));
//
// update only when its needed
blockAddresses->pop_back();
// update only when its needed
blockAddresses->pop_back();
BinaryOperations::initBases((void*)file_base, data);
size_t last_value;
BinaryOperations::initBases((void*)file_base, data);
size_t last_value;
bool run = 1;
bool run = 1;
if (!blockAddresses->empty()) {
last_value = get<0>(blockAddresses->back());
} else {
if (!blockAddresses->empty()) {
last_value = get<0>(blockAddresses->back());
} else {
last_value = 0;
}
last_value = 0;
}
for (; run && runtime_address > 0;) {
if (BinaryOperations::isWrittenTo(runtime_address)) {
printvalueforce2(runtime_address);
outs() << "SelfModifyingCode!\n";
outs().flush();
}
if ((blockAddresses->size() == 0 ||
(last_value == get<0>(blockAddresses->back())))) {
// why tf compiler tells this is unused?
ZydisDisassembledInstruction instruction;
ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64,
runtime_address, data + offset, 15,
&instruction);
auto counter = debugging::increaseInstCounter() - 1;
debugging::doIfDebug([&]() {
cout << hex << counter << ":" << instruction.text
<< "\n";
cout << "runtime: " << instruction.runtime_address
<< endl;
});
liftInstruction(builder, instruction, blockAddresses, run);
offset += instruction.info.length;
runtime_address += instruction.info.length;
} else {
break;
}
}
for (; run && runtime_address > 0;) {
if (BinaryOperations::isWrittenTo(runtime_address)) {
printvalueforce2(runtime_address);
outs() << "SelfModifyingCode!\n";
outs().flush();
}
run = 0;
if ((blockAddresses->size() == 0 ||
(last_value == get<0>(blockAddresses->back())))) {
// why tf compiler tells this is unused?
ZydisDisassembledInstruction instruction;
ZydisDisassembleIntel(ZYDIS_MACHINE_MODE_LONG_64, runtime_address,
data + offset, 15, &instruction);
auto counter = debugging::increaseInstCounter() - 1;
debugging::doIfDebug([&]() {
cout << hex << counter << ":" << instruction.text << "\n";
cout << "runtime: " << instruction.runtime_address << endl;
});
liftInstruction(builder, instruction, blockAddresses, run);
offset += instruction.info.length;
runtime_address += instruction.info.length;
} else {
break;
}
}
}
run = 0;
}
}
void InitFunction_and_LiftInstructions(ZyanU64 runtime_address,
uint64_t file_base) {
ZydisDecoder decoder;
ZydisFormatter formatter;
ZydisDecoder decoder;
ZydisFormatter formatter;
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64,
ZYDIS_STACK_WIDTH_64);
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
ZydisDecoderInit(&decoder, ZYDIS_MACHINE_MODE_LONG_64, ZYDIS_STACK_WIDTH_64);
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
LLVMContext context;
string mod_name = "my_lifting_module";
llvm::Module lifting_module = llvm::Module(mod_name.c_str(), context);
LLVMContext context;
string mod_name = "my_lifting_module";
llvm::Module lifting_module = llvm::Module(mod_name.c_str(), context);
vector<llvm::Type*> argTypes;
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::PointerType::get(context, 0));
argTypes.push_back(llvm::PointerType::get(context, 0)); // temp fix TEB
vector<llvm::Type*> argTypes;
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::Type::getInt64Ty(context));
argTypes.push_back(llvm::PointerType::get(context, 0));
argTypes.push_back(llvm::PointerType::get(context, 0)); // temp fix TEB
auto functionType =
llvm::FunctionType::get(llvm::Type::getInt64Ty(context), argTypes, 0);
auto functionType =
llvm::FunctionType::get(llvm::Type::getInt64Ty(context), argTypes, 0);
string function_name = "main";
auto function =
llvm::Function::Create(functionType, llvm::Function::ExternalLinkage,
function_name.c_str(), lifting_module);
string function_name = "main";
auto function =
llvm::Function::Create(functionType, llvm::Function::ExternalLinkage,
function_name.c_str(), lifting_module);
string block_name = "entry";
auto bb = llvm::BasicBlock::Create(context, block_name.c_str(), function);
llvm::IRBuilder<> builder = llvm::IRBuilder<>(bb);
string block_name = "entry";
auto bb = llvm::BasicBlock::Create(context, block_name.c_str(), function);
llvm::IRBuilder<> builder = llvm::IRBuilder<>(bb);
auto RegisterList = InitRegisters(builder, function, runtime_address);
auto RegisterList = InitRegisters(builder, function, runtime_address);
GEPStoreTracker::initDomTree(*function);
GEPStoreTracker::initDomTree(*function);
shared_ptr<vector<BBInfo>> blockAddresses = make_shared<vector<BBInfo>>();
shared_ptr<vector<BBInfo>> blockAddresses = make_shared<vector<BBInfo>>();
blockAddresses->push_back(make_tuple(runtime_address, bb, RegisterList));
blockAddresses->push_back(make_tuple(runtime_address, bb, RegisterList));
asm_to_zydis_to_lift(builder, (uint8_t*)file_base, runtime_address,
blockAddresses, file_base);
asm_to_zydis_to_lift(builder, (uint8_t*)file_base, runtime_address,
blockAddresses, file_base);
string Filename = "output.ll";
error_code EC;
llvm::raw_fd_ostream OS(Filename, EC);
if (EC) {
llvm::errs() << "Could not open file: " << EC.message();
return;
}
lifting_module.print(OS, nullptr);
string Filename = "output.ll";
error_code EC;
llvm::raw_fd_ostream OS(Filename, EC);
if (EC) {
llvm::errs() << "Could not open file: " << EC.message();
return;
}
lifting_module.print(OS, nullptr);
return;
}
int main(int argc, char* argv[]) {
vector<string> args(argv, argv + argc);
argparser::parseArguments(args);
timer::startTimer();
// use parser
if (args.size() < 3) {
cerr << "Usage: " << args[0] << " <filename> <startAddr>" << endl;
return 1;
}
vector<string> args(argv, argv + argc);
argparser::parseArguments(args);
timer::startTimer();
// use parser
if (args.size() < 3) {
cerr << "Usage: " << args[0] << " <filename> <startAddr>" << endl;
return 1;
}
// debugging::enableDebug();
// debugging::enableDebug();
const char* filename = args[1].c_str();
uint64_t startAddr = stoull(args[2], nullptr, 0);
const char* filename = args[1].c_str();
uint64_t startAddr = stoull(args[2], nullptr, 0);
ifstream ifs(filename, ios::binary);
if (!ifs.is_open()) {
cout << "Failed to open the file." << endl;
return 1;
}
ifstream ifs(filename, ios::binary);
if (!ifs.is_open()) {
cout << "Failed to open the file." << endl;
return 1;
}
ifs.seekg(0, ios::end);
vector<uint8_t> fileData(ifs.tellg());
ifs.seekg(0, ios::beg);
ifs.seekg(0, ios::end);
vector<uint8_t> fileData(ifs.tellg());
ifs.seekg(0, ios::beg);
if (!ifs.read((char*)fileData.data(), fileData.size())) {
cout << "Failed to read the file." << endl;
return 1;
}
ifs.close();
if (!ifs.read((char*)fileData.data(), fileData.size())) {
cout << "Failed to read the file." << endl;
return 1;
}
ifs.close();
auto fileBase = fileData.data();
auto fileBase = fileData.data();
FileHelper::setFileBase(fileBase);
FileHelper::setFileBase(fileBase);
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders = (win::nt_headers_x64_t*)(fileBase + dosHeader->e_lfanew);
auto ADDRESS = ntHeaders->optional_header.image_base;
uint64_t RVA = static_cast<uint64_t>(startAddr - ADDRESS);
uint64_t fileOffset = FileHelper::RvaToFileOffset(ntHeaders, RVA);
uint8_t* dataAtAddress = fileBase + fileOffset;
cout << hex << "0x" << (int)*dataAtAddress << endl;
original_address = ADDRESS;
cout << "address: " << ADDRESS << " filebase: " << (uint64_t)fileBase
<< " fOffset: " << fileOffset << " RVA: " << RVA << endl;
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders = (win::nt_headers_x64_t*)(fileBase + dosHeader->e_lfanew);
auto ADDRESS = ntHeaders->optional_header.image_base;
uint64_t RVA = static_cast<uint64_t>(startAddr - ADDRESS);
uint64_t fileOffset = FileHelper::RvaToFileOffset(ntHeaders, RVA);
uint8_t* dataAtAddress = fileBase + fileOffset;
cout << hex << "0x" << (int)*dataAtAddress << endl;
original_address = ADDRESS;
cout << "address: " << ADDRESS << " filebase: " << (uint64_t)fileBase
<< " fOffset: " << fileOffset << " RVA: " << RVA << endl;
funcsignatures::search_signatures(fileData);
funcsignatures::createOffsetMap();
for (const auto& [key, value] : funcsignatures::siglookup) {
value.display();
}
funcsignatures::search_signatures(fileData);
funcsignatures::createOffsetMap();
for (const auto& [key, value] : funcsignatures::siglookup) {
value.display();
}
long long ms = timer::getTimer();
cout << "\n" << dec << ms << " milliseconds has past" << endl;
long long ms = timer::getTimer();
cout << "\n" << dec << ms << " milliseconds has past" << endl;
InitFunction_and_LiftInstructions(startAddr, (uint64_t)fileBase);
long long milliseconds = timer::stopTimer();
cout << "\n" << dec << milliseconds << " milliseconds has past" << endl;
cout << "Executed " << debugging::increaseInstCounter() - 1
<< " total insts";
InitFunction_and_LiftInstructions(startAddr, (uint64_t)fileBase);
long long milliseconds = timer::stopTimer();
cout << "\n" << dec << milliseconds << " milliseconds has past" << endl;
cout << "Executed " << debugging::increaseInstCounter() - 1 << " total insts";
}
+168 -170
View File
@@ -6,205 +6,203 @@
#include <ratio>
namespace FileHelper {
static void* fileBase = nullptr;
static void* fileBase = nullptr;
void setFileBase(void* base) { fileBase = base; }
void setFileBase(void* base) { fileBase = base; }
win::section_header_t*
GetEnclosingSectionHeader(uint32_t rva, win::nt_headers_x64_t* pNTHeader) {
auto section = pNTHeader->get_sections();
for (unsigned i = 0; i < pNTHeader->file_header.num_sections;
i++, section++) {
if ((rva >= section->virtual_address) &&
(rva < (section->virtual_address + section->virtual_size))) {
win::section_header_t*
GetEnclosingSectionHeader(uint32_t rva, win::nt_headers_x64_t* pNTHeader) {
auto section = pNTHeader->get_sections();
for (unsigned i = 0; i < pNTHeader->file_header.num_sections;
i++, section++) {
if ((rva >= section->virtual_address) &&
(rva < (section->virtual_address + section->virtual_size))) {
return section;
}
}
return 0;
return section;
}
}
return 0;
}
uint64_t secCharacteristics(win::nt_headers_x64_t* ntHeaders,
uint32_t rva) {
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (rva >= sectionHeader->virtual_address &&
rva < (sectionHeader->virtual_address +
sectionHeader->virtual_size)) {
return sectionHeader->characteristics.mem_execute;
}
}
return 0;
uint64_t secCharacteristics(win::nt_headers_x64_t* ntHeaders, uint32_t rva) {
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (rva >= sectionHeader->virtual_address &&
rva <
(sectionHeader->virtual_address + sectionHeader->virtual_size)) {
return sectionHeader->characteristics.mem_execute;
}
}
return 0;
}
uint64_t getSectionCharacteristics(void* fileBase, uint64_t rva) {
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto ADDRESS = rva - ntHeaders->optional_header.image_base;
return secCharacteristics(ntHeaders, ADDRESS);
uint64_t getSectionCharacteristics(void* fileBase, uint64_t rva) {
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto ADDRESS = rva - ntHeaders->optional_header.image_base;
return secCharacteristics(ntHeaders, ADDRESS);
}
uint64_t RvaToFileOffset(win::nt_headers_x64_t* ntHeaders, uint32_t rva) {
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (rva >= sectionHeader->virtual_address &&
rva <
(sectionHeader->virtual_address + sectionHeader->virtual_size)) {
if (sectionHeader->characteristics.mem_execute ||
(sectionHeader->characteristics.mem_read &&
!sectionHeader->characteristics.mem_write)) // remove?
return rva - sectionHeader->virtual_address +
sectionHeader->ptr_raw_data;
else
return 0;
}
}
return 0;
}
uint64_t RvaToFileOffset(win::nt_headers_x64_t* ntHeaders, uint32_t rva) {
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (rva >= sectionHeader->virtual_address &&
rva < (sectionHeader->virtual_address +
sectionHeader->virtual_size)) {
if (sectionHeader->characteristics.mem_execute ||
(sectionHeader->characteristics.mem_read &&
!sectionHeader->characteristics.mem_write)) // remove?
return rva - sectionHeader->virtual_address +
sectionHeader->ptr_raw_data;
else
return 0;
}
}
return 0;
}
uint64_t address_to_mapped_address(void* fileBase, uint64_t rva) {
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto ADDRESS = rva - ntHeaders->optional_header.image_base;
return RvaToFileOffset(ntHeaders, ADDRESS);
}
uint64_t fileOffsetToRVA(uint64_t offset) {
if (!fileBase)
return 0;
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (offset >= sectionHeader->ptr_raw_data &&
offset < (sectionHeader->ptr_raw_data +
sectionHeader->size_raw_data)) {
return ntHeaders->optional_header.image_base + offset -
sectionHeader->ptr_raw_data +
sectionHeader->virtual_address;
}
}
return 0;
uint64_t address_to_mapped_address(void* fileBase, uint64_t rva) {
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto ADDRESS = rva - ntHeaders->optional_header.image_base;
return RvaToFileOffset(ntHeaders, ADDRESS);
}
uint64_t fileOffsetToRVA(uint64_t offset) {
if (!fileBase)
return 0;
auto dosHeader = (win::dos_header_t*)fileBase;
auto ntHeaders =
(win::nt_headers_x64_t*)((uint8_t*)fileBase + dosHeader->e_lfanew);
auto sectionHeader = ntHeaders->get_sections();
for (int i = 0; i < ntHeaders->file_header.num_sections;
i++, sectionHeader++) {
if (offset >= sectionHeader->ptr_raw_data &&
offset <
(sectionHeader->ptr_raw_data + sectionHeader->size_raw_data)) {
return ntHeaders->optional_header.image_base + offset -
sectionHeader->ptr_raw_data + sectionHeader->virtual_address;
}
}
return 0;
}
} // namespace FileHelper
namespace debugging {
int ic = 1;
int increaseInstCounter() { return ++ic; }
bool shouldDebug = false;
void enableDebug() {
shouldDebug = 1;
cout << "Debugging enabled\n";
}
void printLLVMValue(llvm::Value* v, const char* name) {
if (!shouldDebug)
return;
outs() << " " << name << " : ";
v->print(outs());
outs() << "\n";
outs().flush();
}
void doIfDebug(const std::function<void(void)>& dothis) {
if (!shouldDebug)
return;
(dothis)();
}
template <typename T> void printValue(const T& v, const char* name) {
if (!shouldDebug)
return;
outs() << " " << name << " : " << v << "\n";
outs().flush();
}
int ic = 1;
int increaseInstCounter() { return ++ic; }
bool shouldDebug = false;
void enableDebug() {
shouldDebug = 1;
cout << "Debugging enabled\n";
}
void printLLVMValue(llvm::Value* v, const char* name) {
if (!shouldDebug)
return;
outs() << " " << name << " : ";
v->print(outs());
outs() << "\n";
outs().flush();
}
void doIfDebug(const std::function<void(void)>& dothis) {
if (!shouldDebug)
return;
(dothis)();
}
template <typename T> void printValue(const T& v, const char* name) {
if (!shouldDebug)
return;
outs() << " " << name << " : " << v << "\n";
outs().flush();
}
template void printValue<uint64_t>(const uint64_t& v, const char* name);
template void printValue<uint32_t>(const uint32_t& v, const char* name);
template void printValue<uint16_t>(const uint16_t& v, const char* name);
template void printValue<uint8_t>(const uint8_t& v, const char* name);
template void printValue<int64_t>(const int64_t& v, const char* name);
template void printValue<int32_t>(const int32_t& v, const char* name);
template void printValue<int16_t>(const int16_t& v, const char* name);
template void printValue<int8_t>(const int8_t& v, const char* name);
template void printValue<bool>(const bool& v, const char* name);
template void printValue<ValueLatticeElement>(const ValueLatticeElement& v,
const char* name);
template void printValue<KnownBits>(const KnownBits& v, const char* name);
template void printValue<APInt>(const APInt& v, const char* name);
template void printValue<ROP_info>(const ROP_info& v, const char* name);
template void printValue<uint64_t>(const uint64_t& v, const char* name);
template void printValue<uint32_t>(const uint32_t& v, const char* name);
template void printValue<uint16_t>(const uint16_t& v, const char* name);
template void printValue<uint8_t>(const uint8_t& v, const char* name);
template void printValue<int64_t>(const int64_t& v, const char* name);
template void printValue<int32_t>(const int32_t& v, const char* name);
template void printValue<int16_t>(const int16_t& v, const char* name);
template void printValue<int8_t>(const int8_t& v, const char* name);
template void printValue<bool>(const bool& v, const char* name);
template void printValue<ValueLatticeElement>(const ValueLatticeElement& v,
const char* name);
template void printValue<KnownBits>(const KnownBits& v, const char* name);
template void printValue<APInt>(const APInt& v, const char* name);
template void printValue<ROP_info>(const ROP_info& v, const char* name);
} // namespace debugging
namespace argparser {
void printHelp() {
std::cerr << "Options:\n"
<< " -d, --enable-debug Enable debugging mode\n"
<< " -h Display this help message\n";
void printHelp() {
std::cerr << "Options:\n"
<< " -d, --enable-debug Enable debugging mode\n"
<< " -h Display this help message\n";
}
std::map<std::string, std::function<void()>> options = {
{"-d", debugging::enableDebug},
{"--enable-debug", debugging::enableDebug},
{"-h", printHelp}};
void parseArguments(std::vector<std::string>& args) {
std::vector<std::string> newArgs;
for (const auto& arg : args) {
// cout << arg << "\n";
if (options.find(arg) != options.end())
options[arg]();
else if (*(arg.c_str()) == '-')
printHelp();
else
newArgs.push_back(arg);
}
std::map<std::string, std::function<void()>> options = {
{"-d", debugging::enableDebug},
{"--enable-debug", debugging::enableDebug},
{"-h", printHelp}};
void parseArguments(std::vector<std::string>& args) {
std::vector<std::string> newArgs;
for (const auto& arg : args) {
// cout << arg << "\n";
if (options.find(arg) != options.end())
options[arg]();
else if (*(arg.c_str()) == '-')
printHelp();
else
newArgs.push_back(arg);
}
args.swap(newArgs);
}
args.swap(newArgs);
}
} // namespace argparser
namespace timer {
using clock = std::chrono::high_resolution_clock;
using time_point = std::chrono::time_point<clock>;
using duration = std::chrono::duration<double, std::milli>;
using clock = std::chrono::high_resolution_clock;
using time_point = std::chrono::time_point<clock>;
using duration = std::chrono::duration<double, std::milli>;
time_point startTime;
duration elapsedTime{0};
bool running = false;
time_point startTime;
duration elapsedTime{0};
bool running = false;
void startTimer() {
startTime = clock::now();
running = true;
void startTimer() {
startTime = clock::now();
running = true;
}
double getTimer() { return elapsedTime.count(); }
double stopTimer() {
if (running) {
elapsedTime += clock::now() - startTime;
running = false;
}
return elapsedTime.count();
}
double getTimer() { return elapsedTime.count(); }
double stopTimer() {
if (running) {
elapsedTime += clock::now() - startTime;
running = false;
}
return elapsedTime.count();
void suspendTimer() {
if (running) {
elapsedTime += clock::now() - startTime;
running = false;
}
}
void suspendTimer() {
if (running) {
elapsedTime += clock::now() - startTime;
running = false;
}
}
void resumeTimer() {
if (!running) {
startTime = clock::now();
running = true;
}
void resumeTimer() {
if (!running) {
startTime = clock::now();
running = true;
}
}
} // namespace timer
+19 -20
View File
@@ -8,40 +8,39 @@
namespace FileHelper {
win::section_header_t*
GetEnclosingSectionHeader(uint32_t rva, win::nt_headers_x64_t* pNTHeader);
win::section_header_t*
GetEnclosingSectionHeader(uint32_t rva, win::nt_headers_x64_t* pNTHeader);
uint64_t secCharacteristics(win::nt_headers_x64_t* ntHeaders,
uint32_t rva);
uint64_t secCharacteristics(win::nt_headers_x64_t* ntHeaders, uint32_t rva);
uint64_t getSectionCharacteristics(void* fileBase, uint64_t rva);
uint64_t getSectionCharacteristics(void* fileBase, uint64_t rva);
uint64_t RvaToFileOffset(win::nt_headers_x64_t* ntHeaders, uint32_t rva);
uint64_t RvaToFileOffset(win::nt_headers_x64_t* ntHeaders, uint32_t rva);
uint64_t address_to_mapped_address(void* fileBase, uint64_t rva);
uint64_t address_to_mapped_address(void* fileBase, uint64_t rva);
uint64_t fileOffsetToRVA(uint64_t fileAddress);
uint64_t fileOffsetToRVA(uint64_t fileAddress);
void setFileBase(void* base);
void setFileBase(void* base);
} // namespace FileHelper
namespace debugging {
int increaseInstCounter();
void enableDebug();
void printLLVMValue(llvm::Value* v, const char* name);
void doIfDebug(const std::function<void(void)>& dothis);
template <typename T> void printValue(const T& v, const char* name);
int increaseInstCounter();
void enableDebug();
void printLLVMValue(llvm::Value* v, const char* name);
void doIfDebug(const std::function<void(void)>& dothis);
template <typename T> void printValue(const T& v, const char* name);
} // namespace debugging
namespace argparser {
void parseArguments(std::vector<std::string>& args);
void parseArguments(std::vector<std::string>& args);
} // namespace argparser
namespace timer {
void startTimer();
double stopTimer();
double getTimer();
void suspendTimer();
void resumeTimer();
void startTimer();
double stopTimer();
double getTimer();
void suspendTimer();
void resumeTimer();
} // namespace timer