How do I print a pointer address without materializing the struct in LLDB - c

I'm trying to figure out which of several variables are null in a program. Unfortunately lldb just tells me it can't materialize the struct when I try to build it. Any ideas how I get lldb to print the address of the struct (but not the struct)?
(lldb) print *arg3
error: Couldn't materialize struct: size of variable arg3 (8) disagrees with the ValueObject's size (0)
Errored out in Execute, couldn't PrepareToExecuteJITExpression
(lldb) print (int*) arg3
error: Couldn't materialize struct: size of variable arg3 (8) disagrees with the ValueObject's size (0)
Errored out in Execute, couldn't PrepareToExecuteJITExpression
(lldb) frame variable
(td_val_t *) out = 0x00007fff5fbfe5e8
(char *) fname = 0x00000001000029b0 "bokeh_wrap.visualize"
(td_val_t *) arg1 = <variable not available>
(td_val_t *) arg2 = <variable not available>
(td_val_t *) arg3 = <variable not available>
(PyObject *) pArgs = 0x00000001073cd1e0
(lldb) print #arg1
error: unexpected '#' in program
error: 1 errors parsing expression
(lldb) expr arg1
error: Couldn't materialize struct: size of variable arg1 (8) disagrees with the ValueObject's size (0)
Errored out in Execute, couldn't PrepareToExecuteJITExpression
(lldb) expr &arg1
error: Couldn't materialize struct: size of variable arg1 (8) disagrees with the ValueObject's size (0)
Errored out in Execute, couldn't PrepareToExecuteJITExpression

Your arg variables are not available - that means that LLDB has no clue where any of them are located
Hence, the short answer would be "no, you're out of luck". One might investigate your source code/compiler settings to check why they would be unavailable (out of scope at that location? DWARF simply omitted them because they were optimized out?), but as it stands, we don't know where the variable is, we can't tell you about it.
Longer answer: are you building optimized? Any chance you can build at -O0 and still have the bug reproduce? If so, there's your solution
If this only reproduces in optimized code, it might be time to look at assembly code (LLDB has a disassemble command), and try to figure out where your program is accessing the arg variables from (registers vs some memory location) and manually issue a memory read/register read for that location, then take it from there with your inspection

Related

How to write a bash script that executes gdb on a program

I am recreating the buffer overflow from http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Buffer_Overflow/Buffer_Overflow.pdf and I would like to write a bash script that will gdb on my "stack" executable. The script will then make break points and grab the addresses of the begging (p &buffer) and end (p $ebp) of the buffer that the will be passed into ./exploit <&buffer, $ebp> as arguments.
When I run my script..
#!/bin/sh
gdb stack
b main
b 14
run
b 23
c
p &buffer
p $ebp
When I use it, gdb is opened on my executable. However, the rest of the script is not executed. I assume this is because gdb creates a new process. I have tried " gdb stack "$$" " to get gdb on the same process as my script, however unsuccessful.
Is what I am trying to do possible?
Edit:
New Script: This correctly outputs the addresses to the command line
#!/bin/sh
gdb stack << 'EOF'
b main
run
b 23
c
s
p &buffer
p $ebp
quit
EOF
How do I grab those addresses so I can pass them in as arguments to ./exploit?
Following line of my bash file will be..
./exploit <&buffer> <$ebp>
Try
gdb -batch yourfile
as supossed in man gdb.
Or look here for an example.

Syntax for passing a user-defined variable as a command option

With LLDB version 8 I'm trying to dump the code bytes for a function "fh", using the memory read command, using variables to calculate the length:
(lldb) expr unsigned $addr = (unsigned) fh
(lldb) expr unsigned $next_addr = (unsigned) fi
(lldb) expr unsigned $len = $next_addr - $addr
(lldb) p/x $addr
(unsigned int) $addr = 0x00000286
(lldb) p/x $next_addr
(unsigned int) $next_addr = 0x000002e4
(lldb) p/x $len
(unsigned int) $len = 0x0000005e
Passing $addr as the address is correctly interpreted with a literal integer as the length:
(lldb) memory read --size 1 --format x --count 0x5e $addr
0x00000286: 0xc8 0x47 0202 0x48 0xc9 0x42 ...
but passing $len as an argument to the count option fails:
(lldb) memory read --size 1 --format x --count $len $addr
error: invalid uint64_t string value: '$len'
This also happens with the breakpoint syntax, so it may be a general limitation with option parsing:
(lldb) breakpoint set -l $len
error: invalid line number: $len.
I also tried passing it through a command alias in the hope that substitution of the variable value would then happen earlier, but had similar results:
(lldb) command alias foop memory read --size 1 --format x --count %1 %2
(lldb) foop $len $addr
error: invalid uint64_t string value: '$len'
Is there some other syntax for evaluating a command with variables? I would prefer to avoid relying on the Python support as the toolchain I'm using doesn't reliably provide it.
You can tell whether an option argument will be evaluated or read in directly by looking at the help for the option. For instance, the argument to memory read is given as an <address-expression> and:
(lldb) help address-expression
<address-expression> -- An expression that resolves to an address.
but count is just of type "count" - which is just an unsigned int.
But... Another bit of lldb syntax is that if any argument or option value is surrounded by `` it is first evaluated as an expression and if the result is a scalar, that value is used for the option.
So you want to say:
memory read --size 1 --format x --count `$len` $addr

