IDA PRO, плагины, подсказки и решение проблем

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
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

возьмем функу, которая определяется не правильно

Код:
.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' и в большинстве случаев все будет как надо.
 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
пару плагинов, они правда для ольки, но все же имеют отношения к сабжу

MapConv читает MAP файлы созданые ida и softice и заменяет имена лейблов в ольке, пример как было и как стало после того как добавились лейблы и имена из иды. К тому же в списке имен ( crtl+n ) они тоже появятся.

OllyGraph строит граф выбранной функции, перед использованием надо указать путь до wingraph32.exe, например из иды 5.5 и после получается вот такая красота
 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
справка по иде
 

Вложения

Barack

RAM
Пользователь
Регистрация
28.03.2011
Сообщения
129
Оценка реакций
0
Баллы
18
все посты, как говорится - "то что надо", спс ТС
 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
мини фак, если буду что то находить, буду добавлять

q:Как вернутся на уровень вверх в hex rays?
a:Esc

q:Как убрать переопределение в hex rays?
a:'\' или правой кнопкой Hide casts

q:Почему ида не грузит символы?
a:Создайте переменную среды _NT_SYMBOL_PATH со значением srv*C:\symbols*http://msdl.microsoft.com/download/symbols где C:\symbols, папка куда будут скидываться символы

q:Как переключаться между ida view и hex rays псевдокодом и обратно
a:tab и crtl+tab между окнами аля alt+tab в винде
 

Михрютка

CD-диск
Пользователь
Регистрация
13.08.2011
Сообщения
12
Оценка реакций
0
Баллы
8
Думаю, стоит раскрыть вопрос, как правильно реверсить программы с несколькими файлами (например длл или базонезависимым кодом), в т.ч. с использованием отладки в ида про.
 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
Легкое создание структур, оказывается ида давно умеет создавать структуры одним щелчком мыши, подробнее тут http://www.hexblog.com/?p=71, ниже скрины моего примера. ( ida61 )




 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
Наводим лоск на функции с большим колвом используемых структур, на примере get_api с поиском базы через tib->peb->ldr, вот такой вот код

