strndup call is currupting stack frames - c

I have seen a strange behavior with "strndup" call on AIX 5.3 and 6.1.
If I call strndup with size more than the size of actual source string length, then there is a stack corruption after that call.
Following is the sample code where this issue can come:
int main ()
{
char *dst_str = NULL;
char src_str[1023] = "sample string";
dst_str = strndup(src_str, sizeof(src_str));
free(dst_str);
return 0;
}
Does anybody have experienced this behavior?
If yes please let me know.
As per my observation, there must be a patch from OS where this issue got fixed. but i could not get that patch if at all there is any. Please throw some light.
Thanks & Regards,
Thumbeti

You are missing a #include <string.h> in your code. Please try that—I am fairly sure it will work. The reason is that without the #include <string.h>, there is no prototype for strndup() in scope, so the compiler assumes that strndup() returns an int, and takes an unspecified number of parameters. That is obviously wrong. (I am assuming you're compiling in POSIX compliant mode, so strndup() is available to you.)
For this reason, it is always useful to compile code with warnings enabled.
If your problem persists even after the change, there might be a bug.
Edit: Looks like there might be a problem with strndup() on AIX: the problem seems to be in a broken strnlen() function on AIX. If, even after #include <string.h> you see the problem, it is likely you're seeing the bug. A google search shows a long list of results about it.
Edit 2:
Can you please try the following program and post the results?
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *test1 = "abcdefghijabcdefghijabcdefghijk";
char *test2 = "012345678901234567890123456789";
char *control = "01234567890123456789012345678";
char *verify;
free(strndup(test1, 30));
verify = strndup(test2, 29); /* shorter then first strndup !!! */
fprintf(stderr,">%s<\n",verify);
if (strcmp(control, verify))
printf("strndup is broken\n");
}
(Taken from https://bugzilla.samba.org/show_bug.cgi?id=1097#c10.)
Edit 3: After seeing your output, which is >01234567890123456789012345678<, and with no strndup is broken, I don't think your version of AIX has the strndup bug.
Most likely you are corrupting memory somewhere (given the fact that the problem only appears in a large program, under certain conditions). Can you make a small, complete, compilable example that exhibits the stack corruption problem? Otherwise, you will have to debug your memory allocation/deallocation in your program. There are many programs to help you do that, such as valgrind, glibc mcheck, dmalloc, electricfence, etc.

Old topic, but I have experienced this issue as well. A simple test program on AIX 6.1, in conjunction with AIX's MALLOCDEBUG confirms the issue.
#include <string.h>
int main(void)
{
char test[32] = "1234";
char *newbuf = NULL;
newbuf = strndup(test, sizeof(test)-1);
}
Compile and run the program with buffer overflow detection:
~$ gcc -g test_strndup2.c
~$ MALLOCDEBUG=catch_overflow ./a.out
Segmentation fault (core dumped)
Now run dbx to analyze the core:
~$ dbx ./a.out /var/Corefiles/core.6225952.22190412
Type 'help' for help.
[using memory image in /var/Corefiles/core.6225952.22190412]
reading symbolic information ...
Segmentation fault in strncpy at 0xd0139efc
0xd0139efc (strncpy+0xdc) 9cc50001 stbu r6,0x1(r5)
(dbx) where
strncpy() at 0xd0139efc
strndup#AF5_3(??, ??) at 0xd03f3f34
main(), line 8 in "test_strndup2.c"
Tracing through the instructions in strndup, it appears that it mallocs a buffer that is just large enough to handle the string in s plus a NULL terminator. However, it will always copy n characters to the new buffer, padding with zeros if necessary, causing a buffer overflow if strlen(s) < n.
char* strndup(const char*s, size_t n)
{
char* newbuf = (char*)malloc(strnlen(s, n) + 1);
strncpy(newbuf, s, n-1);
return newbuf;
}

Alok is right. and with the gcc toolchain under glibc, you would need to define _GNU_SOURCE to get the decl of strndup, otherwise it's not decl'd, e.g.:
#include <string.h>
...
compilo:
gcc -D_GNU_SOURCE a.c

Thanks a lot for your prompt responses.
I have tried the given program.
following is the result:
bash-2.05b# ./mystrndup3
>01234567890123456789012345678<
In my program I have included , still problem is persistent.
Following is the strndup declaration in prepossessed code.
extern char * strndup(const char *, size_t);
I would like to clarify one thing, with small program I don't get effect of stack corruption. It is consistently appearing in my product which has huge amount of function calls.
Using strndup in the following way solved the problem:
dst_str = strndup(src_str, srtlen(src_str));
Please note: used strlen instead of sizeof as i need only the valid string.
I am trying to understand why it is happening.
Behavior i am seeing with my product when i use strndup with large size:
At the "exit" of main, execution is coring with "illegal instruction"
intermittently "Illegal Instruction" in the middle of execution (after strndup call).
Corrupt of some allocated memory, which is no where related to strndup.
All these issues are resolved by just modifying the usage of strndup with actual size of source string.
Thanks & Regards,
Thumbeti

Related

using c11 standard with clang for use of strcpy_s

I'm running OS X Sierra and trying to compile a c program that uses strcpy_s, but my installed clang compiler is using the c99 standard, but from what I've read strcpy_s requires c11.
Here's the code I'm trying to compile
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
if(strcpy_s(destination, sizeof(destination), source))
printf("string copied - %s",destination);
return 0;
}
And here's the command I'm using to compile
$ clang copytest.c -o copytest
copytest.c:11:5: warning: implicit declaration of function 'strcpy_s' is invalid in C99 [-Wimplicit-function-declaration]
if(strcpy_s(copied_string, sizeof(copied_string), source))
^
1 warning generated.
Undefined symbols for architecture x86_64:
"_strcpy_s", referenced from:
_main in copytest-e1e05a.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried compiling with the standard flag...
clang -std=c11 copytest.c -o copytest
but I get the same exact "invalid in c99" warning. I've also tried compiling with gcc instead, and I still get the same c99 warning.
I tried upgrading via homebrew which shows the following
Warning: gcc 9.2.0 is already installed and up-to-date
I have clang version 9.0.0
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
My xcode version is Xcode 9.2, which from everything I've read should come with c11 support.
Am I doing something wrong with the compiling, is my code itself incorrect? This is the only similar question I found on here, but it didn't even have an answer. Thanks
The _s functions are an optional component of the 2011 C standard (Annex K), and, to the best of my knowledge, they have never been implemented as an integrated part of any C library. Portable code cannot rely on their availability. (Microsoft's C compilers for Windows implement an overlapping set of functions with the same names but different semantics (and sometimes even a different argument list), and at least one bolt-on implementation does exist. See this old answer, and the much longer question and answer it links to, for more detail.)
Also, the _s functions do not solve the problem that they were intended to solve (unsafe string handling); it is necessary to put actual thought into a proper fix for each use of strcpy, instead of globally search-and-replacing strcpy with strcpy_s, etc., as was the hope of the authors of Annex K. If you do put appropriate amounts of thought into a proper fix, you won't need any of the _s functions to implement it. For instance, here's a fixed version of your example program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char source[] = "Test string";
char destination[50];
size_t srclen = strlen(source);
if (srclen + 1 > sizeof destination) {
fprintf(stderr, "string too long to copy - %zu bytes, need %zu\n",
sizeof destination, srclen + 1);
return 1;
} else {
memcpy(destination, source, srclen + 1);
printf("string copied - %s\n", destination);
return 0;
}
}
And here's an even better version:
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: ./test 'message of arbitrary length'\n");
return 1;
}
char *destination = strdup(argv[1]);
if (!destination) {
perror("strdup");
return 1;
}
printf("string copied - '%s'\n", destination);
free(destination);
return 0;
}
Therefore: Never use any of the _s functions. If you need to write a program that compiles on Windows with no warnings, put #define _CRT_SECURE_NO_WARNINGS 1 at the top of each file to make MSVC stop giving you bad advice.
If all, or even most, programmers wrote the suggested solutions above all the time, then these functions wouldn't be needed. We have a lot of evidence that many programmers do not write such careful code, going back to Spaf's notes on the Robert T Morris finger worm in the late 1980's.
You also would prefer not to have to duplicate 10 lines of code for every call site of strcpy. That leads to unreadable code. More so, what zwol suggests is really just an implementation of the function he claims we don't need. A good programmer would take that, stick it in a header, and name it something helpful, maybe checked_strcpy? Or even strcpy_s?
The second suggested implementation, which is purportedly better is not - it would cause an allocation when we might already have a buffer. Allocations are expensive, using this approach everywhere would be bad for perf. It also introduces new complexity because now we'd have to free every duplicated string - imagine doing that with repeated calls to strcat.
There is a fairly nicely done cross-platform implementation here:
https://github.com/intel/safestringlib
I'm also not sure whether this is actually any different, but worth taking a look - https://github.com/coruus/safeclib

