Реверсинг программы с использованием строковых команд. Часть 3

Дата публикации 22 мар 2019 | Редактировалось 17 май 2019
Для сравнения вводимого пароля с эталонным значением чаще всего применяют строковые команды. Достоинством применения таких команд, в данном случае, является сокращение кода. Учитывать быстродействие при выполнении сравнения и медленном клавиатурном вводе как-то не уместно. В программе 2.5 применена процедура Pas1 proc, которая влияет только на оформление программы. Но если процедур будет достаточно много, то это сильно повлияет на поиск пароля. А если при этом предположить, что и сравнение паролей будет происходить в процедуре, то поиск пароля будет через чур затруднителен.
Программа 2.5. Использование строковых команд с запросом пароля:
Код (ASM):
  1. include win64a.inc
  2. ;Pas1 PROTO
  3. .data
  4.   Password db "12345" ; проверка только первых пяти символов
  5. len1 equ ($-Password)/type Password
  6. Buf dq 5 ;
  7. Err1 dq 0
  8. Msg1 db "Пароль совпал",0
  9. Msg2 db "Пароль не корректен",0
  10. Title1 db "Проверка пароля",0
  11. stdout dq 0  ;
  12. stdin dq 0  ;
  13. cRead dq 0  ;
  14. cWritten dq 0 ;
  15. Msg db "Please enter your password, 5 characters",10,10,0 ;
  16. .code
  17. Pas1 proc
  18. lea rsi,Password  ;адрес первого элемента строки
  19. lea rdi,Buf ;адрес второго элемента строки
  20. mov rcx,len1
  21. repe cmpsb ;побайтно проверяется len раз
  22. jz m2  ;
  23. inc Err1 ; счетчик несовпадений
  24. m2:
  25. ret
  26. Pas1 endp
  27. WinMain proc
  28. sub rsp,28h;
  29. mov rbp,rsp
  30. invoke GetStdHandle,STD_OUTPUT_HANDLE
  31. mov stdout,rax
  32. invoke GetStdHandle,STD_INPUT_HANDLE
  33. mov stdin,rax
  34. invoke WriteConsole,stdout,ADDR Msg,sizeof Msg,ADDR cWritten,0
  35. invoke ReadConsole,stdin,ADDR Buf,5,ADDR cRead,0
  36. invoke Pas1
  37. .if (Err1==0);
  38. invoke MessageBox,0,addr Msg1,addr Title1,MB_OK
  39. .else
  40. invoke MessageBox,0,addr Msg2,addr Title1,MB_OK
  41. .endif
  42. invoke RtlExitUserProcess,0 ;ExitProcess,0
  43. WinMain endp
  44. end
Рассмотрим программу определения количества элементов массива, которые равняются 128 и вывода директории расположения этой программы на логическом диске. Эту программу в дальнейшем соединим с программой запроса пароля (программа 2.6).

Программа 2.6.
;Посчитать количество элементов массива, которые равны 128
;и вывести директорию расположения программы
Код (ASM):
  1. include win64a.inc ;
  2. .data
  3. mas1 db 5,17,128,69,5,17,128,69,5,17,128,128 ; массив данных
  4. len1 equ ($-mas1)/type mas1  ; длина массива
  5. titl1 db "Массив.  (masm64)",0
  6. buf1 dq 1 dup(0),0 ;
  7. fmt db "Вывести кол. элементов массива из 12 чисел, которые равняются 128.",10,10,
  8. "Количество повторений числа 128 - %d",10,
  9. "Директория программы: - %s",10,10,
  10. "Автор:  Рысованый А.Н.,НТУ ХПИ",0
  11. dir db 256 dup(0) ;переменная для хранения пути к текущей директории
  12. count_128 dq 0
  13. .code
  14. WinMain proc
  15. sub rsp,28h
  16. mov rbp,rsp
  17. lea rdi,mas1  ; адрес начала элементов массива
  18. mov rcx,len1  ; кол. чисел массива
  19. cycle:
  20. movzx rax,byte ptr [rdi] ; занесение байтового адреса элемента массива
  21. cmp rax,128  ; сравнение элемента массива с 128
  22. jz inc128  ; переход на inc128 при совпадении
  23. jmp skip  ; иначе продолжить
  24. inc128:
  25. inc count_128  ; +1 к счётчику повторений числа 128
  26. skip:
  27. inc rdi  ;
  28. loop cycle
  29. invoke GetCurrentDirectory,255,addr dir; получение директории
  30. invoke wsprintf,addr buf1,addr fmt,count_128,addr dir
  31. invoke MessageBox,0,addr buf1,addr titl1,MB_OKCANCEL + MB_ICONQUESTION
  32. invoke RtlExitUserProcess,0  ; ExitProcess,0
  33. WinMain endp
  34. end