Код:
.text:0042474C 000 55                                   push    ebp
.text:0042474D 004 8B EC                                mov     ebp, esp
.text:0042474F 004 83 EC 14                             sub     esp, 14h
.text:00424752 018 64 A1 18 00 00 00                    mov     eax, large fs:18h
.text:00424758 018 8B 40 30                             mov     eax, [eax+30h]
.text:0042475B 018 8B 40 0C                             mov     eax, [eax+0Ch]
.text:0042475E 018 8B 40 1C                             mov     eax, [eax+1Ch]
.text:00424761 018 8B 50 08                             mov     edx, [eax+8]
.text:00424764 018 8B 42 3C                             mov     eax, [edx+3Ch]
.text:00424767 018 8B 44 10 78                          mov     eax, [eax+edx+78h]
.text:0042476B 018 83 65 F0 00                          and     [ebp+var_10], 0
.text:0042476F 018 03 C2                                add     eax, edx
.text:00424771 018 8B 48 24                             mov     ecx, [eax+24h]
.text:00424774 018 53                                   push    ebx
.text:00424775 01C 8B 58 1C                             mov     ebx, [eax+1Ch]
.text:00424778 01C 56                                   push    esi
.text:00424779 020 03 CA                                add     ecx, edx
.text:0042477B 020 57                                   push    edi
.text:0042477C 024 8B 78 20                             mov     edi, [eax+20h]
.text:0042477F 024 8B 40 18                             mov     eax, [eax+18h]
приводим к нормальному виду, для этого погрузим скрипт который я положил выше, дабы подгрузить необходимые структуры, а потом наводим на 0x18h в строке
Код:
.text:00424752 018 64 A1 18 00 00 00                    mov     eax, large fs:18h
нажимаем 'T' и выбираем _TIB.SelfLinear, и дальше т.о. код преобразуется в наглядный и приятный для глаз
Код:
.text:0042474C 000 55                                   push    ebp
.text:0042474D 004 8B EC                                mov     ebp, esp
.text:0042474F 004 83 EC 14                             sub     esp, 14h
.text:00424752 018 64 A1 18 00 00 00                    mov     eax, large fs:_TIB.SelfLinear
.text:00424758 018 8B 40 30                             mov     eax, [eax+_TIB.PebPtr]; _PEB
.text:0042475B 018 8B 40 0C                             mov     eax, [eax+_PEB.Ldr]; _PEB_LDR_DATA
.text:0042475E 018 8B 40 1C                             mov     eax, [eax+_PEB_LDR_DATA.InInitializationOrderModuleList.Flink]; _LDR_MODULE
.text:00424761 018 8B 50 08                             mov     edx, [eax+_LDR_MODULE.InMemoryOrderModuleList.Flink]
.text:00424764 018 8B 42 3C                             mov     eax, [edx+IMAGE_DOS_HEADER.e_lfanew]; _IMAGE_NT_HEADERS
.text:00424767 018 8B 44 10 78                          mov     eax, [eax+edx+IMAGE_NT_HEADERS.OptionalHeader.Exports.VirtualAddress]; IMAGE_OPTIONAL_HEADER32 / IMAGE_OPTIONAL_HEADER64
.text:0042476B 018 83 65 F0 00                          and     [ebp+var_10], 0
.text:0042476F 018 03 C2                                add     eax, edx
.text:00424771 018 8B 48 24                             mov     ecx, [eax+IMAGE_EXPORT_DIRECTORY.AddressOfNameOrdinals]
.text:00424774 018 53                                   push    ebx
.text:00424775 01C 8B 58 1C                             mov     ebx, [eax+IMAGE_EXPORT_DIRECTORY.AddressOfFunctions]
.text:00424778 01C 56                                   push    esi
.text:00424779 020 03 CA                                add     ecx, edx
.text:0042477B 020 57                                   push    edi
.text:0042477C 024 8B 78 20                             mov     edi, [eax+IMAGE_EXPORT_DIRECTORY.AddressOfNames]
.text:0042477F 024 8B 40 18                             mov     eax, [eax+IMAGE_EXPORT_DIRECTORY.NumberOfNames]
к тому же все это еще и передается в hex rays, правда не всегда, видимо что то еще влияет на это, в общем ниже пример другой функции
Код:
  v3 = __readfsdword(offsetof(_TIB, SelfLinear));
  if ( !*(v3 + offsetof(_TIB, ActivationCtxStack)) )
    *(v3 + offsetof(_TIB, ActivationCtxStack)) = v3 + offsetof(_TIB, vdm);
  return sub_4017F5(
           *(*(*(*(v3 + offsetof(_TIB, PebPtr)) + offsetof(_PEB, Ldr))
             + offsetof(_PEB_LDR_DATA, InInitializationOrderModuleList))
           - 0x10
           + 0x18),
           a1);
 

frosty

floppy-диск
Пользователь
Регистрация
26.06.2011
Сообщения
1
Оценка реакций
0
Баллы
8
PyEmu - эмулятор, написанный на питоне, удобно использовать вместе с idapython.
Скачать его можно тут http://code.google.com/p/pyemu/

Постараюсь показать на примере, как юзать.

У нас есть драйвер с зашифрованной секцией .cdata, начало секции выглядит так:
Код:
00021680  D6 4C B3 0E EF 4C 81 0E  E3 4C 94 0E EF 4C AB 0E  гL¦.яLБ.уLФ.яLл.
00021690  DE 4C 94 0E FA 4C F7 0E  DA F5 F6 0E CE F5 F6 0E  ¦LФ.·Lў.-їЎ.+їЎ.
000216A0  BE F5 F6 0E A2 F5 F6 0E  96 F5 F6 0E 8A 4C F7 0E  -їЎ.вїЎ.ЦїЎ.КLў.
000216B0  D6 4C A4 0E F3 4C 84 0E  FE 4C 92 0E E7 4C A5 0E  гLд.єLД.¦LТ.чLе.
000216C0  E5 4C 98 0E FE 4C AB 0E  F9 4C 8E 0E F9 4C 83 0E  хLШ.¦Lл.•LО.•LГ.
В этой секции содержаться строки и другие данные, знать которые необходимо для дальнейшего
анализа драйвера.

