BearParser
Portable Executable parsing library (from PE-bear)
AbstractByteBuffer.cpp
Go to the documentation of this file.
1 #include "AbstractByteBuffer.h"
2 
4 {
5  if (unit == 0) {
6  printf("Invalid roundup unit!\n");
7  return 0;
8  }
9  bufsize_t unitsNum = size / unit;
10  bufsize_t roundDown = unitsNum * unit;
11  if (roundDown < size) unitsNum ++;
12  return unitsNum * unit;
13 }
14 
15 //--------------------------------------------------
17 {
18  if (buf == NULL) return false;
19  if (buf->getContent() == NULL || buf->getContentSize() == 0) {
20  return false;
21  }
22  return true;
23 }
24 //---
25 
26 BYTE AbstractByteBuffer::operator[](std::size_t idx)
27 {
28  bufsize_t offset = static_cast<bufsize_t>(idx);
29  if (offset >= getContentSize() ) {
30  throw BufferException("Too far offset requested!");
31  }
32  return this->getContent()[idx];
33 }
34 
35 offset_t AbstractByteBuffer::getOffset(void *ptr, bool allowExceptions)
36 {
37  if (ptr == NULL) return INVALID_ADDR;
38  BYTE* buf = this->getContent();
39  bufsize_t bufSize = this->getContentSize();
40 
41  if (buf == NULL || bufSize == 0) {
42  if (allowExceptions) throw BufferException("Buffer if empty!");
43  return INVALID_ADDR;
44  }
45  if (ptr < buf) {
46  if (allowExceptions) throw BufferException("Pointer before buffer begining!");
47  return INVALID_ADDR;
48  }
49  offset_t offset = static_cast<BYTE*>(ptr) - buf;
50  if (offset >= bufSize) {
51  if (allowExceptions) throw BufferException("Pointer does not belong to buffer!");
52  return INVALID_ADDR;
53  }
54  return offset;
55 }
56 
57 BYTE* AbstractByteBuffer::getContentAt(offset_t offset, bufsize_t size, bool allowExceptions)
58 {
59  if (offset == INVALID_ADDR) {
60  if (allowExceptions) throw BufferException("Invalid address requested!");
61  return NULL;
62  }
63  if (size == 0) {
64  if (allowExceptions) throw BufferException("Zero size requested!");
65  return NULL;
66  }
67 
68  bufsize_t fileSize = this->getContentSize();
69  BYTE* buf = this->getContent();
70  if (buf == NULL) return NULL;
71 
72  if (offset >= fileSize ) {
73  if (allowExceptions) throw BufferException("Too far offset requested!");
74  return NULL;
75  }
76 
77  if (offset + size > fileSize) {
78  if (allowExceptions) throw BufferException("Too big size requested!");
79  return NULL;
80  }
81  BYTE *cntnt = buf + offset;
82  return cntnt;
83 }
84 
86 {
87  if (startOffset == INVALID_ADDR) return 0;
88 
89  offset_t contentSize = getContentSize();
90  if (contentSize < startOffset) return 0;
91 
92  bufsize_t limit = static_cast<bufsize_t>(contentSize - startOffset);
93  return limit;
94 }
95 
96 
97 BYTE* AbstractByteBuffer::getContentAtPtr(BYTE *ptr, bufsize_t size, bool allowExceptions)
98 {
99  offset_t offset = getOffset(ptr, allowExceptions);
100  if (offset == INVALID_ADDR) return NULL;
101 
102  return getContentAt(offset, size, allowExceptions);
103 }
104 
105 bool AbstractByteBuffer::setBufferedValue(BYTE *dstPtr, BYTE *srcPtr, bufsize_t srcSize, bufsize_t paddingSize, bool allowExceptions)
106 {
107  if (dstPtr == srcPtr) return false;
108  if (dstPtr == NULL || srcPtr == NULL) return false;
109 
110  offset_t dstStart = getOffset(dstPtr);
111  if (dstStart == INVALID_ADDR) {
112  printf("Invalid copy destination!");
113  if (allowExceptions) throw BufferException("Invalid copy destination!");
114  return false;
115  }
116 
117  bufsize_t size = srcSize + paddingSize;
118  bufsize_t dstMaxSize = static_cast<bufsize_t>(getContentSize() - dstStart);
119  if (dstMaxSize < size) {
120  //throw BufferException("Cannot copy: too big content size!");
121  size = dstMaxSize;
122  }
123  if (memcmp(dstPtr, srcPtr, size) == 0) {
124  return false; //no changes required
125  }
126  if (paddingSize != 0) { //add padding
127  memset(dstPtr, 0, size);
128  }
129  memcpy(dstPtr, srcPtr, srcSize);
130  return true;
131 }
132 
133 bool AbstractByteBuffer::setStringValue(offset_t rawOffset, QString newText)
134 {
135  std::string newTextStr = newText.toStdString();
136  const bufsize_t newTextLen = static_cast<bufsize_t>(newTextStr.length());
137 
138  BYTE *dstPtr = this->getContentAt(rawOffset, newTextLen + 1); //with terminating '\0'
139  if (!dstPtr) {
140  // cannot get a suitable buffer for the string
141  return false;
142  }
143  const char* newTextC = newTextStr.c_str();
144  bool isOk = setBufferedValue(dstPtr, (BYTE*)newTextC, newTextLen, 1);
145  return isOk;
146 }
147 
149 {
150  if (size == BUFSIZE_MAX) {
151  size = this->getContentSize() - rawOffset;
152  }
153  char *ptr = (char*) getContentAt(rawOffset, size);
154  if (!ptr) return "";
155  size_t asciiLen = pe_util::getAsciiLen(ptr, size);
156 
157  return QString::fromUtf8(ptr, static_cast<int>(asciiLen));
158 }
159 
161 {
162  const bufsize_t unitSize = sizeof(WORD);
163  bufsize_t size = unitSize;
164  if (len != BUFSIZE_MAX) {
165  size = len * unitSize;
166  }
167  WORD* ptr = (WORD*) this->getContentAt(rawOffset, size);
168  if (ptr == NULL) return "";
169  return QString::fromUtf16(ptr, static_cast<int>(len));
170 }
171 
173 {
174  const bufsize_t unitSize = sizeof(WORD);
175  bufsize_t size = unitSize;
176  if (len != BUFSIZE_MAX && len != -1) {
177  size = len * unitSize;
178  }
179  WORD* ptr = (WORD*) getContentAt(rawOffset, size);
180  if (!ptr) return "";
181 
182  size_t asciiLen = pe_util::getAsciiLenW(ptr, len);
183  return QString::fromUtf16(ptr, static_cast<int>(asciiLen));
184 }
185 
187 {
188  BYTE* area = this->getContentAt(rawOffset, size);
189  if (area == NULL) return false;
190 
191  for (bufsize_t i = 0; i < size; i++) {
192  if (area[i] != 0) return false;
193  }
194  return true;
195 }
196 
198 {
199  bufsize_t bufSize = this->getContentSize();
200  BYTE* buf = this->getContent();
201 
202  if (buf == NULL) return false;
203 
204  memset(buf, filling, bufSize);
205  return true;
206 }
207 
208 bool AbstractByteBuffer::pasteBuffer(offset_t rawOffset, AbstractByteBuffer *buf, bool allowTrunc)
209 {
210  if (isValid(buf) == false || isValid(this) == false) return false;
211  if (buf == NULL || buf->getContent() == NULL) return false;
212  BYTE* source = buf->getContent();
213  bufsize_t sizeToFill = buf->getContentSize();
214 
215  bufsize_t mySize = this->getContentSize();
216  if (static_cast<offset_t>(mySize) <= rawOffset) {
218  "Too far offset requested: %llX while mySize: %lX",
219  static_cast<unsigned long long>(rawOffset),
220  static_cast<unsigned long>(mySize)
221  );
222  return false;
223  }
224  BYTE *target = this->getContentAt(rawOffset, sizeToFill);
225  if (target == NULL) {
226  if (allowTrunc == false) return false;
227  sizeToFill = mySize - rawOffset;
228  target = this->getContentAt(rawOffset, sizeToFill);
229  }
230  if (target == NULL) return false;
231  memcpy(target, source, sizeToFill);
232  return true;
233 }
234 
236 {
237  if (rawOffset == INVALID_ADDR || size == 0) return false;
238 
239  BYTE *ptr = (BYTE*) this->getContent();
240  if (ptr == NULL) return false;
241 
242  offset_t startOffset = this->getOffset(ptr);
243  if (startOffset == INVALID_ADDR) return false;
244 
245  offset_t endOffset = startOffset + this->getContentSize();
246 
247  offset_t srchdEnd = rawOffset + size;
248  if (rawOffset >= startOffset && srchdEnd <= endOffset) {
249  //printf("Fount in bounds: %x - %x block: %x-%x\n", startOffset, endOffset, rawOffset, srchdEnd);
250  return true;
251  }
252  return false;
253 }
254 
256 {
257  if (rawOffset == INVALID_ADDR || size == 0) return false;
258 
259  BYTE *ptr = (BYTE*) this->getContent();
260  if (ptr == NULL) return false;
261 
262  offset_t startOffset = this->getOffset(ptr);
263  if (startOffset == INVALID_ADDR) return false;
264 
265  offset_t endOffset = startOffset + this->getContentSize();
266 
267  offset_t srchdEnd = rawOffset + size;
268  if (rawOffset >= startOffset && rawOffset <= endOffset) {
270  "Found in bounds: %llX - %llX end: %llX",
271  static_cast<unsigned long long>(startOffset),
272  static_cast<unsigned long long>(endOffset),
273  static_cast<unsigned long long>(rawOffset)
274  );
275  return true;
276  }
277  if (srchdEnd >= startOffset && srchdEnd <= endOffset) {
279  "Found in bounds: %llX - %llX",
280  static_cast<unsigned long long>(startOffset),
281  static_cast<unsigned long long>(endOffset)
282  );
283  return true;
284  }
285  return false;
286 }
287 
288 uint64_t AbstractByteBuffer::getNumValue(offset_t offset, bufsize_t size, bool* isOk)
289 {
290  if (isOk) (*isOk) = false;
291  if (size == 0 || offset == INVALID_ADDR) return (-1);
292 
293  void* ptr = this->getContentAt(offset, size);
294  if (ptr == NULL) {
295  return (-1);
296  }
297  uint64_t val = (-1);
298 
299  if (size == sizeof(uint8_t)) val = *((uint8_t*) ptr);
300  else if (size == sizeof(uint16_t)) val = *((uint16_t*) ptr);
301  else if (size == sizeof(uint32_t)) val = *((uint32_t*) ptr);
302  else if (size == sizeof(uint64_t)) val = *((uint64_t*) ptr);
303  else {
304  return (-1);
305  }
306  if (isOk) (*isOk) = true;
307  return val;
308 }
309 
310 bool AbstractByteBuffer::setNumValue(offset_t offset, bufsize_t size, uint64_t newVal)
311 {
312  if (size == 0 || offset == INVALID_ADDR) return false;
313  void* ptr = this->getContentAt(offset, size);
314  if (ptr == NULL) {
316  "Cannot get Ptr at: %llX of size: %lX!",
317  static_cast<unsigned long long>(offset),
318  static_cast<unsigned long>(size)
319  );
320  return false;
321  }
322 
323  if (size == sizeof(uint8_t)) {
324  uint8_t nVal = newVal;
325  uint8_t* valPtr = (uint8_t*) ptr;
326  if ((*valPtr) == nVal) return false;
327  (*valPtr) = nVal;
328  }
329  else if (size == sizeof(uint16_t)) {
330  uint16_t nVal = newVal;
331  uint16_t* valPtr = (uint16_t*) ptr;
332  if ((*valPtr) == nVal) return false;
333  (*valPtr) = nVal;
334  }
335  else if (size == sizeof(uint32_t)) {
336  uint32_t nVal = newVal;
337  uint32_t* valPtr = (uint32_t*) ptr;
338  if ((*valPtr) == nVal) return false;
339  (*valPtr) = nVal;
340  }
341  else if (size == sizeof(uint64_t)) {
342  uint64_t nVal = newVal;
343  uint64_t* valPtr = (uint64_t*) ptr;
344  if ((*valPtr) == nVal) return false;
345  (*valPtr) = nVal;
346  } else {
347  Logger::append(Logger::D_ERROR, "Wrong size!");
348  return false;
349  }
350  return true;
351 }
352 
353 //--------------------------------------------
354 
356  : parent(v_parent), offset(v_offset), size(v_size)
357 {
358  if (v_parent == NULL) throw BufferException("Cannot make subBuffer for NULL buffer!");
359 }
360 
362 {
363  bufsize_t maxSize = this->parent->getContentSize();
364  if (offset > maxSize) {
365  return 0;
366  }
367  if (offset + size > maxSize) {
368  bufsize_t trimedSize = maxSize - offset;
369  return trimedSize;
370  }
371  return size;
372 }
373 
375 {
376  return this->parent->getContentAt(offset, getContentSize());
377 }
const bufsize_t BUFSIZE_MAX
uint32_t bufsize_t
const offset_t INVALID_ADDR
uint64_t offset_t
virtual bufsize_t getContentSize()=0
bufsize_t getMaxSizeFromOffset(offset_t startOffset)
bool intersectsBlock(offset_t rawOffset, bufsize_t size)
virtual BYTE * getContentAtPtr(BYTE *ptr, bufsize_t size, bool allowExceptions=false)
QString getStringValue(offset_t rawOffset, bufsize_t len=BUFSIZE_MAX)
bool setNumValue(offset_t offset, bufsize_t size, uint64_t newVal)
virtual bool setBufferedValue(BYTE *dstPtr, BYTE *srcPtr, bufsize_t srcSize, bufsize_t paddingSize, bool allowExceptions=false)
virtual BYTE * getContentAt(offset_t offset, bufsize_t size, bool allowExceptions=false)
bool pasteBuffer(offset_t rawOffset, AbstractByteBuffer *buf, bool allowTrunc)
virtual BYTE * getContent()=0
bool setStringValue(offset_t rawOffset, QString newText)
uint64_t getNumValue(offset_t offset, bufsize_t size, bool *isOk)
bool containsBlock(offset_t rawOffset, bufsize_t size)
BYTE operator[](size_t idx)
static bool isValid(AbstractByteBuffer *buf)
QString getWStringValue(offset_t rawOffset, bufsize_t len)
QString getWAsciiStringValue(offset_t rawOffset, bufsize_t len)
bool isAreaEmpty(offset_t rawOffset, bufsize_t size)
virtual offset_t getOffset(void *ptr, bool allowExceptions=false)
bool fillContent(BYTE filling)
BufferView(AbstractByteBuffer *parent, offset_t offset, bufsize_t size)
AbstractByteBuffer * parent
bufsize_t size
virtual BYTE * getContent()
virtual bufsize_t getContentSize()
bool append(dbg_level lvl, const char *format,...)
Definition: Util.cpp:8
@ D_ERROR
Definition: Util.h:26
@ D_INFO
Definition: Util.h:26
bufsize_t roundupToUnit(bufsize_t size, bufsize_t unit)
size_t getAsciiLen(const char *ptr, size_t maxCount, bool acceptNotTerminated=false)
Definition: Util.cpp:46
size_t getAsciiLenW(const WORD *ptr, size_t maxCount, bool acceptNotTerminated=false)
Definition: Util.cpp:58