Эта программа не консольная. Следовательно, при получении ехе-файла необходимо использовать bat-файл, в котором присутствуют командные слова SUBSYSTEM:WINDOWS.
Результат выполнения программы 2.6 приведен на рис. 2.9.

upload_2019-1-31_22-7-7.png
В начале программы командой lea rdi,mas1 заносится адрес начала массива. Счетчик количества чисел массива организован в регистре rcx.
Цикл анализа чисел массива на равенство числу 128 организован по метке cycle.
В этом цикле сначала считывается из массива первое число и расширяется до формата регистра rax, в которое и заносится. Затем командой cmp rax,128 сравнивается (операция вычитания) с числом 128. В случае, если числа совпали, то командой
inc count_128 в счетчик прибавляется единица.
В заключительной части программы считывается директория расположения программы, которая затем поочередно со значением счетчика совпадений функцией wsprintf преобразовывается в символы и выводится в упрощенное окно.
Объединим рассмотренные программы (программа 2.5 и 2.6) в общую программу (программа 2.7).
Программа 2.7.
Код (ASM):
  1. include win64a.inc
  2. ;Pas1 PROTO
  3. .data
  4.   Password db "12345" ; проверка только первых пяти символов
  5. len1 equ ($-Password)/type Password
  6. Buf dq 5 ;
  7. Err1 dq 0
  8. Msg1 db "Пароль совпал",0
  9. Msg2 db "Пароль не корректен",0
  10. Title1 db "Проверка пароля",0
  11. stdout dq 0  ;
  12. stdin dq 0  ;
  13. cRead dq 0  ;
  14. cWritten dq 0 ;
  15. Msg db "Please enter your password, 5 characters",10,10,0 ;
  16. .code
  17. Pas1 proc
  18. lea rsi,Password   ; адрес первого элемента строки
  19. lea rdi,Buf  ; адрес второго элемента строки
  20. mov rcx,len1
  21. repe cmpsb   ; по-байтно проверяется len раз
  22. jz m2    ;
  23. inc Err1   ; счетчик несовпадений
  24. m2:
  25. ret
  26. Pas1 endp
  27. WinMain proc
  28. sub rsp,28h;
  29. mov rbp,rsp
  30. invoke GetStdHandle,STD_OUTPUT_HANDLE
  31. mov stdout,rax
  32. invoke GetStdHandle,STD_INPUT_HANDLE
  33. mov stdin,rax
  34. invoke WriteConsole,stdout,ADDR Msg,sizeof Msg,ADDR cWritten,0
  35. invoke ReadConsole,stdin,ADDR Buf,5,ADDR cRead,0
  36. invoke Pas1
  37. .if (Err1==0);
  38. invoke MessageBox,0,addr Msg1,addr Title1,MB_OK
  39. .data
  40. mas1 db 5,17,128,69,5,17,128,69,5,17,128,128 ; массив данных
  41. len2 equ ($-mas1)/type mas1  ; длина массива
  42. titl1 db "Массив.  (masm64)",0
  43. buf1 dq 1 dup(0),0 ;
  44. fmt db "Вывести кол. элементов массива из 12 чисел, которые равняются 128.",10,10,
  45. "Количество повторений числа 128 - %d",10,
  46. "Директория программы: - %s",10,10,
  47. "Автор:  Рысованый А.Н.,НТУ ХПИ",0
  48. dir db 256 dup(0) ;переменная для хранения пути к текущей директории
  49. count_128 dq 0
  50. .code
  51. lea rdi,mas1  ; адрес начала элементов массива
  52. mov rcx,len2  ; количество чисел массива
  53. cycle:
  54. movzx rax,byte ptr [rdi] ; занесение байтового адреса элемента массива
  55. cmp rax,128  ; сравнение элемента массива с 128
  56. jz inc128  ; переход на inc128 при совпадении
  57. jmp skip  ; иначе продолжить
  58. inc128:
  59. inc count_128  ; +1 к счётчику повторений числа 128
  60. skip:
  61. inc rdi  ;
  62. loop cycle
  63. invoke GetCurrentDirectory,255,addr dir; получение директории
  64. invoke wsprintf,addr buf1,addr fmt,count_128,addr dir
  65. invoke MessageBox,0,addr buf1,addr titl1,MB_OKCANCEL+ MB_ICONQUESTION
  66. .else
  67. invoke MessageBox,0,addr Msg2,addr Title1,MB_OK
  68. .endif
  69. invoke RtlExitUserProcess,0 ;ExitProcess,0
  70. WinMain endp
  71. end
