> For the complete documentation index, see [llms.txt](https://sansong.gitbook.io/cyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sansong.gitbook.io/cyber/rev/anti-debugging/nanomites.md).

# Nanomites

Les **nanomites** sont une technique anti-debug qui utilise 2 processus qui se tracent mutuellement et communiquent pour s'assurer de la survie de l'autre.

L'idée est que:

* Deux processus existent, un père s'occupe du fils&#x20;
* Le père s'attache au fils avec des API de débogage (sous Linux : [<mark style="color:red;">ptrace</mark>](/cyber/rev/anti-debugging/ptrace.md))&#x20;
* Les deux processus communiquent entre eux pendant l'exécution

Le fils utilise des exceptions et appels systèmes pour donner le contrôle au père qui peut modifier sa mémoire et ses registres avant de lui redonner la main.

{% hint style="success" %}
C'est l'idée principale, en pratique il y a pleins de façons différentes de le faire. Il peut y avoir plusieurs niveaux de traçage entre les processus (par exemple un processus père qui contrôle un processus qui lui-même en contrôle un autre, etc.)
{% endhint %}

## Exemple sous Linux

1. Un processus parent créé un fils avec <mark style="color:red;">`fork`</mark>
2. Quand le père s'exécute il appelle <mark style="color:red;">`waitpid`</mark> et se met en pause jusqu'à un changement d'état du processus fils
3. Le fils appelle <mark style="color:red;">`child_subroutine`</mark>

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FNlf10apn2KPkr4yBkJES%2FCapture%20d'%C3%A9cran%202024-04-21%20161723.png?alt=media&amp;token=520612cf-dc18-4aae-8cf1-3da4a38439ff" alt="" width="563"><figcaption></figcaption></figure>

4. Le fils utilise <mark style="color:red;">`ptrace`</mark> avec la requête <mark style="color:red;">`PTRACE_TRACEME`</mark> pour empêcher un debugger de s'y attacher (un processus ne peut être tracé que par un autre processus à la fois)
5. Il défini un handler qui sera exécuté quand le signal 8 ([<mark style="color:red;">SIGFPE</mark>](https://www.linuxtricks.fr/wiki/signaux-unix-unix-signals)) sera déclenché
6. Il déclenche le signal 8 avec une division par zéro

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2Flr1SfDcgUTXJk2aHqZDB%2FCapture%20d'%C3%A9cran%202024-04-21%20161926.png?alt=media&amp;token=4e760527-1c5b-4ede-a82e-70163858152c" alt="" width="558"><figcaption></figcaption></figure>

7. Le père reprend le contrôle et peut modifier les registres et la mémoire du fils avant de lui redonner la main

Si on exécute le code avec <mark style="color:red;">`strace`</mark> on voit les signaux et les registres accédés/modifiés.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FBCftfpjyfXFv4eekyc83%2FELF%20x64%20-%20Nanomites_strace.png?alt=media&amp;token=26b9a07e-083e-471f-bd72-ad4653b92757" alt=""><figcaption></figcaption></figure>

Etant donné qu'on ne peut pas débugger le fils, il faut bien comprendre comment les 2 communiquent. La logique du programme est en principe à l'intérieur du processus fils protégé.

**Contrôle du fils par le père**

|                                                                                                    Requête                                                                                                   |                                                         Actions sur le processus fils                                                        |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------: |
| <p><mark style="color:red;"><code>PTRACE\_PEEKTEXT</code></mark></p><p><mark style="color:red;"><code>PTRACE\_PEEKDATA</code></mark></p><p><mark style="color:red;"><code>PTRACE\_PEEKUSER</code></mark></p> |                                                             Lecture de la mémoire                                                            |
| <p><mark style="color:red;"><code>PTRACE\_POKETEXT</code></mark></p><p><mark style="color:red;"><code>PTRACE\_POKEDATA</code></mark></p><p><mark style="color:red;"><code>PTRACE\_POKEUSER</code></mark></p> |                             <p>Modification de la mémoire<br><em>(par exemple de son code avec POKETEXT)</em></p>                            |
|                                    <p><mark style="color:red;"><code>PTRACE\_GETREGS</code></mark></p><p><mark style="color:red;"><code>PTRACE\_SETREGS</code></mark></p>                                    | <p></p><p>Lecture des registres<br>Modification des registres<br><em>(par exemple de rip pour modifier le flux d'exécution du fils)</em></p> |

{% hint style="success" %}
Liste des requêtes ptrace: <https://sites.uclouvain.be/SystInfo/usr/include/sys/ptrace.h.html>
{% endhint %}

## Deal with Nanomites

### Hook ptrace avec LD\_PRELOAD

{% hint style="success" %}
D'après ce [writeup](https://blog.efiens.com/post/midas/justctf2020-re-writeups/)
{% endhint %}

```c
long int ptrace(enum __ptrace_request __request, ...){
    pid_t caller = getpid();
    va_list list;
    va_start(list, __request);
    pid_t pid = va_arg(list, pid_t);
    void* addr = va_arg(list, void*);
    void* data = va_arg(list, void*);
    long int (*orig_ptrace)(enum __ptrace_request __request, pid_t pid, void *addr, void *data);
    orig_ptrace = dlsym(RTLD_NEXT, "ptrace");
    long int result = orig_ptrace(__request, pid, addr, data);
    if (__request == PTRACE_SETREGS){
        unsigned long rip = *((unsigned long*)data + 16);
        printf("SETREGS: rip: 0x%lx\n", rip);  
    } else if (__request == PTRACE_POKETEXT){
        printf("POKETEXT: (addr , data) = (0x%lx , 0x%lx)\n", (unsigned long)addr - 0x555555554000, (unsigned long)data);
    }
    return result;
}
```

{% hint style="warning" %}
À adapter en fonction des requêtes utilisées par <mark style="color:red;">`ptrace`</mark>
{% endhint %}

```sh
gcc -shared -fPIC -ldl ptrace_hook.c -o ptrace_hook.so
```

```python
from pwn import *
r = process("./supervisor", env={"LD_PRELOAD":"./ptrace_hook.so"}, aslr=False)
r.interactive()
```

### Identifier vers quels registres pointent les variables

Les registres du fils sont récupérés comme ça:

```c
ptrace(PTRACE_GETREGS, pid, 0LL, regs)
```

<mark style="color:red;">`regs`</mark> pointe vers la structure <mark style="color:red;">`user_regs_struct`</mark> définié dans <mark style="color:red;">`sys/user.h`</mark>

```c
// <sys/user.h>
struct user_regs_struct {
  unsigned long r15;
  unsigned long r14;
  unsigned long r13;
  unsigned long r12;
  unsigned long rbp;
  unsigned long rbx;
  unsigned long r11;
  unsigned long r10;
  unsigned long r9;
  unsigned long r8;
  unsigned long rax;
  unsigned long rcx;
  unsigned long rdx;
  unsigned long rsi;
  unsigned long rdi;
  unsigned long orig_rax;
  unsigned long rip;
  unsigned long cs;
  unsigned long eflags;
  unsigned long rsp;
  unsigned long ss;
  unsigned long fs_base;
  unsigned long gs_base;
  unsigned long ds;
  unsigned long es;
  unsigned long fs;
  unsigned long gs;
};
```

Souvent le code décompilé utilise une variable <mark style="color:red;">`regs`</mark> dont la taille est inférieure à celle de la structure <mark style="color:red;">`user_regs_struct`</mark> et les registres sont accédés avec d'autres variables.

{% hint style="danger" %}
Ici <mark style="color:red;">`regs`</mark> ne fait que 96 octets alors que <mark style="color:red;">`user_regs_struct`</mark> en fait 216 (27\*8)

-> les variables <mark style="color:red;">`v13`</mark> à <mark style="color:red;">`v16`</mark> pointent vers des registres de la structure
{% endhint %}

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2F4FXP0XT6qe3ZARbocEe8%2Fa.png?alt=media&amp;token=e9075b5c-64d0-4c8e-a8f2-c641280be74f" alt=""><figcaption></figcaption></figure>

Pour savoir laquelle pointe vers quel registre on peut utiliser les indications au début de la fonction:

```c
char regs[96]; // [rsp+20h] [rbp-118h] BYREF
__int64 v13; // [rsp+80h] [rbp-B8h]
__int64 v14; // [rsp+88h] [rbp-B0h]
__int64 v15; // [rsp+90h] [rbp-A8h]
__int64 v16; // [rsp+A0h] [rbp-98h]
__int64 v17; // [rsp+F8h] [rbp-40h]
```

On connait leur offset par rapport à <mark style="color:red;">`rbp`</mark> et donc la taille de chaque variable:

* **regs:** <mark style="color:orange;">`0x118 - 0xB8 = 0x60 = 96 octets`</mark>
* **v13:** <mark style="color:red;">`0xB8 - 0xB0 = 0x8 = 8 octets`</mark>
* **v14:** <mark style="color:orange;">`0xB0 - 0xA8 = 0x8 = 8 octets`</mark>
* **v15:** <mark style="color:red;">`0xA8 - 0x98 = 0x10 = 16 octets`</mark>
* **v16:** <mark style="color:orange;">`0x98 - 0x40 = 0x58 = 88 octets`</mark>

Sachant que chaque élément de la structure fait 8 octets on peut faire le mapping.

<figure><img src="https://1813806532-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZRRTPIEA4wb6exZozwS0%2Fuploads%2FR3Xo5VR9fl6ANv9zWFHs%2Fnanocombattants_father_child2.drawio.png?alt=media&amp;token=ebe727aa-0a37-4aed-9e5a-a85aa3f5b08c" alt="" width="546"><figcaption><p>Répartition des registres</p></figcaption></figure>

On sait donc comment les variables pointent vers les registres:

* <mark style="color:orange;">`regs -> r15`</mark>
* <mark style="color:red;">`v13 -> rdx`</mark>
* <mark style="color:orange;">`v14 -> rsi`</mark>
* <mark style="color:red;">`v15 -> rdi`</mark>
* <mark style="color:orange;">`v16 -> rip`</mark>

{% hint style="success" %}
Le zero flag <mark style="color:red;">`ZF`</mark> est accédé avec <mark style="color:red;">`eflags`</mark> (c'est le 7e bit)

Si <mark style="color:red;">`var`</mark> pointe vers <mark style="color:red;">`eflags`</mark>, <mark style="color:red;">`ZF`</mark> est souvent accédé comme ça: <mark style="color:red;">`var & 0x40`</mark>
{% endhint %}

## Sources

{% embed url="<https://malwareandstuff.com/nanomites-on-linux/>" %}

{% embed url="<https://blog.efiens.com/post/midas/justctf2020-re-writeups/>" %}

{% embed url="<https://doar-e.github.io/blog/2014/10/11/taiming-a-wild-nanomite-protected-mips-binary-with-symbolic-execution-no-such-crackme/>" %}

{% embed url="<https://tbrindus.ca/correct-ld-preload-hooking-libc/>" %}
