Дизассемблирование и отладка BootManager'а OSL2000

Тема в разделе "WASM.RESEARCH", создана пользователем serenya, 28 май 2009.

  1. serenya

    serenya New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    2
    Добрый день, уважаемые участники!

    Занялся я исследованием бут-менеджера OSL2000 v9.21 в чисто "ознакомительных целях", т.к. он мне понравился исчерпывающим функционалом, удобным интерфейсом, малым объёмом и тем, что он не мусорит в разделах.

    Для этого я инсталлировал OSL2000 и выгрузил WinHEX'ом первые 63 сектора в бинарник. Открыв его с помощью IDA 4.9 и пропустив обычный код с проверками я наткнулся на участок кода, который загружает основной код, декодирует его и передаёт ему управление. Привожу код, снабдив для удобства комментариями (org 600h):

    Код (Text):
    1. seg000:0700           mov     si, 4       ; начальный сектор для чтения
    2. seg000:0703           mov     bx, 1000h   ; сегмент, куда будут грузиться данные
    3. seg000:0706           mov     es, bx
    4. seg000:0708           mov     bx, 100h    ; смещение
    5. seg000:070B loc_70B:                          
    6. seg000:070B           mov     dx, 80h     ; подготовка данных для чтения диска 80h=hdd0
    7. seg000:070E           mov     cx, si      ; CL=номер сектора для чтения
    8. seg000:0710           call    sub_67C     ; здесь вызывается int 13h функция 2 - чтение
    9.                                           ; сектора с пяти попыток, если не удаётся то
    10.                                           ; CF=1 если успешно то результат в ES:BX
    11. seg000:0713           jb      short locret_75A ; на обработку ошибки и выход
    12. seg000:0715           inc     si          ; следующий сектор
    13. seg000:0716           add     bx, 200h    ; сместились в буфере на 512 байт
    14. seg000:071A           dec     ds:word_7A6 ; тут хранится кол-во секторов (55)
    15. seg000:071E           jnz     short loc_70B ; пока все не прочитаем
    16. seg000:0720           xor     bx, bx
    17. seg000:0722           mov     dl, 5Ah     ; это маска
    18. seg000:0724           mov     si, 100h    ; задаем смещение
    19. seg000:0727           mov     di, si      ; источник и приёмник равны
    20. seg000:0729           mov     cx, ds:word_7A8 ; тут хранится число байт кода (27908)
    21. seg000:072D           cld                
    22. seg000:072E           push    ds          ; сохраняем ds
    23. seg000:072F           push    es          ; es по прежнему равен 1000h
    24. seg000:0730           pop     ds          ; ds=es=1000h
    25. seg000:0731 loc_731:                      
    26. seg000:0731           ror     dl, 1       ; двигаем маску по-кругу
    27. seg000:0733           ror     dl, 1
    28. seg000:0735           ror     dl, 1
    29. seg000:0737           ror     dl, 1
    30. seg000:0739           inc     dl          ; инкремент
    31. seg000:073B           lodsb               ; поместили в al байт из [es:si]
    32. seg000:073C           xor     al, dl      ; наложили маску
    33. seg000:073E           stosb               ; поместили al в [es:di]
    34. seg000:073F           xor     ah, ah      ; чтобы мусора небыло
    35. seg000:0741           add     bx, ax      ; считаем контрольную сумму
    36. seg000:0743           loop    loc_731
    37. seg000:0745           pop     ds          ; востановливаем ds
    38. seg000:0746           cmp     bx, ds:word_7A4 ; сравниваем CRC
    39. seg000:074A           jb      short locret_75A ; на обработку ошибки и выход
    40. seg000:074C           cli
    41. seg000:074D           mov     sp, cs      ; непонятно зачем,
    42. seg000:074F           mov     ss, sp      ; но переместили стэк
    43. seg000:0751           mov     sp, 0FFFEh
    44. seg000:0754           sti
    45. seg000:0755           jmp     far ptr 1000h:100h ; уходим на декодированный код
    Для дальнейших изысков я повторил эту операцию таким образом:

    Код (Text):
    1.   xor_mask := $5A;
    2.   for i := 1 to buf1.size do
    3.   begin
    4.     asm
    5.       ror xor_mask,1
    6.       ror xor_mask,1
    7.       ror xor_mask,1
    8.       ror xor_mask,1
    9.       inc xor_mask
    10.     end;
    11.     buf2.code[i] := buf1.code[i] xor xor_mask;
    12.   end;
    где buf1 и buf2 имеют следующую структуру

    Код (Text):
    1.   record
    2.     e01: array [1..416] of byte; // начальные данные первого сектора
    3.     e02, e03, e04, sector_count, size, e05, e06, e07: word;
    4.     e08: array [1..5*16] of byte; // конечные данные первого сектора
    5.     e09: array [1..3*512] of byte; // ещё 3 сектора
    6.     code: array [1..(63-4)*512] of byte; // собственно код (начинается с 4-го сектора)
    7.   end;
    Но в результате получаю на выходе по смещению 800h инструкцию
    Код (Text):
    1. iret
    и невразумительную кашу.

    Подскажите, пожалуйста, где я недосмотрел?

    С уважением,
    Сергей Игнатов.
     
  2. vasia

    vasia New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2009
    Сообщения:
    9
    Вероятно, в асме ror мотает dl (байт) по кругу, в переписанном коде - в зависимости от размера переменной xor_mask.
     
  3. bendme

    bendme New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2009
    Сообщения:
    179
    А зачем ты в своем цикле на каждом шаге маску пересчитываешь?
     
  4. bendme

    bendme New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2009
    Сообщения:
    179
    блин, обложался, не читайте предыдущий пост
     
  5. serenya

    serenya New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    2
    Нет, xor_mask имеет размер байт, и даже если заменить на регистр - результат тот-же :dntknw:

    Код (Text):
    1.     asm
    2.       push dx
    3.       mov dl,xor_mask
    4.       ror dl,1
    5.       ror dl,1
    6.       ror dl,1
    7.       ror dl,1
    8.       inc dl
    9.       mov xor_mask,dl
    10.       pop dx
    11.     end;
    В таком "лобовом" варианте результат тот-же :dntknw:
     
  6. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    serenya
    Похоже, один декодирует с первого сектора? Но в оригинале расшифровка начинается с четвёртого, если не ошибаемся. К тому времени, когда самосделанный декодер дойдёт до четвёртого сектора, значение xor_mask будет уже не $5A, а... $8D.


    По идее в этом случае нужно смотреть на 600h. (Первый сектор – ноль, второй – 200h, третий – 400h,..)


    А вообще, всё декодирование удобнее сделать с помощью скриптов прямо в иде, ага?