I have the following code written in C:
#include <windows.h>
#include <stdio.h>
WCHAR* test(){
WCHAR var[256];
int nSize = GetEnvironmentVariableW(L"SystemRoot", NULL, 0);
GetEnvironmentVariableW(L"SystemRoot", &var, nSize);
wprintf(L"%s\n", var);
return var;
}
int main() {
WCHAR* var = test();
wprintf(L"%s\n", var);
return 0;
}
When I compile it in Visual Studio and run it it works as expected. It prints result two times - in main func and in test. Output is:
C:\Windows
C:\Windows
But when I compile it on linux with mingw compiler via command
i686-w64-mingw32-gcc -o test.exe -O3 -Os -static -s test.c
it gives this output after starting:
C:\Windows
(null)
Why do the test() func return NULL when I'm using mingw and what to do to make it work properly?
Thanks.
You cannot return the address of a local variable, you get a compiler warning (which is actually more of an error).
You want this:
#include <windows.h>
#include <stdio.h>
WCHAR* test(WCHAR var[], int nSize) {
GetEnvironmentVariableW(L"SystemRoot", var, nSize);
wprintf(L"%s\n", var);
return var;
}
int main() {
// declare var outside the test function
WCHAR var[256];
// pass the address of var to test
test(var, 256);
wprintf(L"%s\n", var);
return 0;
}
But be aware that 256 (like in var[256]) may not be enough. I leave it as an exercise to you to resolve this issue properly.
Related
I have a binary file (ELF) that I don't write, but I want to use 1 function from this binary (I know the address/offset of the function), that function not exported from the binary.
My goal is to call this function from my C code that I write and compile this function statically in my binary (I compile with gcc).
How can I do that please?
I am going to answer the
call to this function from my c code that I write
part.
The below works under certain assumptions, like dynamic linking and position independent code. I haven't thought for too long about what happens if they are broken (let's experiment/discuss, if there's interest).
$ cat lib.c
int data = 42;
static int foo () { return data; }
gcc -fpic -shared lib.c -o lib.so
$ nm lib.so | grep foo
00000000000010e9 t foo
The above reproduces having the address that you know. The address we know now is 0x10e9. It is the virtual address of foo before relocation. We'll model the relocation the dynamic loader does by hand by simply adding the base address at which lib.so gets loaded.
$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>
#define FOO_VADDR 0x10e9
typedef int(*func_t)();
int callback(struct dl_phdr_info *info, size_t size, void *data)
{
if (!(strstr(info->dlpi_name, "lib.so")))
return 0;
Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
func_t f = (func_t)addr;
int res = f();
printf("res = %d\n", res);
return 0;
}
int main()
{
void *handle = dlopen("./lib.so", RTLD_LAZY);
if (!handle) {
puts("failed to load");
return 1;
}
dl_iterate_phdr(&callback, NULL);
dlclose(handle);
return 0;
}
And now...
$ gcc 1.c -ldl && ./a.out
res = 42
Voila -- it worked! That was fun.
Credit: this was helpful.
If you have questions, feel free to read the man and ask in the comments.
As for
compile this function statically in my binary
I don't know off the bat. This would be trickier. Why do you want that? Also, do you know whether the function depends on some data (or maybe it calls other functions) in the original ELF file, like in the example above?
i wrote this code for call function from there address:
$ cat main.c
#include <stdlib.h>
#include <stdio.h>
int test(){
printf("%s\n","[*] i'm in test");
return 1;
}
int main(int argc,char **argv){
int (*m)();
m=&test;
printf("[*] test func addr is: %p\n", m);
(*m)();
return 0;
}
$ gcc -o main main.c
$ ./main
[*] test func addr is: 0x8048414
[*] i'm in test
$
no problem
but i want run function, and pass there address from argv in commandline..
for example if address of function test() is 0x222222, i want after run program with this command ./main 222222, test() function run ..
my code is:
$ cat main.c
#include <stdlib.h>
#include <stdio.h>
int test(){
printf("%s\n","[*] i'm in test");
return 1;
}
int main(int argc,char **argv){
int (*m)();
long conv ;
int num;
num=conv=strtol(argv[1],NULL,10);
printf("[*] argv[1] is: %d\n", num);
m=&test;
printf("[*] test func addr is: %p\n", m);
m=num;
(*m)();
return 0;
}
$ gcc -o main main.c
main.c: In function ‘main’:
main.c:17:3: warning: assignment makes pointer from integer without a cast [enabled by default]
$ ./main 8048444
[*] argv[1] is: 8048444
[*] test func addr is: 0x8048444
Segmentation fault (core dumped)
$
but no run!
However, it is true that instead of 10 you should use 16 because addresses are always in hexadecimal format but your code will still run fine even if the argument is 10. Your code is producing segmentation fault because of this assignment: m=num. This assigns an arbitrary value to m instead of address of test and on calling (*m)() a segmentation fault is produced as m is pointing to an invalid location. You should change the last two lines as:
num=m;
(*num)();
This would run the test function properly.
Memory addresses are in base 16 not base 10
try changing strtol(argv[1],NULL,10); to strtol(argv[1],NULL,16);
I am trying to use two .c files together. I am lost at how to do this, I have a simple setup for each file but I get a undefined reference to format_lines error when I try to compile. Any help would be muchly appreciated;
formatter.h
#ifndef _FORMATTER_H_
#define _FORMATTER_H_
#include <stdio.h>
char **format_file(FILE *);
char **format_lines(char **, int);
void test();
#endif
formatter.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "formatter.h"
char **format_file(FILE *infile) {
return NULL;
}
char **format_lines(char **lines, int num_lines) {
char **result = NULL;
#ifdef DEBUG
result = (char **)malloc(sizeof(char *) * 2);
if (result == NULL) {
return NULL;
}
result[0] = (char *)malloc(sizeof(char) * 80);
if (result[0] == NULL) {
return NULL;
}
strncpy(result[0], "(machine-like voice) EXTERMINATE THEM!", 79);
result[1] = (char *)malloc(sizeof(char) * 2);
if (result[1] == NULL) {
return NULL;
}
result[1][0] = '\0';
#endif
}
void test(){
print("here");
}
and sengfmt.c
#include <stdio.h>
#include <stdlib.h>
#include "formatter.h"
int main(int argc, char *argv[]) {
test();
#ifdef DEBUG
printf("%s does nothing right now.\n", argv[0]);
#endif
exit(0);
}
When I try to compile, I just type this.
$ gcc sengfmt3.c
/tmp/cc7Ttgne.o: In function `main':
sengfmt3.c:(.text+0x15): undefined reference to `test'
collect2: ld returned 1 exit status
I suspect that your main used to try to call format_lines
You need to do this
gcc formatter.c sendgfmt.c -o myprog
You must list all the c files that you want compiled together
If you have code in multiple source files, then you need to build with all the source files.
There are two ways of doing this:
Compile and link all source files using using one command:
$ gcc sengfmt3.c someOtherSourceFile.c someThirdSourceFile.c
First make object files of all source files, and then link the object files together. This is more work, but if you have a makefile or other build-system it will be better since only the modified source files will be recompiled, and might save you some build-time:
$ gcc -c sengfmt3.c
$ gcc -c someOtherSourceFile.c
$ gcc -c someThirdSourceFile.c
$ gcc sengfmt.o someOtherSourceFile.o someThirdSorceFile.o
Note the command-line option -c for the compilation, this tells GCC to generate object files. Also note that for the linking command (the last one) the file extensions have changed from .c to .o.
The command in point 1 does this internally, using temporary files which are removed when done.
I'm stuck with a weird problem.
I have two files a.c and b.c as follows:
b.c:
#include <stdlib.h>
int *foo() {
int *x;
x = (int *) malloc(sizeof(int));
*x = 4;
return x;
}
I compile b.c to b.so using gcc:
$ gcc -o b.so -shared -fpic
a.c:
#include <stdio.h>
#include <dlfcn.h>
int main() {
void *hdl;
hdl = dlopen("./b.so", RTLD_LAZY);
int *((*fn)(void));
int *x;
x = (*fn)();
fn = dlsym(hdl, "foo");
printf("%d", *x);
}
I compile a.c using gcc:
$ gcc -fpic -ldl a.c
Now when I run it:
$ ./a.out
Segmentation fault
Where I'm I going wrong?
This works when the function in b.c doesn't return a pointer.
And moreover, I tried checking for errors using dlerror(), but it reports none.
By inspection, you are using fn before you have initialized it. It doesn't yet point to foo, it doesn't yet point to anything in particular, and I suspect the resultant behavior is undefined.
You are not finding the symbol and calling the function.
When you do x = (*fn)(); it doesnt make call to the function foo from b.c.
You have to first get the symbol loaded into your function pointer.
int *x;
fn = dlsym(hdl, "foo");
x = fn();
printf("%d", *x);
The above should work.
EDIT:
Sample program for dlopen,dlsym can be found here with man page info for the same.
Could be just a problem with your example, but in the code you provide, you need to switch the following lines:
x = (*fn)();
fn = dlsym(hdl, "foo");
These two lines appear to be in the wrong order:
x = (*fn)();
fn = dlsym(hdl, "foo");
I have a function in which one of the function arguments is an integer. During function invocation I am passing an enumerated datatype to this function. After building using gcc, any access to the INTEGER variable inside the function causes a segmentation fault.
Sample code:
void somefun (unsigned int nState)
{
switch (nState) // <-- Crashes on this line
{
//
// functionality here ...
//
}
}
enum {
UNDEFINED = -1,
STATE_NICE,
STATE_GREEDY
} E_STATE;
int main (int argc, char *argv [])
{
somefun (STATE_NICE);
}
First off, The enum is defined in main() and does not exist for somefun(). You should define the enum outside of main, although I cannot see how this is causing a crash.
After defining the enum outside of the main you should define somefun to be somefun( E_STATE nState ) and test again.
I compiled and ran that code exactly (cut & paste) on my computer, using gcc version 4.2.4, with no errors or segmentation fault. I believe the problem might be somewhere else.
Actually runs for me:
bash $ cat bar.c
#include <stdio.h>
void somefun (unsigned int nState)
{
switch (nState) // <-- Crashes on this line
{
//
// functionality here ...
//
default:
printf("Hello?\n");
}
}
int main (int argc, char *argv [])
{
enum {
UNDEFINED = -1,
STATE_NICE,
STATE_GREEDY
} E_STATE;
somefun (STATE_NICE);
return 0;
}
bash $ gcc -Wall bar.c -o bar
bar.c: In function 'main':
bar.c:22: warning: unused variable 'E_STATE'
bash $ ./bar
Hello?
bash $
Made a couple of changes, but it ran without them. (1) added a tag in the switch just so it had something; (2) added the #include <stdio.h> and printf so I could tell that it had run; (3) added the return 0; to eliminate an uninteresting warning.
It did run successfully with none of the changes, it just didn't do anything visible.
So, what's the OS, what's the hardware architecture?
Update
The code changed while I was trying it, so here's a test of the updated version:
bash $ cat bar-prime.c
#include <stdio.h>
void somefun (unsigned int nState)
{
switch (nState) // <-- Crashes on this line
{
//
// functionality here ...
//
default:
printf("Hello?\n");
}
}
enum {
UNDEFINED = -1,
STATE_NICE,
STATE_GREEDY
} E_STATE;
int main (int argc, char *argv [])
{
somefun (STATE_NICE);
return 0;
}
bash $ gcc -Wall bar-prime.c -o bar-prime && ./bar-prime
Hello?
bash $
Still works. Are you getting a core file in your version? Have you tried getting a stack trace?
Your situation is like specific to sun sparc hardware or similar. Please post uname -a and output of dmesg
From all your answers it seems that the code is logically correct, and I need to investigate the real reason for the crash. I will investigate it and post it soon.