GDB on any executable? - debugging

Is it possible to use the GNU debugger on executables that were not compiled with GNU tools(gcc, gas, g++) and dump the assembly code?

Yes, you can use gdb on any executable. Without debugging symbols, some of the commands won't work, but there's plenty of commands that work at the assembly level. stepi to single-step instructions, you can print registers (using C-like expression syntax: print $rbx+($rax<<$rcx)) and modify them.
But for generating an assembly dump of the whole program, objdump -d is easier. objdump -D if there's code in weird places (which is sometimes the case with malware). And objdump -s for a view of the data segment.

Related

Use dtrace, lldb or gdb to find which file or line of code was responsible for a line of output in stdout or stderr?

I see a string being output to my Terminal, when I ran an executable. I have the source code (in C) of the executable, but it was not written by me. I compiled it with -g flag. Is there any way to know which line in which file resulted in the output, with dtrace, lldb, gdb, or any other means?
I am using macOS 10.13. When I ran gdb and the following:
catch syscall write
I got this error:
The feature 'catch syscall' is not supported on this architecture yet.
Is there any way that can achieve my goal?
lldb tends to be better supported on macOS than gdb. You should be able to trace this call by using its conditional breakpoint feature.
While you can certainly trace the write() call with dtrace and get a stack trace using the ustack() action, I think you'll have a harder time pinpointing the state of the program than if you break on it in the debugger.
Your comment suggests you might be searching for a substring match. I suspect you can create a conditional breakpoint in lldb that matches a substring using something like this:
br s -n write -c 'strnstr((const char*)$rsi, "test", $rdx) != NULL'
I'm assuming lldb does not have argument names for the write function, so I'm using x86-64 calling convention register names directly. ($rdi = first argument, which would be the file descriptor; $rsi = second argument, buffer; $rdx = third argument, buffer length)

How can I make bash execute an ELF binary from stdin?

