I've been writing shell scripts (to make things easier to use) but this time i wanted to do it in C, and one command that i used the most is xxd -r, to "patch" a binary file.
Exemple :
echo "0000050: 2034" | xxd -r - my_binary_file
My question is : is there a way to do something similar in C ?
(I hope my question is clear)
Universally, you could use fopen (with "w" on Unix and "wb" on Windows), fseek, and fwrite.
Of if you prefer posix style, open, seek, and write.
On Win32, the posix equivalents are CreateFile, SetFilePointer, and WriteFile
Well you could still use your command and call it in C code using system() function.
system("echo "0000050: 2034" | xxd -r - my_binary_file")
NOTE: you can dynamically build above string with file name and parameters using sprintf() function and then pass it to the system function() as shown below.
#include <string.h>
#include <stdlib.h>
int main(){
char acBuffer[512]; //Allocate as reuiquired only
memset(acBuffer, 0x00, sizeof(acBuffer));
sprintf(acBuffer, "echo \"%s\" | xxd -r - %s", "0000050: 2034", "YourBinaryFile");
system(acBuffer); //You can check the return type if you want to
return 0;
}
Related
F
I'm using Graphviz to render .dot file as graphs, and typically I would write in my terminal :
dot -Tpng yourFile.dot -o yourOutput.png to produce a .png image representing my graph. (I'm using a Unix environment btw)
Now let's say I have the following C function:
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 255
typedef struct placeholder mystruct;
struct placeholder {
...
}
void outputGraph(mystruct str, char* outputName) {
char command[MAXSIZE];
char* tmpFile = "temp.dot";
char imageFile[MAXSIZE];
snprintf(imageFile, MAXSIZE, "%s.png", outputName);
FILE* file = fopen(tmpFile, "w");
writeStructToFile(str, file);
snprintf(command, MAXSIZE, "dot -Tpng %s -o %s", tmpFile, imageFile);
system(command);
snprintf(command, MAXSIZE, "rm %s", tmpFile);
system(command);
}
(my function WriteStructToFile is another one that I made and is working properly so the problem is somewhere else)
From what I understood about the system() function, it should produce the image output just the same as when I execute the same command myself.
Well, it does execute without any errors, but there is no image in the directory where I'm working.
At first, I thought, it's easy, system() doesn't start a new shell in the same working directory, so I tried to see the output of system(pwd); and it was my current working directory. So back to the starting point.
I also tried to check the value system(command) by doing int status = system(command); and then printf("status : %d\n", status); and, well, it printed 0.
Now I'm kinda clueless, I really don't see why it doesn't produce the image output.
I'd be very interested in any ideas or even solutions you have.
This is not the most elegant code, but it works & may help you debug your problem. It calls dot in three different ways. All three work as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char command[50];
int rc;
strcpy(command, "dot -Tdot this.gv" );
rc=system(command);
printf("\n\n+++ call #1 returned %d\n", rc);
strcpy(command, "dot -Tdot this.gv -oout1.dot" );
rc=system(command);
printf("\n\n+++ call #2 returned %d\n", rc);
strcpy(command, "dot -Tdot this.gv -o out2.dot" );
rc=system(command);
printf("\n\n+++ call #3 returned %d\n", rc);
return(0);
}
snprintf(command, MAXSIZE, "touch %s", tmpFile);
system(command);
Why do you code that?
You certainly don't need to use system(3) then touch(1). You could use appropriate syscalls(2) (open(2) and close(2) here) or at least fopen(3) followed by fclose(3).
You might in some cases consider using popen(3) with pclose(3)
Of course, after
snprintf(command, MAXSIZE, "dot -Tpng %s -o %s", tmpFile, imageFile);
int bad = system(command);
You need to first check that bad is 0 and you probably want to use stat(2) or access(2) to check that imageFile exists.
There could be many reasons why system with a dot command fails. For example, a bad $PATH variable. I suggest using popen(3) with pclose(3) and probably /usr/bin/dot in the command.
Compile your C code using GCC as gcc -Wall -Wextra -g and use GDB to debug your executable. Both strace(1) and ltrace(1) could help you understand the behavior of your program.
Consider reading Advanced Linux Programming and studying for inspiration the source code of some simple open source Linux shells, such as sash or (more complex) GNU bash.
Be aware that Graphviz could be used as a library.
I wasn't closing the temp.dot file in which I was writing. My mistake.
I shall now remember to always close files that I open!
A big thank you to everyone who helped on here.
(Whether it was for the problem or on how to use properly SO)
I have this paper, on C language, which requires some greek sentences to be printed in the terminal.
In the code template that is given to us there is this line of code:
system("chcp 1253>nul");
This is supposed to print the greek characters.
In my Ubuntu Terminal I see:
�������� ����� �� ����� ����� ��� �������� ���� ������
So, how can I print greek characters in my terminal?
This is supported out of the box in most Linuxes. The only thing one must do is use
setlocale(LC_ALL, "");
in the beginning of the program. This relies on the fact that UTF-8 is the default choice of encoding for users' locales. The standard says that this call switches to user's current locale. The default is to use the "C" locale which may or may not support national characters.
By default gcc interprets the source code as encoded in UTF-8. Compile-time options exist to change that, but it is recommendedd to keep everything in UTF-8 on Linux. Sources that come from Windows are probably not encoded in UTF-8 and need to be recoded. Use the iconv utility for that;l. If the source is associated with a particular legacy code page, try that code page name as the source encoding.
A C program (comforming to ISO C99 or later, or POSIX.1 or later) that inputs or outputs non-ASCII text should use wide strings, wide I/O, and localization.
For example:
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
int main(void)
{
/* Tell the C library to use the current locale settings. */
setlocale(LC_ALL, "");
/* Standard output is used with the wide I/O functions. */
fwide(stdout, 1);
/* Print some Greek text. */
wprintf(L"Γειά σου Κόσμε!\n");
return EXIT_SUCCESS;
}
Note that wide string literals are written using L"..." whereas normal (ASCII or narrow) string literals as "...". Similarly, wide character constants (of type wint_t) are written with the L prefix; for example, L'€'.
When compiling, you do need to tell the compiler what character set the source code uses. In Linux, GCC uses the locale settings, but also provides an option -finput-charset=windows-1252 to change it to Windows Western European, for example.
Rather than fiddle with the flags, I recommend you write a Bash helper script, say to-utf8:
#!/bin/bash
if [ $# -lt 2 ] || [ ":$1" = ":-h" ] || [ ":$1" = ":--help" ]; then
printf '\n'
printf 'Usage: %s [ -h | --help ]\n' "$0"
printf ' %s windows-1252 file.c [ ... ]\n' "$0"
printf '\n'
exit 0
fi
charset="$1"
shift 1
Work=$(mktemp) || exit 1
trap "rm -f '$Work'" EXIT
for src in "$#" ; do
iconv -f "$charset//TRANSLIT" -t UTF-8 "$src" > "$Work" || exit $?
sed -e 's|\r$||' "$Work" > "$src" || exit $?
printf '%s: Converted successfully.\n' "$src"
done
exit 0
If you want, you can install that system-wide using
sudo install -o 0 -g 0 -m 0755 to-utf8 /usr/bin/
The first command-line parameter is the source character set (use iconv --list to see them all), followed by a list of files to fix.
The script creates an automatically deleted temporary file. The iconv line converts the character set of each file to UTF-8, saving the result into the temporary file. The sed file changes any CRLF (\r\n) newlines to LF (\n), overwriting the contents of the file.
(Rather than use a second temporary file to hold the contents, having sed to direct its output to the original file, means the original file keeps its owner and group intact.)
I am currently working on a cat program. The problem I am having is that whenever I execute the unix command:
./catpr file1 file2 file3 | grep string
I don't know how to mark the end of the parsing by pointing out there exists a pipe operator. I am currently developing this cat program in C by using system calls, so I use argv to keep track of the arguments; however, whenever I look at the content in the array that corresponds to '|', something really weird shows up.
So what you basically need is you need to search a pattern in three files.
Since you have specified that you are using system calls to perform what you can do is give the string as input argument to program. Just do the following for compiling
./catpr file1 file2 file3 string
Just inside the program give the system call with grep. I am providing the complete program for you. I hope this is what you need.
#include <stdio.h>
#include <string.h>
int main(int a,char *argv[])
{
char com[256]="";
strcat(com,"cat ");
strcat(com,argv[1]);
strcat(com," ");
strcat(com,argv[2]);
strcat(com," ");
strcat(com,argv[3]);
strcat(com," | grep ");
strcat(com,argv[4]); //this is your search pattern
system(com);
}
I´m trying to execute the next linux command
cat file_a file_b file_c | wc –l > result.txt
in a C program, but I´m not able to do it properly. I have very low level of C programming, and I would like to see how to make that command works in a C program.
This is the code I developed without success:
void main() {
execlp("/bin/sh", "/bin/sh", "-c", "cat file1 file2 fileN | wc –l > lines.txt", 0);
}
I follow your example.
Its results:
implicit declaration of function 'execlp' is invalid in C99
And some other warning errors.
But I think it would be better if you use the system() C-function, here is what I've done:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
system("cat filea fileb filec | wc -l > result.txt");
return EXIT_SUCCESS;
}
After compilation that works!
If you want to run just a command without needing to read the resulting output, you could use the C-function system(), but if you want to run it getting its results, you should use popen().
system()
popen()
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.