Для упрощения объединения программ применена упрощенная сегментация (несколько сегментов data и code).
При объединении особое внимание надо обращать на поиск одинаковых имен в разных программах. Например, в программе анализа массива присутствовала переменная с именем len1, которую в общей программе было переименовано в len2.
Детально рассмотрим этапы поиска пароля в программе 2.7.
  1. Запускаем отладчик x64Dbg и открываем исследуемый ехе-файл. Для этого открываем в отладчике x64Dbg ехе-файл анализируемой программы и нажимаем F9 для ее выполнения.
  2. Находим функцию вывода сообщения. Для этого последовательно нажимаем в отладчике x64Dbg на клавишу F8 до момента приглашения ввода пароля функцией WriteConsole. В консольном окне появилось приглашение о вводе пароля: "Please enter your password, 5 characters".
    Вводим пароль, например, 123. Нажимаем на клавиатуре Enter. В консольном окне, вроде бы ничего и не отображается. Переходим в окно отладчика x64Dbg. Продолжаем не спеша нажимать F8 для выполнения каждой строки кода. После выполнения функции ReadConsole введенный ранее пароль отобразится и процесс анализа кода продолжится (курсор сдвинется на следующую строчку кода).
  3. Находим место анализа паролей
    Найти пароль с первого прохода анализа кода не всегда возможно. Как правило, если пароль не обнаружен, то ищут сообщение о неправильном пароле. А затем анализируют ту часть кода, которая ограничена от последней рассмотренной команды до вывода сообщения о неправильном пароле. Необходимо найти место сравнения. Во многих случаях, когда не стараются скрыть пароль, сравнение происходит при помощи команды cmp. Теоретически сравнение можно произвести, в качестве примера, простой командой sub или другой, по результату выполнения которой устанавливаются необходимые для анализа признаки выполнения операции.
    И так, возвращаемся к ранее проанализируемой функции ReadConsole. После этой функции следующей строкой есть вызов процедуры
    call pas4-64-2.7FF666DD1000
    А после вызова этой процедуры (рис. 2.10) расположена команда сравнения
    cmp qword ptr ds:[7FF666DD300D],0


    upload_2019-1-31_22-7-40.png

    Всегда следует качественно анализировать содержимое полей команд сравнения.
    Чтобы посмотреть значение ячейки памяти необходимо подвести курсор к строке с адресом ячейки, нажать правую клавишу мышки и выбрать Перейти к дампу / Константа.
    В ячейке памяти с адресом 7FF78FE2300D находится значение 01, которое сравнивается со вторым операндом в команде (с нулем).
    Следующей строкой после команды сравнения cmp расположена команда
    jne pas4-64-2.7FF666DD1148, которая в случае неравенства операндов (по признаку ZF) перейдет на адрес 7FF666DD1148. А если по команде jnz содержимое ячейки памяти с адресом 7FF666DD300D и нуля совпадут, то можно сделать предположение, что пароли совпали. Поэтому надо исправить код операции так, чтобы после ввода произвольного пароля, результат был правильным.
Изменение команды ветвления
В связи с тем, что в анализируемой программе следующая строчка кода относится к параметрам функции MessageBox, которая выводит сообщение о правильном пароле, то можно осуществить перенаправление двумя вариантами:
  • вставить команды nop;
  • вставить команду jmp c новым адресом 00007FF78FE210B2. Этот вариант изменения является более универсальным.
Чтобы исключить команду переходя по условию необходимо вставить команды nop. Для этого подводим курсор к строке с командой
jne pas4-64-2.7FF78FE21148,
дважды нажимаем левую клавишу мышки, ставим отметку в окошке Заполнить командами NOP и вводим NOP (рис. 2.11).


upload_2019-1-31_22-8-5.png
  1. Внесение изменений
Внести изменения в отладчике x64Dbg можно двумя способами.
Первый способ: выбираем Файл/ Исправить файл. В новом окне выбрать пункт Исправить файл. Затем – новое имя и расширение ехе.
Второй способ: выбрать пиктограмму с названием Исправления, нажать на кнопку Исправить файл, а далее новое имя и расширение ехе.
После внесенных изменений ехе-файл с новым именем на любой пароль реагирует как на лицензионный.

0 2.266
Alex81524

Alex81524
New Member

Регистрация:
12 фев 2008
Публикаций:
5