OpenDis
-------

Author:		Joxean Koret
Location:	Basque Country
License:	GPL v2

What is called "OpenDis"?
-------------------------

OpenDis is an "assembly beautifier" tool created with the aim to make easier the life
of a security researcher in the job of finding vulnerabilities by reading raw assembler
code, that is, doing an static analysis.

Please, remember that it's not IDA Pro -- but is cheaper ;) --

What it does?
-------------

It encapsulates as "PROCEDURES" the functions, breaks the code when it found a branch, call
or jump like instruction, relationates variables with the .rodata section, identifies local
variables, function arguments, highlights error prone blocks and analyzes various common
vulnerable constructions (currently only strcpy and printf are checked) and, when working 
with stripped binaries, tries to identify procedures.

It also "tries" to show only the code the programers wrote and identifies functions even if
the binary is stripped.

How can I do a binary diff?
---------------------------

First of all, you need to convert the binaries to the OpenDis database format. If you want
to known who to do this read the section "How to create OpenDis databases". After you
created your database (the first and the second binary versions of an executable, object,
or library) you will need to execute a command like the following:

$INGUMA_DIR/dis/> ./asmdiff.py original.db fixed.db windiff.exe

or

$INGUMA_DIR/dis/> ./asmdiff.py original.db fixed.db kompare

The last option is the command to run to see the differences. You can run a simple "diff",
but a graphical tool is recommended.

How to create OpenDis databases
-------------------------------

To create a database in OpenDis format you need to execute a command like the following:

$INGUMA_DIR/dis> ./dis.py binary.o -s=binary.db

An OpenDis database with the name binary.db will be created.

What is the format of OpenDis databases?
----------------------------------------

OpenDis database are Python's [c]pickle objects so, be carefull using databases that comes
from untrusted sources...

OpenDis fails when decompiling *.a objects!
-------------------------------------------

Yes, is a known issue. As a workaround, extract all object files from the *.a file and
analyze all of these one per one.

Will be fixed in future versions.

What platforms it support?
--------------------------

OpenDis runs in any platform in which Python and objdump (will make use of it internally)
runs. But, if the question is what CPUs are supported, at the moment, only x86 and AVR are
supported ones.

It's stupid! It doesn't found a mistake with the common XXX construction?
-------------------------------------------------------------------------

Hack the asmcallbacks module and send me back the changes ;) I will add these to the next 
releases.

How can it found procedures/functions in stripped binaries?
-----------------------------------------------------------

For x86 based processors by looking for the sequence of instructions:

	push	%ebp
	mov	%esp, %ebp

For AVR based ones by looking for the sequence of instructions:

	push	r28
	push	r29

Well, using "advanced anti-reverse engineering" techniques it can be defeated but is an
approach. I'm very interested in adding (in the near future, who knowns when...) a flow
analysis module which can detect these kind of anti-reverse engineering techniques easy.


How can I add support for another processor, such as MIPS?
----------------------------------------------------------

Take a look to the file asmconstants.py. You will need to add another key to the following
dictionary objects:

	AVAILABLE_CPUS
	IGNORE_INSTRUCTIONS
	INTERESTING_INSTRUCTIONS
	USER_CONTROLLED_DATA
	FUNCTION_START
	FUNCTION_END

OpenDis can't disassemble my <very-strange-architecture>!
---------------------------------------------------------

You need to recompile "objdump" with the --enable-targets=all (recommended) flag or get
a working copy of objdump which is aware of your <very-strange-architecture>.

In example, in Debian based distributions do the following:

$ apt-get source binutils
(...bla, ble, bli, blo, blu...)
$ tar -xvzf binutils-*
(...more bla, ble, and blu...)
$ cd binutils-*
$ ./configure --enable-targets=all && make && su -c "make install"

I can't use it in Win32!
------------------------