Why the buffer isn't overflowing with this code?

This is the C code that I am compiling:
#include <stdio.h>
#include <stdlib.h>
int main(){
long val=0x41414141;
char buf[20];
printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
printf("Here is your chance: ");
scanf("%24s",&buf);
printf("buf: %s\n",buf);
printf("val: 0x%08x\n",val);
if(val==0xdeadbeef)
system("/bin/sh");
else {
printf("WAY OFF!!!!\n");
exit(1);
}
return 0;
}
Here, I am expecting an overflow in long val if user inputs string 24 character long, changing the value in val. But it just doesn't get overflowed even if string is long enough. Can someone please explain this behaviour?
I am on macOS. This is what gcc -v spits out:
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.0.0 (clang-800.0.42.1)
Target: x86_64-apple-darwin16.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Also, after googling a bit I tried gcc with these flags:
gcc -g -fno-stack-protector -D_FORTIFY_SOURCE=0 -o overflow_example overflow_example.c
still, the result is same.
This code is part of narnia wargame challenge on overthewire. I managed to crack this challenge on their remote shell, where it was behaving as expected. Now, I am trying to reproduce this same challenge on my local system and facing this issue. Please help.
EDIT: For all the people yelling out about UB: like I said, this was one of the challenge to be solved on overthewire, so it cannot have UB. There are some blogs (here's on I found) that provide walkthrough for this challenge with reasonable logical explanation for why the code behaves the way it does, with which I agree. I also understand that the compiled binary is platform dependent. So, what am I to do to produce this binary with potential overflow on my local system?
It's undefined behavior because C functions do not check whether an argument is too big for its buffer or not.
Apparantly the variables get laid out differently on the stack on your mac.
Wrapping them in a struct will ensure that they are placed in the order you want.
Since there is the possibility of padding, let's turn it off. For gcc, the precompiler directe #pragma pack controls struct packing.
int main(){
#pragma pack(1)
struct {
char buf[20];
long val=0x41414141;
} s;
#pragma pack()
printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
printf("Here is your chance: ");
scanf("%24s",&s.buf);
printf("buf: %s\n",s.buf);
printf("val: 0x%08x\n",s.val);
if(s.val==0xdeadbeef)
system("/bin/sh");
else {
printf("WAY OFF!!!!\n");
exit(1);
}
return 0;
}
I'm not sure what you mean.
1) Are you concerned that your input string will create a number that will be too big to store in a long. This will not happen the number will simply wrap round.
2) Are you concerned that you'll read to memory beyond the bounds of buf? In C this will produce undefined behavior not necessarily a crash.
buf is on the stack (could be just as well on the heap) so you can just keep writing to memory from the address where buf starts. The compiler will generate code that will not do a bounds check for you. So if you go beyond the 20byte you'll eventually start overwriting other parts of memory that do not belong block of memory you've set aside for buf.

How can I make atoi work in my ADS project?

I want to use atoi function in my program, but I found it not working.
#include <ctype.h>
int value;
value=atoi(buf);
char buf points to "1000" or something like, terminated by \0. I have checked it.
But the value evaluates always to zero. I have tried strtol(), but I get the same error.
My ADS (ARM Developer Suit) is v1.2 (s3c2440). I can find the libs in armlib path (c_t_xx.l).
I use axd debug mode, so I can trace my code. I found "bl
__rt_ctype_table", so I think asm code linked right.
Please give any advice to fix this issue.
ARM might have a problem with string functions, you haven't mentioned whether it returns a value and it's incorrect (i heard it's a bug and it's better you should write the function on your own) or there is no value at all.
anyway look at the arm article about it i think it's the solution - ARM article about string functions
The following code should work,
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
char buff[5] = "1000\0";
i=atoi(buff);
printf("i=%d\n", i);
return 0;
}
#./a.out
#i=1000

Simple bufferoverflow using scanf (Mac OS X 10.6.5 64-Bit)

For educational purposes I'm trying to accomplish a bufferoverflow that directs the program to a different adress.
This is the c-program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void secret1(void) {
puts("You found the secret function No. 1!\n");
}
int main () {
char string[2];
puts("Input: ");
scanf("%s", string);
printf("You entered %s.\n", string);
return 0;
}
I used gdb to find the address of secret1 as well es the offset the my variable string to the RIP. Using this information I created the following python-exploit:
import struct
rip = 0x0000000100000e40
print("A"*24 + struct.pack("<q", rip))
So far everything works - the program jumps to secret1 and then crashes with "Segmentation fault".
HOWEVER, if I extend my program like this:
...
void secret1(void) {
puts("You found the secret function No. 1!\n");
}
void secret2(void) {
puts("You found the secret function No. 2!\n");
}
void secret3(void) {
puts("You found the secret function No. 3!\n");
}
...
...it SegFaults WITHOUT jumping to any of the functions, even tho the new fake RIPs are correct (i.e. 0x0000000100000d6c for secret1, 0x0000000100000d7e for secret2). The offsets stay the same as far as gdb told me (or don't they?).
I noticed that none of my attempts work when the program is "big enough" to place the secret-functions in the memory-area ending with 0x100000 d .. - it works like a charm tho, when they are somewhere in 0x100000 e ..
It also works with more than one secret function when I compile it in 32-Bit-mode (addresses changed accordingly) but not in 64-Bit-mode.
-fno-stack-protector // doesn't make any difference.
Can anybody please explain this odd behaviour to me? Thank you soooo much!
Perhaps creating multiple hidden functions puts them all in a page of memory without execute permission... try explicitly giving RWX permission to that page using mprotect. Could be a number of other things, but this is the first issue I would address.
As for the -fno-stack-protector gcc option, I was convinced for a while this was obfuscated on gcc 4.2.1. But after playing with it a bit more, I have learned that in order for canary stack protection to be enabled, sizeof(buffer) >= 8 must be true. Additionally, it must be a char buffer, unless you specify the -fstack-protector-all or -fnostack-protector-all options, which enable canaries even for functions that don't contain char buffers. I'm running OS X 10.6.5 64-bit with aforementioned gcc version and on a buffer overflow exploit snippet I'm writing, my stack changes when compiling with -fstack-protector-all versus compiling with no relevant options (probably because the function being exploited doesn't have a char buffer). So if you want to be certain that this feature is either disabled or enabled, make sure to use the -all variants of the options.

