Сейчас на форуме: _MBK_ (+5 невидимых)

 eXeL@B —› Вопросы новичков —› Джамп на сам-себя.
Посл.ответ Сообщение

Ранг: 13.8 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 03 октября 2010 15:09
· Личное сообщение · #1

Доброго времени суток форумчане.
Загрузил в Олю файл, и стал "позновать мир". Наткнулся на следующий код:

Code:
  1. 003700B1                   xor ecx,ecx
  2. 003700B3                   push ecx
  3. 003700B4                   push ecx
  4. 003700B5                   push esi
  5. 003700B6                   call 003703DA          ; по вызываемому адресу находятся инструкции 'pop eax, call eax'
  6. 003700BB                   push ecx
  7. 003700BC                   push ecx
  8. 003700BD                   call dword ptr ss:[ebp+44h]               ; kernel32.CreateThread
  9. 003700C0  - EB FE      jmp short 003700C0
  10.  
  11. 003700C2                   mov eax, dword ptr ds:[esi+3Ch]


Вот дошёл я до адреса 003700С0 и понял что пишу эти строки в правильном подфоруме.
Нажимаю на F8 и регистр EIP показывает что без подсказки Реверсеров с crackl@b'a мне не выйти из этого лабиринта.
Любопытства ради поставил бряк на 003700C2 и нажал F9, чисто позырить что будя дальше. И бряк сработал! Также смотрю в Оле окно 'Threads' и вижу что поток создался.
Вот собственно просьба: У кого есть время и желание, пожалуйста поясните истину этого кода и как это вапще сработало ?
Заранее благодарю.



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 октября 2010 15:49
· Личное сообщение · #2

cosinus
Хм. Хороший код. Выполнено сцепление калбэка и вызывающего кода в графе, это мутирующий код. Использован следующий способ. Перед калбэком определяется макро, связующее посредством процедурного ветвления вызывающий код:
Code:
  1. %GET_CURRENT_GRAPH_ENTRY macro
  2.          pop eax
  3.          Call Eax
  4. endm

Например в данном случае:
Code:
  1. rThreadStartupRoutine:
  2.          %GET_CURRENT_GRAPH_ENTRY
  3. ThreadStartupRoutine proc StartupContext:PVOID
  4.          ...

Тогда загрузка ссылки на калбэк происходит следующим образом:
Code:
  1. %GET_GRAPH_ENTRY macro PGET_CURRENT_GRAPH_ENTRY
  2.          Call PGET_CURRENT_GRAPH_ENTRY
  3. endm
  4.  
  5.          %GET_GRAPH_ENTRY rThreadStartupRoutine

Я использую аналогичный способ, только делаю блок выполняющий возврат глобальным для сокращения размера:
Code:
  1. %GET_CURRENT_GRAPH_ENTRY macro
  2.          Call GetGraphReference
  3. endm
  4.  
  5. %GET_GRAPH_ENTRY macro PGET_CURRENT_GRAPH_ENTRY
  6.          Call PGET_CURRENT_GRAPH_ENTRY
  7. endm
  8.  
  9. %GET_GRAPH_REFERENCE macro
  10. GetGraphReference::
  11.          pop eax
  12.          ret
  13. endm


Модель основана на том факте, что инструкция Call загружает в стек адрес следующей за ней инструкции.

Если не секрет откуда взят этот код ?



Ранг: 13.8 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 03 октября 2010 16:43 · Поправил: cosinus
· Личное сообщение · #3

Clerk откровенно говоря нифига не понял
Если вас не затруднит, "на пальцах" поясните. После нажатия F9 какой именно код выполнялся?
Джамп на сам-себя ?, то как я из него вышел... Ведь по сути это тупик.

Code:
  1. 003703DA               pop eax
  2. 003703DB               call eax
  3. 003703DD               pushad
  4. 003703DE               mov esi,dword ptr ss:[esp+24h]


P.S. Так же в этом файле присутствует следущий приём:

Code:
  1. 00401386               mov eax,esp
  2. 00401388               xor al,al
  3. 0040138A               push 00401FED
  4. 0040138F               ret
  5.  
  6. ;==================================
  7. 00401FED    0000            add byte ptr ds:[eax],al
  8. 00401FEF    0000            add byte ptr ds:[eax],al
  9. 00401FF1    0000            add byte ptr ds:[eax],al
  10. 00401FF3    0000            add byte ptr ds:[eax],al
  11. 00401FF5    0000            add byte ptr ds:[eax],al
  12. 00401FF7    0000            add byte ptr ds:[eax],al
  13. 00401FF9    0000            add byte ptr ds:[eax],al
  14. 00401FFB    0000            add byte ptr ds:[eax],al
  15. 00401FFD    0000            add byte ptr ds:[eax],al
  16. 00401FFF    00              ???         ; Command crosses end of memory block
  17. ;==================================

