Skip to content

Commit 34e1de3

Browse files
author
Triton Library
committed
Merge branch 'dev-v1.0'
2 parents a8f7793 + 5ee3cc2 commit 34e1de3

File tree

21 files changed

+620
-188
lines changed

21 files changed

+620
-188
lines changed

.build_number

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1597
1+
1599

.github/workflows/vcpkg.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ jobs:
1111
matrix:
1212
os:
1313
- macOS-latest
14-
- ubuntu-20.04
14+
- ubuntu-latest
1515
- windows-2022
1616
include:
1717
- os: windows-2022
1818
platform: windows
1919
vcpkg-triplet: x64-windows-static-release-md
2020
cmake-preset: windows-x64
2121
python-executable: python
22-
- os: ubuntu-20.04
22+
- os: ubuntu-latest
2323
platform: linux
2424
vcpkg-triplet: x64-linux-release
2525
cmake-preset: linux-x64
@@ -38,7 +38,7 @@ jobs:
3838
name: Get vcpkg
3939
with:
4040
repository: 'microsoft/vcpkg'
41-
ref: '2024.05.24'
41+
ref: '2025.06.13'
4242
path: '${{ github.workspace }}/_vcpkg'
4343
fetch-depth: 0
4444

src/examples/cpp/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,15 @@ set_property(TARGET block PROPERTY CXX_STANDARD 17)
4949
target_link_libraries(block triton)
5050
add_test(TestBlock block)
5151
add_dependencies(check block)
52+
53+
find_package(LIEF QUIET)
54+
find_package(fmt QUIET)
55+
if(LIEF_FOUND AND fmt_FOUND)
56+
message(STATUS "LIEF found")
57+
message(STATUS "FMT found")
58+
add_executable(hooking_libc hooking_libc.cpp)
59+
set_property(TARGET hooking_libc PROPERTY CXX_STANDARD 17)
60+
target_link_libraries(hooking_libc triton LIEF::LIEF fmt::fmt)
61+
add_test(TestHookingLibc hooking_libc)
62+
add_dependencies(check hooking_libc)
63+
endif()

