mirror of
https://github.com/NaC-L/Mergen.git
synced 2026-05-12 09:40:34 +00:00
2 width indent
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
IndentWidth: 2
|
||||
PointerAlignment: Left
|
||||
NamespaceIndentation: All
|
||||
+133
-155
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+11
-11
@@ -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
File diff suppressed because it is too large
Load Diff
+283
-290
@@ -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
File diff suppressed because it is too large
Load Diff
+61
-61
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user