mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 01:17:36 +00:00
GitBook: [master] one page modified
This commit is contained in:
parent
68b07dcb54
commit
dee8f275eb
1 changed files with 77 additions and 0 deletions
|
@ -416,5 +416,82 @@ Note that the symbolic file could also contain constant data merged with symboli
|
||||||
```
|
```
|
||||||
{% endhint %}
|
{% endhint %}
|
||||||
|
|
||||||
|
### Applying Constrains
|
||||||
|
|
||||||
|
{% hint style="info" %}
|
||||||
|
Sometimes simple human operations like compare 2 words of length 16 **char by char** \(loop\), **cost** a lot to a **angr** because it needs to generate branches **exponentially** because it generates 1 branch per if: `2^16`
|
||||||
|
Therefore, it's easier to **ask angr get to a previous point** \(where the real difficult part was already done\) and **set those constrains manually**.
|
||||||
|
{% endhint %}
|
||||||
|
|
||||||
|
```python
|
||||||
|
# After perform some complex poperations to the input the program checks
|
||||||
|
# char by char the password against another password saved, like in the snippet:
|
||||||
|
#
|
||||||
|
# #define REFERENCE_PASSWORD = "AABBCCDDEEFFGGHH";
|
||||||
|
# int check_equals_AABBCCDDEEFFGGHH(char* to_check, size_t length) {
|
||||||
|
# uint32_t num_correct = 0;
|
||||||
|
# for (int i=0; i<length; ++i) {
|
||||||
|
# if (to_check[i] == REFERENCE_PASSWORD[i]) {
|
||||||
|
# num_correct += 1;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# return num_correct == length;
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# ...
|
||||||
|
#
|
||||||
|
# char* input = user_input();
|
||||||
|
# char* encrypted_input = complex_function(input);
|
||||||
|
# if (check_equals_AABBCCDDEEFFGGHH(encrypted_input, 16)) {
|
||||||
|
# puts("Good Job.");
|
||||||
|
# } else {
|
||||||
|
# puts("Try again.");
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# The function checks if *to_check == "AABBCCDDEEFFGGHH". This is very RAM consumming
|
||||||
|
# as the computer needs to branch every time the if statement in the loop was called (16
|
||||||
|
# times), resulting in 2^16 = 65,536 branches, which will take too long of a
|
||||||
|
# time to evaluate for our needs.
|
||||||
|
|
||||||
|
import angr
|
||||||
|
import claripy
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
path_to_binary = argv[1]
|
||||||
|
project = angr.Project(path_to_binary)
|
||||||
|
|
||||||
|
initial_state = project.factory.entry_state()
|
||||||
|
|
||||||
|
simulation = project.factory.simgr(initial_state)
|
||||||
|
|
||||||
|
# Get an address to check after the complex function and before the "easy compare" operation
|
||||||
|
address_to_check_constraint = 0x8048671
|
||||||
|
simulation.explore(find=address_to_check_constraint)
|
||||||
|
|
||||||
|
|
||||||
|
if simulation.found:
|
||||||
|
solution_state = simulation.found[0]
|
||||||
|
|
||||||
|
# Find were the input that is going to be compared is saved in memory
|
||||||
|
constrained_parameter_address = 0x804a050
|
||||||
|
constrained_parameter_size_bytes = 16
|
||||||
|
# Set the bitvector
|
||||||
|
constrained_parameter_bitvector = solution_state.memory.load(
|
||||||
|
constrained_parameter_address,
|
||||||
|
constrained_parameter_size_bytes
|
||||||
|
)
|
||||||
|
|
||||||
|
# Indicate angr that this BV at this point needs to be equal to the password
|
||||||
|
constrained_parameter_desired_value = 'BWYRUBQCMVSBRGFU'.encode()
|
||||||
|
solution_state.add_constraints(constrained_parameter_bitvector == constrained_parameter_desired_value)
|
||||||
|
|
||||||
|
print(solution_state.posix.dumps(sys.stdin.fileno()))
|
||||||
|
else:
|
||||||
|
raise Exception('Could not find the solution')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue