Шалом, снова.
Беру подопытного из этой темы: *тык*
Я был крайне удивлён тем, что особо-то никто и не писал о своих успехах с этим крякми.
Решил сам глянуть, посмотреть шо да как устроено. Оказалось намного хитровыебаннее, чем я ожидал.
Эта статья могла бы выйти чуть пораньше не затупив я на одном месте, но начнём по порядку.
1. Обфускация кода
2. Системные вызовы х32
2.1.Даем пизды Патчим трюк с потоком
3. Нахождение "DLL"
1. Обфускация кода
Обфускация здесь состоит в том, чтобы сравнивать два регистра общегоназначения, затем в зависимости от вида джампа будь-то jne && je джампится на нужный шелл или же на другую проверку регистров, где тоже будет сидеть cmp и какой-нибудь джамп. Или же перейти на следующую инструкцию где уже сидит jmp, который джампит на другую проверку обфускатора (или опять же на шелл), и так вас будет кидать туда-сюда, периодически выполняя нужный программе код
Вот пример кода, который я описал только что
Не сказать, что эта обфускация вызвала у меня какие-то серьезные проблемы с анализом кода, ибо внимание я зацикливал не на трассировку кода, а на вызовы для инжекта.
2. Системные вызовы х32
Переходим к моей любимой части этого крякми. А именно системные вызовы. Зная, кто автор крякми несложно было догадаться, что скорее всего тут не будут вызываться функции из WinAPI (кроме GetProcAddress, он нужен для того чтобы взять адрес Wow64Transition).
Немного теории:
Возможно не все читающие эту статью знают о принципе работы системных вызовов в 32-битной среде.
В 64-битной было всё понятно, смотря лишь таблицу системных номеров в нтдлл.
А в 32-битной появляется какой-то колл.
Приведу пример простого системного вызова
В EAX суется всеми нами известный системный номер, затем в EDX суем адрес Wow64Transition и вызываем его.
Wow64Transition делает джамп в дллку wow64cpu.dll где выполняется уже x64 код и уже там происходит системный вызов. Всё верно, для того чтобы совершить системный вызов в х32 программе надо перейти в х64-битную среду. И необязательно кстати сувать адрес Wow64Transition, можно обойтись и __KiFastSystemCall, суть его в том чтобы вызывать sysenter, по итогу системный вызов все равно будет выполнен, а в регистр EAX будет записан результат вызова (обычно 0, если все прошло хорошо, типо как с GetLastError логика)
Закончили с теорией, перейдем к системным вызовам в крякми.
Байт-код вызова регистра EDX: FF D2, с этим байткодом начинаем искать этот паттерн в крякми.
Находим 12 системных вызовов
Снизу вверх перечислю системные номера, которые я нашел:
Однако, было еще одно место где используются системные вызовы. Но до ЕР оно заполнено 00 (После вызова ЕР это кстати все происходит, забыл просто написать)
Почему же заполнено 00? Да потому что в это место постоянно перезаписывается системный номер для дальнейшего системного вызова, понял я это из-за того что мой трамполайн хук исчез бесследно. Ещё что привлекло мое внимание это сам адрес, который сидит в EDX и вызывается. Да, там был Wow64Transition, однако он находился не на своем месте. По дефолту Wow64Transition находится в выделенной памяти ntdll, а здесь он находился не только вне нтдлл, да еще и вначале секции .data нашего крякми :) Теперь то становится понятно для чего брался адрес, после взятия адреса байты из Wow64Transition записывались в начало .data, первый по патерну CALL EDX в списке вызывал NtProtectVirtualMemory чтобы в оригинальном Wow64Transition поменять протект памяти в секции .data,и затем уже там выполнялись сами системные вызовы.
Т.к. место где перезаписывался постоянно системный номер был на одном и том же адресе, то ничего не мешало выйти на место, где совершается вызов
Самые внимательные возможно заметили, что уже не в первый раз мелькает адрес DWORD PTR DS:[C000B0] :) Он палился, когда мы брали адрес для Wow64Transition, а теперь он палится и перед вызовом нашего шеллкода. Если перейти к нему, то мы там как раз и увидим перезаписанный Wow64Transition.
Сами алгоритмы перезаписи системных номеров и Wow64Transition палить особо смысла нет, но те кто захочет посмотреть поставьте просто бряк на доступ в начало секции .data.
2.1. Патчим трюк с потоком
Ну здесь всё просто, если просмотреть список системных вызовов, которые я кидал до этого, то можно понять что в мануальном Wow64Transition закидывался системный номер 0xD с параметром 0x11 (ThreadHideFromDebugger) и потом несколько раз вызывался NtQueryInformationThread тоже с 0x11 параметром. Поэтому ставить мемори бряки == самоубийство для дебаггера
Но, вам ничего не мешает поставить ret в начале обоих функции, найдя их по паттерну FF D2 :)
3. Нахождение "DLL"
Изначальный инжектор пренадлежит Zer0Memory, сразу скажу для тех, кто ожидал здесь увидеть зафикшенную длл, никакой дллки в крякми нет и не будет, берется часть кода из экзешника с месседжбоксом и записывается в Target.exe
Есть одна проблема, которая мне покоя всё же не даёт и надеюсь получить ответ от автора в телеге, дело в том что 3A никогда не светился в том месте, где происходил вызов настоящего шеллкода с последующей заменой системного номера. Но если занопать место где лежит 3A, то инжекта не будет, а аппаратные бряки на доступ к нему ни в какую не палят доступ. Возможно проблема в моём билде винды, а возможно что я где-то пропустил важный момент и где-то происходил ещё один шеллкод (например в конце секции .data, ибо там частенько менялись байты).
По итогу логику этого инжектора я понял (за исключением одного момента), очень понравилось разбирать этот крякми, надеюсь автор когда-нибудь выпустит ещё один подобный крякми, если появится время. Ну и вроде как я тут не все мемы успел расписать, ну ничо
Подписывайтесь на мой бложик: t.me/colby5engineering
И ещё спасибо моей команде (Easton, Arting) я вас люблю!!
nelfo <3
Всего доброго! :)
Беру подопытного из этой темы: *тык*
Я был крайне удивлён тем, что особо-то никто и не писал о своих успехах с этим крякми.
Решил сам глянуть, посмотреть шо да как устроено. Оказалось намного хитровыебаннее, чем я ожидал.
Эта статья могла бы выйти чуть пораньше не затупив я на одном месте, но начнём по порядку.
1. Обфускация кода
2. Системные вызовы х32
2.1.
3. Нахождение "DLL"
1. Обфускация кода
Обфускация здесь состоит в том, чтобы сравнивать два регистра общегоназначения, затем в зависимости от вида джампа будь-то jne && je джампится на нужный шелл или же на другую проверку регистров, где тоже будет сидеть cmp и какой-нибудь джамп. Или же перейти на следующую инструкцию где уже сидит jmp, который джампит на другую проверку обфускатора (или опять же на шелл), и так вас будет кидать туда-сюда, периодически выполняя нужный программе код
Вот пример кода, который я описал только что
Код:
cmp eax, ebp
je meme_obf ; Проверка проходит, джампимся на meme_obf
jmp 0x8F1C7C
; some code
meme_obf:
cmp ebp, eax
jne 0x8F2B54 ; Проверка не проходит, не джампимся, идем к jmp
jmp 0x8F1C7C ; джамп на шелл
Не сказать, что эта обфускация вызвала у меня какие-то серьезные проблемы с анализом кода, ибо внимание я зацикливал не на трассировку кода, а на вызовы для инжекта.
2. Системные вызовы х32
Переходим к моей любимой части этого крякми. А именно системные вызовы. Зная, кто автор крякми несложно было догадаться, что скорее всего тут не будут вызываться функции из WinAPI (кроме GetProcAddress, он нужен для того чтобы взять адрес Wow64Transition).
Немного теории:
Возможно не все читающие эту статью знают о принципе работы системных вызовов в 32-битной среде.
В 64-битной было всё понятно, смотря лишь таблицу системных номеров в нтдлл.
А в 32-битной появляется какой-то колл.
Приведу пример простого системного вызова
Код:
MOV EAX, 50 ; Системный номер = 50 = NtProtectVirtualMemory
MOV EDX, Wow64TransitionAddress
CALL EDX
RET 14
В EAX суется всеми нами известный системный номер, затем в EDX суем адрес Wow64Transition и вызываем его.
Wow64Transition делает джамп в дллку wow64cpu.dll где выполняется уже x64 код и уже там происходит системный вызов. Всё верно, для того чтобы совершить системный вызов в х32 программе надо перейти в х64-битную среду. И необязательно кстати сувать адрес Wow64Transition, можно обойтись и __KiFastSystemCall, суть его в том чтобы вызывать sysenter, по итогу системный вызов все равно будет выполнен, а в регистр EAX будет записан результат вызова (обычно 0, если все прошло хорошо, типо как с GetLastError логика)
Закончили с теорией, перейдем к системным вызовам в крякми.
Байт-код вызова регистра EDX: FF D2, с этим байткодом начинаем искать этот паттерн в крякми.
Находим 12 системных вызовов
Снизу вверх перечислю системные номера, которые я нашел:
Форматирование (BB-код):
1. MOV EAX, 50 ; NtProtectVirtualMemory
2. MOV EAX, 3A ; NtWriteVirtualMemory
3. MOV EAX, D004 ; NtWaitForSingleObject
4. MOV EAX, D ; NtSetInformationThread
5. MOV EAX, 70052 ; NtResumeThread
6. MOV EAX, 25 ; NtQueryInformationThread
7. MOV EAX, 50 ; NtProtectVirtualMemory
8. MOV EAX, 26 ; NtOpenProcess
9. MOV EAX, 1E ; NtFreeVirtualMemory
10. MOV EAX, 60034 ; NtDelayExecution
11. MOV EAX, С1 ; NtCreateThreadEx
12. MOV EAX, 18 ; NtAllocateVirtualMemory
Однако, было еще одно место где используются системные вызовы. Но до ЕР оно заполнено 00 (После вызова ЕР это кстати все происходит, забыл просто написать)
Почему же заполнено 00? Да потому что в это место постоянно перезаписывается системный номер для дальнейшего системного вызова, понял я это из-за того что мой трамполайн хук исчез бесследно. Ещё что привлекло мое внимание это сам адрес, который сидит в EDX и вызывается. Да, там был Wow64Transition, однако он находился не на своем месте. По дефолту Wow64Transition находится в выделенной памяти ntdll, а здесь он находился не только вне нтдлл, да еще и вначале секции .data нашего крякми :) Теперь то становится понятно для чего брался адрес, после взятия адреса байты из Wow64Transition записывались в начало .data, первый по патерну CALL EDX в списке вызывал NtProtectVirtualMemory чтобы в оригинальном Wow64Transition поменять протект памяти в секции .data,и затем уже там выполнялись сами системные вызовы.
Т.к. место где перезаписывался постоянно системный номер был на одном и том же адресе, то ничего не мешало выйти на место, где совершается вызов
Самые внимательные возможно заметили, что уже не в первый раз мелькает адрес DWORD PTR DS:[C000B0] :) Он палился, когда мы брали адрес для Wow64Transition, а теперь он палится и перед вызовом нашего шеллкода. Если перейти к нему, то мы там как раз и увидим перезаписанный Wow64Transition.
Сами алгоритмы перезаписи системных номеров и Wow64Transition палить особо смысла нет, но те кто захочет посмотреть поставьте просто бряк на доступ в начало секции .data.
2.1. Патчим трюк с потоком
Ну здесь всё просто, если просмотреть список системных вызовов, которые я кидал до этого, то можно понять что в мануальном Wow64Transition закидывался системный номер 0xD с параметром 0x11 (ThreadHideFromDebugger) и потом несколько раз вызывался NtQueryInformationThread тоже с 0x11 параметром. Поэтому ставить мемори бряки == самоубийство для дебаггера
Но, вам ничего не мешает поставить ret в начале обоих функции, найдя их по паттерну FF D2 :)
3. Нахождение "DLL"
Изначальный инжектор пренадлежит Zer0Memory, сразу скажу для тех, кто ожидал здесь увидеть зафикшенную длл, никакой дллки в крякми нет и не будет, берется часть кода из экзешника с месседжбоксом и записывается в Target.exe
Есть одна проблема, которая мне покоя всё же не даёт и надеюсь получить ответ от автора в телеге, дело в том что 3A никогда не светился в том месте, где происходил вызов настоящего шеллкода с последующей заменой системного номера. Но если занопать место где лежит 3A, то инжекта не будет, а аппаратные бряки на доступ к нему ни в какую не палят доступ. Возможно проблема в моём билде винды, а возможно что я где-то пропустил важный момент и где-то происходил ещё один шеллкод (например в конце секции .data, ибо там частенько менялись байты).
По итогу логику этого инжектора я понял (за исключением одного момента), очень понравилось разбирать этот крякми, надеюсь автор когда-нибудь выпустит ещё один подобный крякми, если появится время. Ну и вроде как я тут не все мемы успел расписать, ну ничо
Подписывайтесь на мой бложик: t.me/colby5engineering
И ещё спасибо моей команде (Easton, Arting) я вас люблю!!
nelfo <3
Всего доброго! :)