Методом статического анализа кода было установленно что расшифровка секции происходит
в функции sub_1E778.

Аргументы:
arg_0 - адрес секции
arg_4 - размер
arg_8 - в нашем случае тут 0

Код:
.text:0001E778 sub_1E778       proc near             ; CODE XREF: sub_10D3C+112p
.text:0001E778                                       ; sub_1E7CC+81p ...
.text:0001E778
.text:0001E778 arg_0           = dword ptr  8
.text:0001E778 arg_4           = dword ptr  0Ch
.text:0001E778 arg_8           = dword ptr  10h
.text:0001E778
.text:0001E778                 mov     edi, edi
.text:0001E77A                 push    ebp
.text:0001E77B                 mov     ebp, esp
.text:0001E77D                 mov     edx, [ebp+arg_8]
.text:0001E780                 push    ebx
.text:0001E781                 push    esi
.text:0001E782                 push    edi
.text:0001E783                 shl     ebx, 8
.text:0001E786                 mov     esi, [ebp+arg_4]
.text:0001E789                 test    esi, esi
.text:0001E78B                 jbe     short loc_1E7C0
.text:0001E78D                 mov     ecx, [ebp+arg_0]
.text:0001E790
.text:0001E790 loc_1E790:                           ; CODE XREF: sub_1E778+46j
.text:0001E790                 cmp     ecx, offset byte_21D88
.text:0001E796                 jb      short loc_1E7A0
.text:0001E798                 cmp     ecx, offset dword_21D8C
.text:0001E79E                 jb      short loc_1E7B0
.text:0001E7A0
.text:0001E7A0 loc_1E7A0:                           ; CODE XREF: sub_1E778+1Ej
.text:0001E7A0                 mov     al, ds:byte_21D88[edx]
.text:0001E7A6                 xor     [ecx], al
.text:0001E7A8                 inc     edx
.text:0001E7A9                 mov     eax, 5C94h
.text:0001E7AE                 push    eax
.text:0001E7AF                 pop     edi
.text:0001E7B0
.text:0001E7B0 loc_1E7B0:                           ; CODE XREF: sub_1E778+26j
.text:0001E7B0                 cmp     edx, 4
.text:0001E7B3                 jnz     short loc_1E7BC
.text:0001E7B5                 xor     edx, edx
.text:0001E7B7                 mov     eax, 797h
.text:0001E7BC
.text:0001E7BC loc_1E7BC:                           ; CODE XREF: sub_1E778+3Bj
.text:0001E7BC                 inc     ecx
.text:0001E7BD                 dec     esi
.text:0001E7BE                 jnz     short loc_1E790
.text:0001E7C0
.text:0001E7C0 loc_1E7C0:                           ; CODE XREF: sub_1E778+13j
.text:0001E7C0                 pop     edi
.text:0001E7C1                 pop     esi
.text:0001E7C2                 pop     ebx
.text:0001E7C3                 pop     ebp
.text:0001E7C4                 retn    0Ch
.text:0001E7C4 sub_1E778       endp
Стоит упомянуть что byte_21D88 и dword_21D8C - находится в пределах секции .cdata.

Используем PyEmu для расшифровки секции.
Идея в том что мы задаем начальное состояние эмулятора, загружаем в него память по нужным адресам, задаем значение регистров(если необходимо) и стэка, и выполняем эмуляцию (функции sub_1E778 в нашем случае) .

Скрипт для ida:
Код:
import sys
sys.path.append("C:\\pyemu")
sys.path.append("C:\\pyemu\\lib")

from PyEmu import *
emu = IDAPyEmu()

f = get_func(0x0001E778)
for pos in xrange(f.startEA,f.endEA):
    emu.set_memory(pos, get_original_byte(pos), size=1)

