Stack is totally messed up by trying to produce a buffer overflow - c++

after hours of debugging without any effort, I hope to find some help here on StackOverflow.
I'm currently on a PTP training and due to the fact that I'm only using Linux, i also want to practice the very firsts Labs on my local machine.
What i have to do is to exploit a very simple Program via buffer overflow. Just the Sources are given:
goodpwd.cpp:
#include <iostream>
#include <cstring>
int bf_overflow(char *str){
char buffer[10]; //our buffer
strcpy(buffer,str); //the vulnerable command
return 0;
}
int good_password(){ // a function which is never executed
printf("Valid password supplied\n");
printf("This is good_password function \n");
return 0;
}
int main(int argc, char *argv[])
{
int password=0; // controls whether password is valid or not
printf("You are in goodpwd.exe now\n");
bf_overflow(argv[1]); //call the function and pass user input
if ( password == 1) {
good_password(); //this should never happen
}
else {
printf("Invalid Password!!!\n");
}
printf("Quitting sample1.exe\n");
return 0;
}
I compiled it to get an executable by using
gcc -fno-stack-protector -z execstack -o goodpwd goodpwd.cpp -ggdb -m32 -lstdc++ -no-pie -O0
(I also already tried it without -no-pie and -O0 but I thought maybe the optimization could be the problem..)
I used gdb to debug the executable:
gdb goodpwd -tui -q
After setting a breakpoint to line 6 (the one with the vulnerable strcpy) I executed the following command:
(gdb) run AAAAAAAAAAAAAABCDE
after pressing n to go to the next line, I had a look into the stack:
(gdb) x/20x $esp
this gave me the following result:
0xffffd6f0: 0xffffd748 0x4141a8b0 0x41414141 0x41414141
0xffffd700: 0x41414141 0x45444342 0xffffd700 0x0804923b
0xffffd710: 0xffffd99c 0xf7fe4bd0 0xffffd800 0x08049209
0xffffd720: 0x00000002 0xffffd7f4 0xffffd800 0x00000000
0xffffd730: 0x0804c000 0x00000002 0x08049080 0xffffd760
I cannot explain myself why:
there are two A's at 0xffffd6f4
there are no A's at 0xffffd6f6
I got 16 A's starting at 0xffffd6f8
I got EDCB at 0xffffd704 (because of little endian, thank you #1201ProgramAlarm)
$bsp is 0xffffd708 and $eip is 0x80491a7 but after doing two more steps (leaving the function) $eip is set to 0x804923e because after all I've learned, I'm pretty sure it should be 0x08049209
after those two steps I get those error: main (argc=<error reading variable: Cannot access memory at address 0x4141a8b0>,
argv=<error reading variable: Cannot access memory at address 0x4141a8b4>) at goodpwd.cpp:21
I'd really appreciate if there's someone who's able to help me.
Struggling in module 3 of 43 is not the best feeling I've ever got :D
Edit:
ASLR should be deactivated:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

Maybe it was a bit too late yesterday. But today I found out, that #1202ProgramAlarm made a very good point.
Because of using a little-endian system, 0xffffd704 was right.
My confusions about 0xffffd6f4 and 0xffffd6f6 have been irrelevant because they not influenced the result.
The value of the old $EIP was still in 0xffffd70e but I never touched it.
I just had to enhance the string in the argument and afterwards I've been able to exploit the vulnerability.
It was a lot of fun. Thanks for the advises.

Related

clang AddressSanitizer instructs code improperly, false-positive result

FOREWORD
The current question is pretty damn huge and related to my master thesis, so I am humbly asking for your patience. I encountered a problem that is going to be explained further about half a year ago and the problem was needed an exterior look because at that point I was really stuck and I had nobody to help me. In the end I waved a hand at the problem, but now I am back in business (the second wind, let us put it that way).
INTRODUCTION
Crucial technologies used in the project:
C++, llvm/clang 13.0.1, ASAN, libFuzzer
The underlying idea behind the project I was writting is:
Write a parser of C-code projects to find functions that are presumed to be vulnerable (in the frames of the current question it does not matter how I decide that they are vulnerable)
When I find the vulnerable function, I start to write fuzzer code with libFuzzer for the function.
At this point I have an IR file with my vulnerable function, an IR file with my fuzzer code so it is time
to perform a separate compilation of two files. During the compilation process I instruct them with ASAN and libFuzzer by the clang compiler.
So the two files are coalesced together and I have an executable called, for example, 'fuzzer'. Theoretically, I can execute this executable and libFuzzer is going to fuzz my vulnerable function.
ACTUAL PROBLEM (PART 1)
ASAN intructs my code somehow bad. It gives me the wrong result.
How do I know that?
I found and took a vulnerable function. This function is from the old version of libcurl and is called sanitize_cookie_path. I reproduced the bug with AFL++ and it gave me what I wanted. If you pass a single quote to the function, it is going to 'blow'. Something similar I wanted to do with libFuzzer and ASAN, but as I mentioned earlier these two did not give me the expected result. Having spent some time on the problem, I can say that there is something with ASAN.
PROBLEM REPRODUCTION
I have the code (see below) in the file sanitize_cookie_path.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stddef.h>
static char* sanitize_cookie_path(const char* cookie_path) {
size_t len;
char* new_path = strdup(cookie_path);
if (!new_path) {
return NULL;
}
if (new_path[0] == '\"') {
memmove((void *)new_path, (const void*)(new_path + 1), strlen(new_path));
}
if (new_path[strlen(new_path) - 1] == '\"') {
new_path[strlen(new_path) - 1] = 0x0;
}
if (new_path[0] !='/') {
free(new_path);
new_path = strdup("/");
return new_path;
}
len = strlen(new_path);
if (1 < len && new_path[len - 1] == '/') {
new_path[len - 1] = 0x0;
}
return new_path;
}
int main(int argc, char** argv) {
if (argc != 2) {
exit(1);
}
sanitize_cookie_path('\"');
return 0;
}
My C++ code compiles it with the command:
clang -O0 -emit-llvm path/to/sanitize_cookie_path.c -S -o path/to/sanitize_cookie_path.ll > /dev/null 2>&1
On the IR level of the above code I get rid of the 'main' so only the 'sanitize_cookie_path' function presents.
I generate the simple fuzzer code (see below) for this function:
#include <cstdio>
#include <cstdint>
static char* sanitize_cookie_path(const char* cookie_path) ;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
(void) sanitize_cookie_path((char*) data);
return 0;
}
Then I compile it with the command:
clang -O0 -emit-llvm path/to/fuzz_sanitize_cookie_path.cc -S -o path/to/fuzz_sanitize_cookie_path.ll > /dev/null 2>&1
Two IR files are being compiled with the separate compilation. NOTE that before the separate compilation I perform some business to get them fit each other. For instance, I ditch the 'static' keyword and resolve name mangling from C++ to C code.
I compile them both together with the command:
clang++ -O0 -g -fno-omit-frame-pointer -fsanitize=address,fuzzer -fsanitize-coverage=trace-cmp,trace-gep,trace-div path/to/sanitize_cookie_path.ll path/to/fuzz_sanitize_cookie_path.ll -o path-to/fuzzer > /dev/null 2>&1
The final 'fuzzer' executable is ready.
ACTUAL PROBLEM (PART 2)
If you execute the fuzzer program, it is not going to give you the same results as AFL++ gives you. My fuzzer tumbles down on the '__interceptor_strdup' function from some standard library (see error snippet below). The crash report done by libFuzzer is literally empty (0 bytes), but ideally it had to find that the error is with a quote ("). Having done my own research I found out that ASAN did instruct the code bad and it gives me a false-position result. Frankly speaking I can fuzz the 'printf' function from stdio.h and find the same error.
[sanitize_cookie_path]$ ./fuzzer
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 1016408680
INFO: Loaded 1 modules (11 inline 8-bit counters): 11 [0x5626d4c64c40, 0x5626d4c64c4b),
INFO: Loaded 1 PC tables (11 PCs): 11 [0x5626d4c64c50,0x5626d4c64d00),
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
=================================================================
==2804==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000011 at pc 0x5626d4ba7671 bp 0x7ffe43152df0 sp 0x7ffe431525a0
READ of size 2 at 0x602000000011 thread T0
#0 0x5626d4ba7670 in __interceptor_strdup (/path/to/fuzzer+0xdd670)
#1 0x5626d4c20127 in sanitize_cookie_path (/path/to/fuzzer+0x156127)
#2 0x5626d4c20490 in LLVMFuzzerTestOneInput (/path/to/fuzzer+0x156490)
#3 0x5626d4b18940 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/path/to/fuzzer+0x4e940)
#4 0x5626d4b1bae6 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/path/to/fuzzer+0x51ae6)
#5 0x5626d4b1c052 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/path/to/fuzzer+0x52052)
#6 0x5626d4b0100b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/path/to/fuzzer+0x3700b)
#7 0x5626d4af0297 in main (/path/to/fuzzer+0x26297)
#8 0x7f8e6442928f (/usr/lib/libc.so.6+0x2928f)
#9 0x7f8e64429349 in __libc_start_main (/usr/lib/libc.so.6+0x29349)
#10 0x5626d4af02e4 in _start /build/glibc/src/glibc/csu/../sysdeps/x86_64/start.S:115
I used gdb to enter into the strdup(cookie_path). gdb shows me that the fuzzer tumbles down on the address 0x0000555555631687.
0x0000555555631684 <+452>: mov %rbp,%rsi
0x0000555555631687 <+455>: addr32 call 0x555555674100 <_ZN6__asan18ReportGenericErrorEmmmmbmjb>
0x000055555563168d <+461>: pop %rax
WHAT I TRIED TO DO
I tried to instuct my sanitize_cookie_path.c and fuzz_sanitize_cookie_path.cc with ASAN right at the beginning, not at the IR level but whatever I did nothing worked.
I passed to the 'fuzzer' the so called corpus directory with pre-cooked data to be passed to the fuzzer. I even passed the quote explicitly to the 'fuzzer', but nothing. Example (with the same directory as the fuzzer):
$ mkdir corpus/; echo "\"" > corpus/input; hexdump corpus/input
0000000 0a22
0000002
$ ./fuzzer corpus/
I also googled everything I could about libFuzzer and ASAN, but nothing gave me the results.
Changed compilation command. I got rid of the '-fno-omit-frame-pointer' and '-fsanitize-coverage=trace-cmp,trace-gep,trace-div'.
If there are some uncertainties in the details I have provided, do not hesitate to ask about them and I will iron them out to be more clear for you.
What are some other sites/forums where I can possibly get heard? I would ideally want to contact the developers of ASAN.
I will be more than happy for any help.
UPDATE 04/10/2022
llvm/clang have been upgraded from 13.0.1 to the latest available version in the Arch repository - 14.0.6. The problem still persists.
Opened an issue in the google/sanitizers repository.
Once more I have reread my question and comments, looked again at the code and additionally ran into this thought:
AddressSanitizer is not expected to produce false positives. If you
see one, look again; most likely it is a true positive!
As #Richard Critten and #chi have correctly pointed out in the comments section strdup function needs a NULL terminated string, so I changed my solution
from
(void) sanitize_cookie_path((char*) data);
to
char* string_ = new char[size + 1];
memcpy(string_, data, size);
string_[size] = 0x0;
(void) sanitize_cookie_path(string_);
delete[] string_;
The about solution converts the raw array of bytes data to a NULL terminated string string_ and passes it to the function. This solution works as it is expected.
It was just a stupid mistake that I had overlooked. Thanks again to #Richard Critten and #chi and everyone that tried to help.
Since there is no bug, I am going to retract my false accusations in google/sanitizers.

SystemC: read() and write() to port doesnt work

I am new to systemC It might look stupid but I would appreciate help.
In the below code
In main function :write() to aa and bb shows value 0 when read using aa.read() and bb.read() which should be 10 and 20
And also I think it should enter the method do_add() in the adder module as it is sensitive to a and b and a,b are binded to aa and bb signals but it doesn't call the method do_add(). How does it work and is there any error in the code?
For compiling the code:
g++ -I. -I$SYSTEMC_HOME/include -L. -L$SYSTEMC_HOME/lib-linux64 -Wl,-rpath=$SYSTEMC_HOME/lib-linux64 -o out adder.cpp -lsystemc -lm
./out
#include "systemc.h"
#define WIDTH 32
SC_MODULE(adder) {
sc_in<sc_uint<WIDTH> > a, b;
sc_out<sc_uint<WIDTH> > sum;
void do_add() {
// cout<<"hello"<<endl;
// cout<<a.read()<<b.read()<<"\n";
sum.write(a.read() + b.read());
// cout<<sum.read()<<endl;
}
SC_CTOR(adder) {
SC_METHOD(do_add);
sensitive << a << b;
}
};
int sc_main(int argc, char* argv[]) {
sc_signal<sc_uint<WIDTH> >aa,bb;
adder add("Adder");
add.a(aa);
add.b(bb);
aa.write(10);
bb.write(20);
cout<<aa.read()<<bb.read()<<"\n";
}
There are a number of things here. Firstly, you never actually start the simulation (see function sc_start) and even if you did it would exit immediately since there are no events to process. And lastly, even if you fixed those issues you would still get the same result since SystemC simulates hardware and reading a port in the same delta cycle as it was written will give you the original value on the port not the newly written one. How can hardware change the value of a signal in zero time?
The best advice I can give is to look in the directory where you downloaded SystemC and you will see a directory of PDF documents. On my SystemC it is in a directory called 'docs' (it may be different on yours depending on who installed it and where). If you look in there you will find a 'user guide' and some other PDF documents. These explain how SystemC works and give you examples you can try and modify to your own needs. Also there are some examples in the SystemC sources in the 'examples' folder. You can try playing around with these to get a feel for it and maybe just cut and paste some code and modify it to get what you require.

GDB Patching results in "Cannot access memory at address 0x

I have a program that I need to patch using GDB. The issue is there is a line of code that makes a "less than or equal test" and fails causing the program to end with a Segmentation fault. The program is already compiled and I do not have the source so I cannot change the source code obviously. However, using GDB, I was able to locate where the <= test is done and then I was able to locate the memory address which you can see below.
(gdb) x/100i $pc
... removed extra lines ...
0x7ffff7acb377: jle 0x7ffff7acb3b1
....
All I need to do is change the test to a 'greater than or equal to' test and then the program should run fine. The opcode for jle is 0x7e and I need to change it to 0x7d. My assignment gives instructions on how to do this as follows:
$ gdb -write -q programtomodify
(gdb) set {unsigned char} 0x8040856f = 0x7d
(gdb) quit
So I try it and get...
$ gdb -write -q player
(gdb) set {unsigned char} 0x7ffff7acb377 = 0x7d
Cannot access memory at address 0x7ffff7acb377
I have tried various other memory addresses and no matter what I try I get the same response. That is my only problem, I don't care if it's the wrong address or wrong opcode instruction at this point, I just want to be able to modify the memory.
I am running Linux Mint 14 via VMware Player
Thank
Cannot access memory at address 0x7ffff7acb377
You are trying to write to an address where some shared library resides. You can find out which library that is with info sym 0x7ffff7acb377.
At the time when you are trying to perform the patch, the said shared library has not been loaded yet, which explains the message you get.
Run the program to main. Then you should be able to write to the address. However, you'll need to have write permission on the library to make your write "stick".

GDB gets activated automatically and has 100% CPU activity

I'm using Debian x64 2.6.26 to host a server application we've written in C++. Sometimes GDB gets activated on its own and it uses 100% CPU time giving no room for other processes to run. The GDB version is 6.8-debian. I don't know why this happens and how may i prevent this. It seems that it only happens when out server application is running. I need to know how to stop this from happening or if there is something wrong in our application then how may i find it. Any help is much appreciated.
Thanks
I am inclined to believe that GDB is getting called by a signal handler in some code. Another suspect is some system monitoring daemon like 'monit'. When there is a rogue process eating too much memory or CPU, it might be trying to take a backtrace or dump using GDB. On way to troubleshoot is to use 'lsof' on the GDB process and see what files are opened by GDB and see if it gives you any clue. Using 'ps -ef -o cmd,pid,ppid | grep -i gdb', you can figure out how GDB was launched and if it gives you the PID of the attached process, you will know which process is being inspected.
A sledge hammer approach to stub such automatic execution is replacing 'GDB' with a stub 'GDB' which does nothing. Non existence of GDB might signal an error though. I have done such dirty tricks when I had no time to dig deeper into the problem. In the stub GDB, you can log all the command line arguments and the calling process name.
A sample stub in 'C':
#include <stdio.h>
int
main(int argc, char *argv[]) {
size_t sz;
FILE *fp = 0;
fp = fopen("/tmp/gdbstub.log", "a");
if (fp) {
fprintf(fp, "\n%s invoked:", argv[0]);
for (sz = 0; sz < argc - 1; sz++) {
fprintf(fp, "%s ", argv[sz]);
}
fclose(fp);
}
return 0;
}

help for gdb's stepi command

I need to trace all instrutions of a program using gdb.
After every execution of a instruction, I want gdb invokes a specified function.
Is it a possiable work? How to achieve this?
I searched internet and found "stepi arg" command in gdb could step arg instructions.
But how to find total number of instructions?
After every instruction, how to make gdb to invoke my function automately?
cat t.c
int main() { int x=1; int y=2; int z=x+y; printf("%d",z); return 0; }
gcc t.c
gdb -q ./a.out
break main
run
(no debugging symbols found)...
Breakpoint 1, 0x0000000000400488 in main ()
set logging on
while 1
>stepi
>info registers
end
quit
Now examine gdb.log: it should contain the info you are seeking.
P.S. This isn't a discussion forum. Please don't append questions as "answers". Instead edit your original question to clarify it, or use comments.
GDB always prints "---Type to continue, or q to quit---" during execution because of the height or pagination parameter.
In order to avoid or disable this you have to give the following command either in gdb prompt or .gdbinit file
set height 0 or set pagination off