src/examples/cpp/hooking_libc.cpp

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
#include <iostream>
2+
#include <fstream>
3+
#include <vector>
4+
#include <string>
5+
#include <functional>
6+
#include <triton/context.hpp>
7+
#include <triton/x86Specifications.hpp>
8+
#include <LIEF/ELF.hpp>
9+
#include <fmt/format.h>
10+
#include <sstream>
11+
#include <iomanip>
12+
13+
#define DEBUG 0
14+
15+
std::string getMemoryString(const triton::Context& ctx, triton::uint64 addr) {
16+
std::string s;
17+
size_t index = 0;
18+
19+
while (auto value = ctx.getConcreteMemoryValue(addr + index)) {
20+
char c = static_cast<char>(value);
21+
if (std::isprint(c)) {
22+
s += c;
23+
}
24+
index++;
25+
}
26+
27+
return s;
28+
}
29+
30+
std::string getFormatString(const triton::Context& ctx, triton::uint64 addr) {
31+
std::string s = getMemoryString(ctx, addr);
32+
// Implement string replacements here if needed
33+
return s;
34+
}
35+
36+
triton::uint64 strlenHandler(triton::Context& ctx) {
37+
if constexpr (DEBUG) {
38+
std::cout << "[+] Strlen hooked" << std::endl;
39+
}
40+
auto arg1 = getMemoryString(ctx, static_cast<triton::uint64>(ctx.getConcreteRegisterValue(ctx.registers.x86_rdi)));
41+
return arg1.length();
42+
}
43+
44+
45+
46+
triton::uint64 printfHandler(triton::Context& ctx) {
47+
if constexpr (DEBUG) {
48+
std::cout << "[+] printf hooked" << std::endl;
49+
}
50+
auto format_str = getFormatString(ctx, static_cast<triton::uint64>(ctx.getConcreteRegisterValue(ctx.registers.x86_rdi)));
51+
auto arg1 = ctx.getConcreteRegisterValue(ctx.registers.x86_rsi);
52+
53+
std::stringstream ss;
54+
size_t pos = format_str.find("%ld");
55+
if (pos != std::string::npos) {
56+
ss << format_str.substr(0, pos) << arg1 << format_str.substr(pos + 3);
57+
} else {
58+
ss << format_str;
59+
}
60+
61+
std::string formatted_str = ss.str();
62+
std::cout << formatted_str << std::endl;
63+
return formatted_str.length();
64+
}
65+
66+
triton::uint64 libcMainHandler(triton::Context& ctx) {
67+
if constexpr (DEBUG) {
68+
std::cout << "[+] __libc_start_main hooked" << std::endl;
69+
}
70+
71+
auto main = ctx.getConcreteRegisterValue(ctx.registers.x86_rdi);
72+
73+
ctx.setConcreteRegisterValue(ctx.registers.x86_rsp,
74+
ctx.getConcreteRegisterValue(ctx.registers.x86_rsp) - 8);
75+
76+
auto ret2main = triton::arch::MemoryAccess(static_cast<triton::uint64>(ctx.getConcreteRegisterValue(ctx.registers.x86_rsp)), 8);
77+
ctx.setConcreteMemoryValue(ret2main, main);
78+
79+
ctx.concretizeRegister(ctx.registers.x86_rdi);
80+
ctx.concretizeRegister(ctx.registers.x86_rsi);
81+
82+
std::vector<std::string> argvs = {"sample_1", "my_first_arg"};
83+
84+
triton::uint64 base = 0x20000000;
85+
std::vector<triton::uint64> addrs;
86+
87+
for (const auto& argv : argvs) {
88+
addrs.push_back(base);
89+
ctx.setConcreteMemoryAreaValue(base, reinterpret_cast<const triton::uint8*>(argv.c_str()), argv.length() + 1);
90+
base += argv.length() + 1;
91+
}
92+
93+
triton::uint64 argc = argvs.size();
94+
triton::uint64 argv = base;
95+
for (const auto& addr : addrs) {
96+
ctx.setConcreteMemoryValue(triton::arch::MemoryAccess(base, 8), addr);
97+
base += 8;
98+
}
99+
100+
ctx.setConcreteRegisterValue(ctx.registers.x86_rdi, argc);
101+
ctx.setConcreteRegisterValue(ctx.registers.x86_rsi, argv);
102+
103+
return 0;
104+
}
105+
106+
struct CustomRelocation {
107+
std::string name;
108+
std::function<triton::uint64(triton::Context&)> handler;
109+
triton::uint64 address;
110+
};
111+
112+
std::vector<CustomRelocation> customRelocation = {
113+
{"strlen", strlenHandler, 0x10000000},
114+
{"printf", printfHandler, 0x10000001},
115+
{"__libc_start_main", libcMainHandler, 0x10000002},
116+
};
117+
118+
void hookingHandler(triton::Context& ctx) {
119+
auto pc = ctx.getConcreteRegisterValue(ctx.registers.x86_rip);
120+
for (const auto& rel : customRelocation) {
121+
if (rel.address == pc) {
122+
auto ret_value = rel.handler(ctx);
123+
ctx.setConcreteRegisterValue(ctx.registers.x86_rax, ret_value);
124+
125+
auto ret_addr = ctx.getConcreteMemoryValue(triton::arch::MemoryAccess(
126+
static_cast<triton::uint64>(ctx.getConcreteRegisterValue(ctx.registers.x86_rsp)), 8));
127+
128+
ctx.setConcreteRegisterValue(ctx.registers.x86_rip, ret_addr);
129+
ctx.setConcreteRegisterValue(ctx.registers.x86_rsp,
130+
ctx.getConcreteRegisterValue(ctx.registers.x86_rsp) + 8);
131+
}
132+
}
133+
}
134+
135+
void emulate(triton::Context& ctx, triton::uint64 pc) {
136+
if constexpr (DEBUG) {
137+
std::cout << "[+] Starting emulation." << std::endl;
138+
}
139+
140+
while (pc) {
141+
auto opcode = ctx.getConcreteMemoryAreaValue(pc, 16);
142+
143+
triton::arch::Instruction instruction;
144+
instruction.setOpcode(opcode.data(), opcode.size());
145+
instruction.setAddress(pc);
146+
147+
ctx.processing(instruction);
148+
if constexpr (DEBUG) {
149+
std::cout << instruction << std::endl;
150+
}
151+
152+
if (instruction.getType() == triton::arch::x86::ID_INS_HLT || instruction.getType() == triton::arch::x86::ID_INS_RET) { // add ID_INS_RET too maybe? see issue https://github.com/JonathanSalwan/Triton/issues/912
153+
break;
154+
}
155+
156+
hookingHandler(ctx);
157+
158+
pc = static_cast<triton::uint64>(ctx.getConcreteRegisterValue(ctx.registers.x86_rip));
159+
}
160+
if constexpr (DEBUG) {
161+
std::cout << "[+] Emulation done." << std::endl;
162+
}
163+
}
164+
165+
std::unique_ptr<LIEF::ELF::Binary> loadBinary(triton::Context& ctx, const std::string& path) {
166+
std::unique_ptr<LIEF::ELF::Binary> binary = LIEF::ELF::Parser::parse(path);
167+
if (!binary) {
168+
throw std::runtime_error("Failed to parse ELF binary");
169+
}
170+
171+
for (const auto& segment : binary->segments()) {
172+
if (segment.type() != LIEF::ELF::Segment::TYPE::LOAD) {
173+
continue;
174+
}
175+
triton::uint64 vaddr = segment.virtual_address();
176+
const auto& content = segment.content(); // This is now a span<const uint8_t>
177+
if constexpr (DEBUG) {
178+
std::cout << "[+] Loading 0x" << std::hex << vaddr << " - 0x" << (vaddr + content.size()) << std::endl;
179+
}
180+
181+
// Use data() and size() methods of span
182+
ctx.setConcreteMemoryAreaValue(vaddr, content.data(), content.size());
183+
}
184+
185+
return binary;
186+
}
187+
188+
void makeRelocation(triton::Context& ctx, const LIEF::ELF::Binary& binary) {
189+
for (const auto& pltgot_entry : binary.pltgot_relocations()) {
190+
const std::string& symbolName = pltgot_entry.symbol()->name();
191+
triton::uint64 symbolRelo = pltgot_entry.address();
192+
for (const auto& crel : customRelocation) {
193+
if (symbolName == crel.name) {
194+
if constexpr (DEBUG) {
195+
std::cout << "[+] Hooking " << symbolName << std::endl;
196+
}
197+
ctx.setConcreteMemoryValue(triton::arch::MemoryAccess(symbolRelo, 8), crel.address);
198+
}
199+
}
200+
}
201+
}
202+
203+
int main(int argc, char* argv[]) {
204+
if (argc != 2) {
205+
std::cerr << "Usage: " << argv[0] << " <path_to_binary>" << std::endl;
206+
return 1;
207+
}
208+
209+
triton::Context ctx;
210+
ctx.setArchitecture(triton::arch::ARCH_X86_64);
211+
212+
std::unique_ptr<LIEF::ELF::Binary> binary;
213+
try {
214+
binary = loadBinary(ctx, argv[1]);
215+
} catch (const std::exception& e) {
216+
std::cerr << "Error loading binary: " << e.what() << std::endl;
217+
return 1;
218+
}
219+
220+
makeRelocation(ctx, *binary);
221+
222+
ctx.setConcreteRegisterValue(ctx.registers.x86_rbp, 0x7fffffff);
223+
ctx.setConcreteRegisterValue(ctx.registers.x86_rsp, 0x6fffffff);
224+
225+
triton::uint64 entrypoint = binary->entrypoint();
226+
emulate(ctx, entrypoint);
227+
228+
return 0;
229+
}