print "[*] %s loaded" % get_func_name(f.startEA)

s = get_segm_by_name('.cdata')
for pos in xrange(s.startEA,s.endEA):
    emu.set_memory(pos, get_original_byte(pos), size=1)

print "[*] segment %s loaded %x - %x" % (get_segm_name(s), s.startEA, s.endEA)
print "segment size : %d" % (s.endEA - s.startEA)

emu.set_stack_argument(0x4,s.startEA,name="addr")
emu.set_stack_argument(0x8,s.endEA - s.startEA,name="size")
emu.set_stack_argument(0xc,0,name="key_pos")

emu.execute(start=f.startEA,end=f.endEA-3)
print "[*] done"

for pos in xrange(s.startEA,s.endEA):
    c = emu.get_memory(pos,1)
    patch_byte(pos,c)
Запускаем (File->Script file или Alt-F7):
[*] sub_1E778 loaded
[*] segment _cdata loaded 21680 - 21f00
segment size : 2176
[*] done
Теперь начало секции выглядит так:
Код:
00021680  5C 00 44 00 65 00 76 00  69 00 63 00 65 00 5C 00  \.D.e.v.i.c.e.\.
00021690  54 00 63 00 70 00 00 00  50 B9 01 00 44 B9 01 00  T.c.p...P¦..D¦..
000216A0  34 B9 01 00 28 B9 01 00  1C B9 01 00 00 00 00 00  4¦..(¦...¦......
000216B0  5C 00 53 00 79 00 73 00  74 00 65 00 6D 00 52 00  \.S.y.s.t.e.m.R.
000216C0  6F 00 6F 00 74 00 5C 00  73 00 79 00 73 00 74 00  o.o.t.\.s.y.s.t.
000216D0  65 00 6D 00 33 00 32 00  5C 00 64 00 72 00 69 00  e.m.3.2.\.d.r.i.
000216E0  76 00 65 00 72 00 73 00  5C 00 00 00 2E 00 73 00  v.e.r.s.\.....s.
000216F0  79 00 73 00 00 00 00 00  5C 53 79 73 74 65 6D 52  y.s.....\SystemR
00021700  6F 6F 74 5C 73 79 73 74  65 6D 33 32 5C 00 00 00  oot\system32\...
00021710  2E 00 73 00 79 00 73 00  00 00 00 00 73 00 79 00  ..s.y.s.....s.y.
00021720  73 00 74 00 65 00 6D 00  33 00 32 00 5C 00 64 00  s.t.e.m.3.2.\.d.
00021730  72 00 69 00 76 00 65 00  72 00 73 00 5C 00 00 00  r.i.v.e.r.s.\...
profit! =)

Вернуть секцию в состояние "как было" можно следующим скриптом:
Код:
s = get_segm_by_name('.cdata')
for pos in xrange(s.startEA,s.endEA):
    put_byte(pos,get_original_byte(pos))
Более подробно можно посмотреть в книге Gray Hat Python.
 