Yes, you can. But you need to:

	1. Get a copy of objdump(.exe) and nm(.exe) for Windows. You can use "mingw"
	   or "cygwin", in example.
	2. Change the following lines with the path where you installed the binaries:

		OBJDUMP = "/usr/local/bin/objdump" 
		NM = "/usr/local/bin/nm"

Any sample of a dis.py generated file, please?
----------------------------------------------

Imagine the following vulnerable C program:

$ cat vuln.c

#include <stdio.h>

int main(int argc, char *argv[])
{
char buf[10];

	if (argc > 1) {
		strcpy(buf, argv[1]);
		printf("You say: %s\n", buf);
	}
}

Try running dis.py against the compiled target program by typing:

$ ./dis.py vuln -j -r 

The following output will be generated:

;
; File generated by OpenDis v0.0.1 - C Disassembler & Future Decompiler ;)
; Disassembly code for 'vuln'
;

PROCEDURE main AT ADDRESS 0x08048398
BEGIN ASM
    main:
        0x08048398: push   %ebp
        0x08048399: mov    %esp,%ebp
        0x0804839b: sub    $0x18,%esp           ;24
        0x0804839e: and    $0xfffffff0,%esp             ;4294967280L
        0x080483a1: mov    $0x0,%eax
        0x080483a6: add    $0xf,%eax            ;15
        0x080483a9: add    $0xf,%eax            ;15
        0x080483ac: shr    $0x4,%eax            ;4
        0x080483af: shl    $0x4,%eax            ;4
        0x080483b2: sub    %eax,%esp

    ;
    ; Start: Programmers code starts here?
    ;
    main+0x1a:
        0x080483b4: cmpl   $0x1,argc            ;1
        0x080483b8: jle    080483e4 <main+0x4c>

    main+0x22:
        0x080483ba: mov    argv,%eax
        0x080483bd: add    $0x4,%eax            ;4
        0x080483c0: mov    (%eax),%eax
        0x080483c2: mov    %eax,func_argument_1
        0x080483c6: lea    local_size_10,%eax
        0x080483c9: mov    %eax,(%esp)
        0x080483cc: call   080482e8 <strcpy@plt>
        ; CHECK: Usage of strcpy (Hit 1)

    main+0x39:
        0x080483d1: lea    local_size_10,%eax
        0x080483d4: mov    %eax,func_argument_1
        0x080483d8: movl   $0x80484d8,(%esp)            ;'You say: %s\n'
        0x080483df: call   080482d8 <printf@plt>
        ; CHECK: Usage of printf (Hit 2)

    main+0x4c:
        0x080483e4: leave
        0x080483e5: ret
END ASM;

;
; Interesting jmps/calls in 'vuln'
;
;       call   *%eax; 0x08048338 <call_gmon_start+0x1c>
;       call   *%edx; 0x0804835d <__do_global_dtors_aux+0x19>
;       call   *%eax; 0x08048392 <frame_dummy+0x1f>
;       call   *%eax; 0x0804849a <__do_global_ctors_aux+0x16>

;
; Report of presumable error prone blocks
;
;
; 1) Usage of strcpy in function main:
;
;       0x080483ba: mov    argv,%eax
;       0x080483bd: add    $0x4,%eax            ;4
;       0x080483c0: mov    (%eax),%eax
;       0x080483c2: mov    %eax,func_argument_1
;       0x080483c6: lea    local_size_10,%eax
;       0x080483c9: mov    %eax,(%esp)
;       0x080483cc: call   080482e8 <strcpy@plt>
;
;
;
; 2) Usage of printf in function main:
;
;       0x080483d1: lea    local_size_10,%eax
;       0x080483d4: mov    %eax,func_argument_1
;       0x080483d8: movl   $0x80484d8,(%esp)            ;'You say: %s\n'
;       0x080483df: call   080482d8 <printf@plt>
;
;
;
; Total of 2 hit(s). Happy haunting!

BTW, a asmdiff.py tool is in the way.


