BearParser
Portable Executable parsing library (from PE-bear)
Loading...
Searching...
No Matches
AbstractByteBuffer.cpp
Go to the documentation of this file.
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
26BYTE 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
35offset_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
57BYTE* 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 offset_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! Buffer size: "
74 + QString::number(fileSize) + " vs reguested Offset: 0x" + QString::number(offset, 16));
75 return NULL;
76 }
77 const offset_t endOffset = offset + size;
78 if (endOffset > fileSize) {
79 if (allowExceptions) throw BufferException("Too big size requested! Buffer size: "
80 + QString::number(fileSize) + " vs end of the requested area: 0x" + QString::number(endOffset, 16));
81 return NULL;
82 }
83 BYTE *cntnt = buf + offset;
84 return cntnt;
85}
86
88{
89 if (startOffset == INVALID_ADDR) return 0;
90
91 offset_t contentSize = getContentSize();
92 if (contentSize < startOffset) return 0;
93
94 bufsize_t limit = static_cast<bufsize_t>(contentSize - startOffset);
95 return limit;
96}
97
98
99BYTE* AbstractByteBuffer::getContentAtPtr(BYTE *ptr, bufsize_t size, bool allowExceptions)
100{
101 offset_t offset = getOffset(ptr, allowExceptions);
102 if (offset == INVALID_ADDR) return NULL;
103
104 return getContentAt(offset, size, allowExceptions);
105}
106
107bool AbstractByteBuffer::setBufferedValue(BYTE *dstPtr, BYTE *srcPtr, bufsize_t srcSize, bufsize_t paddingSize, bool allowExceptions)
108{
109 if (dstPtr == srcPtr) return false;
110 if (dstPtr == NULL || srcPtr == NULL) return false;
111
112 offset_t dstStart = getOffset(dstPtr);
113 if (dstStart == INVALID_ADDR) {
114 printf("Invalid copy destination!");
115 if (allowExceptions) throw BufferException("Invalid copy destination!");
116 return false;
117 }
118
119 bufsize_t size = srcSize + paddingSize;
120 bufsize_t dstMaxSize = static_cast<bufsize_t>(getContentSize() - dstStart);
121 if (dstMaxSize < size) {
122 //throw BufferException("Cannot copy: too big content size!");
123 size = dstMaxSize;
124 }
125 if (memcmp(dstPtr, srcPtr, size) == 0) {
126 return false; //no changes required
127 }
128 if (paddingSize != 0) { //add padding
129 memset(dstPtr, 0, size);
130 }
131 memcpy(dstPtr, srcPtr, srcSize);
132 return true;
133}
134
135bool AbstractByteBuffer::setStringValue(offset_t rawOffset, QString newText)
136{
137 std::string newTextStr = newText.toStdString();
138 const bufsize_t newTextLen = static_cast<bufsize_t>(newTextStr.length());
139
140 BYTE *dstPtr = this->getContentAt(rawOffset, newTextLen + 1); //with terminating '\0'
141 if (!dstPtr) {
142 // cannot get a suitable buffer for the string
143 return false;
144 }
145 const char* newTextC = newTextStr.c_str();
146 bool isOk = setBufferedValue(dstPtr, (BYTE*)newTextC, newTextLen, 1);
147 return isOk;
148}
149
150QString AbstractByteBuffer::getStringValue(offset_t rawOffset, bufsize_t size, bool acceptNonTerminated)
151{
152 if (size == BUFSIZE_MAX) {
153 size = this->getContentSize() - rawOffset;
154 }
155 char *ptr = (char*) getContentAt(rawOffset, size);
156 if (!ptr) return "";
157 size_t asciiLen = pe_util::getAsciiLen(ptr, size, acceptNonTerminated);
158
159 return QString::fromUtf8(ptr, static_cast<int>(asciiLen));
160}
161
163{
164 const bufsize_t unitSize = sizeof(WORD);
165 bufsize_t size = unitSize;
166 if (len != BUFSIZE_MAX) {
167 size = len * unitSize;
168 }
169 WORD* ptr = (WORD*) this->getContentAt(rawOffset, size);
170 if (ptr == NULL) return "";
171 return QString::fromUtf16(ptr, static_cast<int>(len));
172}
173
174QString AbstractByteBuffer::getWAsciiStringValue(offset_t rawOffset, bufsize_t len, bool acceptNonTerminated)
175{
176 const bufsize_t unitSize = sizeof(WORD);
177 bufsize_t size = unitSize;
178 if (len != BUFSIZE_MAX && len != -1) {
179 size = len * unitSize;
180 }
181 WORD* ptr = (WORD*) getContentAt(rawOffset, size);
182 if (!ptr) return "";
183
184 size_t asciiLen = pe_util::getAsciiLenW(ptr, len, acceptNonTerminated);
185 return QString::fromUtf16(ptr, static_cast<int>(asciiLen));
186}
187
189{
190 BYTE* area = this->getContentAt(rawOffset, size);
191 if (area == NULL) return false;
192
193 for (bufsize_t i = 0; i < size; i++) {
194 if (area[i] != 0) return false;
195 }
196 return true;
197}
198
200{
201 bufsize_t bufSize = this->getContentSize();
202 BYTE* buf = this->getContent();
203
204 if (buf == NULL) return false;
205
206 memset(buf, filling, bufSize);
207 return true;
208}
209
210bool AbstractByteBuffer::pasteBuffer(offset_t rawOffset, AbstractByteBuffer *buf, bool allowTrunc)
211{
212 if (isValid(buf) == false || isValid(this) == false) return false;
213 if (buf == NULL || buf->getContent() == NULL) return false;
214 BYTE* source = buf->getContent();
215 bufsize_t sizeToFill = buf->getContentSize();
216
217 bufsize_t mySize = this->getContentSize();
218 if (static_cast<offset_t>(mySize) <= rawOffset) {
220 "Too far offset requested: %llX while mySize: %lX",
221 static_cast<unsigned long long>(rawOffset),
222 static_cast<unsigned long>(mySize)
223 );
224 return false;
225 }
226 BYTE *target = this->getContentAt(rawOffset, sizeToFill);
227 if (target == NULL) {
228 if (allowTrunc == false) return false;
229 sizeToFill = mySize - rawOffset;
230 target = this->getContentAt(rawOffset, sizeToFill);
231 }
232 if (target == NULL) return false;
233 memcpy(target, source, sizeToFill);
234 return true;
235}
236
238{
239 if (rawOffset == INVALID_ADDR || size == 0) return false;
240
241 BYTE *ptr = (BYTE*) this->getContent();
242 if (ptr == NULL) return false;
243
244 offset_t startOffset = this->getOffset(ptr);
245 if (startOffset == INVALID_ADDR) return false;
246
247 offset_t endOffset = startOffset + this->getContentSize();
248
249 offset_t srchdEnd = rawOffset + size;
250 if (rawOffset >= startOffset && srchdEnd <= endOffset) {
251 //printf("Fount in bounds: %x - %x block: %x-%x\n", startOffset, endOffset, rawOffset, srchdEnd);
252 return true;
253 }
254 return false;
255}
256
258{
259 if (rawOffset == INVALID_ADDR || size == 0) return false;
260
261 BYTE *ptr = (BYTE*) this->getContent();
262 if (ptr == NULL) return false;
263
264 offset_t startOffset = this->getOffset(ptr);
265 if (startOffset == INVALID_ADDR) return false;
266
267 offset_t endOffset = startOffset + this->getContentSize();
268
269 offset_t srchdEnd = rawOffset + size;
270 if (rawOffset >= startOffset && rawOffset <= endOffset) {
272 "Found in bounds: %llX - %llX end: %llX",
273 static_cast<unsigned long long>(startOffset),
274 static_cast<unsigned long long>(endOffset),
275 static_cast<unsigned long long>(rawOffset)
276 );
277 return true;
278 }
279 if (srchdEnd >= startOffset && srchdEnd <= endOffset) {
281 "Found in bounds: %llX - %llX",
282 static_cast<unsigned long long>(startOffset),
283 static_cast<unsigned long long>(endOffset)
284 );
285 return true;
286 }
287 return false;
288}
289
290template <typename INT_TYPE>
291INT_TYPE _getNumValue(void* ptr)
292{
293 INT_TYPE val = *((INT_TYPE*)ptr);
294 return val;
295}
296
297uint64_t AbstractByteBuffer::getNumValue(offset_t offset, bufsize_t size, bool* isOk)
298{
299 if (isOk) (*isOk) = false;
300 if (size == 0 || offset == INVALID_ADDR) return (-1);
301
302 void* ptr = this->getContentAt(offset, size);
303 if (ptr == NULL) {
304 return (-1);
305 }
306 uint64_t val = (-1);
307 if (size == sizeof(uint8_t)) val = _getNumValue<uint8_t>(ptr);
308 else if (size == sizeof(uint16_t)) val = _getNumValue<uint16_t>(ptr);
309 else if (size == sizeof(uint32_t)) val = _getNumValue<uint32_t>(ptr);
310 else if (size == sizeof(uint64_t)) val = _getNumValue<uint64_t>(ptr);
311 else {
312 return (-1);
313 }
314 if (isOk) (*isOk) = true;
315 return val;
316}
317
318template <typename INT_TYPE>
319bool _setNumValue(void* ptr, INT_TYPE nVal)
320{
321 INT_TYPE* valPtr = (INT_TYPE*)ptr;
322 if ((*valPtr) == nVal) return false;
323 (*valPtr) = nVal;
324 return true;
325}
326
327bool AbstractByteBuffer::setNumValue(offset_t offset, bufsize_t size, uint64_t newVal)
328{
329 if (size == 0 || offset == INVALID_ADDR) return false;
330 void* ptr = this->getContentAt(offset, size);
331 if (ptr == NULL) {
333 "Cannot get Ptr at: %llX of size: %lX!",
334 static_cast<unsigned long long>(offset),
335 static_cast<unsigned long>(size)
336 );
337 return false;
338 }
339
340 if (size == sizeof(uint8_t)) {
341 if (!_setNumValue(ptr, uint8_t(newVal)))
342 return false;
343 }
344 else if (size == sizeof(uint16_t)) {
345 if (!_setNumValue(ptr, uint16_t(newVal)))
346 return false;
347 }
348 else if (size == sizeof(uint32_t)) {
349 if (!_setNumValue(ptr, uint32_t(newVal)))
350 return false;
351 }
352 else if (size == sizeof(uint64_t)) {
353 if (!_setNumValue(ptr, uint64_t(newVal)))
354 return false;
355 } else {
356 Logger::append(Logger::D_ERROR, "Wrong size!");
357 return false;
358 }
359 return true;
360}
361
362bool AbstractByteBuffer::setTextValue(char* textPtr, std::string newText, size_t fieldLimitLen)
363{
364 if (!textPtr) return false;
365
366 size_t newLen = newText.length() + 1;
367 offset_t textOffset = this->getOffset(textPtr);
368 if (textOffset == INVALID_ADDR) {
369 return false;
370 }
371 //check against the buffer overflow
372 if (!this->getContentAt(textOffset, newLen)) {
373 return false;
374 }
375 //if both strings are same, do not overwrite
376 const char* newTextC = newText.c_str();
377 if (!strcmp(newTextC, textPtr)) { //TODO: use a safe comparison
378 return false;
379 }
380 //if the field size is set:
381 if (fieldLimitLen != 0) {
382 if (this->getContentAt(textOffset, fieldLimitLen)) {
383 //clear the previous field
384 memset(textPtr, 0, fieldLimitLen);
385 if (newLen > fieldLimitLen) {
386 newLen = fieldLimitLen;
387 }
388 }
389 }
390 memcpy(textPtr, newTextC, newLen);
391 textPtr[newLen] = '\0';
392 return true;
393}
394
396{
397 BYTE *contentPart = this->getContentAt(offset, contentSize);
398 if (!contentPart) return 0; //invalid offset/size
399
400 if (!fIn.isReadable()) return 0;
401
402 size_t toLoad = fIn.size() < contentSize ? fIn.size() : contentSize;
403 BYTE *fBuf = (BYTE*)::calloc(toLoad, 1);
404 if (!fBuf) {
405 return 0;
406 }
407 size_t loaded = fIn.read((char*)fBuf, toLoad);
408 memset(contentPart, 0, contentSize);
409 memcpy(contentPart, fBuf, loaded);
410 free(fBuf); fBuf = NULL;
411
412 return loaded;
413}
414
415//--------------------------------------------
416
418 : parent(v_parent), offset(v_offset), size(v_size)
419{
420 if (v_parent == NULL) throw BufferException("Cannot make subBuffer for NULL buffer!");
421}
422
424{
425 bufsize_t maxSize = this->parent->getContentSize();
426 if (offset > maxSize) {
427 return 0;
428 }
429 if (offset + size > maxSize) {
430 bufsize_t trimedSize = maxSize - offset;
431 return trimedSize;
432 }
433 return size;
434}
435
437{
438 return this->parent->getContentAt(offset, getContentSize());
439}
INT_TYPE _getNumValue(void *ptr)
bool _setNumValue(void *ptr, INT_TYPE nVal)
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)
QString getStringValue(offset_t rawOffset, bufsize_t len=BUFSIZE_MAX, bool acceptNonTerminated=false)
virtual BYTE * getContentAtPtr(BYTE *ptr, bufsize_t size, bool allowExceptions=false)
virtual BYTE * getContent()=0
bool setTextValue(char *textPtr, std::string newText, size_t fieldLimitLen=0)
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)
offset_t substFragmentByFile(offset_t offset, bufsize_t contentSize, QFile &fIn)
bool pasteBuffer(offset_t rawOffset, AbstractByteBuffer *buf, bool allowTrunc)
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)
bool isAreaEmpty(offset_t rawOffset, bufsize_t size)
virtual offset_t getOffset(void *ptr, bool allowExceptions=false)
QString getWAsciiStringValue(offset_t rawOffset, bufsize_t len, bool acceptNonTerminated=false)
bool fillContent(BYTE filling)
BufferView(AbstractByteBuffer *parent, offset_t offset, bufsize_t size)
AbstractByteBuffer * parent
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