p(eaZ

RAID-массив
Пользователь
Регистрация
03.04.2011
Сообщения
81
Оценка реакций
1
Баллы
13
Python arsenal for RE - сборник и описание питоновских программ для реверсинга.
 

greenzy

(L3) cache
Пользователь
Регистрация
25.10.2010
Сообщения
208
Оценка реакций
1
Баллы
18
не могу создать структуру, точнее нет этого пункта в меню. как быть?
 

E.N.G.Land

(L3) cache
Пользователь
Регистрация
16.10.2008
Сообщения
219
Оценка реакций
0
Баллы
18
В окне структур в первой строке написано:
"; Ins/Del : create\delete structure"
Т.е. чтобы создать структуру нужно нажать Insert.
 

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Оценка реакций
2
Баллы
18
link - IDA plugin to extract resources from loaded file. Запускать из отладчика
link - Reversing C++ programs with IDA pro and Hex-rays
link - Simple IDA Pro plugin to look up APIs on MSDN

Decrypting malware strings with IDA's Appcall bit.ly/arLMLF
 

KraZz

(L3) cache
Пользователь
Регистрация
18.06.2009
Сообщения
196
Оценка реакций
7
Баллы
18
el- пишет:
возьмем функу, которая определяется не правильно
Ну, тут как бы код скомпилированный, скорее всего FASM`ом
Насколько я помню, только FASM страдает такой анальной херней, вставляя в тело функции после call данные в виде строки
Поэтому тут как не старайся шаманить, для "ИДЫ" эта строка (в теле функции) будет всегда кодом, а не данными!

el- пишет:
И теперь функа hex ray'ится, не до конца хорошо ибо не видно вызова get_api, но тут я уже хз что делать
Тут можно как вариант заюзать питон
Скомпилим тестовый сэмпл на MASM32
Код:
.386
.model flat, stdcall
option casemap:none
option prologue:none

.code
ZwSetContextThread proc
  ret 8
ZwSetContextThread endp
get_api proc
  mov eax, ZwSetContextThread
  ret 4
get_api endp
pZwSetContextThread proc ThreadHandle:DWORD, Context:DWORD
  call @F
  db 'ZwSetContextThread',0
@@:	
  call get_api
  jmp eax
pZwSetContextThread endp

start:
  push 0
  push 0
  call pZwSetContextThread
  ret
end start
И открываем его в ИДЕ и вручную приводим код в божеский вид, должно получиться примерно следующее:
Код:
.text:00401000                             ZwSetContextThread proc near
.text:00401000 000 C2 08 00                retn    8
.text:00401000                             ZwSetContextThread endp
.text:00401003                            ; =============== S U B R O U T I N E =======================================
.text:00401003                             get_api proc near
.text:00401003 000 B8 00 10 40 00          mov     eax, offset ZwSetContextThread
.text:00401008 000 C2 04 00                retn    4
.text:00401008                             get_api endp
.text:0040100B                            ; =============== S U B R O U T I N E =======================================
.text:0040100B                            ; LONG __cdecl pZwSetContextThread(LONG ThreadHandle, LONG Context)
.text:0040100B                             pZwSetContextThread proc near
.text:0040100B                             ThreadHandle= dword ptr  4
.text:0040100B                             Context= dword ptr  8
.text:0040100B 000 E8 13 00 00 00          call    loc_401023
.text:00401010 000 5A 77 53 65 74 43 6F 6E+szZwSetContextThread db 'ZwSetContextThread',0
.text:00401023                             loc_401023:
.text:00401023 000 E8 DB FF FF FF          call    get_api
.text:00401028 -04 FF E0                   jmp     eax
.text:00401028                             pZwSetContextThread endp; sp-analysis failed
.text:0040102A                            ; =============== S U B R O U T I N E =======================================
.text:0040102A                             public start
.text:0040102A                             start proc near
.text:0040102A 000 6A 00                   push    0                              ; Context
.text:0040102C 004 6A 00                   push    0                              ; ThreadHandle
.text:0040102E 008 E8 D8 FF FF FF          call    pZwSetContextThread
.text:00401033 008 C3                      retn
.text:00401033                             start endp; sp-analysis failed
Теперь если нажать на функции pZwSetContextThread F5 нам Hex-Rays покажет факинг
Гы-гы, теперь берем и запускаем вот этот питоновский скриптег
Код:
#-*- coding: utf8 -*-
#=================
#from idc import *
#from idaapi import *
#from idautils import *
#=================

NOP = 0x90

def memset(address, value, size):
   for offset in range(size):
      patch_byte(address+offset, value)

def get_instruction_size(address):
   ln = ua_ana0(address)
   if(ln):
      return ln
   else:
      return get_item_size(address)

def AddSection(size):
   seg = getnseg(get_segm_qty()-1)
   startseg = (seg.endEA+0x2000)&0xFFFFF000
   endseg = startseg+size
   add_segm(get_segm_qty()+1, startseg, endseg, ".tmp", "DATA")
   seg = getseg(startseg)
   if not seg:
      return 0
# 0:16bit segment, 1:32bit segment, 2:64bit segment
   seg.bitness = 1
   seg.align = 3
   seg.comb = 2
   return startseg

addrstr = AddSection(0x1000)
nfuncs = get_func_qty()
if nfuncs != 0:
   for n in range(nfuncs):
      func = getn_func(n)
      print("%X %X %d") % (func.startEA, func.endEA-1, n)
      address = func.startEA
      endfunc = func.endEA-1
      func_start = func.startEA
      func_end = func.endEA
      maxfunc = 0
      while endfunc > address:
         #print tag_remove(generate_disasm_line(address))
         instr_size = get_instruction_size(address)
         maxfunc+=1
         if(maxfunc > 200 or instr_size == 0):
            maxfunc = stop
            break
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
         db = get_original_byte(address)
         if(db == 0xE8):
            len = get_original_long(address+1)
            if(len < 512 and get_byte(address+4+len) == 0x00):
               str = get_ascii_contents(address+4, len, ASCSTR_TERMCHR)
               #print str
               memset(address+5, NOP, len);
               do_unknown_range(addrstr, len, DOUNK_SIMPLE);
               patch_many_bytes(addrstr, str+'\0');
               make_ascii_string(addrstr, len, ASCSTR_TERMCHR)
               do_unknown_range(address, 5+len, DOUNK_SIMPLE);
               patch_byte(address, 0x68)
               patch_long(address+1, addrstr)
               ua_code(address)
               add_func(func_start, func_end)
               add_hidden_area(address+5, address+5+len, str, "", "", 0x00FF00)
               addrstr+=len
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
         address = address+instr_size
else:
   print "..."
и видим следующее:
Код:
.text:00401000                             ZwSetContextThread proc near
.text:00401000 000 C2 08 00                retn    8
.text:00401000                             ZwSetContextThread endp
.text:00401003                            ; =============== S U B R O U T I N E =======================================
.text:00401003                             get_api proc near
.text:00401003 000 B8 00 10 40 00          mov     eax, offset ZwSetContextThread
.text:00401008 000 C2 04 00                retn    4
.text:00401008                             get_api endp
.text:0040100B                            ; =============== S U B R O U T I N E =======================================
.text:0040100B                            ; LONG __cdecl pZwSetContextThread(LONG ThreadHandle, LONG Context)
.text:0040100B                             pZwSetContextThread proc near
.text:0040100B 000 68 00 30 40 00          push    403000h                        ; "ZwSetContextThread"
.text:00401010                            ; ZwSetContextThread
.text:00401023 004 E8 DB FF FF FF          call    get_api
.text:00401028 000 FF E0                   jmp     eax
.text:00401028                             pZwSetContextThread endp
.text:0040102A                            ; =============== S U B R O U T I N E =======================================
.text:0040102A                             public start
.text:0040102A                             start proc near
.text:0040102A 000 6A 00                   push    0                              ; Context
.text:0040102C 004 6A 00                   push    0                              ; ThreadHandle
.text:0040102E 008 E8 D8 FF FF FF          call    pZwSetContextThread
.text:00401033 008 C3                      retn
.text:00401033                             start endp; sp-analysis failed
Стоит отметить, что строка по адресу 00401010 свернута и в развернутом виде она выглядит так:
Код:
.text:00401010                            ; [00000013 BYTES: BEGIN OF AREA ZwSetContextThread. PRESS KEYPAD "-" TO COLLAPSE]
.text:00401010 004 90                      nop
.text:00401011 004 90                      nop
.text:00401012 004 90                      nop
.text:00401013 004 90                      nop
.text:00401014 004 90                      nop
.text:00401015 004 90                      nop
.text:00401016 004 90                      nop
.text:00401017 004 90                      nop
.text:00401018 004 90                      nop
.text:00401019 004 90                      nop
.text:0040101A 004 90                      nop
.text:0040101B 004 90                      nop
.text:0040101C 004 90                      nop
.text:0040101D 004 90                      nop
.text:0040101E 004 90                      nop
.text:0040101F 004 90                      nop
.text:00401020 004 90                      nop
.text:00401021 004 90                      nop
.text:00401022 004 90                      nop
.text:00401022                            ; [00000013 BYTES: END OF AREA ZwSetContextThread. PRESS KEYPAD "-" TO COLLAPSE]
При этом этот свернутый код будет подсвечиваться зеленым цветом
А вот теперь, если нажать на функции pZwSetContextThread F5, ву-а-ля
Получим следующее:
Код:
LONG __cdecl pZwSetContextThread(LONG ThreadHandle, LONG Context)
{
  int (*v3)(void); // eax@1

  v3 = (int (*)(void))get_api("ZwSetContextThread");
  return v3();
}
Стоит наверное пояснить, что же делает питоновский скрипт
А все очень просто, вначале создается дополнительная секция с помощью функции AddSection
AddSection нужно передать всего один параметр – размер создаваемой секции
Далее идет перебор всех функций, которые ИДА смогла найти, определить и создать (get_func_qty + getn_func)
А также перебирается каждый адрес в функции и ищется call, вернее байт равный 0xE8
Код:
db = get_original_byte(address)
if(db == 0xE8):
Далее если нашли, то получаем dword (который находится после байта 0xE8)
Код:
len = get_original_long(address+1)
И проверяем по смещению address+4+len, если байт равен нулю, то значит что это признак строки
Код:
if(len < 512 and get_byte(address+4+len) == 0x00):
Получаем строку
Код:
str = get_ascii_contents(address+4, len, ASCSTR_TERMCHR)
Тут стоит пояснить, что для более точно результата детекта строки нужно проверять дополнительно, ну скажем с помощью регулярных выражений (модуль re)
Далее переносится строка в новую секцию (ту которую мы создали) и вместо call`а (0xE8) патчится на 0x68 (push)
А значение push устанавливается равным указателю на ту строку, которую мы перенесли в секцию
А строка в функции заливается нопами (функция memset), что и позволяет впоследствии этой функции "hex ray'ится"
Не знаю, как у тебя на счет питона получится или нет (тут как я понял, "многие" Python "ненавидят"), но ты попробуй, там в принципе ничего сложного нет :)

el- пишет:
Для начала необходимо включить всякую красоту дабы все необходимое было видно, идем в Options->General,
и ставим галки Basic block boundaries, Stack pointer, Number of opcode bytes
Прочитал и вспомнил ЛОЛьную историю с одним плагином (quickopt)
Один чел его выложил, я его посмотрел, и появилось несколько идей расширить функционал этого плагина
Попросил у него исходники, а он там чет выебываться стал.. ну и сам тупо неподумафф добро дал на %)))
=TS= пишет:
А кому очень надо сырцы-- тот отреверсит (или напишет с 0).
Ну а за мной естественно не заржавеет, вот и снял исходники с этого плагина
http://demonteam.narod.ru/quickopt/quickopt.html
Правда эт было очень давно, короче БАЯН нахъ.. но может, кому и пригодится в плане изучения кода...
 

Quake3

генератор Зла
Модератор
Регистрация
03.11.2010
Сообщения
625
Оценка реакций
205
Баллы
45
Вопрос наверное глупый, но не могу сам найти. Подскажите, реально ли как то включить в Иде опцию, чтобы она в режиме hex-rays (Си код) отображала параметры функций в более понятном виде?
Т.е. сейчас как:
Код:
CreateFileA("file.txt", 0x40000000u, 0, 0, 4u, 0x80u, 0);
Я хотел бы как в olly, чтобы вместо этих констант было GENERIC_READ, и так далее.
 

demien

(L2) cache
Пользователь
Регистрация
29.09.2008
Сообщения
496
Оценка реакций
4
Баллы
18
Я хотел бы как в olly, чтобы вместо этих констант было GENERIC_READ, и так далее.
В иде для всех распространенных констант есть определения. Нажми на константу правой кнопкой мышки и выбери Use standart symbolic constant.
 

Quake3

генератор Зла
Модератор
Регистрация
03.11.2010
Сообщения
625
Оценка реакций
205
Баллы
45
Верх