File size: 8,047 Bytes
2f42973 a0f2f20 2f42973 a0f2f20 e14b40e a0f2f20 27b0e71 a0f2f20 f5e14c5 a0f2f20 14e64b4 a0f2f20 e677499 a0f2f20 47b70bf e677499 eea316e e677499 eea316e e677499 eea316e 7641336 eea316e ee5e742 bcf9417 bbe39b8 f485345 bbe39b8 31540ef eea316e bcf9417 bbe39b8 f485345 31540ef f485345 bbe39b8 31540ef ee5e742 bcf9417 bbe39b8 f485345 ee5e742 f485345 bbe39b8 31540ef a0f2f20 47b70bf a0f2f20 3a74cef a0f2f20 ee5e742 47b70bf ee5e742 47b70bf a0f2f20 27b0e71 ee5e742 27b0e71 143b777 27b0e71 3a74cef 27b0e71 a0f2f20 27b0e71 a0f2f20 47b70bf 3a74cef | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | ---
license: eupl-1.2
tags:
- assembly
- arm64
- amd64
- risc-v
- i386
---
# Model Description
ASMTransformers is a project to train and use a machine learning model to compare assembly (arm, amd, risc-v, i386) functions to a database of known functions,
to aid in the process of reverse engineering.
# Status
Not actively maintained after publishing
# Relevant links
* [Github repo ASMtransformers](https://github.com/NetherlandsForensicInstitute/asmtransformers)
# Version
2026-08-06
# Usage
To use this model, use [inference.py in our repository](https://github.com/NetherlandsForensicInstitute/asmtransformers/blob/main/asmtransformers/README.md#inference).
# Intended use
The model has been trained and tested to be used for similarity search of assembly code. It has not been trained/tested on any other languages than arm64, amd64, risc-v or i386,
nor has it been tested on other downstream tasks.
# Architecture description
This model has been trained similarly to [Wang et al.](https://arxiv.org/pdf/2205.12713). We did diverge somewhat from Wang et al. their approach, since our BERT model is trained multilingual.
We also experimented with different training parameters during the Masked Language Modelling (MLM). For example, we set the
--mlm-prob parameter to 0.4 in accordance to [Wettig et al., 2023](https://aclanthology.org/2023.eacl-main.217.pdf). We have done some experiments with different mlm-probs
(namely 0.15, 0.3 and 0.4) and found that 0.4 yielded the best results.
One remarkable aspect of [Wang et al.](https://arxiv.org/pdf/2205.12713)'s paper, was that they came up with the concept of "Jump target prediction". As part of the
MLM procedure, the model also has to predict jump targets: whenever there is a jump in the code, the model shouldn't only predict it to be a
jump instruction, but it should also predict to which line of code it's supposed to jump. The idea is that this leads to better understanding of the long-term relations
in the code, and as Wang et al yielded good results, we have adopted it.
Finetuning happens based on triplet loss: given three functions, of which two are similar (see also [Data](https://huggingface.co/NetherlandsForensicInstitute/Multilingual-ASMBERT/blob/main/README.md#data)) and one is deviant, the model has to pick which two functions
are similar to each other. We used [Batched Semi Hard Triplet Loss](https://sbert.net/docs/package_reference/sentence_transformer/losses.html#batchsemihardtripletloss) to
ensure that the training task is not too easy.
**Estimated training time:**
pretraining: 38 hours on 4 NVIDIA H200s
finetuning: 4 hours on 1 NVIDIA H200
**Full architecture:**
```
[
{
"idx": 0,
"name": "0",
"path": "0_ASMTransformerModule",
"type": "asmtransformers.models.asmsentencebert.ASMTransformerModule"
},
{
"idx": 1,
"name": "1",
"path": "1_Pooling",
"type": "sentence_transformers.sentence_transformer.modules.pooling.Pooling"
}
]
```
**Pretraining parameters used:**
```
{
"architectures": [
"BertForMaskedLM"
],
"attention_probs_dropout_prob": 0.1,
"classifier_dropout": null,
"hidden_act": "gelu",
"hidden_dropout_prob": 0.1,
"hidden_size": 768,
"initializer_range": 0.02,
"intermediate_size": 3072,
"layer_norm_eps": 1e-12,
"max_position_embeddings": 512,
"model_type": "bert",
"num_attention_heads": 12,
"num_hidden_layers": 12,
"pad_token_id": 0,
"position_embedding_type": "absolute",
"torch_dtype": "float32",
"transformers_version": "4.12.5",
"type_vocab_size": 2,
"use_cache": true,
"vocab_size": 6161
}
```
**Preraining parameters used:**
```
{
"epochs": 19,
"eval_steps": 10000,
"batch_size": 512,
"gradient_accumulation_steps": 1,
"mlm_prob": 0.4,
"bf16": True,
"tf32": True
}
```
# Output
The model outputs embeddings of size 768 that can be compared using cosine similarity
# Data
The dataset is built on the official [Debian Repository](https://wiki.debian.org/DebianRepository). To obtain multiple families of
assembly, we used `apt` to cross-build the same source package to multiple architectures. The idea is that this gives us
the same functions for all four architectures. For all four architectures, these functions are compiled with different optimisation:
O0, O1, O2, O3, Os and manually selected set with advanced instructions further referenced here as Oc for Optimised-Custom.
This results in a maximum of 24 (6 optimisation * 4 architectures) different functions
which are semantically similar. (i.e. they represent the same functionality but are written differently)
In practise, it was much easier to obtain amd64 functions than riscv64 functions. Thus, not all functions have 24 semantically similar functions.
The dataset is split into a train, test and an evaluation set. This in done on source package, so all binaries and functions belonging to one source package are part of
either the train or the test set, not both.
**Total amount of functions per architecture**
| Architecture | # functions|
|--------------|------------|
| amd64 |8 202 164|
| i386 |4 868 531|
| arm64 |4 421 768|
| riscv64 |3 791 434 |
-------------------------
**Amount of functions per architecture per optimization**
|Architecture | Optimization | # functions |
|-------------|--------------|-------------|
|amd64 | O0 | 1762442 |
|amd64 | O1 | 1448046 |
|amd64 | O2 | 1403180 |
|amd64 | O3 | 1308199 |
|amd64 | Oc | 899892 |
|amd64 | Os | 1380405 |
|arm64 | O0 | 918402 |
|arm64 | O1 | 824291 |
|arm64 | O2 | 790679 |
|arm64 | O3 | 741057 |
|arm64 | Oc | 331736 |
|arm64 | Os | 815603 |
|i386 | O0 | 1081475 |
|i386 | O1 | 873128 |
|i386 | O2 | 845943 |
|i386 | O3 | 816186 |
|i386 | Oc | 412503 |
|i386 | Os | 839296 |
|riscv64 | O0 | 845154 |
|riscv64 | O1 | 689670 |
|riscv64 | O2 | 670651 |
|riscv64 | O3 | 641428 |
|riscv64 | Oc | 259691 |
|riscv64 | Os | 684840 |
----------------------------
# Preprocessing
Several preprocessing steps have been taken: CFGs are processed to become a flat token list suitable for a tokenizer or
vocabulary builder. This procedure differs slightly between architectures, the processes can be inspected
[here](https://github.com/NetherlandsForensicInstitute/asmtransformers/tree/main/asmtransformers/asmtransformers/preprocessors).
Some operands have been normalized,
to reduce token explosion caused by raw numeric values. These numerical values are expressed as powers of two, such that
4096 would be 2 ** 12, so `#0x2^c`, so would 6000, but 9000 would be `#0x2^d`. As a consequence, small numbers are distinguishable
in the vocabulary list, but bigger numbers get one batched representation.
Finally, jump tokens are normalised to be relative `JUMP_ADDR_*` tokens. (* being the line number of the jump adress in the given
function, rather than in the full CFG)
# Performance
Performance was measured in two ways: Mean Reciprocal Rank (MRR) and Accuracy@1. These metrics are useful for this problem
since we compare a given embedded function to a database of embedded functions, and then rank the database by cosine similarity.
Mean Reciprocal rank shows the mean rank (1 the positive example in the database being ranked first, 0.5 when the positive example
is ranked second, 0.25 when the positive example is ranked fourth, etc). I.e. an MRR of 0.66 shows that the positive example was
usually ranked first or second. Accuracy@1 shows how many times the positive example ranked first. It is a useful metric,
but it's also very strict, which is why we used it combined with MRR.
|model|ARM64 mrr|ARM64 acc|AMD64 mrr|AMD64 acc|RISC-V mrr|RISC-V acc|I386 mrr|I386 acc|crosslingual mrr|crosslingual acc|
|-----|---------|---------|---------|---------|----------|----------|--------|--------|----------------|----------------|
|Multilingual-ASMBERT|0.762|0.685|0.848|0.803|0.615|0.514|0.660|0.575|0.631|0.530| |