Why is fwrite writing more than I tell it to? - c

FILE *out=fopen64("text.txt","w+");
unsigned int write;
char *outbuf=new char[write];
//fill outbuf
printf("%i\n",ftello64(out));
fwrite(outbuf,sizeof(char),write,out);
printf("%i\n",write);
printf("%i\n",ftello64(out));
output:
0
25755
25868
what is going on?
write is set to 25755, and I tell fwrite to write that many bytes to a file, which is at the beginning, and then im at a position besides 25755?

If you are on a DOSish system (say, Windows) and the file is not opened in binary mode, line-endings will be converted automatically and each "line" will add one byte.
So, specify "wb" as the mode rather than just "w" as #caf points out. It will have no effect on Unix like platforms and will do the right thing on others.
For example:
#include <stdio.h>
#define LF 0x0a
int main(void) {
char x[] = { LF, LF };
FILE *out = fopen("test", "w");
printf("%d", ftell(out));
fwrite(x, 1, sizeof(x), out);
printf("%d", ftell(out));
fclose(out);
return 0;
}
With VC++:
C:\Temp> cl y.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
y.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:y.exe
C:\Temp> y.exe
04
With Cygwin gcc:
/cygdrive/c/Temp $ gcc y.c -o y.exe
/cygdrive/c/Temp $ ./y.exe
02

It may depend on the mode in which you opened the file. If you open it as a text file, then \n may be written as \r\n in DOS/Windows systems. However, ftello64() probably only gives the binary file pointer, which would count in the extra \r characters written. Try clearing the outbuf[] of any \n data or try opening the out file as binary ("wb" instead of "w").

The variable write is uninitialized and so the size of the array and the amount written will be essentially random.

Interesting. Works fine on Windows VC++, albeit ftello64 replaced with ftell.

Related

visual studio c++ how to properly use fopen() to open txt file

I am learning c++ and the excersise involves opening a .txt file and reading from it.
The project structure is as following:
int main()
{
static const char* full_name = "C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt";
FILE* my_file = fopen(full_name , "r");
if (my_file == NULL) {
perror("error opening file");
}
}
I am trying to fopen items.txt but with no luck yet..
I am not exactly sure what is the problem since I provide the full path..
METHODS TRIED SO FAR:
Using double backslash in full path
static const char* full_name = "C:\\Users\\Lukas\Desktop\\Programming\\file_system_test\\file_system_test\\items.txt";
Error still persists with:
error opening file: No such file or directory
SOLVED
The only thing that seems to fix this code is to use raw string literal as following:
static const char* full_name3 = R"(C:/Users/Lukas/Desktop/Programming/file_system_test/file_system_test/items.txt)";
FILE* my_file3 = fopen(full_name3, "r");
if (my_file3 == NULL) {
perror("error opening file");
}
Does not return any errors anymore.
Note escape sequences of string literals, so your path:
static const char* full_name = "C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt";
contains \f escape sequence which is interpreted as form feed - new page byte 0x0c in ASCII encoding. This character can't be part of of a path so Invalid argument error is reported.
Also compilers complain that other escape sequences are unknown.
There are three ways to fix it.
As Luka Rahne suggested by using back slash escape sequence \\
Or by using forward slashes (since C suppose to be portable, standard library is able to convert Unix path separator to platform specific path separators).
static const char* full_name = "C:/Users/Lukas/Desktop/Programming/file_system_test/file_system_test/items.txt";
If you are using C++11 or newer (your code is C not C++, but tag says C++), you can leverage raw string literal:
static const char* full_name = R"(C:\Users\Lukas\Desktop\Programming\file_system_test\file_system_test\items.txt)";
Here I did some live testing with msvc (file named: open.c):
#include <stdlib.h>
#include <stdio.h>
int main(int argc, const char argv[])
{
#if VERSION == 0
// here '\f' is used to reproduce error "invalid argument":
static const char name[] = "C:\fUsers\\User\\Downloads\\open.c";
#elif VERSION == 1
static const char name[] = "C:\\Users\\User\\Downloads\\open.c";
#elif VERSION == 2
static const char name[] = "C:/Users/User/Downloads/open.c";
#elif VERSION == 3
static const char name[] = R"(C:\Users\User\Downloads\open.c)";
#endif
FILE* f = fopen(name, "r");
if (!f) {
perror("fopen");
return 1;
}
char buf[256] = "";
fgets(buf, sizeof(buf), f);
printf("%s\n", buf);
fclose(f);
return 0;
}
Here is result of compiling and running from cmd.exe:
C:\Users\User\Downloads>cl open.c /D VERSION=0 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
fopen: Invalid argument
C:\Users\User\Downloads>cl open.c /D VERSION=1 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
#include <stdlib.h>
C:\Users\User\Downloads>cl open.c /D VERSION=2 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
Microsoft (R) Incremental Linker Version 14.28.29336.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:open.exe
open.obj
#include <stdlib.h>
C:\Users\User\Downloads>cl open.c /D VERSION=3 && open.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.28.29336 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
open.c
open.c(11): warning C4129: 'm': unrecognized character escape sequence
open.c(11): warning C4129: 'D': unrecognized character escape sequence
open.c(11): warning C4129: 'o': unrecognized character escape sequence
open.c(11): error C2065: 'R': undeclared identifier
open.c(11): error C2143: syntax error: missing ';' before 'string'
open.c(11): error C2099: initializer is not a constant
So everything works as I described and last version 3 fails since I compile code as C.
I believe your issue is that \ in filename is not properly escaped.
Your filename string should have double backslash characters.
static const char* full_name = "C:\\Users\\Lukas\\Desktop\\Programming\\file_system_test\\file_system_test\\items.txt";
You can test this, by sending this string trough std::cout for debug.

