Markopy
Utilizing Markov Models for brute forcing attacks
node.h
Go to the documentation of this file.
1 /** @file node.h
2  * @brief Node class template
3  * @authors Ata Hakçıl, Osman Ömer Yıldıztugay
4  *
5  * @copydoc Markov::Node
6  */
7 
8 
9 #pragma once
10 #include <vector>
11 #include <map>
12 #include <assert.h>
13 #include <iostream>
14 #include <stdexcept> // To use runtime_error
15 #include "edge.h"
16 #include "random.h"
17 namespace Markov {
18 
19  /** @brief A node class that for the vertices of model. Connected with eachother using Edge
20  *
21  * This class will later be templated to accept other data types than char*.
22  */
23  template <typename storageType>
24  class Node {
25  public:
26 
27  /** @brief Default constructor. Creates an empty Node.
28  */
29  Node<storageType>();
30 
31  /** @brief Constructor. Creates a Node with no edges and with given NodeValue.
32  * @param _value - Nodes character representation.
33  *
34  * @b Example @b Use: Construct nodes
35  * @code{.cpp}
36  * Markov::Node<unsigned char>* LeftNode = new Markov::Node<unsigned char>('l');
37  * Markov::Node<unsigned char>* RightNode = new Markov::Node<unsigned char>('r');
38  * @endcode
39  */
40  Node<storageType>(storageType _value);
41 
42  /** @brief Link this node with another, with this node as its source.
43  *
44  * Creates a new Edge.
45  * @param target - Target node which will be the RightNode() of new edge.
46  * @return A new node with LeftNode as this, and RightNode as parameter target.
47  *
48  * @b Example @b Use: Construct nodes
49  * @code{.cpp}
50  * Markov::Node<unsigned char>* LeftNode = new Markov::Node<unsigned char>('l');
51  * Markov::Node<unsigned char>* RightNode = new Markov::Node<unsigned char>('r');
52  * Markov::Edge<unsigned char>* e = LeftNode->Link(RightNode);
53  * @endcode
54  */
55  Edge<storageType>* Link(Node<storageType>*);
56 
57  /** @brief Link this node with another, with this node as its source.
58  *
59  * *DOES NOT* create a new Edge.
60  * @param Edge - Edge that will accept this node as its LeftNode.
61  * @return the same edge as parameter target.
62  *
63  * @b Example @b Use: Construct and link nodes
64  * @code{.cpp}
65  * Markov::Node<unsigned char>* LeftNode = new Markov::Node<unsigned char>('l');
66  * Markov::Node<unsigned char>* RightNode = new Markov::Node<unsigned char>('r');
67  * Markov::Edge<unsigned char>* e = LeftNode->Link(RightNode);
68  * LeftNode->Link(e);
69  * @endcode
70  */
71  Edge<storageType>* Link(Edge<storageType>*);
72 
73  /** @brief Chose a random node from the list of edges, with regards to its EdgeWeight, and TraverseNode to that.
74  *
75  * This operation is done by generating a random number in range of 0-this.total_edge_weights, and then iterating over the list of edges.
76  * At each step, EdgeWeight of the edge is subtracted from the random number, and once it is 0, next node is selected.
77  * @return Node that was chosen at EdgeWeight biased random.
78  *
79  * @b Example @b Use: Use randomNext to do a random walk on the model
80  * @code{.cpp}
81  * char* buffer[64];
82  * Markov::Model<char> model;
83  * model.Import("model.mdl");
84  * Markov::Node<char>* n = model.starterNode;
85  * int len = 0;
86  * Markov::Node<char>* temp_node;
87  * while (true) {
88  * temp_node = n->RandomNext(randomEngine);
89  * if (len >= maxSetting) {
90  * break;
91  * }
92  * else if ((temp_node == NULL) && (len < minSetting)) {
93  * continue;
94  * }
95  *
96  * else if (temp_node == NULL){
97  * break;
98  * }
99  *
100  * n = temp_node;
101  *
102  * buffer[len++] = n->NodeValue();
103  * }
104  * @endcode
105  */
106  Node<storageType>* RandomNext(Markov::Random::RandomEngine* randomEngine);
107 
108  /** @brief Insert a new edge to the this.edges.
109  * @param edge - New edge that will be inserted.
110  * @return true if insertion was successful, false if it fails.
111  *
112  * @b Example @b Use: Construct and update edges
113  *
114  * @code{.cpp}
115  * Markov::Node<unsigned char>* src = new Markov::Node<unsigned char>('a');
116  * Markov::Node<unsigned char>* target1 = new Markov::Node<unsigned char>('b');
117  * Markov::Node<unsigned char>* target2 = new Markov::Node<unsigned char>('c');
118  * Markov::Edge<unsigned char>* e1 = new Markov::Edge<unsigned char>(src, target1);
119  * Markov::Edge<unsigned char>* e2 = new Markov::Edge<unsigned char>(src, target2);
120  * e1->AdjustEdge(25);
121  * src->UpdateEdges(e1);
122  * e2->AdjustEdge(30);
123  * src->UpdateEdges(e2);
124  * @endcode
125  */
126  bool UpdateEdges(Edge<storageType>*);
127 
128  /** @brief Find an edge with its character representation.
129  * @param repr - character NodeValue of the target node.
130  * @return Edge that is connected between this node, and the target node.
131  *
132  * @b Example @b Use: Construct and update edges
133  *
134  * @code{.cpp}
135  * Markov::Node<unsigned char>* src = new Markov::Node<unsigned char>('a');
136  * Markov::Node<unsigned char>* target1 = new Markov::Node<unsigned char>('b');
137  * Markov::Node<unsigned char>* target2 = new Markov::Node<unsigned char>('c');
138  * Markov::Edge<unsigned char>* res = NULL;
139  * src->Link(target1);
140  * src->Link(target2);
141  * res = src->FindEdge('b');
142  *
143  * @endcode
144  *
145  */
146  Edge<storageType>* FindEdge(storageType repr);
147 
148  /** @brief Find an edge with its pointer. Avoid unless neccessary because comptutational cost of find by character is cheaper (because of std::map)
149  * @param target - target node.
150  * @return Edge that is connected between this node, and the target node.
151  */
152  Edge<storageType>* FindEdge(Node<storageType>* target);
153 
154  /** @brief Return character representation of this node.
155  * @return character representation at _value.
156  */
157  inline unsigned char NodeValue();
158 
159  /** @brief Change total weights with offset
160  * @param offset to adjust the vertice weight with
161  */
162  void UpdateTotalVerticeWeight(long int offset);
163 
164  /** @brief return edges
165  */
166  inline std::map<storageType, Edge<storageType>*>* Edges();
167 
168  /** @brief return total edge weights
169  */
170  inline long int TotalEdgeWeights();
171 
172 
173  std::vector<Edge<storageType>*> edgesV;
174  private:
175 
176  /**
177  @brief Character representation of this node. 0 for starter, 0xff for terminator.
178  */
179  storageType _value;
180 
181  /**
182  @brief Total weights of the vertices, required by RandomNext
183  */
185 
186  /**
187  @brief A map of all edges connected to this node, where this node is at the LeftNode.
188  * Map is indexed by unsigned char, which is the character representation of the node.
189  */
190  std::map<storageType, Edge<storageType>*> edges;
191  };
192 };
193 
194 
195 
196 
197 
198 
199 
200 
201 
202 template <typename storageType>
203 Markov::Node<storageType>::Node(storageType _value) {
204  this->_value = _value;
205  this->total_edge_weights = 0L;
206 };
207 
208 template <typename storageType>
209 Markov::Node<storageType>::Node() {
210  this->_value = 0;
211  this->total_edge_weights = 0L;
212 };
213 
214 template <typename storageType>
215 inline unsigned char Markov::Node<storageType>::NodeValue() {
216  return _value;
217 }
218 
219 template <typename storageType>
220 Markov::Edge<storageType>* Markov::Node<storageType>::Link(Markov::Node<storageType>* n) {
221  Markov::Edge<storageType>* v = new Markov::Edge<storageType>(this, n);
222  this->UpdateEdges(v);
223  return v;
224 }
225 
226 template <typename storageType>
227 Markov::Edge<storageType>* Markov::Node<storageType>::Link(Markov::Edge<storageType>* v) {
228  v->SetLeftEdge(this);
229  this->UpdateEdges(v);
230  return v;
231 }
232 
233 template <typename storageType>
234 Markov::Node<storageType>* Markov::Node<storageType>::RandomNext(Markov::Random::RandomEngine* randomEngine) {
235 
236  //get a random NodeValue in range of total_vertice_weight
237  long int selection = randomEngine->random() % this->total_edge_weights;//distribution()(generator());// distribution(generator);
238  //make absolute, no negative modulus values wanted
239  //selection = (selection >= 0) ? selection : (selection + this->total_edge_weights);
240  for(int i=0;i<this->edgesV.size();i++){
241  selection -= this->edgesV[i]->EdgeWeight();
242  if (selection < 0) return this->edgesV[i]->TraverseNode();
243  }
244 
245  //if this assertion is reached, it means there is an implementation error above
246  std::cout << "This should never be reached (node failed to walk to next)\n"; //cant assert from child thread
247  assert(true && "This should never be reached (node failed to walk to next)");
248  return NULL;
249 }
250 
251 template <typename storageType>
252 bool Markov::Node<storageType>::UpdateEdges(Markov::Edge<storageType>* v) {
253  this->edges.insert({ v->RightNode()->NodeValue(), v });
254  this->edgesV.push_back(v);
255  //this->total_edge_weights += v->EdgeWeight();
256  return v->TraverseNode();
257 }
258 
259 template <typename storageType>
260 Markov::Edge<storageType>* Markov::Node<storageType>::FindEdge(storageType repr) {
261  auto e = this->edges.find(repr);
262  if (e == this->edges.end()) return NULL;
263  return e->second;
264 };
265 
266 template <typename storageType>
267 void Markov::Node<storageType>::UpdateTotalVerticeWeight(long int offset) {
268  this->total_edge_weights += offset;
269 }
270 
271 template <typename storageType>
272 inline std::map<storageType, Markov::Edge<storageType>*>* Markov::Node<storageType>::Edges() {
273  return &(this->edges);
274 }
275 
276 template <typename storageType>
277 inline long int Markov::Node<storageType>::TotalEdgeWeights() {
278  return this->total_edge_weights;
279 }