Why does memory mapping change in GDB after run?
For instance, the main function below is initially at 0x00000560 and then after run it is at 0x80000560.
Is it possible to run/configure gdb the way it shows real mapping from the beginning?
Reading symbols from prog...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x00000560 : push %ebp
0x00000561 : mov %esp,%ebp
0x00000563 : sub $0x10,%esp
0x00000566 : call 0x580
0x0000056b : add $0x1a95,%eax
0x00000570 : movl $0x0,-0x4(%ebp)
0x00000577 : addl $0x1,-0x4(%ebp)
0x0000057b : mov -0x4(%ebp),%eax
0x0000057e : leave
0x0000057f : ret
End of assembler dump.
(gdb) run
Starting program: /home/mike/gdb/prog
[Inferior 1 (process 9607) exited with code 01]
(gdb) disas main
Dump of assembler code for function main:
0x80000560 : push %ebp
0x80000561 : mov %esp,%ebp
0x80000563 : sub $0x10,%esp
0x80000566 : call 0x80000580
0x8000056b : add $0x1a95,%eax
0x80000570 : movl $0x0,-0x4(%ebp)
0x80000577 : addl $0x1,-0x4(%ebp)
0x8000057b : mov -0x4(%ebp),%eax
0x8000057e : leave
0x8000057f : ret
End of assembler dump.
For instance, the main function below is initially at 0x00000560 and then after run it is at 0x80000560.
You have a position-independent executable (really just a special kind of shared library, linked with -pie flag). It is relocated to a random address before it starts executing.
Note that GDB will usually try to disable address randomization, so the random address will not actually vary from run to run under GDB. However, it will vary when the program is run outside of GDB, or if you use (gdb) set disable-randomization off.
Related
I want to make my program more strong in front of hackers, so i have a program::validator class which validate my environment by some parameters. I :
Compile program::validator shared library.
Compile program using -O2 and --ffast-math and link to libprogramvalidator.so.
Run the program with the GDB.
Find the line which actually call program::validator::is_valid_system().
and i want know that i can ignore execution of those line ?
i just want avoid call to is_valid_system function in my ELF executable binary file.
There are several easy ways. You can use GDB jump $address, or return commands to achieve this. Example:
#include <stdio.h>
int is_valid_system()
{
return 0;
}
int main()
{
if (is_valid_system()) {
printf("Life is good\n");
return 0;
}
printf("Invalid system detected\n");
return 1;
}
As you can see, running above program will always print Invalid system and exit with error code 1. Let's confirm that:
gcc t.c && gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out
Invalid system detected
[Inferior 1 (process 180727) exited with code 01]
Ok, now let's make the program print Life is good. Let's do that via return. To achieve that, set a breakpoint on the desired function, set return register ($rax on x86_64) to desired value, and return to force the function to immediately return:
(gdb) b is_valid_system
Breakpoint 1 at 0x1139
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, 0x0000555555555139 in is_valid_system ()
(gdb) set $rax = 1
(gdb) return
#0 0x000055555555514e in main ()
(gdb) c
Continuing.
Life is good
[Inferior 1 (process 196141) exited normally]
Alternatively, you can "jump over" the function. Disasemble the caller, break on the CALL instruction, set return register to desired value, and jump to next instruction:
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555140 <+0>: push %rbp
0x0000555555555141 <+1>: mov %rsp,%rbp
0x0000555555555144 <+4>: mov $0x0,%eax
0x0000555555555149 <+9>: callq 0x555555555135 <is_valid_system>
0x000055555555514e <+14>: test %eax,%eax
0x0000555555555150 <+16>: je 0x555555555165 <main+37>
0x0000555555555152 <+18>: lea 0xeab(%rip),%rdi # 0x555555556004
0x0000555555555159 <+25>: callq 0x555555555030 <puts#plt>
0x000055555555515e <+30>: mov $0x0,%eax
0x0000555555555163 <+35>: jmp 0x555555555176 <main+54>
0x0000555555555165 <+37>: lea 0xea5(%rip),%rdi # 0x555555556011
0x000055555555516c <+44>: callq 0x555555555030 <puts#plt>
0x0000555555555171 <+49>: mov $0x1,%eax
0x0000555555555176 <+54>: pop %rbp
0x0000555555555177 <+55>: retq
End of assembler dump.
(gdb) b *0x0000555555555149
Breakpoint 2 at 0x555555555149
(gdb) run
Starting program: /tmp/a.out
Breakpoint 2, 0x0000555555555149 in main ()
(gdb) set $rax = 1
(gdb) jump *0x000055555555514e
Continuing at 0x55555555514e.
Life is good
[Inferior 1 (process 205378) exited normally]
You could also use GDB to temporarily or permanently patch the is_valid_system out. Details in this answer.
This is another variant of the common mistake "Thinking that you can trust your environment, even when you cannot trust your environment".
You implicitly trust that the compiler is a real compiler, the linker a real linker, GDB the real GDB, and the disassembler a real disassembler. You have given hackers not one but four ways to attack your program.
This question already has an answer here:
Cannot insert breakpoints. Addresses with low values
(1 answer)
Closed 4 years ago.
I am working on implementing a simple stack overflow, which I am examining with gdb. A problem I keep coming up with is gdb not accepting my breakpoints. My c code is quite simple:
void function(int a, int b, int c) {
...//stuff
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
And i'm using gcc -m32 -fno-stack-protector -o example3test example3test.c to complie it.
I have tried just setting a simple breakpoint on the line <+42> just to test if it works.
(gdb) disass main
Dump of assembler code for function main:
0x000005d1 <+0>: lea 0x4(%esp),%ecx
0x000005d5 <+4>: and $0xfffffff0,%esp
0x000005d8 <+7>: pushl -0x4(%ecx)
0x000005db <+10>: push %ebp
0x000005dc <+11>: mov %esp,%ebp
0x000005de <+13>: push %ebx
0x000005df <+14>: push %ecx
0x000005e0 <+15>: sub $0x10,%esp
0x000005e3 <+18>: call 0x470 <__x86.get_pc_thunk.bx>
0x000005e8 <+23>: add $0x1a18,%ebx
0x000005ee <+29>: movl $0x0,-0xc(%ebp)
0x000005f5 <+36>: push $0x3
0x000005f7 <+38>: push $0x2
0x000005f9 <+40>: push $0x1
0x000005fb <+42>: call 0x5a0 <function>
0x00000600 <+47>: add $0xc,%esp
0x00000603 <+50>: movl $0x1,-0xc(%ebp)
0x0000060a <+57>: sub $0x8,%esp
0x0000060d <+60>: pushl -0xc(%ebp)
0x00000610 <+63>: lea -0x1950(%ebx),%eax
0x00000616 <+69>: push %eax
0x00000617 <+70>: call 0x400 <printf#plt>
0x0000061c <+75>: add $0x10,%esp
0x0000061f <+78>: nop
0x00000620 <+79>: lea -0x8(%ebp),%esp
0x00000623 <+82>: pop %ecx
0x00000624 <+83>: pop %ebx
0x00000625 <+84>: pop %ebp
0x00000626 <+85>: lea -0x4(%ecx),%esp
0x00000629 <+88>: ret
End of assembler dump.
(gdb) break *0x000005fb
Breakpoint 1 at 0x5fb
(gdb) run
Starting program: /home/jasmine/tutorials/smashingTheStackForFun/example3test
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x5fb
I'm lost as to why it won't accept this breakpoint. Most of the answers already on here involve not using the * or using wrong notation, from what I can see mine looks right, but I could be wrong.
I'm lost as to why it won't accept this breakpoint.
You have a position independent executable, which is relocated to a different address at runtime.
This will work:
(gdb) start
# GDB stops at main
(gdb) break *&main+42
(gdb) continue
See also this answer.
According to https://www.ethicalhacker.net/columns/heffner/intro-to-assembly-and-reverse-engineering
mov 0xffffffb4,0x1
moves the number 1 into 0xffffffb4.
So, I decided to test this on my own.
In GDB, x is the command to print the value of memory address.
However, when I run
x 0x00000000004004fc
I'm not getting the value of 133 (decimal) or 85 (hexadecimal)
Instead, I'm getting 0x85f445c7. Any idea what is this?
me#box:~/c$ gdb -q test
Reading symbols from test...done.
(gdb) l
1 #include <stdio.h>
2
3 int main(){
4 int a = 1;
5 int b = 13;
6 int c = 133;
7 printf("Value of C : %d\n",c);
8 return 0;
9 }
(gdb) b 7
Breakpoint 1 at 0x400503: file test.c, line 7.
(gdb) r
Starting program: /home/me/c/test
Breakpoint 1, main () at test.c:7
7 printf("Value of C : %d\n",c);
(gdb)
Disassemble
(gdb) disas
Dump of assembler code for function main:
0x00000000004004e6 <+0>: push %rbp
0x00000000004004e7 <+1>: mov %rsp,%rbp
0x00000000004004ea <+4>: sub $0x10,%rsp
0x00000000004004ee <+8>: movl $0x1,-0x4(%rbp)
0x00000000004004f5 <+15>: movl $0xd,-0x8(%rbp)
0x00000000004004fc <+22>: movl $0x85,-0xc(%rbp)
=> 0x0000000000400503 <+29>: mov -0xc(%rbp),%eax
0x0000000000400506 <+32>: mov %eax,%esi
0x0000000000400508 <+34>: mov $0x4005a4,%edi
0x000000000040050d <+39>: mov $0x0,%eax
0x0000000000400512 <+44>: callq 0x4003c0 <printf#plt>
0x0000000000400517 <+49>: mov $0x0,%eax
0x000000000040051c <+54>: leaveq
0x000000000040051d <+55>: retq
End of assembler dump.
(gdb) x 0x00000000004004fc
0x4004fc <main+22>: 0x85f445c7
(gdb)
;DRTL
To print a value in GDB use print or (p in short form) command.
in your command
x 0x00000000004004fc
You have missed p command. You have to use x with p command pair to print value as hexadecimal format, like below:
(gdb) p/x 0x00000000004004fc
If the memory address is some pointer to some structure then you have to cast the memory location before using the pointer. For example,
struct node {
int data;
struct node *next
};
is some structure and you have the address of that structure pointer, then to view the contents of that memory location you have to use
(gdb) p *(struct node *) 0x00000000004004fc
Notable:
The command
x 0x00000000004004fc
Will look at the instruction and related data for this instruction:
0x00000000004004fc <+22>: movl $0x85,-0xc(%rbp)
... as you can see that the left column (address) is equal to the value used for the command (the address to read)
In the instruction 0x85 is clearly the destination address for the mov, and reflected in the printed value; 0x85f445c7 - which stored as MSB (most significant byte) at the address.
When i execute the following commands i get different address of function()
(gdb) break function()
Breakpoint 1 at function() 0x804834a.
(gdb) print function()
Breakpoint 1 at function() 0x8048344.
Why there is difference in both address?
This output can't be correct, it would be if you did something as:
int func(void) {
int a = 10;
printf("%d\n", a);
return 1;
}
after loading it into the gdb:
(gdb) p func
$1 = {int (void)} 0x4016b0 <func>
(gdb) b func
Breakpoint 1 at 0x4016b6: file file.c, line 4.
(gdb) disassemble func
Dump of assembler code for function func:
0x004016b0 <+0>: push %ebp
0x004016b1 <+1>: mov %esp,%ebp
0x004016b3 <+3>: sub $0x28,%esp
0x004016b6 <+6>: movl $0xa,-0xc(%ebp)
0x004016bd <+13>: mov -0xc(%ebp),%eax
0x004016c0 <+16>: mov %eax,0x4(%esp)
0x004016c4 <+20>: movl $0x405064,(%esp)
0x004016cb <+27>: call 0x403678 <printf>
0x004016d0 <+32>: mov $0x1,%eax
0x004016d5 <+37>: leave
0x004016d6 <+38>: ret
End of assembler dump.
(gdb)
Here func points to the exact first instruction in the function, push %ebp, but when you setup a break point, gdb sets it after stack frame initialization instructions:
0x004016b0 <+0>: push %ebp
0x004016b1 <+1>: mov %esp,%ebp
0x004016b3 <+3>: sub $0x28,%esp
at where the instructions of the function actually begins:
=> 0x004016b6 <+6>: movl $0xa,-0xc(%ebp)
0x004016bd <+13>: mov -0xc(%ebp),%eax
0x004016c0 <+16>: mov %eax,0x4(%esp)
0x004016c4 <+20>: movl $0x405064,(%esp)
0x004016cb <+27>: call 0x403678 <printf>
0x004016d0 <+32>: mov $0x1,%eax
0x004016d5 <+37>: leave
0x004016d6 <+38>: ret
here this instruction:
movl $0xa,-0xc(%ebp) ; 0xa = 10
is this part:
int a = 10;
Gdb sets a breakpoint after function prologue, as before the things are properly set up it could not show the expected state like local variables, etc.
Break therefor sets breakpoint and prints address of first instruction after prologue, whereas print prints the address of actual first instruction in function.
You can set a breakpoint to actual first instruction by doing break *0x8048344, then observe the value of local variables there and after prologue.
consider this :
[mdstest:~/onkar/test]$cat test.c
#include<stdio.h>
int main(int argc,char **argv)
{
printf("%p\n",main);
return 0;
}
[mdstest:~/onkar/test]$make
gcc -g -Wall -o test test.c
[mdstest:~/onkar/test]$./test
0x8048368 ------------------------------------- (1)
[mdstest:~/onkar/test]$gdb test
:::::::::::
:::::::::::
(gdb) b main
Breakpoint 1 at 0x8048384: file test.c, line 5.
(gdb) r
Starting program: /home/mdstest/onkar/test/test
[Thread debugging using libthread_db enabled]
Breakpoint 1, main (argc=1, argv=0xbffff2d4) at test.c:5
5 printf("%p\n",main);
(gdb) disassemble
Dump of assembler code for function main:
0x08048368 <+0>: push %ebp
0x08048369 <+1>: mov %esp,%ebp
0x0804836b <+3>: sub $0x8,%esp
0x0804836e <+6>: and $0xfffffff0,%esp
0x08048371 <+9>: mov $0x0,%eax
0x08048376 <+14>: add $0xf,%eax
0x08048379 <+17>: add $0xf,%eax
0x0804837c <+20>: shr $0x4,%eax
0x0804837f <+23>: shl $0x4,%eax
0x08048382 <+26>: sub %eax,%esp
=> 0x08048384 <+28>: sub $0x8,%esp -----------------------------(2)
0x08048387 <+31>: push $0x8048368
0x0804838c <+36>: push $0x8048480
0x08048391 <+41>: call 0x80482b0 <printf#plt>
0x08048396 <+46>: add $0x10,%esp
0x08048399 <+49>: mov $0x0,%eax
0x0804839e <+54>: leave
0x0804839f <+55>: ret
End of assembler dump.
Why are (1) and (2) addresses different ? That is , why some other address
is getting printed in (1) whereas the debugger stops at some other location ?
When a function is called, the calling function does a bit of stuff, and then issues a call instruction pointing to the function being called.
The callee then does a lot of boilerplate of their own - saving registers, shifting the stack pointer to allocate space for stack variables, etc.
When you ask gdb to break at the start of a function, it breaks after that boilerplate, at the start of your actual code - so the address of the function is going to be earlier than the point at which gdb breaks.
"The address of main" is indeed 0x08048368 -- the address of source line 5, where the breakpoint was set, is just after the standard start-of-function boilerplate, just before the code prepping printf's argument and calling it (so that a n will execute that printf-call statement, for example).