Дойдя до адреса 00401FFF и нажатия F8 я переместился на вполне нормальный код, но позвольте приберечь это для следующего вопроса.

Этот файл распознаётся антивирусом как Worm, и распространяется он через флешки.
Уж простите новичка, но не что так не даёт азарта как реверс вируса. Нежели просматривать в отладчике "код по отправке SMS через интернет".



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 октября 2010 17:09
· Личное сообщение · #4

cosinus
После исполнения инструкции по адресу 0x3700B6 в стеке будет адрес возврата 0x3700BB, а Ip = 0x3703DA. Там инструкция Pop Eax извлечёт из стека адрес возврата, а следующее ветвление загрузит в стек адрес 0x3703DD и вернёт управление на следующую за вызывающим ветвлением инструкцию. Что тут может быть не понятно ?
Это такой способ загрузки ссылки, блок эквивалентен Push 0x3703DD. Только при перестройке графа смещение не может быть задано в виде константы или дельтасмещения.

На счёт 0x401386 - там вобще ничего не обычного нет. Просто холостые инструкции, так как !al.



Ранг: 13.8 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 03 октября 2010 17:39 · Поправил: cosinus
· Личное сообщение · #5

Тут всё понятно, что парочка 'pop eax, call eax' эквивалентна команде push 003703DDh.
И что создаётся поток, "код" которого начинается этого адреса.

Непонятно как выбрался из этого кода ?
Code:
  1. 003700C0  - EB FE      jmp short 003700C0


А что касается 00401386, то тут тоже ясно что инструкция add byte ptr ds:[eax],al при al равно 0 является эквивалентом инструкции nop. Но дойдя до адреса 00401FFF нажал F8 и переместился на вполне нормальный код, просто не понятно как это произошло, если на вершине стека (да и под ней) находились адреса "недров" kernel32.dll да и в регистрах тоже ничего интересного не было... а управление перешло на адрес 00402001.
До:


После:


Но давайте сначала о "Джампе на сам-себя" поговорим.



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 октября 2010 17:57 · Поправил: Clerk
· Личное сообщение · #6

cosinus
Поток зацикливается. Что с ним происходит далее - откуда же мне знать, может он так и висит за ненадобностью, может иной поток завершает его или изменяет его контекст, или инициирует исключение в нём, может есчо что, этого никто не знает.

> управление перешло на адрес 00402001.
Ну это ведь следующая страница, кудаже есчо процессор перейдёт. Он выполнит add byte ptr ds:[eax],al(часть инструкции в конце первой страницы, часть в начале следующей ), затем Pushad.



Ранг: 13.8 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 03 октября 2010 18:38 · Поправил: cosinus
· Личное сообщение · #7

>>Любопытства ради поставил бряк на 003700C2 и нажал F9, чисто позырить что будя дальше. И бряк сработал!
Это гвоорит о том что главный поток не остаётся в подвешенном состоянии
Видимо в создаваемом потоке кроется ответ, на то как выйти из джампа-на-сам-себя. Потому что создаётся поток с флагом dwCreationFlags.
цитата:
"Флажки, которые управляют созданием потока. Если установлен флажок CREATE_SUSPENDED, создается поток в состоянии ожидания и не запускается до тех пор, пока не будет вызвана функция ResumeThread. Если это значение нулевое, поток запускается немедленно после создания. В это время, никакие другие значения не поддерживаются."

Я просто прозивал этот момент...


>>Ну это ведь следующая страница, кудаже есчо процессор перейдёт.
Ну тут уж даже не знал об этом. Спасибо.



Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 03 октября 2010 21:05 · Поправил: Clerk
· Личное сообщение · #8

cosinus
> Ну тут уж даже не знал об этом. Спасибо.
Виртуальная память линейная. Про сегментация памяти вы можите не подозревать, так что это только отладчика проблема, связанная с хидером модуля.

> Это гвоорит о том что главный поток не остаётся в подвешенном состоянии
Это говорит о том, что код вызвал другой поток и что вы не умеете обращаться с отладчиком.



Ранг: 13.8 (новичок), 1thx
Активность: 0.010
Статус: Участник

Создано: 03 октября 2010 21:13 · Поправил: cosinus
· Личное сообщение · #9

"Расцикливание" главного потока осуществляется через SetThreadContext.

>>вы не умеете обращаться с отладчиком.
Ну дык стараюсь учиться уметь обращаться

Clerk спасибо за потраченное на меня время.


 eXeL@B —› Вопросы новичков —› Джамп на сам-себя.
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати