ida великолепный инструмент для реверс инженеринга, который я например использую только наверное на несколько процентов, т.к. не знаю всех её возможностей и особенностей, данная тема создана для того, что бы в ней могли делится своими знания или подсказками про сабж. Помогая друг другу мб у нас получится по лучше понять этот сложный инструмент и работать с ним более эффективно.
Я расскажу про пару ошибок hex rays, которые буквально сегодня я научился побеждать, мб это покажется вам интересным или даже полезным. Ошибки positive sp value has been found и call analysis failed которые довольно часто выскакивают в hex rays, по крайне мере в старых версиях, сейчас то у нас есть возможность погонять версию 6.1, в любом случае рассказ ниже.
positive sp value has been found
http://www.hex-rays.com/manual/failures.shtml#04
Для начала необходимо включить всякую красоту дабы все необходимое было видно, идем в Options->General,
и ставим галки Basic block boundaries, Stack pointer, Number of opcode bytes
получается после адреса, первый столбик зеленых цифр это стек (Stack pointer), синий столбики цифр это собственно байткод (Number of opcode bytes) и разделение между блоками кода, после call или jmp/jz/jnz/etc это (Basic block boundaries)
теперь надо рассказать из-за чего сбивается стек, я знаю три причины для этого:
- ида не правильно определила прототипы функций, которые вызываются в коде
- какая то из функций меняет стек, но иде опять же не удалось этого понять
- ида не смогла определить seh_prolog/seh_epilog
возьмем функу, которая определяется не правильно
для начало объявим её прототип, наведя на имя и нажав 'y' и объявим её как int __stdcall pZwSetContextThread(int, int), далее видно что в стек толкается указатель строку, которая находится под call'ом так вот стек должен меняется и на второй и третей строке он должен равняться 004, потом после вызова int __stdcall get_api(int), она чистит за собой стек и к jmp eax он должен равняться нулю. Поэтому нам придется вручную выставить необходимые стековые значения, наводим на самый первый 000, нажимаем alt + k и вбиваем -0x04 все остальные стековые указатели меняются, функа принимает вид
И теперь функа hex ray'ится, не до конца хорошо ибо не видно вызова get_api, но тут я уже хз что делать, в остальных случаях это все же помогает лучше чем сейчас.
собственно тут было рассмотрено пара проблем а именно
- ида не правильно определила прототипы функций, которые вызываются в коде
- какая то из функций меняет стек, но иде опять же не удалось этого понять
с прологом и эпилогом все проще, если иде не удалось определить пролог эпилог, но надо прост навести на него нажать 'n' и переименовать в SEH_prolog, далее ида обычно перестраивает стек и все опять же работает, если же это не помогло, то таким же образом ровняется стек после вызова пролога. Надо так же заметить изменяя стек, вы меняете его не у выбранного блока а у блока ниже и все за ним идущих.
call analysis failed
http://www.hex-rays.com/manual/failures.shtml#11
Тут все проще, иногда иде не удается правильно определить прототипы фунок из-за этого она кстати может портить стек функи из которой они вызываются, такое бывает с какими то редкими апи ( у меня по крайне было с кернел функами ). Так вот тут надо просто определить функи нужный прототип по средством 'y' и в большинстве случаев все будет как надо.
Я расскажу про пару ошибок hex rays, которые буквально сегодня я научился побеждать, мб это покажется вам интересным или даже полезным. Ошибки positive sp value has been found и call analysis failed которые довольно часто выскакивают в hex rays, по крайне мере в старых версиях, сейчас то у нас есть возможность погонять версию 6.1, в любом случае рассказ ниже.
positive sp value has been found
http://www.hex-rays.com/manual/failures.shtml#04
Для начала необходимо включить всякую красоту дабы все необходимое было видно, идем в Options->General,
и ставим галки Basic block boundaries, Stack pointer, Number of opcode bytes
получается после адреса, первый столбик зеленых цифр это стек (Stack pointer), синий столбики цифр это собственно байткод (Number of opcode bytes) и разделение между блоками кода, после call или jmp/jz/jnz/etc это (Basic block boundaries)
теперь надо рассказать из-за чего сбивается стек, я знаю три причины для этого:
- ида не правильно определила прототипы функций, которые вызываются в коде
- какая то из функций меняет стек, но иде опять же не удалось этого понять
- ида не смогла определить seh_prolog/seh_epilog
возьмем функу, которая определяется не правильно
Код:
.text:0042484F pZwSetContextThread proc near ; CODE XREF: inject_function+86p
.text:0042484F
.text:0042484F arg_0 = dword ptr 4
.text:0042484F arg_4 = dword ptr 8
.text:0042484F
.text:0042484F 000 E8 13 00 00 00 call loc_424867
.text:0042484F
.text:0042484F ; ---------------------------------------------------------------------------
.text:00424854 000 5A 77 53 65 74 43 6F+aZwsetcontextthread db 'ZwSetContextThread',0
.text:00424867 ; ---------------------------------------------------------------------------
.text:00424867
.text:00424867 loc_424867: ; CODE XREF: pZwSetContextThreadp
.text:00424867 000 E8 E0 FE FF FF call get_api
.text:00424867
.text:0042486C -04 FF E0 jmp eax
.text:0042486C
.text:0042486C pZwSetContextThread endp; sp-analysis failed
для начало объявим её прототип, наведя на имя и нажав 'y' и объявим её как int __stdcall pZwSetContextThread(int, int), далее видно что в стек толкается указатель строку, которая находится под call'ом так вот стек должен меняется и на второй и третей строке он должен равняться 004, потом после вызова int __stdcall get_api(int), она чистит за собой стек и к jmp eax он должен равняться нулю. Поэтому нам придется вручную выставить необходимые стековые значения, наводим на самый первый 000, нажимаем alt + k и вбиваем -0x04 все остальные стековые указатели меняются, функа принимает вид
Код:
.text:0042484F ; int __stdcall pZwSetContextThread(int, int)
.text:0042484F pZwSetContextThread proc near ; CODE XREF: inject_function+86p
.text:0042484F
.text:0042484F arg_0 = dword ptr 4
.text:0042484F arg_4 = dword ptr 8
.text:0042484F
.text:0042484F 000 E8 13 00 00 00 call loc_424867
.text:0042484F
.text:0042484F ; ---------------------------------------------------------------------------
.text:00424854 004 5A 77 53 65 74 43 6F+aZwsetcontextthread db 'ZwSetContextThread',0
.text:00424867 ; ---------------------------------------------------------------------------
.text:00424867
.text:00424867 loc_424867: ; CODE XREF: pZwSetContextThreadp
.text:00424867 004 E8 E0 FE FF FF call get_api
.text:00424867
.text:0042486C 000 FF E0 jmp eax
.text:0042486C
.text:0042486C pZwSetContextThread endp; sp-analysis failed
И теперь функа hex ray'ится, не до конца хорошо ибо не видно вызова get_api, но тут я уже хз что делать, в остальных случаях это все же помогает лучше чем сейчас.
Код:
int __stdcall pZwSetContextThread(int a1, int a2)
{
JUMPOUT(loc_424867);
}
собственно тут было рассмотрено пара проблем а именно
- ида не правильно определила прототипы функций, которые вызываются в коде
- какая то из функций меняет стек, но иде опять же не удалось этого понять
с прологом и эпилогом все проще, если иде не удалось определить пролог эпилог, но надо прост навести на него нажать 'n' и переименовать в SEH_prolog, далее ида обычно перестраивает стек и все опять же работает, если же это не помогло, то таким же образом ровняется стек после вызова пролога. Надо так же заметить изменяя стек, вы меняете его не у выбранного блока а у блока ниже и все за ним идущих.
call analysis failed
http://www.hex-rays.com/manual/failures.shtml#11
Тут все проще, иногда иде не удается правильно определить прототипы фунок из-за этого она кстати может портить стек функи из которой они вызываются, такое бывает с какими то редкими апи ( у меня по крайне было с кернел функами ). Так вот тут надо просто определить функи нужный прототип по средством 'y' и в большинстве случаев все будет как надо.