Executing machine code in memory

I'm trying to figure out how to execute machine code stored in memory.
I have the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
FILE* f = fopen(argv[1], "rb");
fseek(f, 0, SEEK_END);
unsigned int len = ftell(f);
fseek(f, 0, SEEK_SET);
char* bin = (char*)malloc(len);
fread(bin, 1, len, f);
fclose(f);
return ((int (*)(int, char *)) bin)(argc-1, argv[1]);
}
The code above compiles fine in GCC, but when I try and execute the program from the command line like this:
./my_prog /bin/echo hello
The program segfaults. I've figured out the problem is on the last line, as commenting it out stops the segfault.
I don't think I'm doing it quite right, as I'm still getting my head around function pointers.
Is the problem a faulty cast, or something else?
You need a page with write execute permissions. See mmap(2) and mprotect(2) if you are under unix. You shouldn't do it using malloc.
Also, read what the others said, you can only run raw machine code using your loader. If you try to run an ELF header it will probably segfault all the same.
Regarding the content of replies and downmods:
1- OP said he was trying to run machine code, so I replied on that rather than executing an executable file.
2- See why you don't mix malloc and mman functions:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
int main()
{
char *a=malloc(10);
char *b=malloc(10);
char *c=malloc(10);
memset (a,'a',4095);
memset (b,'b',4095);
memset (c,'c',4095);
puts (a);
memset (c,0xc3,10); /* return */
/* c is not alligned to page boundary so this is NOOP.
Many implementations include a header to malloc'ed data so it's always NOOP. */
mprotect(c,10,PROT_READ|PROT_EXEC);
b[0]='H'; /* oops it is still writeable. If you provided an alligned
address it would segfault */
char *d=mmap(0,4096,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_PRIVATE|MAP_ANON,-1,0);
memset (d,0xc3,4096);
((void(*)(void))d)();
((void(*)(void))c)(); /* oops it isn't executable */
return 0;
}
It displays exactly this behavior on Linux x86_64 other ugly behavior sure to arise on other implementations.
Using malloc works fine.
OK this is my final answer, please note I used the orignal poster's code.
I'm loading from disk, the compiled version of this code to a heap allocated area "bin", just as the orignal code did (the name is fixed not using argv, and the value 0x674 is from;
objdump -F -D foo|grep -i hoho
08048674 <hohoho> (File Offset: 0x674):
This can be looked up at run time with the BFD (Binary File Descriptor library) or something else, you can call other binaries (not just yourself) so long as they are statically linked to the same set of lib's.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
unsigned char *charp;
unsigned char *bin;
void hohoho()
{
printf("merry mas\n");
fflush(stdout);
}
int main(int argc, char **argv)
{
int what;
charp = malloc(10101);
memset(charp, 0xc3, 10101);
mprotect(charp, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
__asm__("leal charp, %eax");
__asm__("call (%eax)" );
printf("am I alive?\n");
char *more = strdup("more heap operations");
printf("%s\n", more);
FILE* f = fopen("foo", "rb");
fseek(f, 0, SEEK_END);
unsigned int len = ftell(f);
fseek(f, 0, SEEK_SET);
bin = (char*)malloc(len);
printf("read in %d\n", fread(bin, 1, len, f));
printf("%p\n", bin);
fclose(f);
mprotect(&bin, 10101, PROT_EXEC | PROT_READ | PROT_WRITE);
asm volatile ("movl %0, %%eax"::"g"(bin));
__asm__("addl $0x674, %eax");
__asm__("call %eax" );
fflush(stdout);
return 0;
}
running...
co tmp # ./foo
am I alive?
more heap operations
read in 30180
0x804d910
merry mas
You can use UPX to manage the load/modify/exec of a file.
P.S. sorry for the previous broken link :|
It seems to me you're loading an ELF image and then trying to jump straight into the ELF header? http://en.wikipedia.org/wiki/Executable_and_Linkable_Format
If you're trying to execute another binary, why don't you use the process creation functions for whichever platform you're using?
An typical executable file has:
a header
entry code that is called before main(int, char **)
The first means that you can't generally expect byte 0 of the file to be executable; intead, the information in the header describes how to load the rest of the file in memory and where to start executing it.
The second means that when you have found the entry point, you can't expect to treat it like a C function taking arguments (int, char **). It may, perhaps, be usable as a function taking no paramters (and hence requiring nothing to be pushed prior to calling it). But you do need to populate the environment that will in turn be used by the entry code to construct the command line strings passed to main.
Doing this by hand under a given OS would go into some depth which is beyond me; but I'm sure there is a much nicer way of doing what you're trying to do. Are you trying to execute an external file as a on-off operation, or load an external binary and treat its functions as part of your program? Both are catered for by the C libraries in Unix.
It is more likely that that it is the code that is jumped to by the call through function-pointer that is causing the segfault rather than the call itself. There is no way from the code you have posted to determine that that code loaded into bin is valid. Your best bet is to use a debugger, switch to assembler view, break on the return statement and step into the function call to determine that the code you expect to run is indeed running, and that it is valid.
Note also that in order to run at all the code will need to be position independent and fully resolved.
Moreover if your processor/OS enables data execution prevention, then the attempt is probably doomed. It is at best ill-advised in any case, loading code is what the OS is for.
What you are trying to do is something akin to what interpreters do. Except that an interpreter reads a program written in an interpreted language like Python, compiles that code on the fly, puts executable code in memory and then executes it.
You may want to read more about just-in-time compilation too:
Just in time compilation
Java HotSpot JIT runtime
There are libraries available for JIT code generation such as the GNU lightning and libJIT, if you are interested. You'd have to do a lot more than just reading from file and trying to execute code, though. An example usage scenario will be:
Read a program written in a scripting-language (maybe
your own).
Parse and compile the source into an
intermediate language understood by
the JIT library.
Use the JIT library to generate code
for this intermediate
representation, for your target platform's CPU.
Execute the JIT generated code.
And for executing the code you'd have to use techniques such as using mmap() to map the executable code into the process's address space, marking that page executable and jumping to that piece of memory. It's more complicated than this, but its a good start in order to understand what's going on beneath all those interpreters of scripting languages such as Python, Ruby etc.
The online version of the book "Linkers and Loaders" will give you more information about object file formats, what goes on behind the scenes when you execute a program, the roles of the linkers and loaders and so on. It's a very good read.
You can dlopen() a file, look up the symbol "main" and call it with 0, 1, 2 or 3 arguments (all of type char*) via a cast to pointer-to-function-returning-int-taking-0,1,2,or3-char*
Use the operating system for loading and executing programs.
On unix, the exec calls can do this.
Your snippet in the question could be rewritten:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
return execv(argv[1],argv+2);
}
Executable files contain much more than just code. Header, code, data, more data, this stuff is separated and loaded into different areas of memory by the OS and its libraries. You can't load a program file into a single chunk of memory and expect to jump to it's first byte.
If you are trying to execute your own arbitrary code, you need to look into dynamic libraries because that is exactly what they're for.

Resources