How to get fscanf to scan the next Line in C

The text file is a list of words similar to this. each world is on a new line
When i run my code, the only thing being printed is "hi".... how do i get it to continue to read the next lines
hi
hello
welcome
#include <stdio.h>
#include <stdlib.h>
int main()
{
char data[100];
// OPENS THE FILE
FILE *fp = fopen("/classes/cs3304/cs330432/Programs/StringerTest/people.txt", "r");
if (fp == NULL)
{
printf("Unable to open the file\n");
} else {
fscanf(fp, "%s", data);
printf("%s", data);
fclose(fp);
}
}
How to get fscanf to scan the next Line in C
Read the documentation of fscanf. You cannot scan lines with it. And fscanf can fail, and you should handle its failure.
A possible approach is to read the next line using fgets (or getline, or readline) and later to parse it using sscanf.
Be also aware that in 2021, UTF-8 is used everywhere. So document on paper what your program should do if your people.txt file contains a line like Être ou ne pas être or a line with СТАРЫНКЕВИЧ (in Cyrillic letters).
If allowed, use a recent GCC compiler as gcc -Wall -Wextra -g (asking for all warnings and debug info), improve your code to get no warnings, and then use the GDB debugger to understand the behavior of your program. You could install Debian on your laptop to get gcc and gdb
The documentation of your program could use EBNF notation to specify what are the valid inputs.
Consider generating parts of your C code with tools like GNU bison.
When fopen fails you could use perror to report the error.
You may want to read the wikipage about recursive descent parsing.
You may want to study -for inspiration- the source code of GNU coreutils.

step into standard wstdio functions in Visual Studio 2019

