I've started reading about buffer overflow and how hackers use it to execute custom code instead of the regular compiled one and now I'm trying to reproduce some basic situations, with a vurnerable function that copy data into a char array with the unsafe strcpy.
The point is that when I change the return address with one of an assembly instrution of a function defined in the program it works fine, while when I inject code directly in bytes it returned SEGMENTATION FAULT.
I'm using the Kali distribution x64 v3.18
I've disabled the address space layout randomization (ASLR):
echo 0 > /proc/sys/kernel/randomize_va_space
And disabled the stack protection code added by the compiler:
gcc -g -fno-stack-protector exbof.c -o exbof
Code:
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv){
char buffer[500] = {0};
strcpy(buffer, argv[1]);
return 0;
}
Usage:
./exbof `perl -e 'print "x90"x216; // nop sled
print CUSTOM_CODE; // my code
print "xff"x(500 - 216 - CODE_LENGTH); // fill empty space
print "xff"xOFFSET // distance between the last byte
// of buffer and the return address
printf("\\x%lx", BUFFER_ADDRESS + int(rand(26)) * 8);'`
Output:
Segmentation Fault
In GDB:
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffxyzt in ?? ()
I've used GDB to debug it and the code write the new address corrrectly in the stack.
I'm using a shellcode exec found online, but I've also tried to inject a piece of code in bytes from my program and when I checked with GDB the assembly code injected turned out to be valid code and exactly the same of the original one.
It seems to me that any address out of the .text memory segment doesn't work.
Suggestions?
Solution:
As suggested by #andars, it's necessary to set up the flag that mark the stack as executable.
So, if you want to try this and start playing with buffer overflows, you have to:
disable the address space layout randomization (ASLR):
echo 0 > /proc/sys/kernel/randomize_va_space
disable the stack protection code added by the compiler:
gcc -g -fno-stack-protector your_program.c -o your_program
set up a flag in the program header to mark the stack as executable:
execstack -s your_program
or you can do it directly at assembly time or at link time:
gcc -g -fno-stack-protector -z execstack your_program.c -o your_program
Related
I've been using WASM via emscripten for a few weeks now and had been making good progress, until this error:
exception thrown: RuntimeError: function signature mismatch,RuntimeError: function signature mismatch
This started happening in code that previously worked and seems to be something to do with WASMs lack of support for 64bit integers in javascript and the offsets used in file management. I've made an isolated case:
#include <iostream>
int main(int argc, char const *argv[])
{
char test[30];
std::cout << __LINE__ << std::endl;
FILE *f = fopen("minimal_call_dispatch.cpp","ra");
std::cout << __LINE__ << std::endl;
fseek(f, 100, SEEK_SET);
std::cout << __LINE__ << std::endl;
fclose(f);
std::cout << __LINE__ << std::endl;
return 0;
}
building with:
call emcc -o ./test.js test_file.cpp -s WASM=1 -s NO_EXIT_RUNTIME=1 -std=c++1z
Which outputs '6\n8\n' before failing on 'fseek' due to the mentioned error.
Somewhere along the line, I suspect that wasm is trying to use headers that communicate with javascript that have 64bit integers instead of 32bit ones but I can't see how that could have happened.
I'm going to try re-installing emscripten but even if that works, I'd like to get a better idea of what's causing this.
As a work around, does anybody know how to get emcc to ignore worries over 64bit integers and silently convert them to 32bit? I'm not looking to address more than 3gigs of ram, after all.
You got the error simply because your code is wrong.
You really don't need to worry about 32bit/64bit stuff. The current WebAssembly spec do not have 64-bit machine and it only have 32-bit addresses (but it supports 64-bit integer i64 internally and calculates 64-bit integers well. It just doesn't have 64-bit addresses.)
This means that the compiler is already knows the target machine is 32-bit and size_t will be 32-bit as will.
In the comments, I asked if you want to open the file or want to create the file. This is important because using "ra" with fopen() will cause segmentation fault when the file doesn't exist because of r flag!
Okay, lets try this in the native environment.
g++ test_file.cpp -o test.out
running ./test.out will prints the following if test_file.cpp doesn't exist:
6
8
[2] 14464 segmentation fault (core dumped) ./test.out
So your code is wrong, but why Emscripten throws the error differently? When you use emcc without debugging flags like -g, it will have the minimized environment that doesn't catch errors like segfault because such smart runtime will increase the binary size which is critical in the web environment. As a result the runtime keeps running ignoring segfualt and it will end up with a random error. So function signature mismatch doesn't mean anything.
You can build it using debugging-related options:
emcc -o ./test.html test_file.cpp -s WASM=1 -std=c++1z \
-g4 -s ASSERTIONS=2 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=1 \
--source-map-base http://your_server_ip:port/
Then opening test.html you will see the correct error now:
exception thrown: RuntimeError: abort(segmentation fault) at Error
Now you won't get the misleading errors like signature mismatch :)
By the way, replace fopen("minimal_call_dispatch.cpp","ra"); with fopen("minimal_call_dispatch.cpp","a"); will fix the error.
With the correct --source-map-base server IP settings, you will have a better debugging experience. For example, you will get the source test_file.cpp in the browser so that you can set breakpoints to the .cpp file.
Have fun with debugging :)
I am trying to set breakpoints in a MIPS32r6 program that computes the Mandelbrot Set in Brainfsck. The program itself is written in C++, compiled with Clang, and I am debugging with LLDB.
The issue that I am having is that when in LLDB, I can set certain breakpoints, mainly on lower line numbers, with no issues. However, after Line #70 in Main.cpp, the breakpoints are coming up as 'unresolved' (even though executing breakpoint list shows them with completely reasonable addresses). That is to say, all breakpoints that I try to set after Line #70 are coming up as unresolved, and all reasonable breakpoints before Line #70 resolve without issue.
I've placed a copy of the binary that I've linked here: http://filebin.ca/2tJzo2LLBJWO/MipsTest.bin
And a copy of Main.cpp here: https://paste.ee/p/WYs8Y
I am building with the following options:
clang -mcompact-branches=always -fasynchronous-unwind-tables -funwind-tables -fexceptions -fcxx-exceptions -mips32r6 -O0 -g -glldb ...
lld --discard-none -znorelro --eh-frame-hdr ...
At this point, I am unsure as to what might be causing this issue.
I'd try doing target modules dump line-table Main.cpp in lldb to see what lldb thinks the line table looks like. Then look at the binary's DWARF line table with something like readelf --debug-dump=decodedline MipsTest.bin (I think that's right - I'm looking at a readelf main page on the web).
Using your sample binary, I get:
(lldb) b s -l 72
Breakpoint 1: where = MipsTest.bin`main + 544 at Main.cpp:72, address = 0x000134a0
So we found an address for the breakpoint. If it is unresolved when you run, that means we weren't able to implement the breakpoint at that address (e.g. for some reason couldn't write the trap into the program memory there.)
Afternoon,everbody.
I have an application 'test' compiled by main.c . A dynamic liabrary 'libtest.so' which is compiled by test.cpp with '-g'. In main.c I invoke the 'libtest.so' with 'dlopen' . And now I want to set a breakpoint in test.cpp ,but the gdb never hit it. I do as follow:
gdb ./test -d /home/lcl/test
break test.cpp:35
run
can anybody give me some tips ,thanks!
You should first verify that dlopen is actually succeeding (it's likely that it's not).
To do so:
set a breakpoint in main.c after dlopen.
confirm that returned handle is not NULL
At that point, GDB should have loaded symbols for libtest.so, and libtest.so should show up in info shared GDB output.
If everything looks good, info break should show an active breakpoint in test.cpp:35 at some address. If that breakpoint is never hit, it's likely that you never actually exercise that line of code.
I've written a large program and I'm having a really hard time tracking down a segmentation fault. I posted a question but I didn't have enough information to go on (see link below - and if you do, note that I spent almost an entire day trying several times to come up with a minimally compilable version of the code that reproduced the error to no avail).
https://stackoverflow.com/questions/16025411/phantom-bug-involving-stdvectors-mpi-c
So now I'm trying my hand at valgrind for the first time. I just installed it (simply "sudo apt-get install valgrind") with no special installation to account for MPI (if there is any). I'm hoping for concrete information including file names and line numbers (I understand it's impossible for valgrind to provide variable names). While I am getting useful information, including
Invalid read of size 4
Conditional jump or move depends on uninitialised value(s)
Uninitialised value was created by a stack allocation
4 bytes in 1 blocks are definitely lost
in addition to this magical thing
Syscall param sched_setaffinity(mask) points to unaddressable byte(s) at 0x433CE77: syscall (syscall.S:31) Address 0x0 is not stack'd, malloc'd or (recently) free'd
I am not getting file names and line numbers. Instead, I get
==15095== by 0x406909A: ??? (in /usr/lib/openmpi/lib/libopen-rte.so.0.0.0)
Here's how I compile my code:
mpic++ -Wall -Wextra -g -O0 -o Hybrid.out (…file names)
Here are two ways I've executed valgrind:
valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log.txt mpirun -np 1 Hybrid.out
and
mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out
The second version based on instructions in
Segmentation faults occur when I run a parallel program with Open MPI
which, if I'm understanding the chosen answer correctly, appears to be contradicted by
openmpi with valgrind (can I compile with MPI in Ubuntu distro?)
I am deliberately running valgrind on one processor because that's the only way my program will execute to completion without the segmentation fault. I have also run it with two processors, and my program seg faulted as expected, but the log I got back from valgrind seemed to contain essentially the same information. I'm hoping that by resolving the issues valgrind reports on one processor, I'll magically solve the issue happening on more than one.
I tried to include "-static" in the program compilation as suggested in
Valgrind not showing line numbers in spite of -g flag (on Ubuntu 11.10/VirtualBox)
but the compilation failed, saying (in addition to several warnings)
dynamic STT_GNU_IFUNC symbol "strcmp" with pointer equality in '…' can not be used when making an executably; recompile with fPIE and relink with -pie
I have not looked into what "fPIE" and "-pie" mean. Also, please note that I am not using a makefile, nor do I currently know how to write one.
A few more notes: My code does not use the commands malloc, calloc, or new. I'm working entirely with std::vector; no C arrays. I do use commands like .resize(), .insert(), .erase(), and .pop_back(). My code also passes vectors to functions by reference and constant reference. As for parallel commands, I only use MPI_Barrier(), MPI_Bcast(), and MPI_Allgatherv().
How do I get valgrind to show the file names and line numbers for the errors it is reporting? Thank you all for your help!
EDIT
I continued working on it and a friend of mine pointed out that the reports without line numbers are all coming from MPI files, which I did not compile from source, and since I did not compile them, I can't use the -g option, and hence, don't see lines. So I tried valgrind again based on this command,
mpirun -np 1 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out
but now for two processors, which is
mpirun -np 2 valgrind --tool=memcheck --leak-check=full --track-origins=yes --log-file=log4.txt -v ./Hybrid.out
The program ran to completion (I did not see the seg fault reported in the command line) but this execution of valgrind did give me line numbers within my files. The line valgrind is pointing to is a line where I call MPI_Bcast(). Is it safe to say that this appeared because the memory problem only manifests itself on multiple processors (since I've run it successfully on np -1)?
It sounds like you are using the wrong tool. If you want to know where a segmentation fault occurs use gdb.
Here's a simple example. This program will segfault at *b=5
// main.c
int
main(int argc, char** argv)
{
int* b = 0;
*b = 5;
return *b;
}
To see what happened using gdb; (the <---- part explains input lines)
svengali ~ % g++ -g -c main.c -o main.o # include debugging symbols in .o file
svengali ~ % g++ main.o -o a.out # executable is linked (no -g here)
svengali ~ % gdb a.out
GNU gdb (GDB) 7.4.1-debian
<SNIP>
Reading symbols from ~/a.out...done.
(gdb) run <--------------------------------------- RUNS THE PROGRAM
Starting program: ~/a.out
Program received signal SIGSEGV, Segmentation fault.
0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
5 *b = 5;
(gdb) bt <--------------------------------------- PRINTS A BACKTRACE
#0 0x00000000004005a3 in main (argc=1, argv=0x7fffffffe2d8) at main.c:5
(gdb) print b <----------------------------------- EXAMINE THE CONTENTS OF 'b'
$2 = (int *) 0x0
(gdb)
I followed this post to print stack trace How to generate a stacktrace when my gcc C++ app crashes . It works well in x86 linux. Can anyone teach me how to make it work on arm-linux?
I am using arm-linux-gcc 4.4.3.
[root#FriendlyARM /]# ./test1
Error: signal 11:
[0x0]
in x86
mickey#mickeyvm:~/Desktop/workspace/test/testCatchSeg/src$ ./test1
Error: signal 11:
./test1(_Z7handleri+0x19)[0x804876d]
[0xedd400]
./test1(_Z3bazv+0x10)[0x80487c2]
./test1(_Z3barv+0xb)[0x80487e1]
./test1(_Z3foov+0xb)[0x80487ee]
./test1(main+0x22)[0x8048812]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x84de37]
./test1[0x80486c1]
This is how I compile for arm-linux
arm-linux-g++ -g -rdynamic ./testCatchSeg.cpp -o testCatchSeg
ARM does not store the return address on the stack when branching to a subroutine but rather expects any function calling subroutines to save the link register to its own stack frame before calling other functions, so it is impossible to follow stack frames without debug information.
I just got backtrace() to work with GCC for ARM. The key for me was compiling with -funwind-tables. Otherwise the stack depth was always 1 (i.e. empty).