BearParser
Portable Executable parsing library (from PE-bear)
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 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
97BYTE* 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
105bool 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
133bool 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
208bool 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
288uint64_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
310bool 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)
virtual BYTE * getContent()=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)
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)
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