For some obscure reason I have written a bash script which generates some source code, then compiles it, using
... whatever ... | gcc -x c -o /dev/stdout
Now, I want to execute the result on the compilation. How can I make that happen? No use of files please.
As Charles Duffy said, to execute a binary, you'd have to tell your operating system (which seems to be a Unix variant) to load and execute something – and Unix systems only take files to execute them directly.
What you could do is have a process that prepares a memory region containing the ELF binary, fork and jump into that region - but even that is questionable, considering that there's CPU support to suppress exactly that operation (R^X). Basically, what you need is a runtime linker, and shells do not (and also: should not) include something like that.
Let's drop the Bash requirement (which really just sounds like you're trying to find an obvious hole in an application that is older than I am grumpy):
Generally, requiring ELF (which is a file format) and avoiding files at the same time is a tad complicated. GCC generates machine code. If you just want to execute known machine code, put it into some buffer, build a function pointer to that and call it. Simple as that. However, you'd obviously don't have all the nice relocation and dynamic linking that the process of executing an ELF binary or loading a shared object (dlopen) would have.
If you want that, I'd look in the direction of things like LLVM – I know, for a fact, that there's people building "I compile C++ at runtime and execute it" with LLVM as executing instance, and clang as compiler. In the end, what your gcc|something is is really just JIT – an old technology :)
If your goal is to not write to the filesystem at all, then neither bash nor any other UNIX program will be able to help you execute an ELF from a pipe - execve only takes a path to a regular file as its filename and will fail (setting errno to EACCES) if you pass it a special file (device or named pipe) or a directory.
However, if your goal is to keep the executable entirely in RAM and not touch the hard disk (perhaps because the disk is read-only) you can do something with the same effect on your machine by using tmpfs, which comes with many UNIX-like systems (and is used in Linux to implement semaphores) and allows you to create a full-permissions filesystem that resides entirely in RAM:
$ sudo mount -t tmpfs -o size=10M tmpfs /mnt/mytmpfs
You can then write your binary to that:
... whatever ... | gcc -x c -o /mnt/mytmpfs/program.out
/mnt/mytmpfs/program.out
and bash will load it for you as if it was on disk.
Note, however, that you do still need enough RAM onboard the device to store and execute the program - though due to the nature of most executable binaries, you would need that anyway.
If you don't want to leave the program behind on your ramdisk (or normal disk, if that is acceptable) for others to find, you can also delete the file immediately after starting to execute it:
/mnt/mytmpfs/program.out &
rm /mnt/mytmpfs/program.out
The name will disappear immediately, but the process will internally hold a hard link to that file, then release that hard link when it terminates, allowing the file to be immediately deleted from disk. (However, the storage won't actually be freed until the program exits, and the program will not be able to exec itself either).

what do the "-o" "-f" "-c" and "-g" etc mean in make?

I'm reading up on makefiles for my C++ program, and from this article http://myweb.stedwards.edu/laurab/help/makefilehelp.html
My understanding is that:
-o somefile :
specifies that any files after somefile will be outputted to somefile
-c somefile :
stops somefile from linking/compiling unless it is updated and ran
although I'm not sure because the manual: http://linux.die.net/man/1/g++
simply states that -c will stop the linker from running.
-g somefile:
spits out debugging information
Also, I found no information regarding -f from the manual, and explanations on what they do were scarce in all the makefile tutorials I read. I'm guessing this might be basic info, but I can't find what they do in the manual..
Also, is there a command for g++ in command prompt that allows me to look up the uses of commands like these?
Ex HELP "-f" except that doesn't work...
-o file
This will simply specify the output file name. By default, I think it is a.out
-c
When calling g++ with -c, it will only compile, without performing the link operation.
This is very useful in big project, so you can compile file by file and link afterward. This way, you do not have to recompile the whole project when you edit just one file.
-g N
-g will specify the level of debugging symbols you want to add. g++ can add a lot of symbols when compiling that can be read later on by debuggers like gdb. Usually, when you develop, you compile with -g 3. Be careful to remove it for the release. It makes the binary much bigger and slower.
Depending on this, you will have more or less information within gdb.
-f
Within g++, -f is not a flag by itself, it just a prefix. However, in your example, -f is not sent to g++ but to make. As said in the previous anwser, -f for make specify which Makefile to use.
The -f flag in make is defined as follows,
make -f makefile Specifies a different makefile. The argument makefile is a pathname of a description file, which is also referred to as the makefile. A pathname of '-' shall denote the standard input. There can be multiple instances of this option, and they shall be processed in the order specified. The effect of specifying the same option-argument more than once is unspecified.

Output from fortran application not showing up in Matlab

I'm having some issues with output from a fortran application being executed from within Matlab. We use Matlab to call a number of fortran applications and to display output and results.
I'm using gfortran on OSX to build one of these programs, which does a large amount of file output and a little output to stdout to track progress. stdout output is accomplished mainly through print * statements, but I've tried write( * , * ) as well. The program uses OpenMP, but none of the print * or write( * , * ) statements are performed within OpenMP parallel sections.Everything works fine when the program is executed from a terminal. However, when the program is executed from within matlab, there is no output from stdout. The file output works fine though.
Additionally, the same code, when compiled with Intel's ifort, displays its output in matlab without issue. Unfortunately I don't have regular access to the Intel compiler.
I'm positive that the output is going to stdout (not stderr), and I've tried flushing both from within the code (call flush(6) & call flush(0)), but this doesn't seem to make a difference.
I'm not sure what could be causing this. Any thoughts?
some relevant information:
OS: OSX 10.6.8 (64bit mode)
Matlab: R2012b
gfortran: 4.7.2 (obtained via fink)
compile flags: -cpp -fopenmp -ffree-line-length-0 -fno-range-check -m64 -static-libgfortran -fconvert=little-endian -fstrict-aliasing
EDIT:
I've done some more testing, creating a simple 'hello' program:
program printTest
write (*,*) 'hello'
end program
compiled with...
gfortran test.f90 -o test
which exhibits the same behavior.
I've also tried compiling with an earlier version of gfortran (4.2.1), which produced some interesting results. it executes fine in terminal, but in matlab I get the following:
!./test
dyld: lazy symbol binding failed: Symbol not found: __gfortran_set_std
Referenced from: /Users/sah/Desktop/./test
Expected in: /Applications/MATLAB_R2012b.app/sys/os/maci64/libgfortran.2.dylib
dyld: Symbol not found: __gfortran_set_std
Referenced from: /Users/sah/Desktop/./test
Expected in: /Applications/MATLAB_R2012b.app/sys/os/maci64/libgfortran.2.dylib
./test: Trace/breakpoint trap
This leads me to believe its a library issue. using -static-libgfortran produces the same result in this case.
I believe Matlab is a single threaded application. When you invoke a multithreaded executive, I have seen various issues with piping the output back to Matlab. Have you considered recompiling into a Fortran mex file?
I am not sure a mex file would print to stdout any better than a standalone executable.
There are other options. One is to write(append) all your diagnostics to a file and just look at the file when you want to. Emacs, for example, automatically "revert"s the contents of a file every second or whatever you set the interval to. Another option might be to convert the fortran source into matlab source (see f2matlab) and keep it all in matlab.
bb
According to the system function documentation
[status, result] = system('command') returns completion status to the status variable and returns the result of the command to the result variable.
[status,result] = system('command','-echo') also forces the output to the Command Window.
So you should use '-echo' parameter to the system call to see the output directly in the command window
system(['cd "',handles.indir,'";chmod u+x ./qp.exe',... ';./qp.exe'], '-echo')
or you can assign the stdout to a variable:
[ret txt] = system(['cd "',handles.indir,'";chmod u+x ./qp.exe',... ';./qp.exe'])

DOS debug like program for 32-bit x86 assembly

Many of you may recall the old DOS program--debug. Though outdated in many respects, one of the nice things about it was that one could easily find the byte-sequence for a given instruction without having to go through the steps of writing a program, compiling, disassembling, examining the file contents, .... Enter the instruction, then dump the instruction address. 'debug' regrettably does not do 32 bit instructions.
Does anyone know of a tool that does something similar for 32-bit x86 instructions? I don't want to go through the whole compile process; I just need to be able to enter a couple of instructions and have it spew out the length of the instruction and its byte sequence.
DOS debug was an interactive assembler as well as a debugger, entering assembly code resulted in that line being converted immediately to machine code - which is what you dumped out.
So all you need is to automate your favourite assembler with a script or batch-file.
Here's a bash function I came up with in a minute or two using the popular nasm assembler:
opcode() {
echo $* > tmp.S && nasm tmp.S -o tmp.o && od -x tmp.o
rm -f tmp.o tmp.S
}
Takes less than a second. Invocation looks like this:
$ opcode mov eax, [ebx]
0000000 6667 038b
0000004
$ opcode fadd st0,st1
0000000 c1d8
0000002
Not brilliant, but you can tweak od command-line for better output. This idea should work with any command-line assembler as long as you tell it to use a simple binary output format.
There are a few simple, 32-bit command line debuggers to be found. Based on your description, OllyDbg might fit your needs well. At least some versions of Microsoft's Debugging Tools for Windows include one named CDB, which stands for Commandline DeBugger (though I haven't verified that the linked version includes it...)

Resources