Qu'est-ce qu'une méthode relativement rapide et facile pour rechercher ce que signifie un opcode arbitraire (par exemple, 0xC8
) en x86?
Le manuel du développeur de logiciels Intel n'est pas très amusant à parcourir ...
Vérifiez ce tableau très complet des opcodes x86 sur x86asm.net .
Juste CTRL+F
et tu as fini! Assurez-vous de lire la ligne correcte, comme C8
par exemple peut apparaître à plusieurs endroits.
Voici un joli visuel sympa. N'entre pas dans les détails, mais si vous avez juste besoin de rechercher une valeur hexadécimale très rapidement, cela devrait le faire-
Source: http://pnx.tf/files/x86_opcode_structure_and_instruction_overview.png
Bien que le manuel du développeur de logiciels Intel lui-même ne soit certainement pas très pratique à parcourir, les tableaux d'opcode de ce manuel pourraient vous aider. Jetez un oeil à l'annexe A "Opcode Map" dans le volume 2B du manuel, cela pourrait être utile.
Une référence rapide pour rechercher des opcodes est tas de sable . J'ai besoin de deux clics pour savoir ce que fait 0xc8 (c'est enter
, btw).
Il y a aussi asmjit/asmdb projet, qui fournit le domaine public base de données X86/X64 dans un format de type JSON (c'est un module de nœud en fait, il suffit de le demander () à partir du nœud ou inclure dans le navigateur). Il est conçu pour un traitement supplémentaire (par exemple pour écrire des valideurs, des assembleurs, des désassembleurs), mais il est également très facile d'ouvrir simplement le fichier de base de données et de l'explorer.
AsmDB est livré avec un outil appelé x86util.js, qui peut indexer la base de données x86 en une représentation beaucoup plus conviviale qui peut être utilisée pour faire quelque chose avec. Écrivons un outil simple dans node.js qui imprime toutes les instructions qui ont le même octet d'opcode que vous fournissez:
const asmdb = require("asmdb");
const x86isa = new asmdb.x86.ISA();
function printByOpCode(opcode) {
x86isa.instructions.forEach(function(inst) {
if (inst.opcodeHex === opcode) {
const ops = inst.operands.map(function(op) { return op.data; });
console.log(`INSTRUCTION '${inst.name} ${ops.join(", ")}' -> '${inst.opcodeString}'`);
}
});
}
if (process.argv.length < 3)
console.log("USAGE: node x86search.js XX (opcode)")
else
printByOpCode(process.argv[2]);
Essayez-le:
$ node x86search.js A9
INSTRUCTION 'pop gs' -> '0F A9'
INSTRUCTION 'test ax, iw' -> '66 A9 iw'
INSTRUCTION 'test eax, id' -> 'A9 id'
INSTRUCTION 'test rax, id' -> 'REX.W A9 id'
INSTRUCTION 'vfmadd213sd xmm, xmm, xmm/m64' -> 'VEX.DDS.LIG.66.0F38.W1 A9 /r'
INSTRUCTION 'vfmadd213sd xmm, xmm, xmm/m64' -> 'EVEX.DDS.LIG.66.0F38.W1 A9 /r'
INSTRUCTION 'vfmadd213ss xmm, xmm, xmm/m32' -> 'VEX.DDS.LIG.66.0F38.W0 A9 /r'
INSTRUCTION 'vfmadd213ss xmm, xmm, xmm/m32' -> 'EVEX.DDS.LIG.66.0F38.W0 A9 /r'
$ node x86search.js FF
INSTRUCTION 'call r32/m32' -> 'FF /2'
INSTRUCTION 'call r64/m64' -> 'FF /2'
INSTRUCTION 'dec r16/m16' -> '66 FF /1'
INSTRUCTION 'dec r32/m32' -> 'FF /1'
INSTRUCTION 'dec r64/m64' -> 'REX.W FF /1'
INSTRUCTION 'fcos ' -> 'D9 FF'
INSTRUCTION 'inc r16/m16' -> '66 FF /0'
INSTRUCTION 'inc r32/m32' -> 'FF /0'
INSTRUCTION 'inc r64/m64' -> 'REX.W FF /0'
INSTRUCTION 'jmp r32/m32' -> 'FF /4'
INSTRUCTION 'jmp r64/m64' -> 'FF /4'
INSTRUCTION 'Push r16/m16' -> '66 FF /6'
INSTRUCTION 'Push r32/m32' -> 'FF /6'
INSTRUCTION 'Push r64/m64' -> 'FF /6'
De plus, il existe des outils de ligne de commande qui peuvent être utilisés pour un démontage rapide et sale, mais ceux-ci nécessitent toutes les instructions (contrairement à avoir uniquement l'octet d'opcode), voici quelques conseils:
Utiliser llvm-mc de LLVM projet:
$ echo "0x0f 0x28 0x44 0xd8 0x10" | llvm-mc -disassemble -triple=x86_64 -output-asm-variant=1
.text
movaps xmm0, xmmword ptr [rax + 8*rbx + 16]
Utilisation de ndisasm à partir du projet nasm :
$ echo -n -e '\x0f\x28\x44\xd8\x10' | ndisasm -b64 -
00000000 0F2844D810 movaps xmm0,oword [rax+rbx*8+0x10]
Il existe également un projet AsmGrid du même auteur que AsmDB. C'est un explorateur AsmDB en ligne en cours qui utilise des couleurs pour visualiser les différentes propriétés de chaque instruction.
Une autre façon, en utilisant un débogueur (gdb, windbg, ollydbg, ...) ou un désassembleur (IDA), puis de définir des séquences d'octets dans une région de mémoire accessible en écriture. Enfin, démontage à l'adresse de départ de ces séquences d'octets.
La couture est compliquée, mais utile dans certaines situations lorsque vous craquez/inversez.
Sandpile est probablement ce que vous recherchez. Pourtant, la meilleure façon de voir l'encodage x86 n'est pas en hexadécimal mais plutôt en octal . Soudainement, x86 n'a pas l'air si moche et cela a du sens. L'explication classique est tirée d'Usenet alt.lang.asm vers 1992: