# Binary Analysis Process

Up to now, we know how ELF files are structured, but the question remains: **how do we analyse ELF files?**

A possible flow can be:

* File analysis (`file`, `nm`, `ldd`, content visualization, `foremost`, `binwalk`).
* Static Analysis (disassemblers and decompilers).
* Behavioural Analysis (`strace`, `LD_PRELOAD`).
* Dynamic Analysis (debuggers).

## Identifying a file

Files should be seen as containers (this includes ELF files).

* May have the expected content type.
  * But it may have unexpected behaviour (e.g. bug or malware).
* May have unexpected, additional content (e.g. polyglots).
  * More common in DRM schemes and malware to hide binary blobs.

Files should not be trusted.

* Both the expected and additional content may be malicious.
* Static analysis is safe (as long as nothing is executed).
* Dynamic analysis is not safe. Sandboxes and VMs must be used.

### Questions to answer

* What type of file do we have?
  * Are there hidden contents?
* What is the architecture?
* Is it 64/32 or ARM7/ARM9/ARM9E/ARM10?
* Where is the starting address?
* What does the main function do?
* What will the program do?

Some basic tools go a long way.

* `file`: (try to identify) the type of file.
  * Only applies to a top container. `file` is not able to look into enclosed binary blobs.
  * Alternatives that complement `file` are `binwalk` and `foremost`.
* `xxd`: hexdump the file, allowing for rapidly detecting patterns.
  * `less` also helps to hold the content in the terminal.
* `strings`: prints null-terminated sequence chars.
  * By default, with more than 4 characters (-n setting).
* `ldd`: print shared object dependencies.
  * Libraries registered in the ELF are required (typically for dynamically relocated symbols).
* `nm`: dumps symbols from `.symtab` (or `.dyntab` with `–D`).

## Disassembler Basics  `ghidra`

* `ghidra` is an open-source tool developed by the NSA and released to the public doing Disassembly and Static Analysis.
  * The development branch has support for Dynamic Analysis (should be released “soon”).
* Works on Windows, Linux and macOS (Java-based).
* Not the most important tool (IDA is), but is gaining huge traction. It’s free and very powerful with a huge number of platforms and a **fine decompiler**.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FPIbyPR4dxQpdrWxUiVV2%2FScreenshot%20from%202024-03-27%2019-30-19.png?alt=media&#x26;token=16a644d3-4187-4cf8-8ee1-b842a5feb79c" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2F3G47hMRHulynOvdNpOSD%2FScreenshot%20from%202024-03-27%2019-31-11.png?alt=media&#x26;token=dff2e868-63ea-4827-bcce-4fac6236e5f4" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FA0saTwFhsyLsncC98pcr%2FScreenshot%20from%202024-03-27%2019-31-24.png?alt=media&#x26;token=c4715e6b-9b37-4a44-9e13-ebc4b0f3a9b5" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2Fe6V4dthPtlu0UR63AcVa%2FScreenshot%20from%202024-03-27%2019-31-38.png?alt=media&#x26;token=a60bd1c6-4f05-4866-a5a7-19f6b189e98e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FXQm8bJ2xgcFB9Ppzgx12%2FScreenshot%20from%202024-03-27%2019-31-50.png?alt=media&#x26;token=4daa40ee-f1d2-4820-995b-14e0770aaf87" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FgOu4yLrbuOTOFaqR5GHE%2FScreenshot%20from%202024-03-27%2019-32-09.png?alt=media&#x26;token=db43304e-3b22-4dc5-a6e6-b7d8d0cc7b04" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FPhVFfquRsU0LXbWEaVry%2FScreenshot%20from%202024-03-27%2019-32-24.png?alt=media&#x26;token=9748264f-5911-4120-af2a-ee0879cda915" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FzA6yKyD2aMU0FVkX0SIt%2FScreenshot%20from%202024-03-27%2019-32-36.png?alt=media&#x26;token=1980a569-5c19-4d71-bdeb-9ab367277021" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FWU6auLKL3RHesVt0lPye%2FScreenshot%20from%202024-03-27%2019-33-02.png?alt=media&#x26;token=b98635d8-8687-42de-b1f4-d4fc40c2fd9e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FgkLPiJFMHt1DxE828lDW%2FScreenshot%20from%202024-03-27%2019-33-23.png?alt=media&#x26;token=b0db643c-4c4e-4ec8-bd56-edd0cb326bd7" alt=""><figcaption></figcaption></figure>