I want to find the reason why with the new feature setlocale(LC_ALL, ".utf8") the standard function fgetwc() can't read '\u2013' (EN DASH) from a utf8 text file and instead returns WEOF. Maybe find a workaround.
I disabled "Only my code" and enabled symbol downloading for C:\WINDOWS\SysWOW64\ucrtbased.dll that contains fgetwc
However, when I try to step into that function it cannot find fgetwc.cpp.
These two locations don't contain that file and I can't find any other place:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\crt\src\
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\crt\src\
This is my test program:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <stdlib.h>
int main()
{
wint_t wc; // = L'\u2013';
FILE* file;
printf("%s\n", setlocale(LC_ALL, ".utf8"));
file = fopen("test.txt", "r");
wc = fgetwc(file);
// ffff '?' 0 0
fprintf(stdout, "%04x '%lc' %d %d\n", wc, wc, ferror(file), feof(file));
return 0;
}
It prints ffff instead of 2013. ferror() and feof() return false.
test.txt:
–
It's encoded as E2 80 93
For reading the UTF-8 file, optionally drop the setlocale call, and replace the fopen line with:
file = fopen("test.txt", "r, ccs=utf-8");
The fopen documentation states:
ccs=encoding -- Specifies the encoded character set to use (one of UTF-8, UTF-16LE, or UNICODE) for this file. Leave unspecified if you want ANSI encoding.
This appears to imply that the ccs=UTF-8 encoding must be specified explicitly in order to read a file as UTF-8 text.
Though, on the other hand, "ANSI" used to mean either the active codepage, or the system default locale. With the recent support in Windows 10 1903 and later for UTF-8 as an active codepage, it would be expected that "ANSI encoding" be the same as "UTF-8 encoding" when the current locale is UTF-8. However, that does not seem to be the case with the current implementation of the UCRT.
For writing the wide char, #include <io.h> and <fcntl.h>, and replace the fprintf line with:
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"%04x '%wc' %d %d\n", wc, wc, ferror(file), feof(file));
The printf documentation states:
wprintf is a wide-character version of printf; format is a wide-character string. wprintf and printf behave identically if the stream is opened in ANSI mode. printf does not currently support output into a UNICODE stream.

About `argv` and opening a file with command line