src/libtriton/arch/arm/aarch64/aarch64Semantics.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,10 @@ namespace triton {
256256
case ID_INS_CNEG: this->cneg_s(inst); break;
257257
case ID_INS_CSEL: this->csel_s(inst); break;
258258
case ID_INS_CSET: this->cset_s(inst); break;
259+
case ID_INS_CSETM: this->csetm_s(inst); break;
259260
case ID_INS_CSINC: this->csinc_s(inst); break;
260-
case ID_INS_CSNEG: this->csneg_s(inst); break;
261261
case ID_INS_CSINV: this->csinv_s(inst); break;
262+
case ID_INS_CSNEG: this->csneg_s(inst); break;
262263
case ID_INS_EON: this->eon_s(inst); break;
263264
case ID_INS_EOR: this->eor_s(inst); break;
264265
case ID_INS_EXTR: this->extr_s(inst); break;
@@ -1734,6 +1735,28 @@ namespace triton {
17341735
}
17351736

17361737

1738+
void AArch64Semantics::csetm_s(triton::arch::Instruction& inst) {
1739+
auto& dst = inst.operands[0];
1740+
1741+
/* Create symbolic operands */
1742+
triton::uint512 temp = 1;
1743+
auto op1 = this->astCtxt->bv((temp << dst.getBitSize()) - 1, dst.getBitSize());
1744+
auto op2 = this->astCtxt->bv(0, dst.getBitSize());
1745+
1746+
/* Create the semantics */
1747+
auto node = this->getCodeConditionAst(inst, op1, op2);
1748+
1749+
/* Create symbolic expression */
1750+
auto expr = this->symbolicEngine->createSymbolicExpression(inst, node, dst, "CSETM operation");
1751+
1752+
/* Spread taint */
1753+
expr->isTainted = this->taintEngine->setTaint(dst, this->getCodeConditionTainteSate(inst));
1754+
1755+
/* Update the symbolic control flow */
1756+
this->controlFlow_s(inst);
1757+
}
1758+
1759+
17371760
void AArch64Semantics::csinc_s(triton::arch::Instruction& inst) {
17381761
auto& dst = inst.operands[0];
17391762
auto& src1 = inst.operands[1];

src/libtriton/ast/llvm/llvmToTriton.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,19 @@ namespace triton {
4444
}
4545
return node;
4646
}
47+
else if (call->getCalledFunction()->getName().find("llvm.fshl.i") != std::string::npos) {
48+
// (X << (Z % BW)) | (Y >> (BW - (Z % BW)))
49+
// https://llvm.org/docs/LangRef.html#llvm-fshl-intrinsic
50+
auto x = this->do_convert(call->getArgOperand(0));
51+
auto y = this->do_convert(call->getArgOperand(1));
52+
auto z = this->do_convert(call->getArgOperand(2));
53+
auto bw = this->actx->bv(x->getBitvectorSize(), x->getBitvectorSize());
54+
55+
auto LHS = this->actx->bvshl(x, z);
56+
auto RHS = this->actx->bvlshr(y, this->actx->bvsub(bw, z));
57+
58+
return this->actx->bvor(LHS, RHS);
59+
}
4760
/* We symbolize the return of call */
4861
return this->var(instruction->getName().str(), instruction->getType()->getScalarSizeInBits());
4962
}

0 commit comments

Comments
 (0)