C - Variadic function compiles but gives segmentation fault

I have a variadic function in C to write in a log file, but as soon as it is invoked, it gives a segmentation fault in the header.
In the main process, the call has this format:
mqbLog("LOG_INFORMATION",0,0,"Connect",0,"","Parameter received");
and the function is defined this way:
void mqbLog(char *type,
int numContext,
double sec,
char *service,
int sizeData,
char *data,
char *fmt,
...
)
{
//write the log in the archive
}
It compiles OK. When I debug the process, the call to the mqbLog function is done, and it gives me the segmentation fault in the open bracket of the function, so I can ask about the function values:
(gdb) p type
$1 = 0x40205e "LOG_INFORMATION"
(gdb) p numContext
$2 = 0
(gdb) p sec
$3 = 0
(gdb) p service
$4 = 0x0
(gdb) p sizeData
$5 = 4202649
(gdb) p data
$6 = 0x0
Any ideas will be gratefully received.
Based on the gdb output, it looks like the caller didn't have a prototype for the function it was calling. As #JonathanLeffler noticed, you wrote 0 instead of 0.0, so it's passing an integer where the callee is expecting a double.
Judging from the pointer value, this is probably on x86-64 Linux with the System V calling convention, where the register assigned for an arg is determined by it being e.g. the third integer arg. (See the x86 wiki for ABI/calling convention docs).
So if the caller and callee disagree about the function signature, they will disagree about which arg goes in which register, which I think explains why gdb is showing args that don't match the caller.
In this case, the caller puts "Connect" (the address) in RCX, because it's the 4th integer/pointer arg with that implicit declaration.
The caller looks for the value of service in RDX, because its caller's 3rd integer/pointer arg.
sec is 0.0 in the callee apparently by chance. It's just using whatever was sitting in XMM0. Or maybe possibly uninitialized stack space, since the caller would have set AL=0 to indicate that no FP args were passed in registers (necessary for variadic functions only). Note al = number of fp register args includes the fixed non-variadic args when the prototype is available. Compiling your call with the prototype available includes a mov eax, 1 before the call. See the source+asm for compiling with/without the prototype on the Godbolt compiler explorer.
In a different calling convention (e.g. -m32 with stack args), things would break at least a badly because those args would be passed on the stack, but int and double are different sizes.
Writing 0.0 for the FP args would make the implicit declaration match the definition. But don't do this, it's still a terrible idea to call undeclared functions. Use -Wall to have the compiler tell you when your code does bad things.
You function might still crash; who knows what other bugs you have in code that's not shown?
When your code crashes, you should look at the asm instruction it crashed on to figure out which pointer was bad — e.g. run disas in gdb. Even if you don't understand it yourself, including that in a debugging-help question (along with register values) can help a lot.

gdb showing different address than in code

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)

calling a function using expr during an LLDB session

I'm trying to get a better grasp of LLDB and am currently stuck trying to call a locally defined function (using LLDB's expr) while debugging some code. For the sake of simplicity, lets consider this toy code:
testing_lldb.c:
unsigned long factorial(unsigned input) {
unsigned long ret_val = 0;
if (input == 0)
ret_val = 1;
else
ret_val = input * (factorial(input-1));
return ret_val;
}
I compile it like this:
$ clang -g -Weverything -c lldb_test.c
and then run LLDB by typing:
$ lldb testing_lldb.o
In my LLDB session, I'd like to be able to call factorial(). My first attempt:
(lldb) expr unsigned long i = factorial(i);
error: 'factorial' has unknown return type;
cast the call to its declared return type
The error message includes a clear hint, so I try again:
(lldb) expr unsigned long i = (unsigned long)factorial(i);
error: warning: function 'factorial' has internal linkage but is not defined
note: used here
error: Can't run the expression locally: Interpreter doesn't handle one of the expression's opcodes
Fine, I try to define factorial() manually by following the answer for this SO question:
(lldb) expr typedef unsigned long (*$factorial_type)(unsigned)
(lldb) expr $factorial_type $factorial_function = ($factorial_type)0x0000000000000000
(lldb) expr unsigned long i = (unsigned long)factorial(i);
error: warning: function 'factorial' has internal linkage but is not defined
note: used here
error: Can't run the expression locally: Interpreter doesn't handle one of the expression's opcodes
And this gives me exactly same error as above. I double checked the starting address of factorial() by running:
(lldb) image lookup -Avi -n factorial
Question
Given testing_lldb.c, what's required to be able to use factorial() in expressions in LLDB?
Some details regarding the enviroment:
$ uname -r
3.16.0-4-amd64
$ lldb -v
lldb version 3.4.2 ( revision )
$ clang -v
Debian clang version 3.4.2-14 (tags/RELEASE_34/dot2-final) (based on LLVM 3.4.2)
Target: x86_64-pc-linux-gnu
You can only use the expression parser to evaluate expressions that run functions if you are debugging a live process. You are not only not debugging a live process, but you are also debugging a .o file - which isn't fully linked - so it could never run. lldb can inspect .o files, dump the symbol tables and some things like that, but not everything will work.
You want to add a little main function to your "testing_lldb.c", and build a runnable program (drop the -c flag.) Then set a breakpoint on main:
(lldb) break set -n main
run the program
(lldb) run
then when you hit the breakpoint, try calling your function.

Resources