libTriton  version 1.0 build 1549
taintEngine.cpp
Go to the documentation of this file.
1
2/*
3** Copyright (C) - Triton
4**
5** This program is under the terms of the Apache License 2.0.
6*/
7
10
11
12
13namespace triton {
14 namespace engines {
15 namespace taint {
16
18 : modes(modes),
19 symbolicEngine(symbolicEngine),
20 cpu(cpu) {
21 if (this->symbolicEngine == nullptr)
22 throw triton::exceptions::TaintEngine("TaintEngine::TaintEngine(): The symbolicEngine cannot be null.");
23 }
24
25
27 : modes(other.modes),
28 cpu(other.cpu) {
29 this->symbolicEngine = other.symbolicEngine;
30 this->taintedMemory = other.taintedMemory;
32 }
33
34
36 this->cpu = other.cpu;
37 this->modes = other.modes;
38 this->symbolicEngine = other.symbolicEngine;
39 this->taintedMemory = other.taintedMemory;
41 return *this;
42 }
43
44
45 /* Returns the tainted addresses */
46 const std::unordered_set<triton::uint64>& TaintEngine::getTaintedMemory(void) const {
47 return this->taintedMemory;
48 }
49
50
51 /* Returns the tainted registers */
52 std::unordered_set<const triton::arch::Register*> TaintEngine::getTaintedRegisters(void) const {
53 std::unordered_set<const triton::arch::Register*> res;
54
55 for (auto id : this->taintedRegisters)
56 res.insert(&this->cpu.getRegister(id));
57
58 return res;
59 }
60
61
62 /* Returns true of false if the memory address is currently tainted */
63 bool TaintEngine::isMemoryTainted(const triton::arch::MemoryAccess& mem, bool mode) const {
64 triton::uint64 addr = mem.getAddress();
65 triton::uint32 size = mem.getSize();
66
67 for (triton::uint32 index = 0; index < size; index++) {
68 if (this->taintedMemory.find(addr+index) != this->taintedMemory.end())
69 return TAINTED;
70 }
71
72 /* Spread the taint through pointers if the mode is enabled */
73 if (mode && this->modes->isModeEnabled(triton::modes::TAINT_THROUGH_POINTERS)) {
75 return TAINTED;
77 return TAINTED;
79 return TAINTED;
80 }
81
82 return !TAINTED;
83 }
84
85
86 /* Returns true of false if the address is currently tainted */
88 for (triton::uint32 index = 0; index < size; index++) {
89 if (this->taintedMemory.find(addr+index) != this->taintedMemory.end())
90 return TAINTED;
91 }
92
93 return !TAINTED;
94 }
95
96
97 /* Returns true of false if the register is currently tainted */
99 if (this->taintedRegisters.find(reg.getParent()) != this->taintedRegisters.end())
100 return TAINTED;
101
102 return !TAINTED;
103 }
104
105
106 /* Abstract taint verification. */
108 switch (op.getType()) {
110 case triton::arch::OP_MEM: return this->isMemoryTainted(op.getConstMemory());
112 default:
113 throw triton::exceptions::TaintEngine("TaintEngine::isTainted(): Invalid operand.");
114 }
115 }
116
117
118 /* Taint the register */
120 this->taintedRegisters.insert(reg.getParent());
121 return TAINTED;
122 }
123
124
125 /* Untaint the register */
127 this->taintedRegisters.erase(reg.getParent());
128 return !TAINTED;
129 }
130
131
132 /* Sets the flag (taint or untaint) to an abstract operand (Register or Memory). */
134 switch (op.getType()) {
136 case triton::arch::OP_MEM: return this->setTaintMemory(op.getConstMemory(), flag);
138 default:
139 throw triton::exceptions::TaintEngine("TaintEngine::setTaint(): Invalid operand.");
140 }
141 }
142
143
144 /* Sets the flag (taint or untaint) to a memory. */
146 if (flag == TAINTED)
147 this->taintMemory(mem);
148
149 else if (flag == !TAINTED)
150 this->untaintMemory(mem);
151
152 return flag;
153 }
154
155
156 /* Sets the flag (taint or untaint) to a register. */
158 if (flag == TAINTED)
159 this->taintRegister(reg);
160
161 else if (flag == !TAINTED)
162 this->untaintRegister(reg);
163
164 return flag;
165 }
166
167
168 /* Taint the memory */
170 triton::uint64 addr = mem.getAddress();
171 triton::uint32 size = mem.getSize();
172
173 for (triton::uint32 index = 0; index < size; index++)
174 this->taintedMemory.insert(addr+index);
175
176 return TAINTED;
177 }
178
179
180 /* Taint the address */
182 this->taintedMemory.insert(addr);
183 return TAINTED;
184 }
185
186
187 /* Untaint the memory */
189 triton::uint64 addr = mem.getAddress();
190 triton::uint32 size = mem.getSize();
191
192 for (triton::uint32 index = 0; index < size; index++)
193 this->taintedMemory.erase(addr+index);
194
195 return !TAINTED;
196 }
197
198
199 /* Untaint the address */
201 this->taintedMemory.erase(addr);
202 return !TAINTED;
203 }
204
205
206 /* Abstract union tainting */
208 triton::uint32 t1 = op1.getType();
209 triton::uint32 t2 = op2.getType();
210
212 return this->taintUnion(op1.getConstMemory(), op2.getConstImmediate());
213
215 return this->taintUnion(op1.getConstMemory(), op2.getConstMemory());
216
218 return this->taintUnion(op1.getConstMemory(), op2.getConstRegister());
219
221 return this->taintUnion(op1.getConstRegister(), op2.getConstImmediate());
222
224 return this->taintUnion(op1.getConstRegister(), op2.getConstMemory());
225
227 return this->taintUnion(op1.getConstRegister(), op2.getConstRegister());
228
229 throw triton::exceptions::TaintEngine("TaintEngine::taintUnion(): Invalid operands.");
230 }
231
232
233 /* Abstract assignment tainting */
235 triton::uint32 t1 = op1.getType();
236 triton::uint32 t2 = op2.getType();
237
239 return this->taintAssignment(op1.getConstMemory(), op2.getConstImmediate());
240
242 return this->taintAssignment(op1.getConstMemory(), op2.getConstMemory());
243
245 return this->taintAssignment(op1.getConstMemory(), op2.getConstRegister());
246
248 return this->taintAssignment(op1.getConstRegister(), op2.getConstImmediate());
249
251 return this->taintAssignment(op1.getConstRegister(), op2.getConstMemory());
252
254 return this->taintAssignment(op1.getConstRegister(), op2.getConstRegister());
255
256 throw triton::exceptions::TaintEngine("TaintEngine::taintAssignment(): Invalid operands.");
257 }
258
259
262 triton::uint64 memAddrDst = memDst.getAddress();
263 triton::uint32 writeSize = memDst.getSize();
264
265 flag = this->unionMemoryImmediate(memDst);
266
267 /* Taint each byte of reference expression */
268 for (triton::uint32 i = 0; i != writeSize; i++) {
269 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
270 if (byte == nullptr)
271 continue;
272 byte->isTainted = flag;
273 }
274
275 return flag;
276 }
277
278
281 triton::uint64 memAddrDst = memDst.getAddress();
282 triton::uint64 memAddrSrc = memSrc.getAddress();
283 triton::uint32 writeSize = memDst.getSize();
284
285 flag = this->unionMemoryMemory(memDst, memSrc);
286
287 /* Taint each byte of reference expression */
288 for (triton::uint32 i = 0; i != writeSize; i++) {
289 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
290 if (byte == nullptr)
291 continue;
292 byte->isTainted = this->isMemoryTainted(memAddrDst + i) | this->isMemoryTainted(memAddrSrc + i);
293 }
294
295 return flag;
296 }
297
298
301 triton::uint64 memAddrDst = memDst.getAddress();
302 triton::uint32 writeSize = memDst.getSize();
303
304 flag = this->unionMemoryRegister(memDst, regSrc);
305
306 /* Taint each byte of reference expression */
307 for (triton::uint32 i = 0; i != writeSize; i++) {
308 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
309 if (byte == nullptr)
310 continue;
311 byte->isTainted = flag;
312 }
313
314 return flag;
315 }
316
317
319 return this->unionRegisterImmediate(regDst);
320 }
321
322
324 return this->unionRegisterMemory(regDst, memSrc);
325 }
326
327
329 return this->unionRegisterRegister(regDst, regSrc);
330 }
331
332
335 triton::uint64 memAddrDst = memDst.getAddress();
336 triton::uint32 writeSize = memDst.getSize();
337
338 flag = this->assignmentMemoryImmediate(memDst);
339
340 /* Taint each byte of reference expression */
341 for (triton::uint32 i = 0; i != writeSize; i++) {
342 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
343 if (byte == nullptr)
344 continue;
345 byte->isTainted = flag;
346 }
347
348 return flag;
349 }
350
351
354 triton::uint64 memAddrDst = memDst.getAddress();
355 triton::uint64 memAddrSrc = memSrc.getAddress();
356 triton::uint32 writeSize = memDst.getSize();
357
358 flag = this->assignmentMemoryMemory(memDst, memSrc);
359
360 /* Taint each byte of reference expression */
361 for (triton::uint32 i = 0; i != writeSize; i++) {
362 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
363 if (byte == nullptr)
364 continue;
365 byte->isTainted = this->isMemoryTainted(memAddrSrc + i);
366 }
367
368 return flag;
369 }
370
371
374 triton::uint64 memAddrDst = memDst.getAddress();
375 triton::uint32 writeSize = memDst.getSize();
376
377 flag = this->assignmentMemoryRegister(memDst, regSrc);
378
379 /* Taint each byte of reference expression */
380 for (triton::uint32 i = 0; i != writeSize; i++) {
381 const triton::engines::symbolic::SharedSymbolicExpression& byte = this->symbolicEngine->getSymbolicMemory(memAddrDst + i);
382 if (byte == nullptr)
383 continue;
384 byte->isTainted = flag;
385 }
386
387 return flag;
388 }
389
390
392 return this->assignmentRegisterImmediate(regDst);
393 }
394
395
397 return this->assignmentRegisterMemory(regDst, memSrc);
398 }
399
400
402 return this->assignmentRegisterRegister(regDst, regSrc);
403 }
404
405
406 /* reg <- reg */
407 bool TaintEngine::assignmentRegisterRegister(const triton::arch::Register& regDst, const triton::arch::Register& regSrc) {
408 if (this->isRegisterTainted(regSrc)) {
409 this->taintRegister(regDst);
410 return TAINTED;
411 }
412
413 this->untaintRegister(regDst);
414 return !TAINTED;
415 }
416
417
418 /* reg <- imm */
419 bool TaintEngine::assignmentRegisterImmediate(const triton::arch::Register& regDst) {
420 this->untaintRegister(regDst);
421 return !TAINTED;
422 }
423
424
425 /* reg <- mem */
426 bool TaintEngine::assignmentRegisterMemory(const triton::arch::Register& regDst, const triton::arch::MemoryAccess& memSrc) {
427 if (this->isMemoryTainted(memSrc)) {
428 this->taintRegister(regDst);
429 return TAINTED;
430 }
431
432 this->untaintRegister(regDst);
433 return !TAINTED;
434 }
435
436
437 /* mem <- mem */
438 bool TaintEngine::assignmentMemoryMemory(const triton::arch::MemoryAccess& memDst, const triton::arch::MemoryAccess& memSrc) {
439 bool isTainted = !TAINTED;
440 triton::uint32 readSize = memSrc.getSize();
441 triton::uint64 addrSrc = memSrc.getAddress();
442 triton::uint64 addrDst = memDst.getAddress();
443
444 for (triton::uint32 offset = 0; offset < readSize; offset++) {
445 if (this->isMemoryTainted(addrSrc+offset)) {
446 this->taintMemory(addrDst+offset);
448 }
449 else
450 this->untaintMemory(addrDst+offset);
451 }
452
453 /* Spread the taint through pointers if the mode is enabled */
454 if (this->modes->isModeEnabled(triton::modes::TAINT_THROUGH_POINTERS)) {
455 if (this->isMemoryTainted(memSrc)) {
456 this->taintMemory(memDst);
458 }
459 }
460
461 return isTainted;
462 }
463
464
465 /* mem <- imm */
466 bool TaintEngine::assignmentMemoryImmediate(const triton::arch::MemoryAccess& memDst) {
467 this->untaintMemory(memDst);
468 return !TAINTED;
469 }
470
471
472 /* mem <- reg */
473 bool TaintEngine::assignmentMemoryRegister(const triton::arch::MemoryAccess& memDst, const triton::arch::Register& regSrc) {
474 /* Check source */
475 if (this->isRegisterTainted(regSrc)) {
476 this->taintMemory(memDst);
477 return TAINTED;
478 }
479
480 /* Spread destination */
481 this->untaintMemory(memDst);
482 return !TAINTED;
483 }
484
485
486 /* reg U imm */
487 bool TaintEngine::unionRegisterImmediate(const triton::arch::Register& regDst) {
488 return this->isRegisterTainted(regDst);
489 }
490
491
492 /* reg U reg */
493 bool TaintEngine::unionRegisterRegister(const triton::arch::Register& regDst, const triton::arch::Register& regSrc) {
494 if (this->isRegisterTainted(regSrc)) {
495 this->taintRegister(regDst);
496 return TAINTED;
497 }
498 return this->isRegisterTainted(regDst);
499 }
500
501
502 /* mem U mem */
503 bool TaintEngine::unionMemoryMemory(const triton::arch::MemoryAccess& memDst, const triton::arch::MemoryAccess& memSrc) {
504 bool isTainted = !TAINTED;
505 triton::uint32 writeSize = memDst.getSize();
506 triton::uint64 addrDst = memDst.getAddress();
507 triton::uint64 addrSrc = memSrc.getAddress();
508
509 /* Check source */
510 for (triton::uint32 offset = 0; offset < writeSize; offset++) {
511 if (this->isMemoryTainted(addrSrc+offset)) {
512 this->taintMemory(addrDst+offset);
514 }
515 }
516
517 /* Spread the taint through pointers if the mode is enabled */
518 if (this->modes->isModeEnabled(triton::modes::TAINT_THROUGH_POINTERS)) {
519 if (this->isMemoryTainted(memSrc)) {
520 this->taintMemory(memDst);
522 }
523 }
524
525 /* Check destination */
526 if (this->isMemoryTainted(memDst, false)) {
527 return TAINTED;
528 }
529
530 return isTainted;
531 }
532
533
534 /* reg U mem */
535 bool TaintEngine::unionRegisterMemory(const triton::arch::Register& regDst, const triton::arch::MemoryAccess& memSrc) {
536 if (this->isMemoryTainted(memSrc)) {
537 this->taintRegister(regDst);
538 return TAINTED;
539 }
540 return this->isRegisterTainted(regDst);
541 }
542
543
544 /* mem U imm */
545 bool TaintEngine::unionMemoryImmediate(const triton::arch::MemoryAccess& memDst) {
546 if (this->isMemoryTainted(memDst), false) {
547 return TAINTED;
548 }
549 return !TAINTED;
550 }
551
552
553 /* mem U reg */
554 bool TaintEngine::unionMemoryRegister(const triton::arch::MemoryAccess& memDst, const triton::arch::Register& regSrc) {
555 if (this->isRegisterTainted(regSrc)) {
556 this->taintMemory(memDst);
557 return TAINTED;
558 }
559
560 if (this->isMemoryTainted(memDst), false) {
561 return TAINTED;
562 }
563
564 return !TAINTED;
565 }
566
567 }; /* taint namespace */
568 }; /* engines namespace */
569}; /* triton namespace */
This interface is used as abstract CPU interface. All CPU must use this interface.
virtual TRITON_EXPORT const triton::arch::Register & getRegister(triton::arch::register_e id) const =0
Returns register from id.
This class is used to represent an immediate.
Definition: immediate.hpp:37
This class is used to represent a memory access.
TRITON_EXPORT const triton::arch::Register & getConstBaseRegister(void) const
LEA - Returns the base register operand.
TRITON_EXPORT const triton::arch::Register & getConstSegmentRegister(void) const
LEA - Returns the segment register operand.
TRITON_EXPORT triton::uint64 getAddress(void) const
Returns the address of the memory.
TRITON_EXPORT triton::uint32 getSize(void) const
Returns the size (in bytes) of the memory vector.
TRITON_EXPORT const triton::arch::Register & getConstIndexRegister(void) const
LEA - Returns the index register operand.
This class is used as operand wrapper.
TRITON_EXPORT triton::arch::operand_e getType(void) const
Returns the abstract type of the operand.
TRITON_EXPORT const triton::arch::MemoryAccess & getConstMemory(void) const
Returns the memory operand as const.
TRITON_EXPORT const triton::arch::Register & getConstRegister(void) const
Returns the register operand.
TRITON_EXPORT const triton::arch::Immediate & getConstImmediate(void) const
Returns the immediate operand.
This class is used when an instruction has a register operand.
Definition: register.hpp:44
TRITON_EXPORT triton::arch::register_e getParent(void) const
Returns the parent id of the register.
Definition: register.cpp:58
TRITON_EXPORT SharedSymbolicExpression getSymbolicMemory(triton::uint64 addr) const
Returns the shared symbolic expression corresponding to the memory address.
std::unordered_set< triton::arch::register_e > taintedRegisters
The set of tainted registers. Currently it is an over approximation of the taint.
Definition: taintEngine.hpp:69
TRITON_EXPORT bool taintRegister(const triton::arch::Register &reg)
Taints a register. Returns TAINTED if the register has been tainted correctly. Otherwise it returns t...
TRITON_EXPORT bool setTaint(const triton::arch::OperandWrapper &op, bool flag)
Sets the flag (taint or untaint) to an abstract operand (Register or Memory).
TRITON_EXPORT bool setTaintMemory(const triton::arch::MemoryAccess &mem, bool flag)
Sets the flag (taint or untaint) to a memory.
TRITON_EXPORT bool untaintMemory(triton::uint64 addr)
Untaints an address. Returns !TAINTED if the address has been untainted correctly....
TRITON_EXPORT bool isTainted(const triton::arch::OperandWrapper &op) const
Abstract taint verification. Returns true if the operand is tainted.
TRITON_EXPORT std::unordered_set< const triton::arch::Register * > getTaintedRegisters(void) const
Returns the tainted registers.
Definition: taintEngine.cpp:52
TRITON_EXPORT bool isMemoryTainted(triton::uint64 addr, triton::uint32 size=1) const
Returns true if the addr is tainted.
Definition: taintEngine.cpp:87
std::unordered_set< triton::uint64 > taintedMemory
The set of tainted addresses.
Definition: taintEngine.hpp:66
TRITON_EXPORT bool taintUnion(const triton::arch::OperandWrapper &op1, const triton::arch::OperandWrapper &op2)
Abstract union tainting.
TRITON_EXPORT bool setTaintRegister(const triton::arch::Register &reg, bool flag)
Sets the flag (taint or untaint) to a register.
TRITON_EXPORT bool taintAssignment(const triton::arch::OperandWrapper &op1, const triton::arch::OperandWrapper &op2)
Abstract assignment tainting.
TRITON_EXPORT TaintEngine(const triton::modes::SharedModes &modes, triton::engines::symbolic::SymbolicEngine *symbolicEngine, triton::arch::CpuInterface &cpu)
Constructor.
Definition: taintEngine.cpp:17
TRITON_EXPORT bool untaintRegister(const triton::arch::Register &reg)
Untaints a register. Returns !TAINTED if the register has been untainted correctly....
TRITON_EXPORT bool taintMemory(triton::uint64 addr)
Taints an address. Returns TAINTED if the address has been tainted correctly. Otherwise it returns th...
TRITON_EXPORT bool isRegisterTainted(const triton::arch::Register &reg) const
Returns true if the register is tainted.
Definition: taintEngine.cpp:98
TRITON_EXPORT const std::unordered_set< triton::uint64 > & getTaintedMemory(void) const
Returns the tainted addresses.
Definition: taintEngine.cpp:46
TRITON_EXPORT TaintEngine & operator=(const TaintEngine &other)
Copies a TaintEngine.
Definition: taintEngine.cpp:35
The exception class used by the taint engine.
Definition: exceptions.hpp:149
constexpr triton::uint32 flag
flag size in bit
Definition: cpuSize.hpp:58
std::shared_ptr< triton::modes::Modes > SharedModes
Shared Modes.
Definition: modes.hpp:66
@ TAINT_THROUGH_POINTERS
[taint] Spread the taint if an index pointer is already tainted (see #725).
Definition: modesEnums.hpp:38
std::shared_ptr< triton::engines::symbolic::SymbolicExpression > SharedSymbolicExpression
Shared Symbolic Expression.
Definition: ast.hpp:40
const bool TAINTED
Defines a tainted item.
Definition: taintEngine.hpp:46
const bool UNTAINTED
Defines an untainted item.
Definition: taintEngine.hpp:49
std::uint64_t uint64
unisgned 64-bits
Definition: tritonTypes.hpp:42
std::uint32_t uint32
unisgned 32-bits
Definition: tritonTypes.hpp:39
The Triton namespace.