## CFGs

It is useful to think of machine code in a graph structure, called a control-flow graph.

A node in a CFG is a group of adjacent instructions called a **basic block**:

* The only jumps into a basic block are to the first instruction.
* The only jumps out of a basic block are from the last instruction.
* I.e., a basic block always executes as a unit.

Edges between blocks represent possible jumps.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2Fy5OoKje03R58887Scog2%2Fimage.png?alt=media&#x26;token=75db9d3e-e3d8-4dbe-8bf4-3bbfe1961627" alt=""><figcaption></figcaption></figure>

Basic block _a_ dominates basic block _b_ if every path to _b_ passes through _a_ first. Strictly dominates if _a != b_.

Basic block _b_ post-dominates _a_ if every path through _a_ also passes through _b_ later.

## Disassembly

The disassembly process involves analyzing the binary and converting binary code to assembly.

* But “binary” is just a sequence of bytes, that must be mapped in the scope of a given architecture.
* Conversion depends on many factors, including compiler and flags.

The process is not perfect and may induce RE Analysts in error.

* Present instructions that do not exist.
* Ignore instructions that are in the binary code.

Main approaches:

* Linear Disassembly.
* Recursive Disassembly.

### Linear Disassembly

The simplest approach towards analyzing a program: **Iterate over all code segments, disassembling the binary code as opcodes are found**.

Start at some address and follow the binary.

* Entry point or other point in the binary file.
* The entry point may not be known.

Works best with:

* binary blobs such as from firmware (start at the beginning).
* objects which do not have data at the beginning.
* architecture uses variable length instructions (x86).

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FDQ4xtZWmSeU39in5poJa%2Fimage.png?alt=media&#x26;token=a28b55ec-efbb-45c9-b426-9a874cff3542" alt=""><figcaption></figcaption></figure>

It is vital to define the initial address for decompiling.

An offset error will result in invalid or wrong instructions being decoded.

Linear disassembly will also try to disassemble data from the binary as if it were actual code.

Linear Disassembly is oblivious to the actual Program Flow.

With x86, because each opcode has a variable length, the code tends to auto-synchronize, but the first instructions will be missed.

#### Issues

With ELF files in x86, linear disassembly tends to be useful.

* Compilers do not emit inline data and the process rapidly synchronizes.
* Still, padding and alignment efforts may create some wrong instructions.

With PE files, compilers may emit inline data and Linear Disassembly is not adequate.

* Every time data is found, disassembly becomes desynchronized.

Other architectures (ARM) and binary objects usually are not suited for Linear Disassembly.

* Obfuscation may include code as data, which is loaded dynamically.
* Fixed-length instruction sets will not easily synchronize.

#### So why is it useful?

Code in the binary blob may be executed with a dynamic call.

* Some JMP/CALL with an address computed dynamically and unknown to the static analyzer.

Linear Disassembly will decompile everything:

* whether or not it is called - May be useful to uncover hidden program code.
* even if the binary blob is not a structured executable – Boot sector, firmware.

Readily available with simple tools: objdump and gdb.

* Gdb memory dump (x/i) will also use Linear Disassembly.

### Recursive Disassembly

A more complex approach that disassembles code from an initial point, **while following the control flow**.

* That is: follows **jmp**, **call** and **ret**.

**As long as the start point is correct**, or it synchronizes rapidly, flow can be fully recovered.

* This is the standard process for more complex tools such as **ghidra** and **IDA**.

Goes around inline data as no instruction will exist that will make the program execute at such an address.

* Well… control flow can easily be forged with `((void (`_`)(int, char`_`)) ptr)()`.

<figure><img src="https://1103423335-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FvyEajzuIz0PAtDiV6JcU%2Fuploads%2FQ5xXaaeWRNLiFrbTV8j5%2FScreenshot%20from%202024-03-27%2022-04-23.png?alt=media&#x26;token=baa3736b-502b-44e3-b433-a6ac42a2aee8" alt=""><figcaption></figcaption></figure>