I have this code:
#include <stdio.h>
int main ( int argc, char *argv[] )
{
FILE *file;
int x;
if ( argc != 2 )
printf( "Use: %s file name", argv[0] );
else {
if ((file=fopen( argv[1], "r" ))== 0 )
printf( “Couldn't open the file.\n" );
else {
while (( x = fgetc( file ) ) != EOF) printf( "%c", x );
fclose( file );
}
}
return 0;
}
Now, having this code, how do I execute a file from terminal (that is on the pic as well as my configuration of NetBeans). http://i.stack.imgur.com/6WRh3.png
First, better replace your statement (in your program above)
printf( “Couldn't open the file.\n" );
with
perror(argv[1]);
then, simply compile your program in your terminal, e.g. type there a shell command similar to
gcc -Wall -g mysource.c -o myprog
(Read more about invoking GCC: the -Wall option asks for nearly all warnings and is very useful -so never miss it-; you could even add -Wextra to get even more warnings; the -g is asking for DWARF debugging information in the ELF executable and enables you to use later gdb)
assuming your source code is in a file named mysource.c in the current working directory (use pwd command to query that current directory, ls -al to list it, and cd builtin command to change it)
at last, run your program as
./myprog sometestfile.txt
You might want to use the debugger. Read first about GDB, and try perhaps
gdb ./myprog
(I am guessing you are on Linux or some other POSIX compliant operating system, and using GCC compiler)
Read more about perror(3), command line interface, shells, globbing, glob(7), PATH variable
Later, you'll want to have some bigger program of yours made in several translation units, having some common header file (to be #included in all of them). Then you'll use a builder like GNU make. You could use a good editor like emacs, some version control like git, etc...
(you might realize that NetBeans is not very useful, because you can have even better developing comfort with your own collection of tools; having the freedom to choose your tools is worthwhile!)
PS. Perhaps replace printf( "%c", x ); with the shorter and more efficient putchar(x); ...

Directing Shellcode Output to a File - C

I'm using this code from here: Read and Execute Shellcode from a .txt File
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>
int main(void)
{
FILE *file = fopen("text.txt", "r");
unsigned char *buf;
int length = 0;
struct stat st;
int v;
// get file size and allocate. We're going to convert to bytes
// from text, so this allocation will be safely large enough
fstat(fileno(file), &st);
buf = valloc(st.st_size);
while (fscanf(file, "\\x%02x", &v) == 1)
{
buf[length++] = v;
}
fclose(file);
mprotect(buf, length, PROT_EXEC);
int (*ret)() = (int (*)())buf;
ret();
return 0;
}
And I'm compiling with: gcc -fno-stack-protector -z execstack testshell.c -o testshell
It runs just fine but the shellcode it executes writes to the terminal, but I would like to somehow redirect that to a file.
I tried:
./testshell > output.txt
but couldn't seem to get that to capture the results of the shellcode either.
How can I capture the output of any shellcode it runs, and if possible redirect that to a file?
Update: The shellcode I am using, and it outputs with a sys_write syscall output to a file descriptor (It does a calculation and prints to the screen) -
\xeb\x4d\x5e\x66\x83\xec\x0c\x48\x89\xe0\x48\x31\xc9\x68\x33\x09\x00\x7c\x48\x89\xcf\x80\xc1\x0c\x40\x8a\x3e\x40\xf6\xd7\x40\x88\x38\x48\xff\xc6\x68\x16\x96\xd0\xd9\x48\xff\xc0\xe2\xea\x2c\x0c\x48\x89\xc6\x68\xf2\xf5\x44\x48\x48\x31\xc0\x48\x89\xc7\x04\x01\x48\x89\xc2\x80\xc2\x0b\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xae\xff\xff\xff\x85\xa7\xaa\xc7\x9e\x87\xa5\xa5\x8e\xb7\x87\xba\x31\x80\xe0\x55\xef\xa1\x93\x0c\x4e\x1c\xdc\x34\x53\xb3\x8b\x43\x48\x68\x30\x1d\x4b\x65\x5b\x52\x41\x4e\x44\x53\x54\x52\x32\x5d
Transferring comments into an answer, giving credit where credit's due.
Deanie said:
This should work if the shellcode is writing to stdout and not stderr. Try:
./testshell > output.txt 1>&2
To which user2059300, the OP, responded:
No dice on the 1>&2, the output still occurs in the terminal and not in output.txt
And David C. Rankin said:
I think he meant ./testshell > output.txt 2>&1 to redirect both stdout & stderr to output.txt.
But user2059300 stated:
Still a no-go on that, … I provided the shellcode I'm testing.
Then I asked:
How does the shell code do the writing? What is it doing? I'm not going to dissect it for you; shell code tends to be very platform specific, and you've not identified which system you're using. Granted, it is reasonably easy to guess that you're using Linux on an Intel machine, but it might be 32-bit or 64-bit Linux, and what the shell code does still needs to be understood to know how to redirect its output. If it opens the terminal and writes to it, you'll be hard put to avoid the output appearing on the terminal, for example.
And user2059300 stated:
It's a sys_write syscall output to a file descriptor.
prompting me to ask:
Which file descriptor? 0, 1, 2, or another?
David C. Rankin noted:
That's still up in the air. Dumping to assembly shows a call to fprintf, but redirecting both stderr and stdout does nothing. It's almost like a kernel printf is being used.
And I countered with:
That's why I listed 0 as a candidate file descriptor. File descriptor 0 is usually a dup of file descriptors 1 and 2, so you can both write to 0 (standard input) and read from 1 and 2 (standard output and standard error). Of course, doing so is totally unsupported and non-portable (and you can't do it via the file streams stdin, stdout, stderr), but then shell code in general is non-portable.
And that seems to have been the key. David C. Rankin confirmed:
Hah! You nailed it. ./testshell > output.txt 0>&1 worked just fine. Learning has occurred… Thanks. That is the first, and hopefully the last time, I'll run across that. I'm too old to be learning those tricks.
and so did user2059300:
Thank you guys so much. Learning has indeed occurred. ./testshell > output.txt 0>&1
Obviously, I didn't know that was going to be the solution, but when the I/O redirection of standard output and standard error failed, it became a possibility. That behaviour has a very long history (7th Edition Unix, probably before that, too), though seldom if ever explicitly documented.

Resources