What's the significance of the App Verifier error pattern `fafa`? - c++

My program is crashing in app verifier and I don't fully understand the crash. I have a buffer which is dynamically allocated thus from the number of bytes in a file:
DWORD dwSizeBytes = (DWORD)liSize.QuadPart+2;
TCHAR* JSONBufferW = new TCHAR [dwSizeBytes/sizeof(TCHAR)];
memset(JSONBufferW, 0, dwSizeBytes);
Where dwSizeBytes (I can see this in the crash dump) is 38. After this I read some data from a file:
if(!ReadFile(hFile, JSONBufferW, dwSizeBytes, &dwSizeBytes, NULL))
{
status = GetLastError();
TRACE_ERROR(g_hTrace, "ReadFile() failed for %S, error code=%d", strCompletePath, status);
}
This assigns 36 to dwSizeBytes leaving the last two bytes in the buffer NULL so that the buffer is NULL terminated. However under app verifier this later causes a crash when I attempt to construct a std::wstring from the buffer.
When I look at the buffer's allocation block in windbg I see that it looks like this:
0:022> dd 0x00000000`07560fd0-0x48 0x00000000`07560fd0
00000000`07560f88 00001000 00000000 abcdbbbb 00000000
00000000`07560f98 07191000 00000000 00000026 00000000
00000000`07560fa8 00001000 00000000 00000000 00000000
00000000`07560fb8 00000000 00000000 0025a230 00000000
00000000`07560fc8 00001000 dcbabbbb 0022007b
Note the 0x26 which shows my buffer is supposed to be 38 in size. Now I look at the buffer it's self and see:
0:022> dc 0x00000000`07560fd0
00000000`07560fd0 0022007b 006f006d 00650064 003a0022 {.".m.o.d.e.".:.
00000000`07560fe0 006d0022 006e0061 00610075 0022006c ".m.a.n.u.a.l.".
00000000`07560ff0 000a007d d0d0fafa d0d0d0d0 d0d0d0d0 }...............
This shows that my buffer has been filled by ReadFile but where the NULL should have been left at buf[36] and buf[37] (remember the memset) there is an app verifier fill code fafa (remember the unicode bytes are flipped so d0d0 is actually after fafa.
I've looked here: which has shown me how app verifier leaves these fill codes after allocations. But fafa is not listed, so what does it mean? And why is it in the place where memset should have cleared?

I don't have a source for this at the moment, but one of the features AppVerifier does is completely fills your buffer with a pattern prior to invoking ReadFile. You request to read 38 bytes, AppVerifier fills your buffer with 38 bytes of pattern, and ReadFile only reads 36 bytes from the file. Thus your last 2 bytes are fill pattern rather than the expected NULL characters.

Related

EEPROM protocol misconception

I am currently using a michrochip's eeprom ( 24cw160 ) connected with an stm32f4 (11RET) via i2c. The configurations and the connection seem to work as my logical analyzer prints some i2c messages (with ACK) and I can send data and receive data back. After reading the reference manual(especially pages 13 and 18 that have the schematics for the two operations I am doing) I am expecting the code below to send the data 0,1,2... to the addresses after x10 sequentially and then receiving the same data back and printing them :
while(true){
HAL_Delay(1000);
std::array<uint8_t,100> arr{};
int counter=0;
for(auto&i :arr){
i=counter;
counter++;
}
auto ret1 = HAL_I2C_Mem_Write_DMA(&hi2c1 , 0xa0 , 0x10 , 1 ,arr.data() , arr.size());
HAL_Delay(1000);
std::array<uint8_t,100> arr2{};
arr2.fill(1);
auto ret2 = HAL_I2C_Mem_Read( &hi2c1 , 0xa1 , 0x10 , 1 , arr2.data() , arr2.size(),100);
printf("arr2:\n");
for(auto i:arr2){
printf("%d,",(int)i);
}
printf("\nWrite ret status: %d\nRead ret status: %d\n",ret1,ret2);
}
Instead what I get on my terminal is :
arr2:
70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
Write ret status: 0
Read ret status: 0
arr2:
68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
Write ret status: 0
Read ret status: 0
Notice ,that the first line of prints has some differences with the second and the second is recurring (so the while true at the first time print a little bit different things than the others) I honestly think I have confused myself with the constant parameters I give to HAL_I2C_Mem_Write and read and I would like some explanation on that too.
For more info comment me and I will provide all the necessary diagnostics/initializations etc.
Thanks to the comments I managed to send a byte at whatever address I want . One noticed error on the previous code is the MemAddress parameter( third parameter of HAL_I2C_Write_Mem) ,because my eeprom is 11 bit addressable I should declare to hal that it is 16 and not 8 as the 5 extra bits are ignored bits ,but less than 11 might malfunction.
A second problem was that I was trying to write more than 32 bytes and I was reading only the first 32 as the protocol doesn't accept writing or reading more than one 32 byte page at a time. So here is the modified code with some comments on the changes:
std::array<uint8_t,32> arr{0}; //32 bytes instead of something silly
unsigned counter=0;
for(auto&i :arr){
i=counter;
counter++;
}
// 0x20 is a start of a page so it can write all 32 bits
// I2C_MEMADD_SIZE_16BIT is the value 2 instead of 1 I had
// The extra 5 bits are ignored
// For the testing I call the blocking write
auto ret1 = HAL_I2C_Mem_Write(&hi2c1 , 0xa0 , 0x20 , I2C_MEMADD_SIZE_16BIT , arr.data() , arr.size(),4);
HAL_Delay(4);
std::array<uint8_t,32> arr2{0};
arr2.fill(1);
auto ret2 = HAL_I2C_Mem_Read( &hi2c1 , 0xa1 , 0x20 , I2C_MEMADD_SIZE_16BIT , arr2.data() ,arr2.size(),4);
HAL_Delay(4);
printf("arr2: ");
for(auto i:arr2)
printf(" %d,",(int)i);
printf("\nWrite ret status: %d\nRead ret status: %d\n",ret1,ret2);

How to use ReadFile() in c++ to read bytes of length that are not multiple of 512

I am trying to read raw bytes to a drive. But the function ReadFile() only allowing me to read bytes of length 512 or its multiple. I cannot read bytes of length 10, 180,1000 etc.
DWORD NumberOfBytesRead=0;
ReadFile(hDevice, nullbuffer, (DWORD)512, &NumberOfBytesRead, (LPOVERLAPPED)NULL); //works
ReadFile(hDevice, nullbuffer, (DWORD)1024, &NumberOfBytesRead, (LPOVERLAPPED)NULL); //works
ReadFile(hDevice, nullbuffer, (DWORD)1000, &NumberOfBytesRead, (LPOVERLAPPED)NULL); //error 87
ReadFile(hDevice, nullbuffer, (DWORD)300, &NumberOfBytesRead, (LPOVERLAPPED)NULL); //error 87
Is there some way to overcome this?
The rules for direct access of the device mandate that you must read aligned blocks of data. That's not something that you can change. It's a hard rule that you must follow.
Given this rule, you must read into a buffer that is a multiple of the required block size. If you wish only to access some part of that buffer, you can pick that part out after you have read from the device.

VC++ wcscpy_s randomly assert on "Buffer is too small"

You can see the parameter sent to the function does not exceed the buffer size from the code below.
This problem happened randomly, and only happened in debug build.
#include <thread>
#include <sstream>
#define BUF_SZ 32
int main()
{
wchar_t src[BUF_SZ]{};
bool running = true;
std::thread th([&] {
for (double g = 0; g < 100000; g += .1)
{
std::wstringstream ws;
ws << g;
wcscpy_s(src, BUF_SZ, ws.str().c_str());
}
running = false;
});
wchar_t dst[BUF_SZ]{};
while (running)
wcscpy_s(dst, src); // assert on "Buffer is too small" randomly
th.join();
return 0;
}
Thanks to Mr. Steve Wishnousky from MSFT VC++ team, here is the complete explanation of the problem.
Wcscpy_s does not operate atomically on the buffers and will only work
correctly if the buffers do not change contents during the runtime of
wcscpy_s.
Another thing to note is that in Debug mode, the wcscpy_s function
will fill the rest of the buffer in with a debug mark (0xFE) to
indicate that the data there is now invalid to assume it's contents,
in order to detect potential runtime errors.
The error happens differently every time of course, but lets assume
this error happens when src=1269.9 and wcscpy_s(dst, src) is called.
The actual contents of src is: "1 2 6 9 . 9 null 0xfe 0xfe ...".
wcscpy_s copies over the 1269.9 but as it's about to read the null,
the other wcscpy_s just wrote a new value to src so it's now: "1 2 7 0
null 0xfe 0xfe ...". Instead of reading the null corresponding from
the previous src, it reads the 0xfe, so it thinks this is a real
character. Since there is no null terminator until we reach the end of
the buffer, the Debug runtime asserts that the buffer was too small
for the input.
In the Release build, the 0xFE debug marks aren't placed in the
buffer, so it will eventually find a null character. You can also
disable the debug marks by calling _CrtSetDebugFillThreshold:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/crtsetdebugfillthreshold?view=vs-2019.
Note that the Debug marks are actually catching a real correctness
problem here though. This "buffer changed during wcscpy_s" issue could
happen for any value. For example, if src=1269.9, wcscpy_s could copy
over the 126, but then as it's about to read the 9, src is updated to
1270 and the value that would end up in dest would be "1260".
Since the string copy will need to copy "src" characters and a terminating null character you'll need to provide a buffer which is at least one character bigger than sizeof "src".
I suggest you could try to use:
wcscpy_s(dst, sizeof src+1, src);

Different behavior on read() depending on file descriptor representing a file, anonymous pipe or socket when writing to non writable memory

I have the following code:
#include <sys/mman.h>
#include <unistd.h>
#include <cstdio>
int main() {
char *p = (char *)mmap(0, 0x3000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
munmap(p + 0x2000, 0x1000);
p += 0x800;
printf("%zd\n", read(0, p, 0x3000));
return 0;
}
When compiling it and running it with input that will write past writable memory, I get different behaviors based on the way this input is fed:
$ python3 -c 'print("A"*0x3000)' | ./test
4096
$ python3 -c 'print("A"*0x3000)' > input.bin; ./test < input.bin
6144
$ nc.traditional -l -p 1337 -e ./test &
[1] 25855
$ python3 -c 'print("A"*0x3000)' | nc localhost 1337
-1
[1]+ Done nc.traditional -l -p 1337 -e ./test
I would have expected the read() call to return the same result in all cases, but this is not the case. Why do I get different behaviors?
The strace output from this command shows that the full 12288 (0x3000) bytes are written in one go:
$ strace python3 -c 'print("A"*0x3000)' | ./test
...
write(1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 12288) = 12288
...
Using strace on the ./test command at the other end of the pipe shows that only 4096 (0x1000) bytes are read:
$ python3 -c 'print("A"*0x3000)' | strace ./test
...
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 12288) = 4096
...
If the standard input for ./test comes from input.bin (which contains 12288 'A's followed by a newline), strace shows that 6144 (0x1800) bytes are read:
$ strace ./test < input.bin
...
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 12288) = 6144
...
I think the explanation can only be found by delving into the kernel's code for reading from a pipe in the pipe_read function in "fs/pipe.c". Internally, the pipe contains a cyclic array of struct pipe_buffer, each of which contains a pointer to a page of data. The pipe_read function loops through these buffers copying the contents to the user until all requested data has been read, there is nothing left in the pipe (after waiting for more data from the writer when in blocking mode), or a fault occurs when copying data to the user. The reason why only 4096 bytes are returned instead of 6144 when the fault occurs seems to be due to this bit of code:
written = copy_page_to_iter(buf->page, buf->offset, chars, to);
if (unlikely(written < chars)) {
if (!ret)
ret = -EFAULT;
break;
}
ret += chars;
buf->offset += chars;
buf->len -= chars;
(The above section is from Linux kernel version 4.19.)
Here, chars is the amount to be copied from the current pipe buffer, written is the amount that was actually copied, and ret is the return value of the function, which is normally the number of bytes read. The initial value of ret is 0. written normally gets set to chars unless an address fault occurs, in which case it will be less than chars.
The fault occurs when copying the second page from the pipe. The first page was copied successfully so ret will be 4096. When copying the second page, an address fault occurs in the user buffer after 6144 - 4096 = 2048 (0x800) bytes, so the break; statement is reached to break out of the loop before the ret += chars; statement is reached. ret is not set to -EFAULT because it is non-zero. However, the partial copy of 2048 bytes from the second page of the pipe to the user buffer have been disregarded as far as the returned value of the pipe_buf function indicates. (The disregarded data is not discarded from the pipe. The position in the pipe is only moved on after a successful copy, so a subsequent call to pipe_read will continue from the same point.)
Note that although read only returned 4096, it seems likely that it actually copied 6144 bytes to the user buffer. This could be confirmed by examining the buffer contents from p + 4096 onwards after returning from the read call.
I'm sure the relevant part of the pipe_read function could be rewritten to properly account for the partially copied portion, but I don't know if the core kernel developers would consider it a bug worth fixing. For example, a fix might replace the above code with something like the following (untested) code:
written = copy_page_to_iter(buf->page, buf->offset, chars, to);
ret += written;
buf->offset += written;
buf->len -= written;
if (unlikely(written < chars)) {
if (!ret)
ret = -EFAULT;
break;
}
I am pretty sure that your ./test program would manage to read 6144 bytes from the pipe with this change to the kernel code.

Buffer overflow successful, but it shouldn't be?

This is my program, with a vulnerable char buffer, name[400].
void greeting(char *temp1,char *temp2)
{
char name[400];
strcpy(name,temp2);
printf("Hello %s %s\n", temp1, name);
}
int main(int argc,char *argv[])
{
greeting(argv[1],argv[2]);
return 0;
}
Compiled as follows on Linux (64-bit) with ASLR disabled:
gcc -m32 -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 -z execstack -o buffer buffer.c
(gdb) run Mr `perl -e 'print "A" x 400'`
Hello Mr AAAAAAA.... (truncated)
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info reg eip ebp
eip 0x41414141
ebp 0x41414141
I'm assuming here that a null byte is added, resulting in the overflow, but what I don't understand is how the EIP can be 0x41414141 with only a 1 byte overflow?
EDIT: After more probing with gdb, there is no null byte added, and there is no overflow at all when only 400 bytes are entered. So how does my EIP end up pointing to my buffer contents without any overflow? I'm assuming that the absense of a null byte causes problems for printf().
C string are NUL terminated, so you end up with a 1-byte overflow with a value of zero (NUL).
The one-byte NUL overflow modifies the saved value of $ebp to point lower on the stack than it should. This results in restoring an incorrect value into $esp, and control of $eip.
Take specific note of the value of ebp. After the call, the value of $ebp is still the same, but the value it points to (the value which main will restore off the stack) has been adjusted, and points into the middle of our controlled buffer.
When greeting returns into main, nothing happens. However, when main restores the stack frame with a leave instruction, the stack pointer $esp is set into the middle of our controlled buffer. When the ret instruction is executed, we have control over $eip.
Note that I've used a cyclic pattern generated by pwntools rather than the standard AAAAA since we can use it to calculate offsets. For example 'aaaa' => 0, 'aaab' => 1, 'aaba' => 2.
Before Strcpy
EBP: 0xffffc6e8 --> 0xffffc6f8 --> 0x0
ESP: 0xffffc54c --> 0xffffc558 --> 0xffffc5c8 --> 0xf63d4e2e
EIP: 0x8048466 (<greeting+25>: call 0x8048320 <strcpy#plt>)
After Strcpy
EBP: 0xffffc6e8 --> 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc54c --> 0xffffc558 ("aaaabaaacaaadaaaeaaafaaagaaahaaa"...)
EIP: 0x804846b (<greeting+30>: lea eax,[ebp-0x190])
Before leave in main
EBP: 0xffffc600 ("raabsaabtaabuaabvaabwaabxaabyaab"...)
ESP: 0xffffc6f0 --> 0xffffc9bb ("Mister")
EIP: 0x80484b1 (<main+39>: leave)
After leave in main
EBP: 0x62616172 (b'raab')
ESP: 0xffffc604 ("saabtaabuaabvaabwaabxaabyaabzaac"...)
EIP: 0x80484b2 (<main+40>: ret)
At ret in main
EBP: 0x62616172 (b'raab')
ESP: 0xffffc608 ("taabuaabvaabwaabxaabyaabzaacbaac"...)
EIP: 0x62616173 (b'saab')