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);
Related
I tried to mimic the way jemalloc replaces ptmalloc by replacing malloc myself, and the replacement resulted in a direct segment error
code1.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
void *ptr = malloc(10);
printf("%p\n", ptr);
return EXIT_SUCCESS;
}
code2.c:
#include <stdlib.h>
#include <stdint.h>
void *malloc(size_t size)
{
return (void *)10;
}
Compile instructions
gcc -c code2.c
ar r libcode2.a code2.o
gcc code1.c -L. -lcode2 -g
gdb
Breakpoint 1, main (argc=1, argv=0x7fffffffe318) at code1.c
17 void *ptr = malloc(10);
(gdb) s
18 printf("%p\n", ptr);
(gdb) p ptr
$1 = (void *) 0xa
(gdb) n
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e46658 in __GI__IO_file_overflow () from /lib64/libc.so.6
the replacement resulted in a direct segment error code1.c
If you replace malloc with a non-functional variant, you better not call any libc functions which may use malloc in their implementation.
Here you called printf, which itself uses malloc internally. Use GDB where command to observe where the crash happened.
I am actually surprised your program made it as far as reaching main() -- I expected it to crash much earlier (there are 1000s of instruction executed long before main is reached).
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.
Consider the following code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("main\n");
int a;
scanf("%d", &a);
printf("a = %d\n", a);
return 0;
}
int main1() {
printf("main1\n");
int a;
scanf("%d", &a);
printf("a = %d\n", a);
exit(0);
return 0;
}
int main2() {
printf("main2\n");
int a = getchar() - '0';
int b = getchar() - '0';
int c = getchar() - '0';
printf("a = %d\n", 100 * a + 10 * b + c);
exit(0);
return 0;
}
Assuming that the code resides in a file called test.c, the following works fine (it prints "a = 123"):
gcc -o test test.c
echo 123 | ./test
If, however, I run the program with a custom entry point, I get the dreaded Segmentation fault:
gcc -o test test.c -e"main1"
echo 123 | ./test
But if I replace the scanf with three getchars, the program runs fine again despite being run with a custom entry point:
gcc -o test test.c -e"main2"
echo 123 | ./test
To make things even more interesting, these problems occur with gcc 7.4.0 but not with gcc 4.8.4.
Any ideas?
The -e command line flag redefines the actual entry point of your program, not the “user” entry point. By default, using GCC with the GNU C standard library (glibc) this entry point is called _start, and it performs further setup before invoking the user-provided main function.
If you want to replace this entry point and continue using glibc you’ll need to perform further setup yourself. But alternatively you can use the following method to replace the main entry point, which is much simpler:
gcc -c test.c
objcopy --redefine-sym main1=main test.o
gcc -o test test.o
Note, this will only work if you don’t define main in your code, otherwise you’ll get a “multiple definition of `main'” error from the linker.
I have an array foo declared in a C file, which is then declared as extern in the corresponding header. I then access foo from another file, but the address of the first element in the array is an invalid address, and differs from that in the compilation unit where foo is defined. This has been built from the Pebble SDK, using ARM CodeSourcery compilers.
Example code:
test1.h
extern int foo[];
void testRoutine();
test1.c
#include <pebble.h>
#include "test1.h"
void testRoutine()
{
APP_LOG(APP_LOG_LEVEL_INFO, "Hello World! foo: 0x%x", (unsigned int)&foo[0]);
}
int foo[] = {1,2,3,4,5,6};
main.c
#include <pebble.h>
#include "test1.h"
int main()
{
APP_LOG(APP_LOG_LEVEL_INFO, "Start of test");
testRoutine(); // Print the address of foo from the perspective of test1.c
APP_LOG(APP_LOG_LEVEL_INFO, "foo: 0x%x", (unsigned int)&foo[0]);
return 0;
}
Expected output:
Start of test
Hello World! foo: 0x12345678
foo: 0x12345678
Actual output:
Start of test
Hello World! foo: 0x20081234
foo: 0x21941234 (placeholders, I can't get the real addresses right now)
This code works as expected in standard x86 GCC, but does not work on the ARM compiler. Have I messed up the code, or is there a compiler bug here?
I tried to reproduce your problem without success on Debian 64 bits:
Main.c:
#include <stdio.h>
#include "test1.h"
int main()
{
testRoutine(); // Print the address of foo from the perspective of test1.c
printf("foo: 0x%x\n", (unsigned int)&foo[0]);
return 0;
}
test1.h:
extern int foo[];
void testRoutine();
test1.c:
#include <stdio.h>
#include "test1.h"
void testRoutine()
{
printf("Hello World! foo: 0x%x\n", (unsigned int)&foo[0]);
}
int foo[] = {1,2,3,4,5,6};
The result is:
$ ./program
Hello World! foo: 0x600970
foo: 0x600970
However gcc warnings are explicit:
test1.c:7:38: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
You should try with:
APP_LOG(APP_LOG_LEVEL_INFO, "foo: 0x%p", &foo[0]);
Edit:
Since you said you are running it on a 32 bits platform where sizeof(unsigned int)==sizeof(int *), the cast is not the problem. There is some other problem in your program unrelated to this code (stack corruption?).
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");