Wie konvertiere ich Linux 32-Bit-GCC-Inline-Assembly in 64-Bit-Code? [geschlossen]
Ich versuche zu konvertierenRR0D Rasta Ring 0 Debugger vom 32-Bit-Modus in den 64-Bit-Modus (Long-Modus) unter Linux mit gcc. Ich bin mit x86-32-Bit-Assemblys (in MS-DOS-Umgebungen) vertraut, bin jedoch Anfänger in x86-64-Bit-Assemblys und in der Linux-Assemblyprogrammierung im Allgemeinen.
Dieses Projekt ist für die Produktion gedacht (ich benötige einen funktionierenden Nicht-Source-Debugger), aber ich versuche auch zu lernen, wie die 32-Bit-in-64-Bit-Konvertierung durchgeführt wird. Wenn möglich, versuche ich, eine universelle Methode zur Konvertierung von 32-Bit in 64-Bit zu finden, die mit regulären Ausdrücken in jedem 32-Bit-Programm durchgeführt werden kann (damit sie automatisiert werden kann). Mir ist bewusst, dass es keine allgemeine Lösung gibt (64-Bit-Code benötigt möglicherweise mehr Platz als 32-Bit-Code usw. und verbraucht mehr Stapel usw.), aber selbst in diesem Fall würde automatisch konvertierter Code als Ausgangspunkt dienen.
Die Idee wäre, 8-Bit- und 16-Bit-Operanden unverändert zu lassen und 32-Bit-Operanden durch 64-Bit-Operanden zu ersetzen. Dieser Ansatz wird natürlich scheitern, wennpushw %ax; pushw %bx; popl %ecx
wird ersetzt durchpushw %ax; pushw %bx; popq %rcx
, aber wohlerzogene Programme normalerweise nichtpush
zwei 16-Bit-Operanden und dannpop
ein 32-Bit-Operand, oder?
Dies sind die bisherigen Umrechnungen:
Bearbeiten: Fix:pusha
/ pushad
können durch aufeinanderfolgende ersetzt werdenpush
weilpusha
/ pushad
Befehle drücken den Wert vonsp
/ esp
Vor der eigentliche schub vonsp
, undpush sp
Funktioniert genauso in 286+, aber anders in 8088/8086Die Assembler-Datenbank. Dieser Unterschied ist hier kein Problem (für 386+ Code).pusha
undpushad
kann somit durch aufeinanderfolgende ersetzt werdenpush
befehle.
Eine Alternative ist ähnlich wie inOpenSolaris 'privregs.h
Code.
Bearbeiten: Korrektur: Verwenden Sie für alle Befehle die 64-Bit-Speicheradressierung.
pusha
->push %ax; push %cx; push %dx; push %bx; push %sp; push %bp; push %si; push %di
.
Bearbeiten: Fix: Eine gültige Alternative (mitlea
), beachten Sie, dass x86-Prozessoren Little-Endian sind:pusha
->movq %rax, -8(%rsp); lea -8(%rsp), %rax; mov %ax, -10(%rsp); movq -8(%rsp), %rax; movw %cx, -4(%rsp); movw %dx, -6(%rsp); movw %bx, -8(%rsp); movw %bp, -12(%rsp); movw %si, -14(%rsp); movw %di, -16(%rsp); lea -16(%rsp), %rsp
.
pushad
->push %rax; push %rcx; push %rdx; push %rbx; push %rsp; push %rbp; push %rsi; push %rdi
.
Bearbeiten: Fix: Eine gültige Alternative (mitlea
):pushad
->movq %rax, -8(%rsp); movq %rcx, -16(%rsp); movq %rdx, -24(%rsp); movq %rbx, -32(%rsp); lea -32(%rsp), %rax; movq %rax, -40(%rsp); movq -8(%rsp), %rax; movq %rbp, -48(%rsp); movq %rsi, -56(%rsp); movq %rdi, -64(%rsp); lea -64(%rsp), %rsp
.
Bearbeiten: Fix:popa
undpopad
Pop den Wert vonsp
/ esp
aber wirf es weg (Intel Befehlssatz - Popa / Popad). Lasst unspop
es inbx
/ rbx
.
popa
->popw %di; popw %si; popw %bp; popw %bx; popw %bx; popw %dx; popw %cx; popw %ax
.
popad
->popq %rdi; popq %rsi; popq %rbp; popq %rbx; popq %rbx; popq %rdx; popq %rcx; popq %rax
.
pushfd
->pushfq
.
popfd
->popfq
.
Bearbeiten: push
von Segmentregistern, z.pushw %ds
->pushw %ax; pushw %ax; movw %ds, %ax; movw %ax, 2(%rsp); popw %ax
.
Bearbeiten: pop
von Segmentregistern, z.popw %ds
->pushw %ax; movw 2(%rsp), %ax; movw %ax, %ds; popw %ax
.
Bearbeiten: inc %reg16
->add $1, %reg16
, z.B.inc %ax
->add $1, %ax
.
Bearbeiten: dec %reg16
->sub $1, %reg16
, z.B.dec %ax
->sub $1, %ax
.
Bearbeiten: inc %reg32
->add $1, %reg64
, z.B.inc %eax
->add $1, %rax
.
Bearbeiten: dec %reg32
->sub $1, %reg64
, z.B.dec %eax
->sub $1, %rax
.
Bearbeiten: aaa
->?
Bearbeiten: aad
->?
Bearbeiten: aam
->?
Bearbeiten: aas
->?
Bearbeiten: arpl
->?
Bearbeiten: bound
->?
Bearbeiten: daa
->?
Bearbeiten: das
->?
Bearbeiten: lahf
->?
Bearbeiten: sahf
->?
Bearbeiten Behebung: Jeder Befehl mit Direktoperanden, der nicht in die 32-Bit-Operandengröße im 64-Bit-Modus passt, z.pushl $0xDEADBEEF
->pushq %rax; pushq %rax; movq $0xDEADBEEF, %rax; movq %rax, 8(%rsp); popq %rax
.
ret
mit sofortigem Operanden: Ich denke in diesem Fall muss der Quellcode zurückverfolgt werden, um die Größen des letzten zu sehenpush
Operanden und handeln dementsprechend, z.pushl %eax; ret 4
->pushq %rax; ret 8
.
Bearbeiten:: syscalls:int $0x80
->pushq %rdi; movq %rbp, %r9; movq %rdi, %r8; movq %rbx, %rdi; xchgq %rcx, %rsi; -- replace %rax value using a substitution list --; syscall; popq %rdi; xchgq %rcx, %rsi
(Hinweis: 32-Bit-Systemaufrufe können mehr als 6 Parameter haben, 6 in Registern und der Rest im Stapel, 64-Bit-Systemaufrufe dürfen nie mehr als 6 Parameter haben.)
Bearbeiten: Was ist sonst noch zu beachten? Welche anderen Konvertierungen wären erforderlich, um 32-Bit-Code in 64-Bit-Code zu konvertieren (um im Langzeitmodus ausgeführt zu werden)?