I have a program which SIGABRT after >5hrs of execution. It is most likely cause by memory leak after checking by valgrind, but I have problem trace down onto which variable actually causes this issue based on valgrind report (which simply contains addresses and ???).
I try to use valgrind and gdb to step through. However since it takes 5hrs to reach the leak (after looping for 428 rounds), I would like to set a breakpoint, let say, when loop=428, and step into the codes. How can I do that?
Based on a simple program below, may I know,
a) how to trace change of value in variable 'a'?
b) how to set a breakpoint when loop = 428?
typedef struct data_attr {
int a[2500];
}stdata;
typedef struct pcfg{
stdata *data;
}stConfig;
int funcA(stConfig* pt){
int loop = 0;
while (loop < NUM_NODE){
pt->data->a[0] = 1000;
pt->data->a[0] = 1001;
loop++;
}
return 0;
}
int main(){
stConfig *p;
p = (stConfig*) malloc(sizeof(stConfig));
p->data = (stdata*) malloc (sizeof(stdata));
funcA(p);
free(p->data);
free (p);
return 0;
}
I am using valgrind 3.7 on ubuntu 10.04
# valgrind terminal,
valgrind -v --vgdb=yes --vgdb-error=0 --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=40 --track-origins=yes --log-file=mr3m1n2500_valgrind_0717_1155.txt ./pt m >& mr3m1n2500_logcheck_0717_1155.txt
# gdb terminal
I tried to get address of 'p' but it returns void, why?
> gdb ./pt
(gdb) target remote | vgdb
Remote debugging using | vgdb
relaying data between gdb and process 12857
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.1.so...done.
done.
Loaded symbols for /lib/ld-linux.so.2
[Switching to Thread 12857]
0x04000850 in _start () from /lib/ld-linux.so.2
(gdb) p $p
$1 = void
(gdb) bt 10
#0 0x04000850 in _start () from /lib/ld-linux.so.2
To trace the change in the value of a variable, you can set watch-point on that variable.
For your case, use: watch p->data->a[index]
To break at the required condition, you can use break break if loop_counter==428
From help break in GDB:
(gdb) help break
Set breakpoint at specified line or function.
break [LOCATION] [thread THREADNUM] [if CONDITION]
LOCATION may be a line number, function name, or "*" and an address.
If a line number is specified, break at start of code for that line.
If a function is specified, break at start of code for that function.
If an address is specified, break at that exact address.
With no LOCATION, uses current execution address of selected stack frame.
This is useful for breaking on return to a stack frame.
THREADNUM is the number from "info threads".
CONDITION is a boolean expression.
Multiple breakpoints at one place are permitted, and useful if conditional.
Do "help breakpoints" for info on other commands dealing with breakpoints.
To set a breakpoint on a condition, use break if condition, in your case break if loop_counter == 428 or similar.
a) To set a break point of that loop if can do something like:
if(loop == 428)
int nop = 0;
And then set the break point for the line int nop = 0. Like this the program only stops when that line is executed which happens in loop 428.
b) I am not sure about this one. Where are you trying to examine the value of 'p'?.
For your first question, how to trace change of value in variable 'a'?
Please use "watch",
watch [-l|-location] expr [thread threadnum] [mask maskvalue]
Set a watchpoint for an expression. gdb will break when the expression expr is written into by the program and its value changes. The simplest (and the most popular) use of this command is to watch the value of a single variable:
(gdb) watch foo
Joachim Pileborg have the answer of your second question.
For your third question, you need to set a break at the line
p->data = (stdata*) malloc (sizeof(stdata));
and then try to print the value of "p".
Related
I am trying to reproduce an example given in the book "The Art of Exploitation" by Jon Erickson. The procedure is actually pretty simple: I want to give commandline-arguments to my program and examine their memory addresses using lldb.
The C class looks something like this:
#include <stdio.h>
int main(int arg_count, char *arg_list[]) {
// something
}
To examine the program with lldb i do the following:
lldb ./a.out
(lldb) target create "./a.out"
Current executable set to '/Users/<path>/a.out' (x86_64).
(lldb) b main
Breakpoint 1: where = a.out`main + 22 at commandline.c:7:50, address = 0x0000000100003f06
(lldb) run first second
Process 4161 launched: '/Users/<path>/a.out' (x86_64)
Process 4161 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100003f06 a.out`main(arg_count=3, arg_list=0x00007ffeefbffa40) at commandline.c:7:50
Target 0: (a.out) stopped.
So now I expect the next three memory-words, after the address stored in arg_list, to point to the adresses of the strings given through the command line. I know that the first argument is always a string that contains the path to my ./a.out file.
(lldb) x/3xw arg_list
0x7ffeefbffa40: 0xefbffbb8 0x00007ffe 0xefbffbe9
(lldb) x/s 0xefbffbb8
error: failed to read memory from 0xefbffbb8.
(lldb) x/s 0x00007ffe
error: failed to read memory from 0x7ffe.
So when I try to examine the memory, it always fails. Does anyone know why? The example in the book uses the gdb debugger and it works fine.
The book looks to be written for 32-bit code, but your system is 64-bit. So the pointers are 64 bits each. Try x/3xg arg_list, where the g is for "giant", gdb's size letter for an 8-byte object. This should give you three 64-bit values starting with 0x00007ffeefbffbb8 and then you can x/s 0x00007ffeefbffbb8.
(You may want to find a different book that matches your system better, or set up a 32-bit Linux VM for following along with it.)
I am developing buffer overflow exercises for students. In this context you often have to provide arbitary bytes as input for programs (return addresses).
Assume this example:
#import <stdio.h>
#import <string.h>
void func() {
char buf[4];
gets(buf);
}
int main (int argc, char** argv) {
func();
return 0;
}
Normally I experiment with gdb, until I found a solution, which can then be formulated like
python -c 'print "A"*8+"\x08\x04\88\72"' | ./program
While developing more and more complex exercises, the difficulty to find a solution increases. Sometimes overwriting the return address in gdb via
set {int}address_of_address = new_address
works, but the python-approach does not. It would be nice to debug this and to be able to enter bytes like "\x04" in gdb, while the program is running, analyzing the effects.
Is there any way to do this?
This question seems related but is answered with the python-approach: Sending arbitrary bytes to fgets from stdin
Mine goes beyond that :-/
It would be nice to debug this and to be able to enter bytes like
"\x04" in gdb, while the program is running, analyzing the effects
To do this you need 2 consoles: the first one to enter bytes in program stdin, the second one for gdb debug session.
You can first run program in 1st console until it stops waiting for bytes from stdin. Then run gdb in 2nd console and attach to a program by it's pid. You will be able to debug and enter bytes simultaneously from 2 different consoles.
"while the program is running" is one part of the problem. The other one is being able to set breakpoints beforehand, to "analyze the effects".
GDB's default behaviour is to run the program as a child process, thus using the same standard streams. So it is impossible to write to the child's stdin while being in GDB's CLI because, at this moment, it is being read by GDB, not your program.
The simplest solution, avoiding tty workarounds (tty command + stty setups + reading/writing to /proc/<pid>/fd/{0,1}), is to make your code testable and "callable" from GDB. You'll then be able to pass your string arguments to your functions in order to test and debug them.
For example:
#include <stdio.h>
#include <unistd.h>
void exploitme(char* str)
{
printf(str);
}
int main()
{
while (1)
{
char str[10];
fgets(str, sizeof (str), stdin);
exploitme(str);
}
return 0;
}
exploitme() is the exploit case correctly wrapped in a single entry point so that it is now possible to call it once everything it uses is correctly initialized. You can then call it using command call once main() breakpoint is reached (so that the C runtime inits, performed in main's caller, are done).
~/test $ gdb ./a.out
(gdb) call exploitme("hello")
You can't do that without a process to debug.
(gdb) b main
Breakpoint 1 at 0x4005ae: file helloworld.c, line 14.
(gdb) r
Starting program: /home/julio/test/a.out
Breakpoint 1, main () at helloworld.c:14
14 fgets(str, sizeof (str), stdin);
(gdb) call exploitme("hello")
(gdb) call exploitme("hello\n")
hellohello
(gdb) call exploitme("AAAAAAAA\x08\x04\88\72\n")
AAAAAAA�:
(gdb) b exploitme
Breakpoint 2 at 0x400592: file helloworld.c, line 6.
(gdb) call exploitme("foo")
Breakpoint 2, exploitme (str=0x602010 "foo") at helloworld.c:6
6 printf(str);
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(exploitme) will be abandoned.
When the function is done executing, GDB will silently stop.
Note that you benefit from GDB's argument expansion which includes the C string evaluation.
The other (longer and more complex) solution, as explained, is to run your program under another tty, so that you can independently write to GDB and your program.
this code is meant to take a list of names in a text file, and convert to email form
so Kate Jones becomes kate.jones#yahoo.com
this code worked fine on linux mint 12, but now the exact same code is giving a segfault on arch linux.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
fp = fopen("original.txt", "r+");
if (fp == NULL )
{
printf("error opening file 1");
return (1);
}
char line[100];
char mod[30] = "#yahoo,com\n";
while (fgets(line, 100, fp) != NULL )
{
int i;
for (i = 0; i < 100; ++i)
{
if (line[i] == ' ')
{
line[i] = '.';
}
if (line[i] == '\n')
{
line[i] = '\0';
}
}
strcat(line, mod);
FILE *fp2;
fp2 = fopen("final.txt", "a");
if (fp == NULL )
{
printf("error opening file 2");
return (1);
}
if (fp2 != NULL )
{
fputs(line, fp2);
fclose(fp2);
}
}
fclose(fp);
return 0;
}
Arch Linux is a fairly fresh install, could it be that there is something else I didn't install that C will need?
I think the problem would be when your original string plus mod exceeds 100 characters.
When you call strcat, it simply copies the string from the second appended to the first, assuming there is enough room in the first string which clearly doesn't seem to be the case here.
Just increase the size of line i.e. it could be
char line[130]; // 130 might be more than what is required since mod is shorter
Also it is much better to use strncat
where you can limit maximum number of elements copied to dst, otherwise, strcat can still go beyond size without complaining if given large enough strings.
Though a word of caution with strncat is that it does not terminate strings with null i.e. \0 on its own, specially when they are shorter than the given n. So its documentation should be thoroughly read before actual use.
Update: Platform specific note
Thought of adding, it is by sheer coincidence that it didn't seg fault on mint and crashed on arch. In practice it is invoking undefined behavior and should crash sooner or latter. There is nothing platform specific here.
Firstly your code isn't producing segmentation fault. Instead it will bring up "Stack Smashing" and throws below libc_message in the output console.
*** stack smashing detected ***: _executable-name-with-path_ terminated.
Stack buffer overflow bugs are caused when a program writes more data to a buffer located on the stack than there was actually allocated for that buffer.
Stack Smashing Protector (SSP) is a GCC extension for protecting applications from such stack-smashing attacks.
And, as said in other answers, your problem gets resolved with incrementing (strcat() function's first argument). from
char line[100]
to
char line[130]; // size of line must be atleast `strlen(line) + strlen(mod) + 1`. Though 130 is not perfect, it is safer
Lets see where the issue exactly hits in your code:
For that I am bringing up disassembly code of your main.
(gdb) disas main
Dump of assembler code for function main:
0x0804857c <+0>: push %ebp
0x0804857d <+1>: mov %esp,%ebp
0x0804857f <+3>: and $0xfffffff0,%esp
0x08048582 <+6>: sub $0xb0,%esp
0x08048588 <+12>: mov %gs:0x14,%eax
0x0804858e <+18>: mov %eax,0xac(%esp)
..... //Leaving out Code after 0x0804858e till 0x08048671
0x08048671 <+245>: call 0x8048430 <strcat#plt>
0x08048676 <+250>: movl $0x80487d5,0x4(%esp)
.... //Leaving out Code after 0x08048676 till 0x08048704
0x08048704 <+392>: mov 0xac(%esp),%edx
0x0804870b <+399>: xor %gs:0x14,%edx
0x08048712 <+406>: je 0x8048719 <main+413>
0x08048714 <+408>: call 0x8048420 <__stack_chk_fail#plt>
0x08048719 <+413>: leave
0x0804871a <+414>: ret
Following the usual assembly language prologue,
Instruction at 0x08048582 : stack grows by b0(176 in decimal) bytes for allowing storage stack contents for the main function.
%gs:0x14 provides the random canary value used for stack protection.
Instruction at 0x08048588 : Stores above mentioned value into the eax register.
Instruction at 0x0804858e : eax content(canary value) is pushed to stack at $esp with offset 172
Keep a breakpoint(1) at 0x0804858e.
(gdb) break *0x0804858e
Breakpoint 1 at 0x804858e: file program_name.c, line 6.
Run the program:
(gdb) run
Starting program: /path-to-executable/executable-name
Breakpoint 1, 0x0804858e in main () at program_name.c:6
6 {
Once program pauses at the breakpoint(1), Retreive the random canary value by printing the contents of register 'eax'
(gdb) i r eax
eax 0xa3d24300 -1546501376
Keep a breakpoint(2) at 0x08048671 : Exactly before call strcat().
(gdb) break *0x08048671
Breakpoint 2 at 0x8048671: file program_name.c, line 33.
Continue the program execution to reach the breakpoint (2)
(gdb) continue
Continuing.
Breakpoint 2, 0x08048671 in main () at program_name.c:33
print out the second top stack content where we stored the random canary value by executing following command in gdb, to ensure it is the same before strcat() is called.
(gdb) p *(int*)($esp + 172)
$1 = -1546501376
Keep a breakpoint (3) at 0x08048676 : Immediately after returning from call strcat()
(gdb) break *0x08048676
Breakpoint 3 at 0x8048676: file program_name.c, line 36.
Continue the program execution to reach the breakpoint (3)
(gdb) continue
Continuing.
Breakpoint 3, main () at program_name.c:36
print out the second top stack content where we stored the random canary value by executing following command in gdb, to ensure it is not corrupted by calling strcat()
(gdb) p *(int*)($esp + 172)
$2 = 1869111673
But it is corrupted by calling strcat(). You can see $1 and $2 are not same.
Lets see what happens because of corrupting the random canary value.
Instruction at 0x08048704 : Pulls the corrupted random canary value and stores in 'edx` register
Instruction at 0x0804870b : xor the actual random canary value and the contents of 'edx' register
Instruction at 0x08048712 : If they are same, jumps directly to end of main and returns safely. In our case random canary value is corrupted and 'edx' register contents is not the same as the actual random canary value. Hence Jump condition fails and __stack_chk_fail is called which throws libc_message mentioned in the top of the answer and aborts the application.
Useful Links:
IBM SSP Page
Interesting Read on SSP - caution pdf.
Since you didn't tell us where it faults I'll just point out some suspect lines:
for(i=0; i<100; ++i)
What if a line is less than 100 chars? This will read uninitialized memory - its not a good idea to do this.
strcat(line, mod);
What if a line is 90 in length and then you're adding 30 more chars? Thats 20 out of bounds..
You need to calculate the length and dynamically allocate your strings with malloc, and ensure you don't read or write out of bounds, and that your strings are always NULL terminated. Or you could use C++/std::string to make things easier if it doesn't have to be C.
Instead of checking for \n only, for the end of line, add the check for \r character also.
if(line[i] == '\n' || line[i] == '\r')
Also, before using strcat ensure that line has has enough room for mod. You can do this by checking if (i < /* Some value far less than 100 */), if i == 100 then that means it never encountered a \n character hence \0 was not added to line, hence Invalid memory Access occurs inside strcat() and therefore Seg Fault.
Fixed it. I simply increased the size of my line string.
I'm writing a program to implement Dinic's max-flow algorithm over a network. The networks can be written either by hand or loaded from a file using stdin redirection.
I've been able to use gdb to debug the program with small files (around 30 lines), but I'm having trouble when I try to debug the program with bigger files (>1000 lines). The code itself is this:
uint32_t read_lines = 0;
while(!feof(stdin))
{
err = fscanf(stdin, "%u %u %u\n", &n1, &n2, &c);
if (err != 3)
{
printf("read_lines=%u\n", read_lines); /*for debugging purposes*/
}
read_lines += 1;
/* write to debug file */
fprintf(debug, "line %u: %u %u %u\n", read_lines, n1, n2, c);
}
If I run the program without gdb, it runs, not ok as it generates a segmentation fault (which is the reason I'm trying to use gdb), but it goes through this part of "parsing" the input file (and writing it into the output debugging file).
However, if I type:
gdb --args ./dinic --mode=NUM --verbose=LOW
(gdb) b 61
(gdb) run < tests/numterc.in
I get:
(gdb) Program exited with 01 code.
and when I open the debugging file it's about 2000 lines, when it should be at most 1000, which is the input file length.
I repeat, this happens with "big" files, it works correct with small ones.
The question would be, am I missing something when using gdb, or is this a gdb bug?
Ok, I could finally get a work-around. It seems that the --args option ain't working well, at least in my case. I have gdb 6.8-debian and debian 5.0.4.
What I had to do was run gdb without the --args option:
$gdb ./dinic
(gdb) b 61
(gdb) run --mode=NUM --verbose=LOW < tests/numterc.in
and it worked well. Maybe someone can find this useful.
I had the same problem and came up with the same solution to specify args in run. The option --args only can pass arguments, but but cannot do redirection of stdin which is usually (in non-debug context) redirected for you by the shell invoking the command. In the debug session your command is invoked by gdb where both argument list and redirections are specified by the value of the args variable. By using the --args option you initialize this variable (and the program file to debug as well). Just do
(gdb) show args
and this should be initialized to --mode=NUM --verbose=LOW in your case. But no redirection, so you specify them with run, which overrides args! So you have two options:
Specify also the redirection in args:
(gdb) set args --mode=NUM --verbose=LOW < tests/numterc.in
Specify also the redirection when invoking run
I have been facing a weird issue in a piece of code.
void app_ErrDesc(char *ps_logbuf, char *pc_buf_err_recno)
{
char *pc_logbuf_in;
char rec_num[10];
char *y = "|";
int i, j;
memset(rec_num, 0, sizeof(rec_num));
memset(pc_buf_err_recno, 0, LOGBUFF);
.....
.....
}
For some reason the first memset call sends a SIGSEGV. Whats more strange is when
inside gdb the same line executes for about 30 times though the function is called
only once and there are no loops inside! Here's a piece of gdb session.
7295 /*Point to logbuffer string*/
(gdb)
7292 memset(rec_num, 0, sizeof(rec_num));
(gdb)
7295 /*Point to logbuffer string*/
(gdb)
7292 memset(rec_num, 0, sizeof(rec_num));
(gdb) n
7295 /*Point to logbuffer string*/
(gdb)
7292 memset(rec_num, 0, sizeof(rec_num));
(gdb)
Program received signal SIGSEGV, Segmentation fault.
I have also tried running the program through valgrind's memcheck tool but not getting anything significant about the above piece of code.
The file that I'm parsing has just one record.
Any pointers are appreciated. Thanks.
It's likely that it's the second memset and the reason is that the outer function is called with an insufficient buffer size. Debuggers can show incorrectly where you are. Try to add logging after each step to find out what exactly crashes.
i suspect the call to the function, so ensure the call is not something like
char pc_buf_err_recno[SMALLER_THAN_LOGBUFF];
char ps_logbuf[TOO_SMALL]
app_ErrDesc(ps_logbuf, pc_buf_err_recno);
Debuggers can be incorrect, particularly if you're getting SEGV. Remember, it's quite possible you've trashed the stack when you get a segmentation fault and the debugger will get confused if that happens.
It's also quite possible the calling function has made a mess, not the current one.
Whats more strange is when inside gdb the same line executes for about 30 times though the function is called only once and there are no loops inside!
This sounds symptomatic of having compiled with optimizations. You may have an easier time pinpointing the problem in GDB if you compile with optimizations turned off.